Tuesday, October 31, 2017

Microsoft Dynamics 365 for Finance and Operations, Enterprise edition : X++ code to post Purchase order invoice by matching a product receipt

Product receipt is the process of recording the products that were ordered, have been received. Once received, the purchase order lines can then be processed for invoicing. There can be multiple product receipts posted against a purchase order and there might be situations where we may need to post an invoice for a particular product receipt.

In Microsoft Dynamics 365 for Finance and Operations, Enterprise edition we can use the match product receipt function during creation of purchase order invoice to select a particular product receipt.


Let's do a quick walk through: Below are three product receipts posted against a purchase order




When we go to invoice the purchase order and use the highlighted option to default invoice lines from the product receipt quantity, system will by-default include all the posted product receipts "multiple" and will show in the product receipt as shown below





To choose a particular product receipt by using the Match product receipt functionality , click on "Match product receipts"





A new form will open where we can select any particular product receipt and the invoice will get updated to refer to the selected product receipt 



Enter the invoice number and post the invoice





We may need to build a process where we need to automate this and want to post invoice for a particular product receipt. You might just have the product receipt number and a purchase order number provided to you.
To do this from X++  code you can use the below code and make it as an API to post Invoice for a particular product receipt. It uses the product receipt number as the invoice number during posting. 





To use it quickly below is the code: 

public static void main (Args _args)
    {
        TmpFrmVirtual               tmpFrmVirtualVend;
        PurchFormLetter_Invoice     purchFormLetter;
        VendPackingSlipJour         vendPackingSlipJour;
        SysQueryRun                 chooseLinesQuery;
        SysQueryRun                 chooseLinesPendingInvoiceQuery;
        container                   conTmpFrmVirtual;
        List                        selectedList    = new List(Types::Record);
        PurchId                     purchId         = "PO00001" ; //Purchase order number
        PackingSlipId               packingSlipId   = "PCK0001"; //Product receipt number

        select firstonly vendPackingSlipJour
                    where vendPackingSlipJour.PurchId == purchId
            && vendPackingSlipJour.PackingSlipId == packingSlipId;

        if (vendPackingSlipJour)
        {
            tmpFrmVirtualVend.clear();
            tmpFrmVirtualVend.TableNum  = vendPackingSlipJour.TableId;
            tmpFrmVirtualVend.RecordNo  = vendPackingSlipJour.RecId;
            tmpFrmVirtualVend.NoYes     = NoYes::Yes;
            tmpFrmVirtualVend.Id        = vendPackingSlipJour.PurchId;
            tmpFrmVirtualVend.insert();
        }

        chooseLinesQuery = new SysQueryRun(queryStr(PurchUpdate));
        chooseLinesQuery.query().addDataSource(tableNum(VendInvoiceInfoTable)).enabled(false);

        // chooseLinesPendingInvoiceQuery needs to be initialized, although it will not be used
        chooseLinesPendingInvoiceQuery = new SysQueryRun(queryStr(PurchUpdatePendingInvoice));
        chooseLinesPendingInvoiceQuery.query().dataSourceTable(tableNum(PurchTable)).addRange(fieldNum(PurchTable,PurchId)).value(queryValue(''));
           
        purchFormLetter = PurchFormLetter::construct(DocumentStatus::Invoice);
        purchFormLetter.chooseLinesQuery (chooseLinesQuery);
        purchFormLetter.parmQueryChooseLinesPendingInvoice(chooseLinesPendingInvoiceQuery);
        purchFormLetter.purchTable (PurchTable::find(PurchId));
        purchFormLetter.transDate (systemDateGet());
        purchFormLetter.parmParmTableNum (strFmt("%1",packingSlipId)); //This is invoice number
        purchFormLetter.printFormLetter (NoYes::No);
        purchFormLetter.sumBy (AccountOrder::Auto);
        purchFormLetter.specQty (PurchUpdate::PackingSlip);
      
        while select tmpFrmVirtualVend
        {
            selectedList.addEnd(tmpFrmVirtualVend);
            conTmpFrmVirtual = selectedList.pack();
        }
        purchFormLetter.selectFromJournal(conTmpFrmVirtual);
        purchFormLetter.reArrangeNow(true);
        purchFormLetter.run();
    }