Site icon Microsoft Business Applications

Settle payment journal against sales invoice in D365 FinOpsApps



Code used to settle posted payment journal transaction against the sales invoice

// <summary>
    /// Settle payment journal (which still has balance) against sales invoice. Each payment journal is make for one sales order only.
    /// No payment is made for multiple order. If balance is available after settle, leave the balance as there might be another invoice
    /// not comes in yet for the same order. This periodic job will settle against them when the invoice is in.
    /// </summary>
    /// <param name = "_contract"></param>
    public void processSettlement(AG_CustSalesPaymSettlementDataContract _contract)
    {
        RefRecId            paymLedgerJournalTransRefRecId = _contract.parmPaymLedgerJournalTransRecId();
        boolean             showInfoLog                    = _contract.parmShowInfoLog();
        LedgerJournalTable  paymLedgerJournalTable;
        LedgerJournalTrans  paymLedgerJournalTrans;
        CustTransOpen       paymCustTransOpen, custTransOpen;
        CustTrans           paymCustTrans;

        //Loop through all payment journal which still has open balance
        while select paymLedgerJournalTable
            where   paymLedgerJournalTable.Posted       == NoYes::Yes
            join    paymLedgerJournalTrans
            where   paymLedgerJournalTrans.JournalNum   == paymLedgerJournalTable.JournalNum
                &&  ((!paymLedgerJournalTransRefRecId)                                      //If specific payment journal line is provided, get that only,
                ||   (paymLedgerJournalTrans.RecId      == paymLedgerJournalTransRefRecId)) //else, get all lines (which satisfy other query criteria)
            join    paymCustTrans
            where   paymCustTrans.Voucher               == paymLedgerJournalTrans.Voucher
                &&  paymCustTrans.RecId                 == paymLedgerJournalTrans.CustTransId
                &&  paymCustTrans.TransType             == LedgerTransType::Payment
            join    paymCustTransOpen
            where   paymCustTransOpen.RefRecId          == paymCustTrans.RecId
        {
           AG_CustSalesPaymSettlementService::settleByPaymJourTrans(paymLedgerJournalTrans, showInfoLog);
        }

    }

    public static void settleByPaymJourTrans(LedgerJournalTrans _paymLedgerJournalTrans, boolean _showInfoLog)
    {
        boolean             useLegacyMethod = false;
        CustTable           custTable;
        LedgerJournalTrans  paymLedgerJournalTrans;
        CustTransOpen       invCustTransOpen, paymCustTransOpen, custTransOpen;
        CustTrans           invCustTrans, paymCustTrans;
        CustInvoiceJour     custInvoiceJour;
        SpecTransManager    manager;
        CustVendTransData   custVendTransData;

        //Given the payment LedgerJournalTrans, find the related CustTrans which has CustTransOpen
        select firstonly paymLedgerJournalTrans
            where   paymLedgerJournalTrans.RecId  == _paymLedgerJournalTrans.RecId
            join    paymCustTrans
            where   paymCustTrans.Voucher         == paymLedgerJournalTrans.Voucher
                &&  paymCustTrans.RecId           == paymLedgerJournalTrans.CustTransId
                &&  paymCustTrans.TransType       == LedgerTransType::Payment
            join    paymCustTransOpen
            where   paymCustTransOpen.RefRecId    == paymCustTrans.RecId;

        //Find the related invoice to be settled against the payment journal in the query above
        select firstonly invCustTrans
            where   invCustTrans.AccountNum      == paymCustTrans.AccountNum
                &&  invCustTrans.MCRPaymOrderID  == paymCustTrans.MCRPaymOrderID
                &&  invCustTrans.TransType       == LedgerTransType::Sales
            join    invCustTransOpen
            where   invCustTransOpen.RefRecId    == invCustTrans.RecId;

        custTable = CustTable::find(paymCustTrans.AccountNum);

        try
        {
            ttsbegin;

            if(paymCustTransOpen && invCustTransOpen)
            {
                //Legacy code for settlement --------------------------------------------------------------------------------------------------------
                if(useLegacyMethod)
                {
                    //Create an object of the CustVendTransData class with the invoice transaction as parameter and mark it for settlement
                    custVendTransData = CustVendTransData::construct(invCustTrans);
                    custVendTransData.markForSettlement(custTable);

                    //Create an object of the CustVendTransData class with the payment transaction as parameter and mark it for settlement
                    custVendTransData = CustVendTransData::construct(paymCustTrans);
                    custVendTransData.markForSettlement(custTable);

                    // Settle all transactions marked for settlement for this customer
                    CustTrans::settleTransact(custTable, null, true, SettleDatePrinc::DaysDate, systemdateget());
                }
                //New code for settlement -----------------------------------------------------------------------------------------------------------
                else
                {
                    //Mark for settlement
                    SpecTransExecutionContext specTransExecutionContext = SpecTransExecutionContext::newFromSource(custTable);
                    SpecTransManager          specTransManager          = SpecTransManager::construct(specTransExecutionContext.parmSpecContext());
                    Amount                    settleAmount              = invCustTransOpen.AmountCur;

                    //Prevent over settle
                    if(settleAmount > (-paymCustTransOpen.AmountCur))
                        settleAmount = (-paymCustTransOpen.AmountCur);

                    //Payment
                    specTransManager.insert(paymCustTransOpen.DataAreaId,
                                            paymCustTransOpen.TableId,
                                            paymCustTransOpen.RecId,
                                            -settleAmount,
                                            paymCustTrans.CurrencyCode);
            
                    //Invoice
                    specTransManager.insert(invCustTransOpen.DataAreaId,
                                            invCustTransOpen.TableId,
                                            invCustTransOpen.RecId,
                                            settleAmount,
                                            invCustTrans.CurrencyCode);
                
                    //Settle
                    if(CustTrans::settleTransaction(specTransExecutionContext, CustTransSettleTransactionParameters::construct()))
                    {
                        if(_showInfoLog)
                            info(strFmt("@AG:AG_SettlementCompletedFor", invCustTrans.MCRPaymOrderID, invCustTrans.Invoice, settleAmount)); //Label: Settlement completed for Sales order %1, Invoice %2, Amount %3
                    }
                }
            }

            ttscommit;
        }
        catch
        {
            error(strFmt("@AG:AG_SettlementForPaymentJournalLineFailed", _paymLedgerJournalTrans.RecId, _paymLedgerJournalTrans.accountDisplay())); //label: Settlement for payment journal line is unsuccessful (RecId: %1, Account: %2)
        }
    }
Exit mobile version