Skip to content
Draft
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 @@ -358,7 +358,7 @@ codeunit 10837 "Payment Management FR"
SetPostingGroup();
SetAccountNo();
InvPostingBuffer[1]."System-Created Entry" := true;
if StepLedger.Sign = StepLedger.Sign::Debit then begin
if (StepLedger.Sign = StepLedger.Sign::Debit) xor IsReversedPaymentLine() then begin
InvPostingBuffer[1].Validate(Amount, Abs(PaymentLine.Amount));
InvPostingBuffer[1].Validate("Amount (LCY)", Abs(PaymentLine."Amount (LCY)"));
end else begin
Expand All @@ -374,7 +374,7 @@ codeunit 10837 "Payment Management FR"
if StepLedger."Detail Level" = StepLedger."Detail Level"::"Due Date" then
InvPostingBuffer[1]."Due Date" := PaymentLine."Due Date";

InvPostingBuffer[1]."Document Type" := StepLedger."Document Type";
InvPostingBuffer[1]."Document Type" := GetPostingDocumentType();
if StepLedger."Document No." = StepLedger."Document No."::"Header No." then
InvPostingBuffer[1]."Document No." := PaymentHeader."No."
else begin
Expand Down Expand Up @@ -424,6 +424,26 @@ codeunit 10837 "Payment Management FR"
end;
end;

local procedure IsReversedPaymentLine(): Boolean
begin
exit(
((PaymentLine."Account Type" = PaymentLine."Account Type"::Customer) and (PaymentLine.Amount > 0)) or
((PaymentLine."Account Type" = PaymentLine."Account Type"::Vendor) and (PaymentLine.Amount < 0)));
end;

local procedure GetPostingDocumentType(): Enum "Gen. Journal Document Type"
begin
if IsReversedPaymentLine() then
case StepLedger."Document Type" of
StepLedger."Document Type"::Payment:
exit(StepLedger."Document Type"::Refund);
StepLedger."Document Type"::Refund:
exit(StepLedger."Document Type"::Payment);
end;

exit(StepLedger."Document Type");
end;

local procedure GetDescriptionForInvPostingBuffer() Description: Text[98]
begin
Description :=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,20 +109,22 @@ codeunit 10838 "PaymentMgt Subscribers FR"
PaymentLine.SetRange("No.", PaymentHeader."No.");
if PaymentLine.FindSet() then
repeat
ToDirectDebitCollectionEntry.Init();
ToDirectDebitCollectionEntry."Entry No." := PaymentLine."Line No.";
ToDirectDebitCollectionEntry."Direct Debit Collection No." := DirectDebitCollection."No.";
ToDirectDebitCollectionEntry.DeletePaymentFileErrors();
if CheckPaymentLine(ToDirectDebitCollectionEntry, PaymentLine, AppliesToEntryNo) then begin
ToDirectDebitCollectionEntry.Validate("Customer No.", PaymentLine."Account No.");
ToDirectDebitCollectionEntry.Validate("Applies-to Entry No.", AppliesToEntryNo);
ToDirectDebitCollectionEntry."Transfer Date" := PaymentHeader."Posting Date";
ToDirectDebitCollectionEntry."Currency Code" := PaymentLine."Currency Code";
ToDirectDebitCollectionEntry.Validate("Transfer Amount", PaymentLine."Credit Amount");
ToDirectDebitCollectionEntry.Validate("Mandate ID", PaymentLine."Direct Debit Mandate ID");
OnCreateTempCollectionEntriesOnBeforeInsert(ToDirectDebitCollectionEntry, PaymentHeader, PaymentLine);
ToDirectDebitCollectionEntry.Insert();
SEPADDCheckLine.CheckCollectionEntry(ToDirectDebitCollectionEntry);
if PaymentLine."Credit Amount" > 0 then begin
ToDirectDebitCollectionEntry.Init();
ToDirectDebitCollectionEntry."Entry No." := PaymentLine."Line No.";
ToDirectDebitCollectionEntry."Direct Debit Collection No." := DirectDebitCollection."No.";
ToDirectDebitCollectionEntry.DeletePaymentFileErrors();
if CheckPaymentLine(ToDirectDebitCollectionEntry, PaymentLine, AppliesToEntryNo) then begin
ToDirectDebitCollectionEntry.Validate("Customer No.", PaymentLine."Account No.");
ToDirectDebitCollectionEntry.Validate("Applies-to Entry No.", AppliesToEntryNo);
ToDirectDebitCollectionEntry."Transfer Date" := PaymentHeader."Posting Date";
ToDirectDebitCollectionEntry."Currency Code" := PaymentLine."Currency Code";
ToDirectDebitCollectionEntry.Validate("Transfer Amount", PaymentLine."Credit Amount");
ToDirectDebitCollectionEntry.Validate("Mandate ID", PaymentLine."Direct Debit Mandate ID");
OnCreateTempCollectionEntriesOnBeforeInsert(ToDirectDebitCollectionEntry, PaymentHeader, PaymentLine);
ToDirectDebitCollectionEntry.Insert();
SEPADDCheckLine.CheckCollectionEntry(ToDirectDebitCollectionEntry);
end;
end;
until PaymentLine.Next() = 0;

