Create payment journal with auto invoice settlement in Dynamics 365 F&O

Create payment journal with auto invoice settlement in Dynamics 365 F&O

Hey Reader, In todays article, I will share the code with you which you can use for creating the customer payment journal with auto settlement of customer open transactions invoices.

Step 1. Enable the Auto settlement parameter

Go to Account Receivable > Setup > Accounts receivable parameters > Settlement. This is standard checkbox.

Auto settlement checkbox

Step 2) Coding

  /// <summary>
    /// Create customer payment journal
    /// </summary>
    /// <param name = "CustAccount">Customer Id</param>
    /// <param name = "salesOrderID">Sales order Id</param>
    /// <param name = "recoveryAmount">Amount to settle or recover</param>
    public static str createCustomerPaymentJournal(CustAccount CustAccount, SalesId salesOrderID, AmountMST recoveryAmount)
    {
        CustTable               custTable,CustTableBank;
        Ledgerjournalname       ledgerjournalname;
        LedgerjournalTable      LedgerjournalTable;
        LedgerjournalTrans      LedgerjournalTrans;
        LedgerjournalCheckPost  LedgerjournalCheckPost;
        NumberSeq               numberSeq;
        RetailStoreTenderTypeTable retailStoreTenderTypeId;

        str error, successMsg;
        ;
        try
        {
            select firstOnly ledgerjournalname where ledgerjournalname.JournalName == CustParameters::find().BT_JournalName;
            select firstOnly custTable where custTable.AccountNum == CustAccount;
            select firstOnly CustTableBank where CustTableBank.AccountNum == CustAccount;

            // create journal
            ttsBegin;
            LedgerjournalTable.JournalName          =   ledgerjournalname.JournalName;
            LedgerjournalTable.initFromLedgerJournalName();
            LedgerjournalTable.JournalNum           =   JournalTableData::newTable(LedgerjournalTable).nextJournalId();
            LedgerjournalTable.Name                 =   strFmt("@BTSCLabel:CusRecoveryChannel",BT_CustomerRecoveryHelper::getDimensionDisplayValue(SalesTable::find(salesOrderID).DefaultDimension,'Retailchannel'));
            LedgerjournalTable.insert();
         
            // create journal Lines
            numberSeq                                   =   NumberSeq::newGetVoucherFromId((ledgerjournalname.NumberSequenceTable));
            LedgerjournalTrans.Voucher                  =   numberSeq.voucher();
            LedgerjournalTrans.JournalNum               =   LedgerjournalTable.JournalNum;
            LedgerjournalTrans.CurrencyCode             =   Ledger::accountingCurrency(CompanyInfo::current());
            LedgerjournalTrans.ExchRate                 =   ExchangeRateHelper::exchRate(LedgerjournalTrans.CurrencyCode);
            LedgerjournalTrans.Approved                 =   NoYes::Yes;
            LedgerjournalTrans.TransactionType          =   LedgerTransType::Payment;
            LedgerjournalTrans.AccountType              =   LedgerJournalACType::Cust;
            LedgerjournalTrans.parmAccount(CustTable.AccountNum,LedgerjournalTrans.AccountType);
            LedgerjournalTrans.Txt                      =   strFmt("@BTSCLabel:custPayRecovery",CustAccount,salesOrderID);
            LedgerjournalTrans.AmountCurCredit          =   recoveryAmount;
            LedgerjournalTrans.TransDate                =  DateTimeUtil::date(DateTimeUtil::getSystemDateTime());
            LedgerjournalTrans.OffsetAccountType        =   LedgerJournalACType::Ledger;
            LedgerjournalTrans.SettleVoucher            = SettlementType::OpenTransact; // It line is mandatory for Auto settlement of invoice

            str custGroup     = BT_CustomerRecoveryHelper::getDimensionDisplayValue(CustTable::find(CustAccount).DefaultDimension,'CustomerGroup');
            str retailChannel = BT_CustomerRecoveryHelper::getDimensionDisplayValue(CustTable::find(CustAccount).DefaultDimension,'Retailchannel');
           // str mainAccount   = DimensionAttributeValueCombination::find(LedgerjournalTable.OffsetLedgerDimension).DisplayValue;
             RecId salesOrderRetailChannelRecId = SalesTable::find(salesOrderID).RetailChannelTable;
             RetailStoreTenderTypeId recoveryPaymentMethod = SalesTable::find(salesOrderID).BT_TenderTypeId;
            str mainAccount   = DimensionAttributeValueCombination::find(RetailStoreTenderTypeTable::find(salesOrderRetailChannelRecId, recoveryPaymentMethod).LedgerDimension).DisplayValue;
            
            
            ledgerJournalTrans.OffsetLedgerDimension    = BT_CustomerRecoveryHelper::generateLedgerDimension(custGroup,retailChannel,mainAccount);
            LedgerjournalTrans.DefaultDimension         =  CustTable::find(CustTable.AccountNum).DefaultDimension;
            LedgerjournalTrans.OffsetDefaultDimension   =  CustTable::find(CustTable.AccountNum).DefaultDimension;
            LedgerjournalTrans.LedgerDimension        = LedgerDynamicAccountHelper::getDynamicAccountFromAccountNumber(CustTable.AccountNum,LedgerJournalACType::Cust);
            LedgerjournalTrans.insert();
            ttsCommit;
            
            // auto journal posting
            LedgerjournalCheckPost      =   LedgerjournalCheckPost::newLedgerJournalTable(LedgerjournalTable,NoYes::Yes);
            LedgerjournalCheckPost.run();

// Returning the successMsg object 
            successMsg = strFmt("The customer payment journal %1 has been created and posted successfully ",LedgerjournalTable.JournalNum);
            info(successMsg);
        }
        catch(Exception::Error)
        {
           // Catching the error message 
            SysInfologEnumerator enumerator = SysInfologEnumerator::newData(infolog.cut());

            while (enumerator.moveNext())
            {
                SysInfologMessageStruct strc = new SysInfologMessageStruct(enumerator.currentMessage());
               Exception exception = enumerator.currentException();

                error = strfmt('%1 %2', error, strc.message());
                error(error);
                successMsg = error;

            }
        }
        catch (Exception::CLRError)
        {
           CLRObject netExcepn = CLRInterop::getLastException();
            error = netExcepn.ToString();
            error(error);
            successMsg = error;
        }

        return successMsg;
      
    }        

