Wednesday 11 January 2017

Auto Inter company Purchase order Invoice posting.

Inter-company Invoice posting.

In this post we can find the code to Automatical post the intercompany purchase order, when you click the sales order invoice.
This is a manual process in the standard AX and would require around 4 steps to the above process. Refere the below link for the Manual process.

Link: Manual Inter-company PO invoice

So for the auto process... we will start with creating the class as below.
class Mk_IntercompanyPOInvoice
{
    CustInvoiceJour     custInvoiceJour;
}

add new method

protected void new(CustInvoiceJour     _custInvoiceJour)
{
    custInvoiceJour = _custInvoiceJour;
}

and a construct method

///

/// Initializes a new instance of the Mk_IntercompanyPOInvoice class
///
///
/// parameter for CustInvoiceJour
///
///
///  A new instance of the Mk_IntercompanyPOInvoice class.
///
///
///
///

public static server Mk_IntercompanyPOInvoice construct(CustInvoiceJour     _custInvoiceJour)
{
    return new Mk_IntercompanyPOInvoice(_custInvoiceJour);
}

Add below methods

public void invoiceIntercompanyPO(SalesTable  _salesTable)
{
    SalesTable      lsalesTable;
    PurchTable      lPurchTable;
    lsalesTable = _salesTable;
    lPurchTable = lsalesTable.interCompanyPurchTable();
    changecompany(lsalesTable.InterCompanyCompanyId)
    {
        //Method to confirm the PO
this.confirmationPO(lPurchTable);
// Method to do product receipt of PO
        this.postProductReceipt(lPurchTable);

    }
    // Invoice the PO
    this.interCompanyUpdate();

}

private void confirmationPO(PurchTable  _purchTable)
{
    PurchFormLetter purchFormLetter;
    PurchTable      lPurchTable;
    lPurchTable = _purchTable;
    //PO confirmation
    purchFormLetter = PurchFormLetter::construct(DocumentStatus::PurchaseOrder);
    purchFormLetter.update(lPurchTable, strFmt("Inv_%1", lPurchTable.PurchId));
}

public void postProductReceipt(PurchTable  _purchTable)
{
    PurchFormLetter             purchFormLetter;
    PurchFormletterParmData     purchFormLetterParmData;
    PurchParmUpdate             purchParmUpdate;
    PurchParmTable              purchParmTable;
    PurchParmLine               purchParmLine;
    PurchTable                  purchTable;
    PurchLine                   purchLine;
    PurchId                     purchId;
    Num                         packingSlipId;

    purchId       = "0000-000187";
    packingSlipId = "MAK3101";
    purchTable    = _purchTable;

    ttsBegin;
    // Create PurchParamUpdate table
    purchFormLetterParmData = PurchFormletterParmData::newData(
        DocumentStatus::PackingSlip,
        VersioningUpdateType::Initial);

    purchFormLetterParmData.parmOnlyCreateParmUpdate(true);
    purchFormLetterParmData.createData(false);
    purchParmUpdate = purchFormLetterParmData.parmParmUpdate();

    // Set PurchParmTable table
    purchParmTable.clear();
    purchParmTable.TransDate                = SystemDateGet();
    purchParmTable.Ordering                 = DocumentStatus::PackingSlip;
    purchParmTable.ParmJobStatus            = ParmJobStatus::Waiting;
    purchParmTable.Num                      = packingSlipId;//To-Do check for number sequence
    purchParmTable.PurchId                  = purchTable.PurchId;
    purchParmTable.PurchName                = purchTable.PurchName;
    purchParmTable.DeliveryName             = purchTable.DeliveryName;
    purchParmTable.DeliveryPostalAddress    = purchTable.DeliveryPostalAddress;
    purchParmTable.OrderAccount             = purchTable.OrderAccount;
    purchParmTable.CurrencyCode             = purchTable.CurrencyCode;
    purchParmTable.InvoiceAccount           = purchTable.InvoiceAccount;
    purchParmTable.ParmId                   = purchParmUpdate.ParmId;
    purchParmTable.insert();

    // Set PurchParmLine table
    while select purchLine
        where purchLine.PurchId == purchTable.purchId
    {
        purchParmLine.InitFromPurchLine(purchLine);

        purchParmLine.ReceiveNow    = PurchLine.PurchQty;
        purchParmLine.ParmId        = purchParmTable.ParmId;
        purchParmLine.TableRefId    = purchParmTable.TableRefId;
        purchParmLine.setQty(DocumentStatus::PackingSlip, false, true);
        purchParmLine.setLineAmount();
        purchParmLine.insert();
    }

    purchFormLetter = PurchFormLetter::construct(DocumentStatus::PackingSlip);
    purchFormLetter.transDate(systemDateGet());
    purchFormLetter.proforma(false);
    purchFormLetter.specQty(PurchUpdate::All);
    purchFormLetter.purchTable(purchTable);

    // This is the ID we hard code as the product receipt ID, if we do the posting via UI
    // user would have the option to manually enter this value
    purchFormLetter.parmParmTableNum(purchParmTable.ParmId);
    purchFormLetter.parmId(purchParmTable.ParmId);
    purchFormLetter.purchParmUpdate(purchFormLetterParmData.parmParmUpdate());
    purchFormLetter.run();
    ttsCommit;
}

