Skip to content
Open
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 @@ -119,11 +119,21 @@ report 2000019 "Suggest Vendor Payments EB"
ApplicationArea = Basic, Suite;
Caption = 'Take Payment Discounts';
ToolTip = 'Specifies if you want the batch job to include vendor ledger entries for which you can receive a payment discount.';

trigger OnValidate()
begin
if IncPmtDiscount then begin
if PmtDiscDueDate = 0D then
PmtDiscDueDate := WorkDate();
end else
PmtDiscDueDate := 0D;
end;
}
field(PmtDiscDueDate; PmtDiscDueDate)
{
ApplicationArea = Basic, Suite;
Caption = 'Payment Discount Date';
Editable = IncPmtDiscount;
ToolTip = 'Specifies the date that will be used to calculate the payment discount.';
}
field(MaximumAmount; MaximumAmount)
Expand Down Expand Up @@ -151,8 +161,11 @@ report 2000019 "Suggest Vendor Payments EB"
begin
if DueDate = 0D then
DueDate := WorkDate();
if PmtDiscDueDate = 0D then
PmtDiscDueDate := WorkDate();
if IncPmtDiscount then begin
if PmtDiscDueDate = 0D then
PmtDiscDueDate := WorkDate();
end else
PmtDiscDueDate := 0D;
if PostingDate = 0D then
PostingDate := WorkDate();
IncCreditMemos := true;
Expand Down
182 changes: 174 additions & 8 deletions src/Layers/BE/Tests/Local/ERMPaymentJournal.Codeunit.al
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,25 @@ codeunit 144003 "ERM Payment Journal"
end;

var
LibraryReportDataset: Codeunit "Library - Report Dataset";
LibraryRandom: Codeunit "Library - Random";
Assert: Codeunit Assert;
LibraryDimension: Codeunit "Library - Dimension";
LibraryERM: Codeunit "Library - ERM";
LibraryUtility: Codeunit "Library - Utility";
LibraryPurchase: Codeunit "Library - Purchase";
LibraryRandom: Codeunit "Library - Random";
LibraryReportDataset: Codeunit "Library - Report Dataset";
LibrarySales: Codeunit "Library - Sales";
Assert: Codeunit Assert;
LibrarySetupStorage: Codeunit "Library - Setup Storage";
LibraryTestInitialize: Codeunit "Library - Test Initialize";
LibraryUtility: Codeunit "Library - Utility";
LibraryVariableStorage: Codeunit "Library - Variable Storage";
LibraryDimension: Codeunit "Library - Dimension";
LibrarySetupStorage: Codeunit "Library - Setup Storage";
isInitialized: Boolean;
refExportProtocolType: Option Domestic,International;
IncorrectNumberOfDimErr: Label 'Incorrect number of dimensions.';
LettersTxt: Label 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', Locked = true;
WrongNumberOfLinesErr: Label 'Wrong number of Payment Journal Lines.';
WrongStatusOfLineErr: Label 'Wrong status of Payment Journal Line.';
WrongPmtDiscErr: Label 'Wrong %1 on the payment journal line.', Comment = '%1 = Field Caption';

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\ —\ Style} \quad \color{gray}{\texttt{\small Iteration\ 4}}$

WrongPmtDiscErr is declared with Comment = '%1 = Field Caption', but none of its 4 call sites pass a FieldCaption — they all pass the field's actual value instead (e.g.

StrSubstNo(WrongPmtDiscErr, PaymentJournalLine."Pmt. Discount Date")). On assertion failure this renders as a nonsensical message like 'Wrong 07/06/26 on the payment journal line.' instead of naming the field that was wrong. Pass PaymentJournalLine.FieldCaption("Pmt. Discount Date") / FieldCaption("Pmt. Disc. Possible") to match the documented Comment.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

WrongStatusOfBatchErr: Label 'Wrong status of Payment Journal Batch.';
LettersTxt: Label 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', Locked = true;
WrongStatusOfLineErr: Label 'Wrong status of Payment Journal Line.';

[Test]
[Scope('OnPrem')]
Expand Down Expand Up @@ -635,6 +636,121 @@ codeunit 144003 "ERM Payment Journal"
VerifyGenJnlLinesWithSameDescription(GenJnlBatch, PaymentJnlLine."Payment Message", 2);
end;

[Test]
[HandlerFunctions('SuggestVendorPaymentsTakeDiscRPH')]
procedure SuggestVendorPaymentsWithoutTakingPaymentDiscount()
var
PaymentJournalLine: Record "Payment Journal Line";
PurchaseHeader: Record "Purchase Header";
VendorLedgerEntry: Record "Vendor Ledger Entry";
VendorNo: Code[20];
begin
// [SCENARIO 637839] Payment discount is not taken when "Take Payment Discounts" is disabled in the "Suggest Vendor Payments EB" report.
Initialize();

// [GIVEN] Create a Vendor with Payment terms with Payment Discount.
VendorNo := CreateVendorWithPaymentDiscount();

// [GIVEN] Create and post a Purchase Invoice.
CreateAndPostPurchaseDocument(PurchaseHeader, PurchaseHeader."Document Type"::Invoice, VendorNo);

