Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ codeunit 37208 "Export Remit. Advice PEPPOL30"
this.AddCacElement(this.RootNode, 'RemittanceAdviceLine', LineNode);
this.AddCbcElement(LineNode, 'ID', Format(SeqNo), ChildNode);

if LineBuffer."Applied Doc. Type" = LineBuffer."Applied Doc. Type"::"Credit Memo" then
if LineBuffer."Applied Doc. Type" in [LineBuffer."Applied Doc. Type"::"Credit Memo", LineBuffer."Applied Doc. Type"::Refund] then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Testing}$

The new refund branch in Export Remit. Advice PEPPOL30 (treating Applied Doc. Type = Refund as a credit line) has no dedicated test coverage in this diff. The new report test (RefundSharingPaymentDocShownOnRemittanceAdviceEntries) exercises report 400 only; it does not validate the PEPPOL XML serializer output for refund-ledger entries, so this branch can regress silently. Add a focused AL test that builds a refund-applied remittance buffer and asserts the exported XML uses CreditLineAmount (and the correct BillingReference element) for a Refund applied-doc-type line.

Agent judgement — not directly backed by a BCQuality knowledge article.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.35.4

this.AddMoneyElement(LineNode, 'CreditLineAmount', LineBuffer."Paid Amount", LineCurrencyCode, ChildNode)
else
this.AddMoneyElement(LineNode, 'DebitLineAmount', LineBuffer."Paid Amount", LineCurrencyCode, ChildNode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,19 +267,25 @@ codeunit 37207 "Remit. Advice Buffer Mgt."
DetailedVendLedgEntry.Reset();
DetailedVendLedgEntry.SetRange("Vendor Ledger Entry No.", AppliedVendLedgEntry."Entry No.");
DetailedVendLedgEntry.SetRange("Entry Type", DetailedVendLedgEntry."Entry Type"::Application);
DetailedVendLedgEntry.SetRange("Document Type", DetailedVendLedgEntry."Document Type"::Payment);
DetailedVendLedgEntry.SetRange("Document No.", PaymentVendLedgEntry."Document No.");
if AppliedVendLedgEntry."Document Type" = AppliedVendLedgEntry."Document Type"::Refund then begin
DetailedVendLedgEntry.SetRange("Document Type", DetailedVendLedgEntry."Document Type"::Refund);
DetailedVendLedgEntry.SetRange("Document No.", AppliedVendLedgEntry."Document No.");
end else begin
DetailedVendLedgEntry.SetRange("Document Type", DetailedVendLedgEntry."Document Type"::Payment);
DetailedVendLedgEntry.SetRange("Document No.", PaymentVendLedgEntry."Document No.");
end;
DetailedVendLedgEntry.SetRange(Unapplied, false);
if not DetailedVendLedgEntry.IsEmpty() then begin
DetailedVendLedgEntry.CalcSums(Amount, "Remaining Pmt. Disc. Possible");
LineAmount := DetailedVendLedgEntry.Amount;

LineDiscount := 0;
if AppliedVendLedgEntry."Currency Code" <> '' then begin
if IsDiscountAppliedToPayment(AppliedVendLedgEntry."Entry No.", PaymentVendLedgEntry."Document No.") then
LineDiscount := DetailedVendLedgEntry."Remaining Pmt. Disc. Possible";
end else
LineDiscount := CurrExchRate.ExchangeAmtFCYToFCY(AppliedVendLedgEntry."Posting Date", '', AppliedVendLedgEntry."Currency Code", AppliedVendLedgEntry."Pmt. Disc. Rcd.(LCY)");
if AppliedVendLedgEntry."Document Type" <> AppliedVendLedgEntry."Document Type"::Refund then
if AppliedVendLedgEntry."Currency Code" <> '' then begin
if IsDiscountAppliedToPayment(AppliedVendLedgEntry."Entry No.", PaymentVendLedgEntry."Document No.") then
LineDiscount := DetailedVendLedgEntry."Remaining Pmt. Disc. Possible";
end else
LineDiscount := CurrExchRate.ExchangeAmtFCYToFCY(AppliedVendLedgEntry."Posting Date", '', AppliedVendLedgEntry."Currency Code", AppliedVendLedgEntry."Pmt. Disc. Rcd.(LCY)");

LineNo += 1;
TempBuffer.Init();
Expand All @@ -297,7 +303,11 @@ codeunit 37207 "Remit. Advice Buffer Mgt."
TempBuffer."Vendor Ledger Entry No." := AppliedVendLedgEntry."Entry No.";
TempBuffer.Insert();

TotalPaid += TempBuffer."Paid Amount";
// A refund reduces the payment total, mirroring report 400's "Amount -= LineAmount"
if AppliedVendLedgEntry."Document Type" = AppliedVendLedgEntry."Document Type"::Refund then
TotalPaid -= TempBuffer."Paid Amount"
else
TotalPaid += TempBuffer."Paid Amount";
TotalDiscount += TempBuffer."Pmt. Discount Amount";

// Applied credit-memo cross-applications (report 400 lines 231-249)
Expand Down Expand Up @@ -357,6 +367,7 @@ codeunit 37207 "Remit. Advice Buffer Mgt."
var
DetailedVendLedgEntry1: Record "Detailed Vendor Ledg. Entry";
DetailedVendLedgEntry2: Record "Detailed Vendor Ledg. Entry";
RefundVendLedgEntry: Record "Vendor Ledger Entry";
EntryNo: Integer;
begin
AppliedVendLedgEntry.Reset();
Expand Down Expand Up @@ -407,6 +418,16 @@ codeunit 37207 "Remit. Advice Buffer Mgt."
end;
until DetailedVendLedgEntry1.Next() = 0;

RefundVendLedgEntry.SetRange("Vendor No.", PaymentVendLedgEntry."Vendor No.");
Comment thread
neeleshsinghal marked this conversation as resolved.
RefundVendLedgEntry.SetRange("Document No.", PaymentVendLedgEntry."Document No.");
RefundVendLedgEntry.SetRange("Document Type", RefundVendLedgEntry."Document Type"::Refund);
if RefundVendLedgEntry.FindSet() then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Performance}$

