How to Invoice the Purchase order based on Packing Slip/Product Receipt by X++

This code will created pending invoice based on VendPackingSlipJour data and posting that’s pending invoice at the end of code.

PurchFormLetter             purchFormLetter; 
PurchTable                  purchTable;
PurchLine                   purchLine;

VendPackingSlipJour         vendPackingSlipJour;
VendPackingSlipTrans        vendPackingSlipTrans;

VendInvoiceInfoTable        vendInvoiceInfoTable;
VendInvoiceInfoLine         vendInvoiceInfoLine;
VendInvoiceInfoSubTable     vendInvoiceInfoSubTable;
VendInvoiceInfoSubLine      vendInvoiceInfoSubLine;

PurchId                     purchId;
PackingSlipId               packingSlipId;
;

purchId = 'PO109832341';
packingSlipId = 'PK109832341';

ttsBegin;
purchTable = PurchTable::find(purchId);

/*If we've more than one packingslip, then we can separate the  Header part(vendInvoiceInfoTable,vendInvoiceInfoSubTable) without while. Header will be created once and we can keep only the Line using vendPackingSlipTrans while statement.*/

while select vendPackingSlipJour
    where vendPackingSlipJour.PurchId == purchTable.PurchId
    && vendPackingSlipJour.PackingSlipId == packingSlipId
{

    //Generate Pending Invoice Header
    vendInvoiceInfoTable.clear();
    vendInvoiceInfoTable.initValue();
    vendInvoiceInfoTable.initFromPurchTable(purchTable);

    vendInvoiceInfoTable.DocumentOrigin  = DocumentOrigin::Manual;
    vendInvoiceInfoTable.CurrencyCode = purchTable.CurrencyCode;
    vendInvoiceInfoTable.DeliveryName = purchTable.DeliveryName;
    vendInvoiceInfoTable.Num = "INV-" + vendPackingSlipJour.PackingSlipId; //add invoice number in here
    vendInvoiceInfoTable.PurchName = purchTable.PurchName;
    vendInvoiceInfoTable.VendInvoiceSaveStatus = VendInvoiceSaveStatus::Pending;
    vendInvoiceInfoTable.DocumentDate = systemDateGet();
    vendInvoiceInfoTable.LastMatchVariance = LastMatchVarianceOptions::OK;
    vendInvoiceInfoTable.ParmJobStatus = ParmJobStatus::Waiting;
    vendInvoiceInfoTable.Approved = NoYes::Yes;
    vendInvoiceInfoTable.Approver = DirPersonUser::currentWorker();

    vendInvoiceInfoTable.DefaultDimension = vendInvoiceInfoTable.copyDimension(purchTable.DefaultDimension);

    vendInvoiceInfoTable.defaultField(fieldNum(VendInvoiceInfoTable,RemittanceLocation),null,purchTable);
    vendInvoiceInfoTable.defaultField(fieldNum(VendInvoiceInfoTable,FixedDueDate),null,purchTable);
    vendInvoiceInfoTable.defaultField(fieldNum(VendInvoiceInfoTable,ExchRate),null,purchTable);
    vendInvoiceInfoTable.defaultField(fieldNum(VendInvoiceInfoTable,TransDate),null,purchTable);
    vendInvoiceInfoTable.defaultField(fieldNum(VendInvoiceInfoTable,PaymMode),null,purchTable);

    vendInvoiceInfoTable.insert();

    //Generate Vend Invoice Info reference
    if(vendInvoiceInfoTable)
    {
        vendInvoiceInfoSubTable.clear();
        vendInvoiceInfoSubTable.initValue();
        vendInvoiceInfoSubTable.defaultRow();

        vendInvoiceInfoSubTable.ParmId = vendInvoiceInfoTable.ParmId;
        vendInvoiceInfoSubTable.OrigPurchId = vendInvoiceInfoTable.PurchId;
        vendInvoiceInfoSubTable.PurchName = vendInvoiceInfoTable.PurchName;
        vendInvoiceInfoSubTable.TableRefId = vendInvoiceInfoTable.TableRefId;

        vendInvoiceInfoSubTable.insert();
    }

    //select all packing slip line
    while select vendPackingSlipTrans
        where vendPackingSlipTrans.PackingSlipId == vendPackingSlipJour.PackingSlipId
        && vendPackingSlipTrans.VendPackingSlipJour == vendPackingSlipJour.RecId
    {
        //Generate Pending Invoice Line
        purchLine = vendPackingSlipTrans.purchLine();
        vendInvoiceInfoLine.clear();
        vendInvoiceInfoLine.initValue();
        vendInvoiceInfoLine.defaultRow(null,purchLine);
        vendInvoiceInfoLine.initFromPurchLine(purchLine);

        vendInvoiceInfoLine.DeliveryName = vendInvoiceInfoTable.DeliveryName;
        vendInvoiceInfoLine.ParmId = vendInvoiceInfoTable.ParmId;
        vendInvoiceInfoLine.TableRefId = vendInvoiceInfoTable.TableRefId;
        vendInvoiceInfoLine.currencyCode = vendInvoiceInfoTable.CurrencyCode;
        vendInvoiceInfoLine.LineNum = any2int(purchLine.LineNumber);

        vendInvoiceInfoLine.InvoiceAccount = vendInvoiceInfoTable.InvoiceAccount;
        vendInvoiceInfoLine.InventDimId = vendPackingSlipTrans.InventDimId;
        vendInvoiceInfoLine.OrderAccount  = vendInvoiceInfoTable.OrderAccount;
        vendInvoiceInfoLine.ItemId = vendPackingSlipTrans.ItemId;
        vendInvoiceInfoLine.InventTransId = vendPackingSlipTrans.InventTransId;

        vendInvoiceInfoLine.DocumentOrigin = DocumentOrigin::Manual;

        vendInvoiceInfoLine.ReceiveNow = vendPackingSlipTrans.Qty;
        vendInvoiceInfoLine.RemainBefore = vendPackingSlipTrans.Qty;
        vendInvoiceInfoLine.RemainBeforeInvent = vendPackingSlipTrans.Qty;

        vendInvoiceInfoLine.PurchPrice = purchLine.PurchPrice;
        vendInvoiceInfoLine.InventNow = vendPackingSlipTrans.Qty;
        vendInvoiceInfoLine.LineAmount = (purchLine.LineAmount / purchLine.QtyOrdered) * vendPackingSlipTrans.Qty;

        vendInvoiceInfoLine.DefaultDimension = purchLine.DefaultDimension;

        vendInvoiceInfoLine.insert();

        //Generate Vend Invoice Info reference from packing slip
        if(vendInvoiceInfoLine.RecId)
        {
            vendInvoiceInfoSubLine.clear();
            vendInvoiceInfoSubLine.initValue();
            vendInvoiceInfoSubLine.defaultRow();
            vendInvoiceInfoSubLine.ParmId = vendInvoiceInfoTable.ParmId;
            vendInvoiceInfoSubLine.LineRefRecId = vendInvoiceInfoLine.RecId;
            vendInvoiceInfoSubLine.ReceiveNow = vendPackingSlipTrans.Qty;
            vendInvoiceInfoSubLine.InventNow = vendPackingSlipTrans.Qty;
            vendInvoiceInfoSubLine.JournalRefRecId = vendPackingSlipTrans.RecId;
            vendInvoiceInfoSubLine.JournalRefTableId = vendPackingSlipTrans.TableId;
            vendInvoiceInfoSubLine.DocumentId = vendPackingSlipTrans.PackingSlipId;
            vendInvoiceInfoSubLine.insert();
        }
    }

    //Posting pending invoice to invoice, without below code it will create pending invoice
    purchFormLetter = PurchFormLetter_Invoice::newFromSavedInvoice(vendInvoiceInfoTable);
    purchFormLetter.update(vendInvoiceInfoTable.purchTable(),vendInvoiceInfoTable.Num);
}

ttsCommit;

info(strFmt('Purchase Order %1 invoiced',purchTable.PurchId));