Expand Down Expand Up @@ -319,6 +321,7 @@ codeunit 10838 "PaymentMgt Subscribers FR"
var
SEPADirectDebitMandate: Record "SEPA Direct Debit Mandate";
CustLedgerEntry: Record "Cust. Ledger Entry";
AppliedEntryCount: Integer;
SummarizeNotAllowedErr: Label 'You cannot export a SEPA customer payment that is applied to multiple documents. Make sure that the Summarize per field in the Suggest Customer Payments window is blank.';
UnappliedLinesNotAllowedErr: Label 'Payment slip line %1 must be applied to a customer invoice.', Comment = '%1 = No.';
AccTypeErr: Label 'Only customer transactions are allowed.';
Expand All @@ -341,12 +344,23 @@ codeunit 10838 "PaymentMgt Subscribers FR"
DirectDebitCollectionEntry.InsertPaymentFileError(StrSubstNo(UnappliedLinesNotAllowedErr, PaymentLine."Line No."))
else begin
PaymentLine.GetAppliesToDocCustLedgEntry(CustLedgerEntry);
if CustLedgerEntry.Count > 1 then
DirectDebitCollectionEntry.InsertPaymentFileError(SummarizeNotAllowedErr);
CustLedgerEntry.FindFirst();
if CustLedgerEntry."Document Type" <> CustLedgerEntry."Document Type"::Invoice then
if CustLedgerEntry.Count > 1 then begin
AppliedEntryCount := CustLedgerEntry.Count;
CustLedgerEntry.SetRange("Document Type", CustLedgerEntry."Document Type"::Invoice);
if CustLedgerEntry.Count <> 1 then
DirectDebitCollectionEntry.InsertPaymentFileError(SummarizeNotAllowedErr);
CustLedgerEntry.SetRange("Document Type", CustLedgerEntry."Document Type"::"Credit Memo");
if CustLedgerEntry.Count <> AppliedEntryCount - 1 then
DirectDebitCollectionEntry.InsertPaymentFileError(SummarizeNotAllowedErr);
CustLedgerEntry.SetRange("Document Type", CustLedgerEntry."Document Type"::Invoice);
end;
if CustLedgerEntry.FindFirst() then begin
if CustLedgerEntry."Document Type" = CustLedgerEntry."Document Type"::Invoice then
AppliesToEntryNo := CustLedgerEntry."Entry No."
else
DirectDebitCollectionEntry.InsertPaymentFileError(StrSubstNo(UnappliedLinesNotAllowedErr, PaymentLine."Line No."));
end else
DirectDebitCollectionEntry.InsertPaymentFileError(StrSubstNo(UnappliedLinesNotAllowedErr, PaymentLine."Line No."));
AppliesToEntryNo := CustLedgerEntry."Entry No.";
end;

exit(not DirectDebitCollectionEntry.HasPaymentFileErrors());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,8 @@ report 10849 "Suggest Cust. Payments"
if SEPADirectDebitMandate.Get(CustLedgEntry."Direct Debit Mandate ID") then
GenPayLine.Validate("Bank Account Code", SEPADirectDebitMandate."Customer Bank Account Code");
GenPayLine."Direct Debit Mandate ID" := CustLedgEntry."Direct Debit Mandate ID";
end;
end else
SetDirectDebitMandate(GenPayLine, SEPADirectDebitMandate);
case SummarizePer of
SummarizePer::" ":
GenPayLine."Due Date" := CustLedgEntry."Due Date";
Expand All @@ -447,6 +448,20 @@ report 10849 "Suggest Cust. Payments"
until TempPaymentPostBuffer.Next() = 0;
end;

local procedure SetDirectDebitMandate(var PaymentLine: Record "Payment Line FR"; var SEPADirectDebitMandate: Record "SEPA Direct Debit Mandate")
var
AppliedCustLedgerEntry: Record "Cust. Ledger Entry";
begin
PaymentLine.GetAppliesToDocCustLedgEntry(AppliedCustLedgerEntry);
AppliedCustLedgerEntry.SetRange("Document Type", AppliedCustLedgerEntry."Document Type"::Invoice);
if not AppliedCustLedgerEntry.FindFirst() then
exit;

PaymentLine."Direct Debit Mandate ID" := AppliedCustLedgerEntry."Direct Debit Mandate ID";
if SEPADirectDebitMandate.Get(PaymentLine."Direct Debit Mandate ID") then
PaymentLine.Validate("Bank Account Code", SEPADirectDebitMandate."Customer Bank Account Code");
end;

local procedure ShowMessage(Text: Text)
begin
if (Text <> '') and GenPayLineInserted then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,61 @@ codeunit 144013 "ERM Payment Management"
PaymentDiscountOnPurchaseCrMemo('', false); // Using Blank for Currency Code, False for Calc. Pmt. Discount,
end;