The new refund-matching loop in FindAppliedEntries narrows AppliedVendLedgEntry to the full primary key (Entry No.) via SetRange and then calls FindFirst() for each refund row instead of using Get(), which is the direct primary-key lookup.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.35.4

repeat
AppliedVendLedgEntry.SetRange("Entry No.", RefundVendLedgEntry."Entry No.");
if AppliedVendLedgEntry.FindFirst() then
AppliedVendLedgEntry.Mark(true);
until RefundVendLedgEntry.Next() = 0;

AppliedVendLedgEntry.SetCurrentKey("Entry No.");
AppliedVendLedgEntry.SetRange("Entry No.");
AppliedVendLedgEntry.SetRange("Closed by Entry No.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,26 +256,37 @@ report 400 "Remittance Advice - Entries"
CalcFields(Amount, "Remaining Amount");
DtldVendLedgEntry.SetRange("Vendor Ledger Entry No.", "Entry No.");
DtldVendLedgEntry.SetRange("Entry Type", DtldVendLedgEntry."Entry Type"::Application);
DtldVendLedgEntry.SetRange("Document Type", DtldVendLedgEntry."Document Type"::Payment);
DtldVendLedgEntry.SetRange("Document No.", "Vendor Ledger Entry"."Document No.");
if "Document Type" = "Document Type"::Refund then begin
DtldVendLedgEntry.SetRange("Document Type", DtldVendLedgEntry."Document Type"::Refund);
DtldVendLedgEntry.SetRange("Document No.", "Document No.");
end else begin
DtldVendLedgEntry.SetRange("Document Type", DtldVendLedgEntry."Document Type"::Payment);
DtldVendLedgEntry.SetRange("Document No.", "Vendor Ledger Entry"."Document No.");
end;
DtldVendLedgEntry.SetRange(Unapplied, false);
if DtldVendLedgEntry.IsEmpty() then
CurrReport.Skip();
DtldVendLedgEntry.CalcSums(Amount, "Remaining Pmt. Disc. Possible");
LineAmount := DtldVendLedgEntry.Amount;

if "Currency Code" <> '' then begin
if IsDiscountAppliedToPayment("Vendor Ledger Entry"."Entry No.", "Vendor Ledger Entry"."Document No.") then
LineDiscount := DtldVendLedgEntry."Remaining Pmt. Disc. Possible"
end else
LineDiscount := CurrExchRate.ExchangeAmtFCYToFCY("Posting Date", '', "Currency Code", "Pmt. Disc. Rcd.(LCY)");
Clear(LineDiscount);
if "Document Type" <> "Document Type"::Refund then
if "Currency Code" <> '' then begin
if IsDiscountAppliedToPayment("Vendor Ledger Entry"."Entry No.", "Vendor Ledger Entry"."Document No.") then
LineDiscount := DtldVendLedgEntry."Remaining Pmt. Disc. Possible"
end else
LineDiscount := CurrExchRate.ExchangeAmtFCYToFCY("Posting Date", '', "Currency Code", "Pmt. Disc. Rcd.(LCY)");

"Vendor Ledger Entry".Amount += LineDiscount;
if "Document Type" = "Document Type"::Refund then
"Vendor Ledger Entry".Amount -= LineAmount;

LAmountWDiscCur := -LineAmount - LineDiscount;
end;

trigger OnPreDataItem()
var
RefundVendLedgEntry: Record "Vendor Ledger Entry";
begin
CreateVendLedgEntry := "Vendor Ledger Entry";
FindApplnEntriesDtldtLedgEntry();
Expand All @@ -294,6 +305,15 @@ report 400 "Remittance Advice - Entries"
Mark(true);
until Next() = 0;

RefundVendLedgEntry.SetRange("Vendor No.", CreateVendLedgEntry."Vendor No.");
RefundVendLedgEntry.SetRange("Document No.", CreateVendLedgEntry."Document No.");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Performance}$