// [GIVEN] Find the Vendor Ledger Entry for the posted Purchase Invoice.
FindInvoiceVendorLedgerEntry(VendorLedgerEntry, VendorNo);

// [WHEN] Run "Suggest Vendor Payments EB" with "Take Payment Discounts" = FALSE.
LibraryVariableStorage.Enqueue(false);
SuggestVendorPayments(VendorNo);

// [WHEN] Filter the Payment Journal Line for the Vendor.
FilterEBPaymentJournalLine(PaymentJournalLine, VendorNo, PaymentJournalLine.Status::Created);
PaymentJournalLine.FindFirst();

// [THEN] Verify that the "Pmt. Discount Date" is Blank, Pmt Discount is not taken, in Payment Journal Line.
Assert.AreEqual(0D, PaymentJournalLine."Pmt. Discount Date", StrSubstNo(WrongPmtDiscErr, PaymentJournalLine.FieldCaption("Pmt. Discount Date")));
Assert.AreEqual(0, PaymentJournalLine."Pmt. Disc. Possible", StrSubstNo(WrongPmtDiscErr, PaymentJournalLine.FieldCaption("Pmt. Disc. Possible")));
LibraryVariableStorage.AssertEmpty();
end;

[Test]
[HandlerFunctions('SuggestVendorPaymentsTakeDiscRPH')]
procedure SuggestVendorPaymentsTakingPaymentDiscount()
var
PaymentJournalLine: Record "Payment Journal Line";
PurchaseHeader: Record "Purchase Header";
VendorLedgerEntry: Record "Vendor Ledger Entry";
VendorNo: Code[20];
begin
// [SCENARIO 637839] Payment discount is taken when "Take Payment Discounts" is enabled in the "Suggest Vendor Payments EB" report.
Initialize();

// [GIVEN] Create a Vendor with Payment terms with Payment Discount.
VendorNo := CreateVendorWithPaymentDiscount();

// [GIVEN] Create and post a Purchase Invoice.
CreateAndPostPurchaseDocument(PurchaseHeader, PurchaseHeader."Document Type"::Invoice, VendorNo);

// [GIVEN] Find the Vendor Ledger Entry for the posted Purchase Invoice.
FindInvoiceVendorLedgerEntry(VendorLedgerEntry, VendorNo);

// [WHEN] Run "Suggest Vendor Payments EB" with "Take Payment Discounts" = TRUE.
LibraryVariableStorage.Enqueue(true);
SuggestVendorPayments(VendorNo);

// [WHEN] Filter the Payment Journal Line for the Vendor.
FilterEBPaymentJournalLine(PaymentJournalLine, VendorNo, PaymentJournalLine.Status::Created);
PaymentJournalLine.FindFirst();

// [THEN] Verify that the "Pmt. Discount Date" and Pmt Discount is taken, in Payment Journal Line.
Assert.AreEqual(WorkDate(), PaymentJournalLine."Pmt. Discount Date", StrSubstNo(WrongPmtDiscErr, PaymentJournalLine.FieldCaption("Pmt. Discount Date")));
Assert.AreEqual(Abs(VendorLedgerEntry."Remaining Pmt. Disc. Possible"), PaymentJournalLine."Pmt. Disc. Possible", StrSubstNo(WrongPmtDiscErr, PaymentJournalLine.FieldCaption("Pmt. Disc. Possible")));
LibraryVariableStorage.AssertEmpty();
end;

[Test]
[HandlerFunctions('SuggestVendorPaymentsPmtDiscDateRPH')]
procedure SuggestVendorPaymentsSelectsDiscountOnlyEntryWithDiscountedAmount()
var
PaymentJournalLine: Record "Payment Journal Line";
PurchaseHeader: Record "Purchase Header";
VendorLedgerEntry: Record "Vendor Ledger Entry";
VendorNo: Code[20];
begin
// [SCENARIO 637839] An invoice due after the "Last Due Date" but within the payment discount window is only suggested when "Take Payment Discounts" is enabled, and then with the discounted amount.
Initialize();

// [GIVEN] A Vendor with Payment Terms granting a payment discount.
VendorNo := CreateVendorWithPaymentDiscount();

// [GIVEN] A posted Purchase Invoice whose "Due Date" is later than its "Pmt. Discount Date".
CreateAndPostPurchaseDocument(PurchaseHeader, PurchaseHeader."Document Type"::Invoice, VendorNo);

// [GIVEN] The invoice Vendor Ledger Entry with its remaining amount and remaining payment discount.
FindInvoiceVendorLedgerEntry(VendorLedgerEntry, VendorNo);
VendorLedgerEntry.CalcFields("Remaining Amount");

// [WHEN] Run "Suggest Vendor Payments EB" with "Last Due Date" = the invoice "Pmt. Discount Date" (before the invoice "Due Date") and "Take Payment Discounts" = FALSE.
LibraryVariableStorage.Enqueue(VendorLedgerEntry."Pmt. Discount Date");
LibraryVariableStorage.Enqueue(false);
SuggestVendorPayments(VendorNo);

