Create payment journal with auto invoice settlement in Dynamics 365 F&O
Syed Amir Ali
Microsoft Certified Dynamics 365 Finance & Operations Expert | MCT | Techno functional Supply Chain
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.
领英推荐
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.
Functional lead consultant - Finance, PMA, SCM, Project Operations
5 个月Hi Amir, does the OOB functionality works for auto settlement?