[Test]
[HandlerFunctions('PaymentClassListModalPageHandler,SuggestCustomerPaymentsRequestPageHandler,ConfirmHandlerTrue')]
procedure PostCustomerInvoiceAndCreditMemoWithOppositeEntries()
var
GenJournalLine: Record "Gen. Journal Line";
PaymentClass: Record "Payment Class FR";
PaymentHeader: Record "Payment Header FR";
PaymentLine: Record "Payment Line FR";
PaymentStepLedger: Record "Payment Step Ledger FR";
InvoiceDebitGLEntry: Record "G/L Entry";
InvoiceCreditGLEntry: Record "G/L Entry";
CreditMemoDebitGLEntry: Record "G/L Entry";
CreditMemoCreditGLEntry: Record "G/L Entry";
CustomerNo: Code[20];
PaymentClassCode: Text[30];
Amount: Decimal;
begin
// [SCENARIO 644993] Invoice and credit memo payment lines post with opposite signs and document types.
Initialize();
Amount := LibraryRandom.RandDecInRange(100, 1000, 2);
CustomerNo := CreateCustomer('');
CreateAndPostGeneralJournal(
GenJournalLine, GenJournalLine."Account Type"::Customer, CustomerNo,
GenJournalLine."Document Type"::Invoice, Amount, WorkDate());
CreateAndPostGeneralJournal(
GenJournalLine, GenJournalLine."Account Type"::Customer, CustomerNo,
GenJournalLine."Document Type"::"Credit Memo", -Amount / 2, WorkDate());
PaymentClassCode := SetupForPaymentSlipPost(PaymentStepLedger."Detail Level"::Line, PaymentClass.Suggestions::Customer);
PaymentStepLedger.SetRange("Payment Class", PaymentClassCode);
PaymentStepLedger.ModifyAll("Document Type", PaymentStepLedger."Document Type"::Payment, true);
CreatePaymentHeader(PaymentHeader);
Commit();
SuggestCustomerPaymentLines(CustomerNo, '', PaymentHeader);

PostPaymentSlipHeaderNo(PaymentHeader."No.");

FindPostedPaymentLine(PaymentLine, PaymentHeader."No.", PaymentLine."Applies-to Doc. Type"::Invoice);
InvoiceDebitGLEntry.Get(PaymentLine."Entry No. Debit");
InvoiceCreditGLEntry.Get(PaymentLine."Entry No. Credit");
InvoiceDebitGLEntry.TestField("Document Type", InvoiceDebitGLEntry."Document Type"::Payment);
InvoiceCreditGLEntry.TestField("Document Type", InvoiceCreditGLEntry."Document Type"::Payment);

FindPostedPaymentLine(PaymentLine, PaymentHeader."No.", PaymentLine."Applies-to Doc. Type"::"Credit Memo");
CreditMemoDebitGLEntry.Get(PaymentLine."Entry No. Debit");
CreditMemoCreditGLEntry.Get(PaymentLine."Entry No. Credit");
CreditMemoDebitGLEntry.TestField("Document Type", CreditMemoDebitGLEntry."Document Type"::Refund);
CreditMemoCreditGLEntry.TestField("Document Type", CreditMemoCreditGLEntry."Document Type"::Refund);
Assert.AreEqual(
InvoiceDebitGLEntry."G/L Account No.", CreditMemoCreditGLEntry."G/L Account No.",
CreditMemoCreditGLEntry.FieldCaption("G/L Account No."));
Assert.AreEqual(
InvoiceCreditGLEntry."G/L Account No.", CreditMemoDebitGLEntry."G/L Account No.",
CreditMemoDebitGLEntry.FieldCaption("G/L Account No."));
end;

local procedure PaymentDiscountOnPurchaseCrMemo(CurrencyCode: Code[10]; CalcPmtDiscOnCrMemos: Boolean)
var
GenJournalLine: Record "Gen. Journal Line";
Expand Down Expand Up @@ -2999,6 +3054,15 @@ codeunit 144013 "ERM Payment Management"
PaymentLine.FindFirst();
end;

local procedure FindPostedPaymentLine(var PaymentLine: Record "Payment Line FR"; PaymentHeaderNo: Code[20]; AppliesToDocumentType: Enum "Gen. Journal Document Type")
begin
PaymentLine.Reset();
PaymentLine.SetRange("No.", PaymentHeaderNo);
PaymentLine.SetRange("Applies-to Doc. Type", AppliesToDocumentType);
PaymentLine.FindFirst();
PaymentLine.TestField(Posted, true);
end;

local procedure FindVATEntry(var VATEntry: Record "VAT Entry"; DocumentNo: Code[20])
begin
VATEntry.SetRange("Document No.", DocumentNo);
Expand Down Expand Up @@ -3381,13 +3445,5 @@ codeunit 144013 "ERM Payment Management"
begin
Reply := true;
end;

#if not CLEAN28
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Payment Management Feature FR", OnAfterCheckFeatureEnabled, '', false, false)]
local procedure OnAfterCheckFeatureEnabled(var IsEnabled: Boolean)
begin
IsEnabled := true;
end;
#endif
}

Loading
Loading