// [THEN] No Payment Journal Line is suggested, because the invoice is not yet due and the payment discount path is disabled.
FilterEBPaymentJournalLine(PaymentJournalLine, VendorNo, PaymentJournalLine.Status::Created);
Assert.RecordIsEmpty(PaymentJournalLine);

// [WHEN] Run "Suggest Vendor Payments EB" again with the same "Last Due Date" and "Take Payment Discounts" = TRUE.
LibraryVariableStorage.Enqueue(VendorLedgerEntry."Pmt. Discount Date");
LibraryVariableStorage.Enqueue(true);
SuggestVendorPayments(VendorNo);

// [THEN] The invoice is suggested through the payment discount path with the "Pmt. Discount Date" retained and the exact discounted amount.
FilterEBPaymentJournalLine(PaymentJournalLine, VendorNo, PaymentJournalLine.Status::Created);
PaymentJournalLine.FindFirst();
Assert.AreEqual(WorkDate(), PaymentJournalLine."Pmt. Discount Date", StrSubstNo(WrongPmtDiscErr, PaymentJournalLine.FieldCaption("Pmt. Discount Date")));
Assert.AreEqual(Abs(VendorLedgerEntry."Remaining Pmt. Disc. Possible"), PaymentJournalLine."Pmt. Disc. Possible", StrSubstNo(WrongPmtDiscErr, PaymentJournalLine.FieldCaption("Pmt. Disc. Possible")));
Assert.AreEqual(Abs(VendorLedgerEntry."Remaining Amount") - Abs(VendorLedgerEntry."Remaining Pmt. Disc. Possible"), Abs(PaymentJournalLine.Amount), StrSubstNo(WrongPmtDiscErr, PaymentJournalLine.FieldCaption(Amount)));
LibraryVariableStorage.AssertEmpty();
end;

local procedure Initialize()
begin
LibraryTestInitialize.OnTestInitialize(CODEUNIT::"ERM Payment Journal");
Expand Down Expand Up @@ -1488,6 +1604,26 @@ codeunit 144003 "ERM Payment Journal"
Assert.RecordCount(GenJournalLine, ExpectedCount);
end;

local procedure CreateVendorWithPaymentDiscount(): Code[20]
var
PaymentTerms: Record "Payment Terms";
Vendor: Record Vendor;
begin
LibraryERM.CreatePaymentTermsDiscount(PaymentTerms, false);
LibraryPurchase.CreateVendor(Vendor);
Vendor.Validate("Payment Terms Code", PaymentTerms.Code);
Vendor.Modify(true);

exit(Vendor."No.");
end;

local procedure FindInvoiceVendorLedgerEntry(var VendorLedgerEntry: Record "Vendor Ledger Entry"; VendorNo: Code[20])
begin
VendorLedgerEntry.SetRange("Document Type", VendorLedgerEntry."Document Type"::Invoice);
VendorLedgerEntry.SetRange("Vendor No.", VendorNo);
VendorLedgerEntry.FindFirst();
end;

[RequestPageHandler]
[Scope('OnPrem')]
procedure ExportPaymentJournalLinesHandler(var FileDomesticPayments: TestRequestPage "File Domestic Payments")
Expand Down Expand Up @@ -1532,5 +1668,35 @@ codeunit 144003 "ERM Payment Journal"
EBPaymentJournalTemplates.FILTER.SetFilter(Name, LibraryVariableStorage.DequeueText());
EBPaymentJournalTemplates.OK().Invoke();
end;

[RequestPageHandler]
procedure SuggestVendorPaymentsTakeDiscRPH(var SuggestVendorPaymentsEB: TestRequestPage "Suggest Vendor Payments EB")
var
TakePmtDiscount: Boolean;
begin
SuggestVendorPaymentsEB.DueDate.SetValue(CalcDate('<3M>', WorkDate()));
TakePmtDiscount := LibraryVariableStorage.DequeueBoolean();
SuggestVendorPaymentsEB.IncPmtDiscount.SetValue(TakePmtDiscount);
if TakePmtDiscount then
SuggestVendorPaymentsEB.PmtDiscDueDate.SetValue(WorkDate())
else
SuggestVendorPaymentsEB.PmtDiscDueDate.SetValue(0D);
SuggestVendorPaymentsEB.OK().Invoke();
end;

[RequestPageHandler]
procedure SuggestVendorPaymentsPmtDiscDateRPH(var SuggestVendorPaymentsEB: TestRequestPage "Suggest Vendor Payments EB")
var
TakePmtDiscount: Boolean;
begin
SuggestVendorPaymentsEB.DueDate.SetValue(LibraryVariableStorage.DequeueDate());
TakePmtDiscount := LibraryVariableStorage.DequeueBoolean();
SuggestVendorPaymentsEB.IncPmtDiscount.SetValue(TakePmtDiscount);
if TakePmtDiscount then
SuggestVendorPaymentsEB.PmtDiscDueDate.SetValue(WorkDate())
else
SuggestVendorPaymentsEB.PmtDiscDueDate.SetValue(0D);
SuggestVendorPaymentsEB.OK().Invoke();
end;
}

Loading