Skip to content
Merged
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 @@ -6,6 +6,7 @@ namespace Microsoft.Bank.DirectDebit;

using Microsoft.Bank.Payment;
using Microsoft.Finance.GeneralLedger.Journal;
using System.Environment.Configuration;

/// <summary>
/// Prepares general journal line data for SEPA credit transfer XML export by copying and organizing
Expand Down Expand Up @@ -58,6 +59,7 @@ codeunit 1222 "SEPA CT-Prepare Source"
AppliedDocNoList: Text;
DescriptionLen: Integer;
IsHandled: Boolean;
RemittanceTruncated: Boolean;
begin
IsHandled := false;
OnBeforeCreateTempJnlLines(FromGenJnlLine, TempGenJnlLine, IsHandled);
Expand Down Expand Up @@ -106,12 +108,17 @@ codeunit 1222 "SEPA CT-Prepare Source"
TempGenJnlLine.Description := CopyStr(AppliedDocNoList, 1, DescriptionLen);
if StrLen(AppliedDocNoList) > DescriptionLen then
TempGenJnlLine."Message to Recipient" :=
CopyStr(AppliedDocNoList, DescriptionLen + 1, DescriptionLen + MaxStrLen(TempGenJnlLine."Message to Recipient"));
CopyStr(AppliedDocNoList, DescriptionLen + 1, MaxStrLen(TempGenJnlLine."Message to Recipient"));
if StrLen(AppliedDocNoList) > DescriptionLen + MaxStrLen(TempGenJnlLine."Message to Recipient") then
RemittanceTruncated := true;
end;

TempGenJnlLine.Insert();
until PaymentHistoryLine.Next() = 0;

if RemittanceTruncated then
NotifyRemittanceTruncated();

OnAfterCreateTempJnlLines(FromGenJnlLine, TempGenJnlLine);
end;

Expand Down Expand Up @@ -149,5 +156,53 @@ codeunit 1222 "SEPA CT-Prepare Source"
local procedure OnCopyJnlLinesOnBeforeTempGenJnlLineInsert(var FromGenJournalLine: Record "Gen. Journal Line"; var TempGenJournalLine: Record "Gen. Journal Line" temporary; GenJournalBatch: Record "Gen. Journal Batch")
begin
end;

local procedure NotifyRemittanceTruncated()
var
MyNotifications: Record "My Notifications";
RemittanceNotification: Notification;
begin
if not GuiAllowed() then
exit;
if not MyNotifications.IsEnabled(GetRemittanceTruncationNotificationId()) then
exit;

RemittanceNotification.Id := GetRemittanceTruncationNotificationId();
RemittanceNotification.Message(RemittanceTruncatedMsg);
RemittanceNotification.Scope(NotificationScope::LocalScope);
RemittanceNotification.AddAction(DontShowAgainTxt, Codeunit::"SEPA CT-Prepare Source", 'DisableRemittanceTruncationNotification');
RemittanceNotification.Send();
end;

/// <summary>
/// Disables the remittance truncation notification for the current user.
/// </summary>
/// <param name="RemittanceNotification">The notification whose action was invoked.</param>
procedure DisableRemittanceTruncationNotification(RemittanceNotification: Notification)
var
MyNotifications: Record "My Notifications";
begin
MyNotifications.Disable(GetRemittanceTruncationNotificationId());
end;

local procedure GetRemittanceTruncationNotificationId(): Guid
begin
exit(RemittanceTruncationNotificationIdTok);
end;

[EventSubscriber(ObjectType::Page, Page::"My Notifications", 'OnInitializingNotificationWithDefaultState', '', false, false)]
local procedure OnInitializingNotificationWithDefaultStateRegisterNotifications()
var
MyNotifications: Record "My Notifications";
begin
MyNotifications.InsertDefault(GetRemittanceTruncationNotificationId(), RemittanceTruncationNotificationNameTxt, RemittanceTruncationNotificationDescriptionTxt, true);
end;

var
RemittanceTruncatedMsg: Label 'The list of applied documents will be shortened in the exported payment file. To avoid this, split the payment or turn off combining entries on the transaction mode.';
DontShowAgainTxt: Label 'Don''t show this again';
RemittanceTruncationNotificationNameTxt: Label 'Remittance information shortened on payment export';
RemittanceTruncationNotificationDescriptionTxt: Label 'Notify me when the list of applied documents is too long for the remittance information and will be shortened in the exported payment file.';
RemittanceTruncationNotificationIdTok: Label 'd9f2b3a7-6c41-4e8b-9a2d-7f0c1e5b84a3', Locked = true;
}

72 changes: 72 additions & 0 deletions src/Layers/NL/Tests/Local/UTTABTelebank.Codeunit.al
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,44 @@ codeunit 144055 "UT TAB Telebank"
AppliedDocNoListErr);
end;

