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:

How to Disable “Advanced Filter or Sort” and Enforce Custom Filters on Any D365FO Form

 In Dynamics 365 Finance and Operations, users can apply filters through the “Advanced filter or sort” feature found under the Options tab...