If you like to settle any open invoice by using the customer payment journal then you can use the below code

    /// <summary>
    /// Specific Invoice settlement while customer payment journal 
    /// </summary>
    /// <param name = "ledgerJournalTrans">Payment journal lines table</param>
    /// <param name = "amounttoSettle">Amount to settle - Journal amount </param>
/// <param name = "custTransOpen_RecId">RecId of customer open transaction</param>
public void settlement(ledgerJournalTrans ledgerJournalTrans,real amounttoSettle, RecId custTransOpen_RecId)
{
    SpecTrans insertSpecTrans;
    ;
    insertSpecTrans.SpecCompany = ledgerJournalTrans.Company;
    insertSpecTrans.SpecTableId = TableNum(ledgerJournalTrans);
    insertSpecTrans.SpecRecId   = ledgerJournalTrans.RecId;
    insertSpecTrans.RefCompany  = ledgerJournalTrans.Company;
    insertSpecTrans.RefTableId  = TableNum(custTransOPen);
    insertSpecTrans.RefRecId    = custTransOpen_RecId;
    insertSpecTrans.Balance01   = amounttoSettle;
    insertSpecTrans.Code        = ledgerJournalTrans.CurrencyCode;
    insertSpecTrans.Payment     = NoYes::No;
    insertSpecTrans.LineNum     = 1;
    insertSpecTrans.insert();

}
        

Happy Learning,

Syed Amir Ali.

Sivanarayana Penuguduru

Functional lead consultant - Finance, PMA, SCM, Project Operations

5 个月

Hi Amir, does the OOB functionality works for auto settlement?

回复

要查看或添加评论,请登录

社区洞察

其他会员也浏览了