The report's equivalent refund-marking loop in the "Vendor Ledger Entry" OnPreDataItem trigger narrows to the full primary key (Entry No.) and calls FindFirst() per refund row; use Get() instead of an index seek in the loop.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.35.4

RefundVendLedgEntry.SetRange("Document Type", RefundVendLedgEntry."Document Type"::Refund);
if RefundVendLedgEntry.FindSet() then
repeat
"Entry No." := RefundVendLedgEntry."Entry No.";
Mark(true);
until RefundVendLedgEntry.Next() = 0;
Comment thread
neeleshsinghal marked this conversation as resolved.

SetCurrentKey("Entry No.");
SetRange("Closed by Entry No.");
MarkedOnly(true);
Expand Down
54 changes: 54 additions & 0 deletions src/Layers/W1/Tests/Report/RemittanceREPCheckUT.Codeunit.al
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ codeunit 133771 "Remittance REP Check UT"
LibraryReportDataset: Codeunit "Library - Report Dataset";
LibraryERM: Codeunit "Library - ERM";
Assert: Codeunit Assert;
EntryNoElementTok: Label 'EntryNo_VendLedgEntry2', Locked = true;
DocTypeElementTok: Label 'DocType_VendLedgEntry2', Locked = true;
LineAmountElementTok: Label 'LAmountWDiscCur', Locked = true;
TotalAmountElementTok: Label 'Amount_VendLedgEntry', Locked = true;

[Test]
[HandlerFunctions('RemittanceAdviceJournalRequestPageHandler')]
Expand Down Expand Up @@ -189,6 +193,46 @@ codeunit 133771 "Remittance REP Check UT"
VerifyPayedDocumentsAndPartiallyPaid(VendorLedgerEntry, GenJournalLine);
end;

