How to: Fix issues related to Intercompany chain and clean up broken inventory transcations

 For those who have worked in Intercompany SO-POs know it very well that sometimes users across different legal entities face challenges in IC SO and IC PO. Issues with qty, statuses of lines or statuses of headers, broken inventory transactions for which nothing can be done.

Below is the script to fix the status on lines, the status on the header, and delete broken inventory transactions:

static void Job1(Args _args)

{

    PurchLine purchLine,purchLineGB;

    InventTrans inventTrans,inventTransGB;

    InventTransOrigin inventTransOrigin,inventTransOriginGB;

    SalesLine salesLine,salesLineGB;

    SalesTable salestable,salestableGB;

    PurchTable purchTable,purchTableGB;

    

    void updateSO(inventTransId _inventTransId, SalesStatus _lineSalesStatus, SalesStatus _orderSalesStatus)

    {

        select forupdate salesLine where salesLine.InventTransId == _inventTransId;

        salesLine.RemainInventPhysical = 0;

        salesLine.RemainSalesPhysical = 0;

        salesLine.SalesStatus =_lineSalesStatus;

        salesLine.doUpdate();

        info(strFmt("Salesline with inventtrans %1 updated ",SalesLine.InventTransId));

        

        while select InventTransOrigin where inventTransOrigin.InventTransId == salesLine.InventTransId

            join forUpdate inventTrans 

            where inventTrans.InventTransOrigin == InventTransOrigin.RecId

               && (inventTrans.StatusIssue == StatusIssue::OnOrder ||

               inventTrans.StatusIssue == StatusIssue::ReservOrdered)

        {

            info(strFmt("InventTrans recid %1 %2 deleted",inventTrans.RecId,inventTrans.dataAreaId));

            InventTrans.doDelete();  

        }   

        select forUpdate salesTable where salesTable.SalesId == salesLine.SalesId;

        SalesTable.SalesStatus = _orderSalesStatus;

        SalesTable.doUpdate();

        info(strFmt("SalesTable with salesId %1 updated ",SalesLine.SalesId));

        info(strFmt("---------------------------------------------------------"));

    }

    

    void updatePO(inventTransId _inventTransId, PurchStatus _linePurchStatus, PurchStatus _orderPurchStatus)

    {

    select forupdate purchLine where purchLine.InventTransId == _inventTransId;

        purchLine.RemainPurchPhysical = 0;

        purchLine.RemainInventPhysical = 0;

        purchLine.PurchStatus = _linePurchStatus;

        purchLine.doUpdate();

        info(strFmt("PurchLine with inventtrans %1 updated ",PurchLine.InventTransId));

   

        while select InventTransOrigin where inventTransOrigin.InventTransId == purchLine.InventTransId

            join forUpdate inventTrans 

            where inventTrans.InventTransOrigin == InventTransOrigin.RecId

               && inventTrans.StatusReceipt == StatusReceipt::Ordered

        {

            info(strFmt("InventTrans recid %1 %2 deleted",inventTrans.RecId,inventTrans.dataAreaId));

            InventTrans.doDelete();  

        }

        

        select forUpdate purchTable where purchTable.PurchId == purchLine.purchId;

        purchTable.PurchStatus = _orderPurchStatus;

        purchTable.doUpdate();

        info(strFmt("PurchTable with purchId %1 updated ",purchLine.purchId));

        info(strFmt("---------------------------------------------------------"));

    }

    

    void updateSOGB(inventTransId _inventTransId, SalesStatus _lineSalesStatus, SalesStatus _orderSalesStatus)

    {

        select forupdate salesLineGB where salesLineGB.InventTransId == _inventTransId;

        salesLineGB.RemainInventPhysical = 0;

        salesLineGB.RemainSalesPhysical = 0;

        salesLineGB.SalesStatus = _lineSalesStatus;

        salesLineGB.doUpdate();

        info(strFmt("Salesline with inventtrans %1 updated ",salesLineGB.InventTransId));

        

        

        while select InventTransOriginGB where InventTransOriginGB.InventTransId == salesLineGB.InventTransId

            join forUpdate inventTransGB 

            where inventTransGB.InventTransOrigin == InventTransOriginGB.RecId

               && (inventTransGB.StatusIssue == StatusIssue::OnOrder ||

               inventTransGB.StatusIssue == StatusIssue::ReservOrdered)

        {

            info(strFmt("InventTransGB recid %1 %2 deleted",inventTransGB.RecId,inventTransGB.dataAreaId));

            InventTransGB.doDelete();  

        }

        select forUpdate salesTableGB where salesTableGB.SalesId == salesLineGB.SalesId;

        SalesTableGB.SalesStatus = _orderSalesStatus;

        SalesTableGB.doUpdate();

        info(strFmt("SalesTable with salesId %1 updated ",SalesLineGB.SalesId));

        info(strFmt("---------------------------------------------------------"));

    }

    void updatePOGB(inventTransId _inventTransId, PurchStatus _linePurchStatus, PurchStatus _orderPurchStatus)

    {

    select forupdate purchLineGB where purchLineGB.InventTransId == _inventTransId;

        purchLineGB.RemainPurchPhysical = 0;

        purchLineGB.RemainInventPhysical = 0;

        purchLineGB.PurchStatus = _linePurchStatus;

        purchLineGB.doUpdate();

        info(strFmt("PurchLine with inventtrans %1 updated ",purchLineGB.InventTransId));

   

        while select InventTransOriginGB where InventTransOriginGB.InventTransId == purchLineGB.InventTransId

            join forUpdate inventTransGB 

            where inventTransGB.InventTransOrigin == InventTransOriginGB.RecId

               && inventTransGB.StatusReceipt == StatusReceipt::Ordered

        {

            info(strFmt("InventTrans recid %1 %2 deleted",inventTransGB.RecId,inventTransGB.dataAreaId));

            InventTransGB.doDelete();  

        }

        

        select forUpdate purchTableGB where purchTableGB.PurchId == purchLineGB.purchId;

        purchTableGB.PurchStatus = _orderPurchStatus;

        purchTableGB.doUpdate();

        info(strFmt("PurchTable with purchId %1 updated ",purchLineGB.purchId));

        info(strFmt("---------------------------------------------------------"));

    }

    ttsBegin;

    changeCompany('FR01')

    {

        updateSO('inventTransId in FR01 LE',SalesStatus::Canceled,SalesStatus::Invoiced); //('lotid', Line status, Header status)

        updatePO('inventTransId in FR01 LE',PurchStatus::Canceled,PurchStatus::Canceled); //('lotid', Line status, Header status)

    }

    changeCompany('GB01')

    {

        updateSOGB('inventTransId in GB01 LE',SalesStatus::Canceled ,SalesStatus::Canceled); //('lotid', Line status, Header status)

        updatePOGB('inventTransId in FR01 LE',PurchStatus::Canceled,PurchStatus::Canceled); //('lotid', Line status, Header status)

    }

    ttsCommit;

}

 Please note this does not break IC chain, just fixes the transcations. Usually this is done when SO and PO are in final state like Invoiced and some opne transcations remain which keeps it open. Also when SO/PO is cancelled in 1 LE and its open in other LE. I have used this script numerous times usually to fix the status to Invoice or Cancelled. 

Note: Always test the results in Testing env before making changes in production enviroment. 

If you need to break the IC chain and process the SO/PO then script is different. Thats for next blog.



Comments

Popular posts from this blog

How to: Import Bank statements from Azure file storage to Dynamics 365 finance and operation using Power automate (formally flow)

How to: Use enum values instead of integers in BI reports for Dynamics 365 finance and operations

How to : get the Deep URL for a particular form with filter in Dynamics 365 Finance and Operations