[Test]
[TransactionModel(TransactionModel::AutoRollback)]
[Scope('OnPrem')]
procedure PrepareSourceTruncatesRemittanceExceedingFieldLengths()
var
PaymentHistory: Record "Payment History";
PaymentHistoryLine: Record "Payment History Line";
TempGenJnlLine: Record "Gen. Journal Line" temporary;
AppliedDocNoList: Text;
DescriptionLen: Integer;
begin
// [SCENARIO] Preparing SEPA CT source from a payment line whose combined applied document numbers
// exceed Description plus Message to Recipient must truncate gracefully instead of raising a length error.

// [GIVEN] A vendor payment history line with applied documents longer than Description + Message to Recipient combined
MockVendorPaymentHistoryWithLongAppliedDocs(PaymentHistory, PaymentHistoryLine);
DescriptionLen := MaxStrLen(TempGenJnlLine.Description);
AppliedDocNoList := PaymentHistoryLine.GetAppliedDocNoList(DescriptionLen);
Assert.IsTrue(
StrLen(AppliedDocNoList) > DescriptionLen + MaxStrLen(TempGenJnlLine."Message to Recipient"),
'Test data must exceed the combined Description and Message to Recipient length.');

// [WHEN] SEPA CT-Prepare Source builds the temporary journal lines
TempGenJnlLine.SetRange("Bal. Account No.", PaymentHistory."Our Bank");
TempGenJnlLine.SetRange("Document No.", PaymentHistory."Run No.");
Codeunit.Run(Codeunit::"SEPA CT-Prepare Source", TempGenJnlLine);

// [THEN] The list is split across Description (first part) and Message to Recipient (next part) without overflow
TempGenJnlLine.Reset();
TempGenJnlLine.FindFirst();
Assert.AreEqual(
CopyStr(AppliedDocNoList, 1, DescriptionLen), TempGenJnlLine.Description,
TempGenJnlLine.FieldName(Description));
Assert.AreEqual(
CopyStr(AppliedDocNoList, DescriptionLen + 1, MaxStrLen(TempGenJnlLine."Message to Recipient")),
TempGenJnlLine."Message to Recipient", TempGenJnlLine.FieldName("Message to Recipient"));
end;

[Test]
[TransactionModel(TransactionModel::AutoRollback)]
[Scope('OnPrem')]
Expand Down Expand Up @@ -814,6 +852,40 @@ codeunit 144055 "UT TAB Telebank"
DetailLine.Insert();
end;

local procedure MockVendorPaymentHistoryWithLongAppliedDocs(var PaymentHistory: Record "Payment History"; var PaymentHistoryLine: Record "Payment History Line")
var
Index: Integer;
begin
PaymentHistory.Init();
PaymentHistory."Our Bank" := LibraryERM.CreateBankAccountNo();
PaymentHistory."Run No." := LibraryUtility.GenerateGUID();
PaymentHistory.Insert();

PaymentHistoryLine.Init();
PaymentHistoryLine."Our Bank" := PaymentHistory."Our Bank";
PaymentHistoryLine."Run No." := PaymentHistory."Run No.";
PaymentHistoryLine."Line No." := 10000;
PaymentHistoryLine."Account Type" := PaymentHistoryLine."Account Type"::Vendor;
PaymentHistoryLine."Account No." := LibraryPurchase.CreateVendorNo();
PaymentHistoryLine."Description 1" := CopyStr(LibraryUtility.GenerateGUID(), 1, MaxStrLen(PaymentHistoryLine."Description 1"));
PaymentHistoryLine.Insert();

// 12 applied documents of 30 characters each exceed Description plus Message to Recipient combined
for Index := 1 to 12 do
MockAppliedVendorDocument(PaymentHistoryLine, Index);
end;

local procedure MockAppliedVendorDocument(PaymentHistoryLine: Record "Payment History Line"; Index: Integer)
Comment thread
dcenic marked this conversation as resolved.
var
VendorLedgerEntry: Record "Vendor Ledger Entry";
begin
VendorLedgerEntry.Init();
Comment thread
dcenic marked this conversation as resolved.
VendorLedgerEntry."Entry No." := LibraryUtility.GetNewRecNo(VendorLedgerEntry, VendorLedgerEntry.FieldNo("Entry No."));
VendorLedgerEntry."External Document No." := CopyStr(PadStr('EXTDOC' + Format(Index), 30, '0'), 1, 30);
VendorLedgerEntry.Insert();
CreateDetailLine(PaymentHistoryLine, VendorLedgerEntry."Entry No.");
end;

local procedure CreateExportProtocol(): Code[20]
var
ExportProtocol: Record "Export Protocol";
Expand Down
Loading