private void  interCompanyUpdate()
{
    CustInvoiceTrans        custInvoiceTrans;
    Map                     inventTransIdMap    = new Map(new DictField(tableNum(CustInvoiceTrans),fieldNum(CustInvoiceTrans, InventTransId)).baseType(), Types::Container);
    MapIterator             miInventTransId;
    Map                     purchIdMap          = new Map(new DictField(tableNum(PurchTable),fieldNum(PurchTable, PurchId)).baseType(), Types::Integer);
    MapIterator             miPurchId;
    Map                     receiveNowMap       = new Map(new DictField(tableNum(PurchLine),fieldNum(PurchLine, InventTransId)).baseType(), Types::Container);
    container               receiveNow;
    PurchFormLetter_Invoice purchFormLetter;
    SysQueryRun             chooseLinesQuery;
    SysQueryRun             chooseLinesPendingInvoiceQuery;

    SalesParmUpdate         salesParmUpdate;

    PurchId                 interCompanyPurchId;
    InventTransId           interCompanyInventTransId;
    PurchLine               purchLine;

    InventTrans             inventTrans;
    InventTransOrigin       inventTransOrigin;

    VendPackingSlipJour     vendPackingSlipJour;
    CustPackingSlipTrans    custPackingSlipTrans;
    CustInvoicePackingSlipQuantityMatch custInvoicePackingSlipQuantityMatch;
    TmpFrmVirtual           tmpFrmVirtualCust;
    TmpFrmVirtual           tmpFrmVirtualVend;
    List                    selectedList = new List(Types::Record);
    container               conTmpFrmVirtual;

    salesParmUpdate = SalesParmUpdate::find(custInvoiceJour.ParmId);
    while select InventTransId, InterCompanyInventTransId, Qty, PdsCWQty, StockedProduct, SourceDocumentLine from custInvoiceTrans
        where custInvoiceTrans.SalesId              == custInvoiceJour.SalesId
               && custInvoiceTrans.InvoiceId            == custInvoiceJour.InvoiceId
               && custInvoiceTrans.InvoiceDate          == custInvoiceJour.InvoiceDate
               && custInvoiceTrans.NumberSequenceGroup  == custInvoiceJour.NumberSequenceGroup
    {
        if (custInvoiceTrans.isStocked())
        {
            inventTransIdMap.insert(custInvoiceTrans.InterCompanyInventTransId, [custInvoiceTrans.Qty, custInvoiceTrans.PdsCWQty]);

            while select PackingSlipId, DatePhysical from inventTrans
                  where inventTrans.InvoiceId     == custInvoiceJour.InvoiceId
                  &&    inventTrans.DateFinancial == custInvoiceJour.InvoiceDate
                  exists join inventTransOrigin
                    where inventTransOrigin.RecId         == inventTrans.InventTransOrigin
                       && inventTransOrigin.InventTransId == custInvoiceTrans.InventTransId
            {
                select firstonly tmpFrmVirtualCust
                       where tmpFrmVirtualCust.Id        == custInvoiceJour.InterCompanyPurchId
                       &&    tmpFrmVirtualCust.ItemId    == inventTrans.PackingSlipId
                       &&    tmpFrmVirtualCust.TransDate == inventTrans.DatePhysical;
                if (!tmpFrmVirtualCust)
                {
                    tmpFrmVirtualCust.clear();
                    tmpFrmVirtualCust.Id        = custInvoiceJour.InterCompanyPurchId;
                    tmpFrmVirtualCust.ItemId    = inventTrans.PackingSlipId;
                    tmpFrmVirtualCust.TransDate = inventTrans.DatePhysical;
                    tmpFrmVirtualCust.insert();

                }
            }
        }
        else
        {
            while select PackingSlipId from custPackingSlipTrans
                exists join custInvoicePackingSlipQuantityMatch
                    where custInvoicePackingSlipQuantityMatch.InvoiceSourceDocumentLine == custInvoiceTrans.SourceDocumentLine
                        && custInvoicePackingSlipQuantityMatch.PackingSlipSourceDocumentLine == custPackingSlipTrans.SourceDocumentLine
            {
                select firstonly tmpFrmVirtualCust
                       where tmpFrmVirtualCust.Id        == custInvoiceJour.InterCompanyPurchId
                       &&    tmpFrmVirtualCust.ItemId    == custPackingSlipTrans.PackingSlipId;

                if (!tmpFrmVirtualCust)
                {
                    tmpFrmVirtualCust.clear();
                    tmpFrmVirtualCust.Id        = custInvoiceJour.InterCompanyPurchId;
                    tmpFrmVirtualCust.ItemId    = custPackingSlipTrans.PackingSlipId;
                    tmpFrmVirtualCust.insert();

                }
            }
        }
    }

    changecompany(custInvoiceJour.InterCompanyCompanyId)
    {
        this.intercompanyAllocateMarkupAndConfirm(inventTransIdMap);
        tmpFrmVirtualVend = null;
        while select tmpFrmVirtualCust
        {
            select firstonly vendPackingSlipJour
                where vendPackingSlipJour.PurchId       == tmpFrmVirtualCust.Id
                &&    vendPackingSlipJour.PackingSlipId == tmpFrmVirtualCust.ItemId;
/*
// This is omitted, due to problems when the intercompany sales order items are delivered one day,
// and the items are received on the intercompany purchase order on the following day
//
                &&    vendPackingSlipJour.DeliveryDate  == tmpFrmVirtualCust.TransDate;
*/
            if (vendPackingSlipJour)
            {
                select firstonly tmpFrmVirtualVend
                       where tmpFrmVirtualVend.TableNum   == vendPackingSlipJour.TableId
                       &&    tmpFrmVirtualVend.RecordNo   == vendPackingSlipJour.RecId
                       &&    tmpFrmVirtualVend.Id         == vendPackingSlipJour.PurchId;
                if (!tmpFrmVirtualVend)
                {
                    tmpFrmVirtualVend.clear();
                    tmpFrmVirtualVend.TableNum      = vendPackingSlipJour.TableId;
                    tmpFrmVirtualVend.RecordNo      = vendPackingSlipJour.RecId;
                    tmpFrmVirtualVend.NoYes         = NoYes::Yes;
                    tmpFrmVirtualVend.Id            = vendPackingSlipJour.PurchId;
                    tmpFrmVirtualVend.insert();
                }
            }
            else
            {
                tmpFrmVirtualVend   = null;
                warning(strFmt("@SYS106122",custInvoiceJour.InterCompanyPurchId));
                break;
            }
        }

        ttsbegin;

        chooseLinesQuery = new SysQueryRun(queryStr(PurchUpdate));

        miInventTransId = new MapIterator(inventTransIdMap);
        miInventTransId.begin();
        while (miInventTransId.more())
        {
            interCompanyInventTransId = miInventTransId.key();
            interCompanyPurchId       = PurchLine::findInventTransId(interCompanyInventTransId).PurchId;

            if (!purchIdMap.exists(interCompanyPurchId))
            {
                while select forupdate purchLine
                      where purchLine.PurchId == interCompanyPurchId
                         && !purchLine.IsDeleted
                {
                    if (inventTransIdMap.exists(purchLine.InventTransId))
                    {
                        [purchLine.PurchReceivedNow, purchLine.PdsCWInventReceivedNow] = inventTransIdMap.lookup(purchLine.InventTransId);
                    }
                    else
                    {
                        receiveNow = [purchLine.PurchReceivedNow, purchLine.InventReceivedNow];
                        receiveNowMap.insert(purchLine.InventTransId, receiveNow);
                        purchLine.PurchReceivedNow = 0;
                    }
                    purchLine.setInventReceivedNow();
                    purchLine.update();
                }
                purchIdMap.insert(interCompanyPurchId, 1);
                chooseLinesQuery.query().dataSourceTable(tableNum(PurchTable)).addRange(fieldNum(PurchTable, PurchId)).value(queryValue(interCompanyPurchId));
            }
            miInventTransId.next();
        }
        ttscommit;
        chooseLinesQuery.query().interactive    (false);
        chooseLinesQuery.saveUserSetup          (false);

        // VendInvoiceInfoTable is the required datasource of the query
        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(custInvoiceJour.InterCompanyPurchId));
        purchFormLetter.transDate               (custInvoiceJour.InvoiceDate);
        purchFormLetter.parmParmTableNum        (custInvoiceJour.InvoiceId);
        purchFormLetter.creditRemaining         (salesParmUpdate.CreditRemaining);
        purchFormLetter.printFormLetter         (NoYes::No);
        purchFormLetter.interCompanyVoucher     (custInvoiceJour.LedgerVoucher);
        purchFormLetter.sumBy                   (AccountOrder::Auto);

        if (tmpFrmVirtualVend)
        {
            purchFormLetter.specQty                 (PurchUpdate::PackingSlip);

            while select tmpFrmVirtualVend
            {
                selectedList.addEnd(tmpFrmVirtualVend);
                conTmpFrmVirtual = selectedList.pack();
            }
            purchFormLetter.selectFromJournal(conTmpFrmVirtual);
        }
        else
        {
            purchFormLetter.specQty                 (PurchUpdate::All);
            purchFormLetter.chooseLines(false);
        }

        purchFormLetter.reArrangeNow(true);
        purchFormLetter.run();

        if (receiveNowMap.elements())
        {
            ttsbegin;
            miPurchId = new MapIterator(purchIdMap);
            miPurchId.begin();
            while (miPurchId.more())
            {
                interCompanyPurchId = miPurchId.key();

                while select forupdate purchLine
                      where purchLine.PurchId == interCompanyPurchId
                         && !purchLine.IsDeleted
                {
                    if (receiveNowMap.exists(purchLine.InventTransId))
                    {
                        receiveNow = receiveNowMap.lookup(purchLine.InventTransId);
                        purchLine.PurchReceivedNow = conPeek(receiveNow, 1);
                        purchLine.InventReceivedNow = conPeek(receiveNow, 2);
                        purchLine.doUpdate();
                    }
                }

                miPurchId.next();
            }
            ttscommit;
        }
    }
}


Now call the above class from SalesTable from clicked method.

void clicked()
{
    Mk_IntercompanyPOInvoice   intercompanyPOInvoice;
    CustInvoiceJour             custInvoiceJour;
    SalesTable                  lSalesTable;
    ;


    //
    if (isRU)
    {
        salesTable.checkMarkupTrans_RU();
    }
    //
    super();
    custInvoiceJour = CustInvoiceJour::findFromSalesId_IN(SalesTable.SalesId);
    if (custInvoiceJour.RecId)
    {
        intercompanyPOInvoice = MK_IntercompanyPOInvoice::construct(custInvoiceJour);
        intercompanyPOInvoice.invoiceIntercompanyPO(SalesTable);
    }
}


Hope this will help you. by....Mallik!!!

No comments:

Update NuGet package to new MS D365FO version

1. Import the NuGet package files from LCS for that particular version please take the PU version files only. a. Goto LCS-->Asset Libra...