[Test]
[HandlerFunctions('RemittanceAdviceEntriesRequestPageHandler')]
[TransactionModel(TransactionModel::AutoRollback)]
procedure RefundSharingPaymentDocShownOnRemittanceAdviceEntries()
var
DetailedVendorLedgEntry: Record "Detailed Vendor Ledg. Entry";
PaymentVendorLedgerEntry: Record "Vendor Ledger Entry";
RefundVendorLedgerEntry: Record "Vendor Ledger Entry";
VendorNo: Code[20];
DocumentNo: Code[20];
RefundAmount: Decimal;
begin
// [FEATURE] [Report] [Remittance Advice - Entries] [AI test 0.4]
// [SCENARIO] A vendor refund sharing the payment's document is rendered as a line on Report 400 - Remittance Advice - Entries
Initialize();

// [GIVEN] Payment and Refund for the same vendor sharing DocumentNo .
Comment thread
neeleshsinghal marked this conversation as resolved.
VendorNo := CreateVendor();
DocumentNo := LibraryUTUtility.GetNewCode();
CreatePaymentAndRefundWithDocumentNo(PaymentVendorLedgerEntry, RefundVendorLedgerEntry, VendorNo, DocumentNo);

// [GIVEN] Refund has an applied refund detailed entry.
RefundAmount :=
CreateDetailedVendorLedgerEntry(
RefundVendorLedgerEntry, RefundVendorLedgerEntry."Entry No.", DetailedVendorLedgEntry."Entry Type"::Application,
DetailedVendorLedgEntry."Document Type"::Refund, 1);

// [WHEN] Run report Remittance Advice - Entries filtered on payment.
LibraryVariableStorage.Enqueue(PaymentVendorLedgerEntry."Entry No.");
REPORT.Run(REPORT::"Remittance Advice - Entries");

// [THEN] Verify that the Refund is displayed as a transaction line on the report with the refund amount.
LibraryReportDataset.LoadDataSetFile();
LibraryReportDataset.AssertElementWithValueExists(EntryNoElementTok, RefundVendorLedgerEntry."Entry No.");
LibraryReportDataset.AssertElementWithValueExists(DocTypeElementTok, Format(RefundVendorLedgerEntry."Document Type"));
LibraryReportDataset.AssertElementWithValueExists(LineAmountElementTok, -RefundAmount);
LibraryReportDataset.AssertElementWithValueExists(TotalAmountElementTok, -RefundAmount);
LibraryVariableStorage.AssertEmpty();
end;

local procedure Initialize()
begin
LibraryVariableStorage.Clear();
Expand Down Expand Up @@ -344,6 +388,16 @@ codeunit 133771 "Remittance REP Check UT"
until VendorLedgerEntry.Next() = 0;
end;

local procedure CreatePaymentAndRefundWithDocumentNo(var PaymentVendorLedgerEntry: Record "Vendor Ledger Entry"; var RefundVendorLedgerEntry: Record "Vendor Ledger Entry"; VendorNo: Code[20]; DocumentNo: Code[20])
Comment thread
neeleshsinghal marked this conversation as resolved.
begin
CreateVendorLedgerEntry(PaymentVendorLedgerEntry, '', VendorNo, PaymentVendorLedgerEntry."Document Type"::Payment); // Blank value for Applies To ID.
PaymentVendorLedgerEntry."Document No." := DocumentNo;
PaymentVendorLedgerEntry.Modify();
CreateVendorLedgerEntry(RefundVendorLedgerEntry, '', VendorNo, RefundVendorLedgerEntry."Document Type"::Refund); // Blank value for Applies To ID.
RefundVendorLedgerEntry."Document No." := DocumentNo;
RefundVendorLedgerEntry.Modify();
end;

[RequestPageHandler]
[Scope('OnPrem')]
procedure RemittanceAdviceJournalRequestPageHandler(var RemittanceAdviceJournal: TestRequestPage "Remittance Advice - Journal")
Expand Down
Loading