From daa2b90121ef4fd1333a721638d44a8829902024 Mon Sep 17 00:00:00 2001 From: v-shikhverma Date: Fri, 24 Jul 2026 16:49:21 +0530 Subject: [PATCH 1/2] Initial Commit --- .../ExportEngine/GenerateFileFEC.Codeunit.al | 78 +++++++++++++++++++ .../src/FECAuditFileExportTests.Codeunit.al | 75 ++++++++++++++++++ 2 files changed, 153 insertions(+) diff --git a/src/Apps/FR/FECAuditFile/app/src/ExportEngine/GenerateFileFEC.Codeunit.al b/src/Apps/FR/FECAuditFile/app/src/ExportEngine/GenerateFileFEC.Codeunit.al index e5dfd0d1ddc..51a89f8a322 100644 --- a/src/Apps/FR/FECAuditFile/app/src/ExportEngine/GenerateFileFEC.Codeunit.al +++ b/src/Apps/FR/FECAuditFile/app/src/ExportEngine/GenerateFileFEC.Codeunit.al @@ -9,6 +9,7 @@ using Microsoft.Bank.Ledger; using Microsoft.Finance.GeneralLedger.Account; using Microsoft.Finance.GeneralLedger.Journal; using Microsoft.Finance.GeneralLedger.Ledger; +using Microsoft.Finance.GeneralLedger.Setup; using Microsoft.Foundation.AuditCodes; using Microsoft.Purchases.Payables; using Microsoft.Purchases.Vendor; @@ -44,6 +45,8 @@ codeunit 10826 "Generate File FEC" SourceCodesDescription: Dictionary of [Code[10], Text[100]]; PayablesAccounts: Dictionary of [Code[20], Code[20]]; ReceivablesAccounts: Dictionary of [Code[20], Code[20]]; + PmtDiscountAccounts: Dictionary of [Code[20], Boolean]; + PmtDiscountAccountsInitialized: Boolean; BankAccounts: Dictionary of [Code[20], Text[100]]; BankAccPostingGroups: Dictionary of [Code[20], Code[20]]; ProgressDialog: Dialog; @@ -233,6 +236,9 @@ codeunit 10826 "Generate File FEC" end; end; + if (PartyNo = '') and IsPaymentDiscountAccount(GLEntry."G/L Account No.") then + GetPartyForPaymentDiscount(GLEntry, PartyNo, PartyName); + AllowMultiplePosting(PartyNo, PartyName, GLEntry, Customer); FindGLRegister(GLRegister, GLEntry."Entry No."); @@ -672,6 +678,78 @@ codeunit 10826 "Generate File FEC" end; end; + local procedure IsPaymentDiscountAccount(GLAccountNo: Code[20]): Boolean + var + GeneralPostingSetup: Record "General Posting Setup"; + CustomerPostingGroup: Record "Customer Posting Group"; + VendorPostingGroup: Record "Vendor Posting Group"; + begin + if GLAccountNo = '' then + exit(false); + + if not PmtDiscountAccountsInitialized then begin + GeneralPostingSetup.SetLoadFields( + "Sales Pmt. Disc. Debit Acc.", "Sales Pmt. Disc. Credit Acc.", + "Purch. Pmt. Disc. Debit Acc.", "Purch. Pmt. Disc. Credit Acc."); + if GeneralPostingSetup.FindSet() then + repeat + AddPmtDiscountAccount(GeneralPostingSetup."Sales Pmt. Disc. Debit Acc."); + AddPmtDiscountAccount(GeneralPostingSetup."Sales Pmt. Disc. Credit Acc."); + AddPmtDiscountAccount(GeneralPostingSetup."Purch. Pmt. Disc. Debit Acc."); + AddPmtDiscountAccount(GeneralPostingSetup."Purch. Pmt. Disc. Credit Acc."); + until GeneralPostingSetup.Next() = 0; + + CustomerPostingGroup.SetLoadFields("Payment Disc. Debit Acc.", "Payment Disc. Credit Acc."); + if CustomerPostingGroup.FindSet() then + repeat + AddPmtDiscountAccount(CustomerPostingGroup."Payment Disc. Debit Acc."); + AddPmtDiscountAccount(CustomerPostingGroup."Payment Disc. Credit Acc."); + until CustomerPostingGroup.Next() = 0; + + VendorPostingGroup.SetLoadFields("Payment Disc. Debit Acc.", "Payment Disc. Credit Acc."); + if VendorPostingGroup.FindSet() then + repeat + AddPmtDiscountAccount(VendorPostingGroup."Payment Disc. Debit Acc."); + AddPmtDiscountAccount(VendorPostingGroup."Payment Disc. Credit Acc."); + until VendorPostingGroup.Next() = 0; + + PmtDiscountAccountsInitialized := true; + end; + + exit(PmtDiscountAccounts.ContainsKey(GLAccountNo)); + end; + + local procedure AddPmtDiscountAccount(GLAccountNo: Code[20]) + begin + if (GLAccountNo <> '') and (not PmtDiscountAccounts.ContainsKey(GLAccountNo)) then + PmtDiscountAccounts.Add(GLAccountNo, true); + end; + + local procedure GetPartyForPaymentDiscount(GLEntry: Record "G/L Entry"; var PartyNo: Code[20]; var PartyName: Text[100]) + var + Customer: Record Customer; + Vendor: Record Vendor; + begin + case GLEntry."Source Type" of + GLEntry."Source Type"::Customer: + begin + Customer.SetLoadFields(Name); + if Customer.Get(GLEntry."Source No.") then begin + PartyNo := Customer."No."; + PartyName := Customer.Name; + end; + end; + GLEntry."Source Type"::Vendor: + begin + Vendor.SetLoadFields(Name); + if Vendor.Get(GLEntry."Source No.") then begin + PartyNo := Vendor."No."; + PartyName := Vendor.Name; + end; + end; + end; + end; + local procedure ResetTransactionData() begin CustVendLedgEntryPartyNo := ''; diff --git a/src/Apps/FR/FECAuditFile/test/src/FECAuditFileExportTests.Codeunit.al b/src/Apps/FR/FECAuditFile/test/src/FECAuditFileExportTests.Codeunit.al index 20e6fc74a6e..63067d52704 100644 --- a/src/Apps/FR/FECAuditFile/test/src/FECAuditFileExportTests.Codeunit.al +++ b/src/Apps/FR/FECAuditFile/test/src/FECAuditFileExportTests.Codeunit.al @@ -2345,6 +2345,63 @@ codeunit 148017 "FEC Audit File Export Tests" VerifyExportGLEntriesReport(GLRegister, AuditFile, '', BankAccount."No.", BankAccount.Name); end; + [Test] + [HandlerFunctions('ConfirmHandlerYes')] + procedure PaymentDiscountLineHasCustomerInfo() + var + Customer: Record Customer; + CustomerPostingGroup: Record "Customer Posting Group"; + CustLedgerEntry: Record "Cust. Ledger Entry"; + GenJournalBatch: Record "Gen. Journal Batch"; + AuditFile: Record "Audit File"; + iStream: InStream; + StartingDate: Date; + InvoiceDocNo: Code[20]; + PaymentDocNo: Code[20]; + InvoiceAmount: Decimal; + DiscountAmount: Decimal; + PmtDiscAccountNo: Code[20]; + begin + // [SCENARIO 639574] CompAuxNum and CompAuxLib are informed for Payment Discount lines in the French Audit File + Initialize(); + StartingDate := GetStartingDate(); + + // [GIVEN] Customer with a payment-discount payment term whose posting group has a Payment Disc. Debit Acc. + CreateCustomer(Customer); + CustomerPostingGroup.Get(Customer."Customer Posting Group"); + if CustomerPostingGroup."Payment Disc. Debit Acc." = '' then begin + CustomerPostingGroup.Validate("Payment Disc. Debit Acc.", LibraryERM.CreateGLAccountNo()); + CustomerPostingGroup.Modify(true); + end; + PmtDiscAccountNo := CustomerPostingGroup."Payment Disc. Debit Acc."; + + // [GIVEN] A posted sales invoice with a possible payment discount + CreateGenJournalBatch(GenJournalBatch); + InvoiceAmount := LibraryRandom.RandDecInRange(1000, 2000, 2); + InvoiceDocNo := + CreateGenJournalLine(GenJournalBatch, "Gen. Journal Document Type"::Invoice, "Gen. Journal Account Type"::Customer, + Customer."No.", StartingDate, InvoiceAmount); + LibraryERM.FindCustomerLedgerEntry(CustLedgerEntry, "Gen. Journal Document Type"::Invoice, InvoiceDocNo); + DiscountAmount := CustLedgerEntry."Original Pmt. Disc. Possible"; + Assert.IsTrue(DiscountAmount > 0, 'The posted invoice should have a possible payment discount.'); + + // [GIVEN] A payment for (invoice amount - discount) applied to the invoice within the discount date, so the discount is granted + PaymentDocNo := + CreateGenJournalLine(GenJournalBatch, "Gen. Journal Document Type"::Payment, "Gen. Journal Account Type"::Customer, + Customer."No.", StartingDate, -(InvoiceAmount - DiscountAmount)); + ApplyAndPostGenJournalLine(PaymentDocNo, "Gen. Journal Document Type"::Invoice, InvoiceDocNo); + + // [WHEN] Export Audit File in FEC format + RunFECExport(AuditFile, '', StartingDate, StartingDate, false); + + // [THEN] The Payment Discount line (posted to the posting group's Payment Disc. Debit Acc.) has + // [THEN] CompAuxNum = Customer No. and CompAuxLib = Customer Name + CreateReadStream(iStream, AuditFile); + Assert.IsTrue( + FindPaymentDiscountLineWithParty(iStream, PmtDiscAccountNo, Customer."No.", Customer.Name), + 'The payment discount line with the customer number and name was not found in the FEC file.'); + end; + local procedure Initialize() begin LibrarySetupStorage.Restore(); @@ -2387,6 +2444,24 @@ codeunit 148017 "FEC Audit File Export Tests" AuditFile."File Content".CreateInStream(FileInStream, TextEncoding::UTF8); end; + local procedure FindPaymentDiscountLineWithParty(var FileInStream: InStream; PmtDiscAccountNo: Code[20]; ExpectedPartyNo: Code[20]; ExpectedPartyName: Text): Boolean + var + LineFields: List of [Text]; + LineToRead: Text; + begin + while not FileInStream.EOS() do begin + FileInStream.ReadText(LineToRead); + LineFields := LineToRead.Split('|'); + if LineFields.Count() >= 8 then + if LineFields.Get(5) = PmtDiscAccountNo then begin // field 5 = CompteNum + Assert.AreEqual(ExpectedPartyNo, LineFields.Get(7), GetErrorTextForAssertStmnt(7)); // field 7 = CompAuxNum + Assert.AreEqual(ExpectedPartyName, LineFields.Get(8), GetErrorTextForAssertStmnt(8)); // field 8 = CompAuxLib + exit(true); + end; + end; + exit(false); + end; + local procedure RunFECExport(var AuditFile: Record "Audit File"; GLAccountNoFilter: Text; StartDate: Date; EndDate: Date; IncludeOpeningBalances: Boolean) var AuditFileExportHeader: Record "Audit File Export Header"; From c552e3ed61c1b2822ae443aa0d6f423b49dd8c0b Mon Sep 17 00:00:00 2001 From: v-shikhverma Date: Wed, 29 Jul 2026 17:33:18 +0530 Subject: [PATCH 2/2] update --- .../ExportEngine/GenerateFileFEC.Codeunit.al | 67 ++++++++++--------- .../src/FECAuditFileExportTests.Codeunit.al | 31 ++------- 2 files changed, 42 insertions(+), 56 deletions(-) diff --git a/src/Apps/FR/FECAuditFile/app/src/ExportEngine/GenerateFileFEC.Codeunit.al b/src/Apps/FR/FECAuditFile/app/src/ExportEngine/GenerateFileFEC.Codeunit.al index 51a89f8a322..e8ca54210ca 100644 --- a/src/Apps/FR/FECAuditFile/app/src/ExportEngine/GenerateFileFEC.Codeunit.al +++ b/src/Apps/FR/FECAuditFile/app/src/ExportEngine/GenerateFileFEC.Codeunit.al @@ -679,44 +679,49 @@ codeunit 10826 "Generate File FEC" end; local procedure IsPaymentDiscountAccount(GLAccountNo: Code[20]): Boolean + begin + if GLAccountNo = '' then + exit(false); + + InitPmtDiscountAccountList(); + exit(PmtDiscountAccounts.ContainsKey(GLAccountNo)); + end; + + local procedure InitPmtDiscountAccountList() var GeneralPostingSetup: Record "General Posting Setup"; CustomerPostingGroup: Record "Customer Posting Group"; VendorPostingGroup: Record "Vendor Posting Group"; begin - if GLAccountNo = '' then - exit(false); + if PmtDiscountAccountsInitialized then + exit; - if not PmtDiscountAccountsInitialized then begin - GeneralPostingSetup.SetLoadFields( - "Sales Pmt. Disc. Debit Acc.", "Sales Pmt. Disc. Credit Acc.", - "Purch. Pmt. Disc. Debit Acc.", "Purch. Pmt. Disc. Credit Acc."); - if GeneralPostingSetup.FindSet() then - repeat - AddPmtDiscountAccount(GeneralPostingSetup."Sales Pmt. Disc. Debit Acc."); - AddPmtDiscountAccount(GeneralPostingSetup."Sales Pmt. Disc. Credit Acc."); - AddPmtDiscountAccount(GeneralPostingSetup."Purch. Pmt. Disc. Debit Acc."); - AddPmtDiscountAccount(GeneralPostingSetup."Purch. Pmt. Disc. Credit Acc."); - until GeneralPostingSetup.Next() = 0; - - CustomerPostingGroup.SetLoadFields("Payment Disc. Debit Acc.", "Payment Disc. Credit Acc."); - if CustomerPostingGroup.FindSet() then - repeat - AddPmtDiscountAccount(CustomerPostingGroup."Payment Disc. Debit Acc."); - AddPmtDiscountAccount(CustomerPostingGroup."Payment Disc. Credit Acc."); - until CustomerPostingGroup.Next() = 0; - - VendorPostingGroup.SetLoadFields("Payment Disc. Debit Acc.", "Payment Disc. Credit Acc."); - if VendorPostingGroup.FindSet() then - repeat - AddPmtDiscountAccount(VendorPostingGroup."Payment Disc. Debit Acc."); - AddPmtDiscountAccount(VendorPostingGroup."Payment Disc. Credit Acc."); - until VendorPostingGroup.Next() = 0; - - PmtDiscountAccountsInitialized := true; - end; + GeneralPostingSetup.SetLoadFields( + "Sales Pmt. Disc. Debit Acc.", "Sales Pmt. Disc. Credit Acc.", + "Purch. Pmt. Disc. Debit Acc.", "Purch. Pmt. Disc. Credit Acc."); + if GeneralPostingSetup.FindSet() then + repeat + AddPmtDiscountAccount(GeneralPostingSetup."Sales Pmt. Disc. Debit Acc."); + AddPmtDiscountAccount(GeneralPostingSetup."Sales Pmt. Disc. Credit Acc."); + AddPmtDiscountAccount(GeneralPostingSetup."Purch. Pmt. Disc. Debit Acc."); + AddPmtDiscountAccount(GeneralPostingSetup."Purch. Pmt. Disc. Credit Acc."); + until GeneralPostingSetup.Next() = 0; + + CustomerPostingGroup.SetLoadFields("Payment Disc. Debit Acc.", "Payment Disc. Credit Acc."); + if CustomerPostingGroup.FindSet() then + repeat + AddPmtDiscountAccount(CustomerPostingGroup."Payment Disc. Debit Acc."); + AddPmtDiscountAccount(CustomerPostingGroup."Payment Disc. Credit Acc."); + until CustomerPostingGroup.Next() = 0; - exit(PmtDiscountAccounts.ContainsKey(GLAccountNo)); + VendorPostingGroup.SetLoadFields("Payment Disc. Debit Acc.", "Payment Disc. Credit Acc."); + if VendorPostingGroup.FindSet() then + repeat + AddPmtDiscountAccount(VendorPostingGroup."Payment Disc. Debit Acc."); + AddPmtDiscountAccount(VendorPostingGroup."Payment Disc. Credit Acc."); + until VendorPostingGroup.Next() = 0; + + PmtDiscountAccountsInitialized := true; end; local procedure AddPmtDiscountAccount(GLAccountNo: Code[20]) diff --git a/src/Apps/FR/FECAuditFile/test/src/FECAuditFileExportTests.Codeunit.al b/src/Apps/FR/FECAuditFile/test/src/FECAuditFileExportTests.Codeunit.al index 63067d52704..9f300daa5a7 100644 --- a/src/Apps/FR/FECAuditFile/test/src/FECAuditFileExportTests.Codeunit.al +++ b/src/Apps/FR/FECAuditFile/test/src/FECAuditFileExportTests.Codeunit.al @@ -2361,6 +2361,7 @@ codeunit 148017 "FEC Audit File Export Tests" InvoiceAmount: Decimal; DiscountAmount: Decimal; PmtDiscAccountNo: Code[20]; + LineToRead: Text; begin // [SCENARIO 639574] CompAuxNum and CompAuxLib are informed for Payment Discount lines in the French Audit File Initialize(); @@ -2391,15 +2392,13 @@ codeunit 148017 "FEC Audit File Export Tests" Customer."No.", StartingDate, -(InvoiceAmount - DiscountAmount)); ApplyAndPostGenJournalLine(PaymentDocNo, "Gen. Journal Document Type"::Invoice, InvoiceDocNo); - // [WHEN] Export Audit File in FEC format - RunFECExport(AuditFile, '', StartingDate, StartingDate, false); + // [WHEN] Export Audit File in FEC format for the Payment Disc. Debit Acc. only + RunFECExport(AuditFile, PmtDiscAccountNo, StartingDate, StartingDate, false); - // [THEN] The Payment Discount line (posted to the posting group's Payment Disc. Debit Acc.) has - // [THEN] CompAuxNum = Customer No. and CompAuxLib = Customer Name + // [THEN] The exported Payment Discount line has CompAuxNum = Customer No. and CompAuxLib = Customer Name CreateReadStream(iStream, AuditFile); - Assert.IsTrue( - FindPaymentDiscountLineWithParty(iStream, PmtDiscAccountNo, Customer."No.", Customer.Name), - 'The payment discount line with the customer number and name was not found in the FEC file.'); + iStream.ReadText(LineToRead); // header + VerifyFilePartyNoAndName(iStream, Customer."No.", Customer.Name); end; local procedure Initialize() @@ -2444,24 +2443,6 @@ codeunit 148017 "FEC Audit File Export Tests" AuditFile."File Content".CreateInStream(FileInStream, TextEncoding::UTF8); end; - local procedure FindPaymentDiscountLineWithParty(var FileInStream: InStream; PmtDiscAccountNo: Code[20]; ExpectedPartyNo: Code[20]; ExpectedPartyName: Text): Boolean - var - LineFields: List of [Text]; - LineToRead: Text; - begin - while not FileInStream.EOS() do begin - FileInStream.ReadText(LineToRead); - LineFields := LineToRead.Split('|'); - if LineFields.Count() >= 8 then - if LineFields.Get(5) = PmtDiscAccountNo then begin // field 5 = CompteNum - Assert.AreEqual(ExpectedPartyNo, LineFields.Get(7), GetErrorTextForAssertStmnt(7)); // field 7 = CompAuxNum - Assert.AreEqual(ExpectedPartyName, LineFields.Get(8), GetErrorTextForAssertStmnt(8)); // field 8 = CompAuxLib - exit(true); - end; - end; - exit(false); - end; - local procedure RunFECExport(var AuditFile: Record "Audit File"; GLAccountNoFilter: Text; StartDate: Date; EndDate: Date; IncludeOpeningBalances: Boolean) var AuditFileExportHeader: Record "Audit File Export Header";