diff --git a/Apps/W1/EDocument/app/Permissions/EDocCoreBasic.PermissionSet.al b/Apps/W1/EDocument/app/Permissions/EDocCoreBasic.PermissionSet.al
index 149349c3ad..e81a34511d 100644
--- a/Apps/W1/EDocument/app/Permissions/EDocCoreBasic.PermissionSet.al
+++ b/Apps/W1/EDocument/app/Permissions/EDocCoreBasic.PermissionSet.al
@@ -7,6 +7,7 @@ namespace Microsoft.eServices.EDocument;
using Microsoft.eServices.EDocument.IO.Peppol;
using Microsoft.EServices.EDocument.OrderMatch;
using Microsoft.eServices.EDocument.Service.Participant;
+using Microsoft.eServices.EDocument.Payments;
permissionset 6103 "E-Doc. Core - Basic"
{
@@ -29,5 +30,6 @@ permissionset 6103 "E-Doc. Core - Basic"
tabledata "E-Doc. Service Supported Type" = im,
tabledata "E-Doc. Imported Line" = imd,
tabledata "E-Doc. Order Match" = imd,
- tabledata "Service Participant" = imd;
+ tabledata "Service Participant" = imd,
+ tabledata "E-Document Payment" = imd;
}
diff --git a/Apps/W1/EDocument/app/Permissions/EDocCoreEdit.PermissionSet.al b/Apps/W1/EDocument/app/Permissions/EDocCoreEdit.PermissionSet.al
index 81acc2e21f..59f059e7f1 100644
--- a/Apps/W1/EDocument/app/Permissions/EDocCoreEdit.PermissionSet.al
+++ b/Apps/W1/EDocument/app/Permissions/EDocCoreEdit.PermissionSet.al
@@ -7,6 +7,7 @@ namespace Microsoft.eServices.EDocument;
using Microsoft.eServices.EDocument.IO.Peppol;
using Microsoft.EServices.EDocument.OrderMatch;
using Microsoft.eServices.EDocument.Service.Participant;
+using Microsoft.eServices.EDocument.Payments;
permissionset 6102 "E-Doc. Core - Edit"
{
@@ -29,5 +30,6 @@ permissionset 6102 "E-Doc. Core - Edit"
tabledata "E-Doc. Service Supported Type" = IMD,
tabledata "E-Doc. Imported Line" = IMD,
tabledata "E-Doc. Order Match" = IMD,
- tabledata "Service Participant" = IMD;
+ tabledata "Service Participant" = IMD,
+ tabledata "E-Document Payment" = IMD;
}
diff --git a/Apps/W1/EDocument/app/Permissions/EDocCoreObjects.PermissionSet.al b/Apps/W1/EDocument/app/Permissions/EDocCoreObjects.PermissionSet.al
index 3000c3ad9d..42292c47c6 100644
--- a/Apps/W1/EDocument/app/Permissions/EDocCoreObjects.PermissionSet.al
+++ b/Apps/W1/EDocument/app/Permissions/EDocCoreObjects.PermissionSet.al
@@ -5,10 +5,12 @@
namespace Microsoft.eServices.EDocument;
using Microsoft.eServices.EDocument.IO;
+using Microsoft.eServices.EDocument.Integration.Payments;
using Microsoft.eServices.EDocument.IO.Peppol;
using Microsoft.EServices.EDocument.OrderMatch;
using Microsoft.EServices.EDocument.OrderMatch.Copilot;
using Microsoft.eServices.EDocument.Service.Participant;
+using Microsoft.eServices.EDocument.Payments;
permissionset 6100 "E-Doc. Core - Objects"
{
Assignable = false;
@@ -28,6 +30,7 @@ permissionset 6100 "E-Doc. Core - Objects"
table "E-Doc. Imported Line" = X,
table "E-Doc. PO Match Prop. Buffer" = X,
table "Service Participant" = X,
+ table "E-Document Payment" = X,
codeunit "E-Document Import Job" = X,
codeunit "E-Doc. Integration Management" = X,
codeunit "E-Doc. Mapping" = X,
@@ -69,6 +72,12 @@ permissionset 6100 "E-Doc. Core - Objects"
codeunit "E-Doc. PO Copilot Matching" = X,
codeunit "E-Doc. Attachment Processor" = X,
codeunit "Service Participant" = X,
+ codeunit "Payment Integration Management" = X,
+ codeunit "Empty Payment Handler" = X,
+ codeunit "Send Payment" = X,
+ codeunit "Receive Payments" = X,
+ codeunit "Get Payment Details" = X,
+ codeunit "Sync Payments Job" = X,
page "E-Doc. Changes Part" = X,
page "E-Doc. Changes Preview" = X,
page "E-Document Activities" = X,
@@ -91,5 +100,6 @@ permissionset 6100 "E-Doc. Core - Objects"
page "E-Doc. PO Copilot Prop" = X,
page "E-Doc. PO Match Prop. Sub" = X,
page "E-Doc. Order Match Act." = X,
- page "Service Participants" = X;
+ page "Service Participants" = X,
+ page "E-Document Payments" = X;
}
diff --git a/Apps/W1/EDocument/app/Permissions/EDocCoreRead.PermissionSet.al b/Apps/W1/EDocument/app/Permissions/EDocCoreRead.PermissionSet.al
index 30362c9850..6b14fa6ff3 100644
--- a/Apps/W1/EDocument/app/Permissions/EDocCoreRead.PermissionSet.al
+++ b/Apps/W1/EDocument/app/Permissions/EDocCoreRead.PermissionSet.al
@@ -7,6 +7,7 @@ namespace Microsoft.eServices.EDocument;
using Microsoft.eServices.EDocument.IO.Peppol;
using Microsoft.EServices.EDocument.OrderMatch;
using Microsoft.eServices.EDocument.Service.Participant;
+using Microsoft.eServices.EDocument.Payments;
permissionset 6101 "E-Doc. Core - Read"
{
@@ -26,5 +27,6 @@ permissionset 6101 "E-Doc. Core - Read"
tabledata "E-Doc. Service Supported Type" = R,
tabledata "E-Doc. Imported Line" = R,
tabledata "E-Doc. Order Match" = R,
- tabledata "Service Participant" = R;
+ tabledata "Service Participant" = R,
+ tabledata "E-Document Payment" = R;
}
\ No newline at end of file
diff --git a/Apps/W1/EDocument/app/src/Document/EDocument.Page.al b/Apps/W1/EDocument/app/src/Document/EDocument.Page.al
index d975f90883..03029d00a8 100644
--- a/Apps/W1/EDocument/app/src/Document/EDocument.Page.al
+++ b/Apps/W1/EDocument/app/src/Document/EDocument.Page.al
@@ -11,6 +11,8 @@ using Microsoft.eServices.EDocument.Integration.Receive;
using Microsoft.Bank.Reconciliation;
using Microsoft.eServices.EDocument.OrderMatch;
using Microsoft.eServices.EDocument.OrderMatch.Copilot;
+using Microsoft.eServices.EDocument.Integration.Payments;
+using Microsoft.eServices.EDocument.Payments;
page 6121 "E-Document"
{
@@ -119,6 +121,17 @@ page 6121 "E-Document"
Importance = Additional;
ToolTip = 'Specifies the electronic document posting date.';
}
+ field("Payment Status"; this.PaymentStatus)
+ {
+ Caption = 'Payment Status';
+ Visible = false;
+ Editable = false;
+ ToolTip = 'Specifies the electronic document payment status.';
+ }
+ field("Paid Amount"; Rec."Paid Amount")
+ {
+ Visible = false;
+ }
}
group(ReceivingCompanyInfo)
{
@@ -346,6 +359,35 @@ page 6121 "E-Document"
end;
}
}
+ group(Payments)
+ {
+ Caption = 'Payments';
+
+ action(ReceivePayments)
+ {
+ Caption = 'Receive Payments';
+ ToolTip = 'Receive payments for the electronic document.';
+ Image = Payment;
+ Visible = false;
+
+ trigger OnAction()
+ begin
+ this.ReceivePaymentsForEDoc();
+ end;
+ }
+ action(SendPayments)
+ {
+ Caption = 'Send Payment';
+ ToolTip = 'Send payment for the electronic document.';
+ Image = Payment;
+ Visible = false;
+
+ trigger OnAction()
+ begin
+ this.SendPaymentsForEDoc();
+ end;
+ }
+ }
group(Troubleshoot)
{
Caption = 'Troubleshoot';
@@ -507,6 +549,8 @@ page 6121 "E-Document"
SetIncomingDocActions();
EDocImport.ProcessEDocPendingOrderMatch(Rec);
+
+ this.SetPaymentStatus();
end;
local procedure SetStyle()
@@ -589,6 +633,49 @@ page 6121 "E-Document"
ShowRelink := false;
end;
+ local procedure SetPaymentStatus()
+ begin
+ if Rec."Paid Amount" = 0 then
+ this.PaymentStatus := this.PaymentStatus::"Not Paid"
+ else
+ if Rec."Paid Amount" < Rec."Amount Incl. VAT" then
+ this.PaymentStatus := this.PaymentStatus::"Partially Paid"
+ else
+ this.PaymentStatus := this.PaymentStatus::Paid;
+ end;
+
+ local procedure ReceivePaymentsForEDoc()
+ var
+ EDocService: Record "E-Document Service";
+ PaymentContext: Codeunit PaymentContext;
+ PaymentIntegrationManagement: Codeunit "Payment Integration Management";
+ EDocServices: Page "E-Document Services";
+ begin
+ EDocServices.LookupMode(true);
+ if EDocServices.RunModal() <> Action::LookupOK then
+ exit;
+
+ EDocServices.GetRecord(EDocService);
+ this.EDocumentErrorHelper.ClearPaymentErrorMessages(Rec);
+ PaymentIntegrationManagement.ReceivePayments(Rec, EDocService, PaymentContext);
+ end;
+
+ local procedure SendPaymentsForEDoc()
+ var
+ EDocService: Record "E-Document Service";
+ PaymentContext: Codeunit PaymentContext;
+ PaymentIntegrationManagement: Codeunit "Payment Integration Management";
+ EDocServices: Page "E-Document Services";
+ begin
+ EDocServices.LookupMode(true);
+ if EDocServices.RunModal() <> Action::LookupOK then
+ exit;
+
+ EDocServices.GetRecord(EDocService);
+ this.EDocumentErrorHelper.ClearPaymentErrorMessages(Rec);
+ PaymentIntegrationManagement.SendPayments(Rec, EDocService, PaymentContext);
+ end;
+
var
EDocumentBackgroundjobs: Codeunit "E-Document Background Jobs";
EDocIntegrationManagement: Codeunit "E-Doc. Integration Management";
@@ -596,6 +683,7 @@ page 6121 "E-Document"
EDocumentErrorHelper: Codeunit "E-Document Error Helper";
EDocumentHelper: Codeunit "E-Document Processing";
ErrorsAndWarningsNotification: Notification;
+ PaymentStatus: Enum "E-Document Payment Progress";
RecordLinkTxt, StyleStatusTxt : Text;
ShowRelink, ShowMapToOrder, HasErrorsOrWarnings, HasErrors, IsIncomingDoc, IsProcessed, CopilotVisible : Boolean;
EDocHasErrorOrWarningMsg: Label 'Errors or warnings found for E-Document. Please review below in "Error Messages" section.';
diff --git a/Apps/W1/EDocument/app/src/Document/EDocument.Table.al b/Apps/W1/EDocument/app/src/Document/EDocument.Table.al
index 4ec6ab4122..e357c0879b 100644
--- a/Apps/W1/EDocument/app/src/Document/EDocument.Table.al
+++ b/Apps/W1/EDocument/app/src/Document/EDocument.Table.al
@@ -11,6 +11,7 @@ using System.Automation;
using System.IO;
using System.Reflection;
using System.Threading;
+using Microsoft.eServices.EDocument.Payments;
table 6121 "E-Document"
{
@@ -182,8 +183,16 @@ table 6121 "E-Document"
Caption = 'Receiving Company Id';
ToolTip = 'Specifies the receiving company id, such as PEPPOL id, or other identifiers used in the electronic document exchange.';
}
-
+ field(32; "Paid Amount"; Decimal)
+ {
+ Caption = 'Paid Amount';
+ Editable = false;
+ FieldClass = FlowField;
+ CalcFormula = sum("E-Document Payment".Amount where("E-Document Entry No." = field("Entry No")));
+ ToolTip = 'Specifies the amount that has already been paid.';
+ }
}
+
keys
{
key(Key1; "Entry No")
diff --git a/Apps/W1/EDocument/app/src/Helpers/EDocumentErrorHelper.Codeunit.al b/Apps/W1/EDocument/app/src/Helpers/EDocumentErrorHelper.Codeunit.al
index b58704193d..21bf573122 100644
--- a/Apps/W1/EDocument/app/src/Helpers/EDocumentErrorHelper.Codeunit.al
+++ b/Apps/W1/EDocument/app/src/Helpers/EDocumentErrorHelper.Codeunit.al
@@ -6,6 +6,7 @@ namespace Microsoft.eServices.EDocument;
using System.Telemetry;
using System.Utilities;
+using Microsoft.eServices.EDocument.Payments;
codeunit 6115 "E-Document Error Helper"
{
@@ -105,6 +106,19 @@ codeunit 6115 "E-Document Error Helper"
ErrorMessage.LogSimpleMessage(ErrorMessage."Message Type"::Error, Message);
end;
+ ///
+ /// Use it to clear errors for E-Document related to payments.
+ ///
+ /// The E-Document record.
+ procedure ClearPaymentErrorMessages(EDocument: Record "E-Document")
+ var
+ ErrorMessage: Record "Error Message";
+ begin
+ ErrorMessage.SetRange("Context Record ID", EDocument.RecordId());
+ ErrorMessage.SetRange("Table Number", Database::"E-Document Payment");
+ ErrorMessage.DeleteAll(false);
+ end;
+
internal procedure GetTelemetryImplErrLbl(): Text
begin
exit(EDocTelemetryImplErr);
diff --git a/Apps/W1/EDocument/app/src/Integration/Interfaces/IDocumentPaymentHandler.Interface.al b/Apps/W1/EDocument/app/src/Integration/Interfaces/IDocumentPaymentHandler.Interface.al
new file mode 100644
index 0000000000..c7f9f45a12
--- /dev/null
+++ b/Apps/W1/EDocument/app/src/Integration/Interfaces/IDocumentPaymentHandler.Interface.al
@@ -0,0 +1,21 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+namespace Microsoft.eServices.EDocument.Integration.Interfaces;
+
+using Microsoft.eServices.EDocument;
+using Microsoft.eServices.EDocument.Integration.Payments;
+using System.Utilities;
+
+///
+/// Interface for sending and receiving payment information for E-Documents using E-Document service
+///
+interface IDocumentPaymentHandler
+{
+ procedure Send(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; PaymentContext: Codeunit PaymentContext)
+
+ procedure Receive(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var PaymentsMetadata: Codeunit "Temp Blob List"; PaymentContext: Codeunit PaymentContext)
+
+ procedure GetDetails(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; PaymentMetadata: Codeunit "Temp Blob"; PaymentContext: Codeunit PaymentContext)
+}
diff --git a/Apps/W1/EDocument/app/src/Integration/Payments/GetPaymentDetails.Codeunit.al b/Apps/W1/EDocument/app/src/Integration/Payments/GetPaymentDetails.Codeunit.al
new file mode 100644
index 0000000000..54ca76f054
--- /dev/null
+++ b/Apps/W1/EDocument/app/src/Integration/Payments/GetPaymentDetails.Codeunit.al
@@ -0,0 +1,60 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+namespace Microsoft.eServices.EDocument.Integration.Payments;
+
+using System.Utilities;
+using Microsoft.eServices.EDocument;
+using Microsoft.eServices.EDocument.Integration.Interfaces;
+
+codeunit 6107 "Get Payment Details"
+{
+ Access = Internal;
+ InherentEntitlements = X;
+ InherentPermissions = X;
+
+ trigger OnRun()
+ begin
+ this.EDocumentService.TestField(Code);
+ this.IDocumentPaymentHandler.GetDetails(this.EDocument, this.EDocumentService, this.PaymentMetadata, this.PaymentContext);
+ end;
+
+ ///
+ /// Sets the global variable PaymentContext.
+ ///
+ /// Payment context codeunit.
+ procedure SetContext(PaymentContext: Codeunit PaymentContext)
+ begin
+ this.PaymentContext := PaymentContext;
+ end;
+
+ ///
+ /// Sets the IDocumentPaymentHandler instance.
+ ///
+ /// IDocumentPaymentHandler implementation used for receiving payment details.
+ procedure SetInstance(PaymentHandler: Interface IDocumentPaymentHandler)
+ begin
+ this.IDocumentPaymentHandler := PaymentHandler;
+ end;
+
+ ///
+ /// Sets the parameters for the payment information receiving.
+ ///
+ /// Electronic document for which payment is received.
+ /// Service for receiving payments.
+ /// TempBlob which contains received payment information.
+ procedure SetParameters(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; PaymentMetadata: Codeunit "Temp Blob")
+ begin
+ this.EDocument.Copy(EDocument);
+ this.EDocumentService.Copy(EDocumentService);
+ this.PaymentMetadata := PaymentMetadata;
+ end;
+
+ var
+ EDocument: Record "E-Document";
+ EDocumentService: Record "E-Document Service";
+ PaymentMetadata: Codeunit "Temp Blob";
+ PaymentContext: Codeunit PaymentContext;
+ IDocumentPaymentHandler: Interface IDocumentPaymentHandler;
+}
diff --git a/Apps/W1/EDocument/app/src/Integration/Payments/Implementations/EmptyPaymentHandler.Codeunit.al b/Apps/W1/EDocument/app/src/Integration/Payments/Implementations/EmptyPaymentHandler.Codeunit.al
new file mode 100644
index 0000000000..8ca1839684
--- /dev/null
+++ b/Apps/W1/EDocument/app/src/Integration/Payments/Implementations/EmptyPaymentHandler.Codeunit.al
@@ -0,0 +1,35 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+namespace Microsoft.eServices.EDocument.Integration.Payments;
+
+using Microsoft.eServices.EDocument;
+using Microsoft.eServices.EDocument.Integration.Interfaces;
+using Microsoft.eServices.EDocument.Payments;
+using System.Utilities;
+
+///
+/// This codeunit is used to provide a default implementation for the "Document Payment Handler" interface.
+///
+codeunit 6105 "Empty Payment Handler" implements IDocumentPaymentHandler
+{
+ Access = Internal;
+ InherentEntitlements = X;
+ InherentPermissions = X;
+
+ procedure Send(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; PaymentContext: Codeunit PaymentContext)
+ begin
+ // This method serves as a placeholder implementation for the IDocumentPaymentHandler interface.
+ end;
+
+ procedure Receive(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var PaymentsMetadata: Codeunit "Temp Blob List"; PaymentContext: Codeunit PaymentContext)
+ begin
+ // This method serves as a placeholder implementation for the IDocumentPaymentHandler interface.
+ end;
+
+ procedure GetDetails(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; PaymentMetadata: Codeunit "Temp Blob"; PaymentContext: Codeunit PaymentContext)
+ begin
+ // This method serves as a placeholder implementation for the IDocumentPaymentHandler interface.
+ end;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocument/app/src/Integration/Payments/PaymentContext.Codeunit.al b/Apps/W1/EDocument/app/src/Integration/Payments/PaymentContext.Codeunit.al
new file mode 100644
index 0000000000..ec3cb5cba7
--- /dev/null
+++ b/Apps/W1/EDocument/app/src/Integration/Payments/PaymentContext.Codeunit.al
@@ -0,0 +1,73 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+namespace Microsoft.eServices.EDocument.Integration.Payments;
+
+using Microsoft.eServices.EDocument.Integration;
+using Microsoft.eServices.EDocument.Payments;
+
+codeunit 6104 PaymentContext
+{
+ ///
+ /// Get the Http Message State codeunit.
+ ///
+ /// codeunit Http Message State that contains http request and response messages.
+ procedure Http(): Codeunit "Http Message State"
+ begin
+ exit(this.HttpMessageState);
+ end;
+
+ ///
+ /// Retrieves the payment date.
+ ///
+ /// Date when the payment was made.
+ procedure GetDate(): Date
+ begin
+ exit(this.Date);
+ end;
+
+ ///
+ /// Retrieves the payment amount.
+ ///
+ /// Amount of the payment.
+ procedure GetAmount(): Decimal
+ begin
+ exit(this.Amount);
+ end;
+
+ ///
+ /// Sets the payment date and amount.
+ ///
+ /// Date when the payment was made.
+ /// Amount of the payment.
+ procedure SetPaymentInformation(Date: Date; Amount: Decimal)
+ begin
+ this.Date := Date;
+ this.Amount := Amount;
+ end;
+
+ ///
+ /// Retrieves the payment status.
+ ///
+ /// Current payment status.
+ procedure GetPaymentStatus(): Enum "Payment Status"
+ begin
+ exit(this.PaymentStatus);
+ end;
+
+ ///
+ /// Sets the payment status.
+ ///
+ /// New payment status.
+ procedure SetPaymentStatus(NewPaymentStatus: Enum "Payment Status")
+ begin
+ this.PaymentStatus := NewPaymentStatus;
+ end;
+
+ var
+ HttpMessageState: Codeunit "Http Message State";
+ PaymentStatus: Enum "Payment Status";
+ Date: Date;
+ Amount: Decimal;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocument/app/src/Integration/Payments/PaymentIntegration.Enum.al b/Apps/W1/EDocument/app/src/Integration/Payments/PaymentIntegration.Enum.al
new file mode 100644
index 0000000000..89c3f23781
--- /dev/null
+++ b/Apps/W1/EDocument/app/src/Integration/Payments/PaymentIntegration.Enum.al
@@ -0,0 +1,19 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+namespace Microsoft.eServices.EDocument.Integration.Payments;
+
+using Microsoft.eServices.EDocument.Integration.Interfaces;
+
+enum 6105 "Payment Integration" implements IDocumentPaymentHandler
+{
+ Extensible = true;
+ Access = Public;
+
+ value(0; "No Integration")
+ {
+ Caption = 'No Integration';
+ Implementation = IDocumentPaymentHandler = "Empty Payment Handler";
+ }
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocument/app/src/Integration/Payments/PaymentIntegrationManagement.Codeunit.al b/Apps/W1/EDocument/app/src/Integration/Payments/PaymentIntegrationManagement.Codeunit.al
new file mode 100644
index 0000000000..e0e6821980
--- /dev/null
+++ b/Apps/W1/EDocument/app/src/Integration/Payments/PaymentIntegrationManagement.Codeunit.al
@@ -0,0 +1,129 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+namespace Microsoft.eServices.EDocument.Integration.Payments;
+
+using System.Utilities;
+using Microsoft.eServices.EDocument;
+using Microsoft.eServices.EDocument.Payments;
+using Microsoft.eServices.EDocument.Integration.Interfaces;
+
+codeunit 6117 "Payment Integration Management"
+{
+ internal procedure ReceivePayments(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; PaymentContext: Codeunit PaymentContext)
+ var
+ PaymentMetadata: Codeunit "Temp Blob";
+ PaymentsMetadata: Codeunit "Temp Blob List";
+ IDocumentPaymentHandler: Interface IDocumentPaymentHandler;
+ Index: Integer;
+ begin
+ IDocumentPaymentHandler := EDocumentService."Payment Integration";
+ this.RunReceivePayments(EDocument, EDocumentService, PaymentsMetadata, IDocumentPaymentHandler, PaymentContext);
+
+ if PaymentsMetadata.IsEmpty() then
+ exit;
+
+ for Index := 1 to PaymentsMetadata.Count() do begin
+ PaymentsMetadata.Get(Index, PaymentMetadata);
+ this.ReceivePaymentDetails(EDocument, EDocumentService, PaymentMetadata, IDocumentPaymentHandler);
+ end;
+ end;
+
+ internal procedure SendPayments(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; PaymentContext: Codeunit PaymentContext)
+ var
+ Payment: Record "E-Document Payment";
+ begin
+ Payment.SetRange("E-Document Entry No.", EDocument."Entry No");
+ Payment.SetFilter(Status, '%1|%2', Payment.Status::Created, Payment.Status::"Sending Error");
+
+ if not Payment.FindSet() then
+ exit;
+
+ repeat
+ this.SendPayment(EDocument, EDocumentService, Payment);
+ until Payment.Next() = 0;
+ end;
+
+ local procedure RunReceivePayments(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; Payments: Codeunit "Temp Blob List"; IDocumentPaymentHandler: Interface IDocumentPaymentHandler; PaymentContext: Codeunit PaymentContext)
+ var
+ ReceivePayments: Codeunit "Receive Payments";
+ begin
+ // Commit needed for "if codeunit run" pattern when catching errors.
+ Commit();
+
+ ReceivePayments.SetInstance(IDocumentPaymentHandler);
+ ReceivePayments.SetService(EDocumentService);
+ ReceivePayments.SetDocument(EDocument);
+ ReceivePayments.SetContext(PaymentContext);
+ ReceivePayments.SetPayments(Payments);
+ if not ReceivePayments.Run() then
+ this.EDocumentErrorHelper.LogErrorMessage(EDocument, Database::"E-Document Payment", EDocument.FieldNo("Paid Amount"), StrSubstNo(this.PaymentReceiveErr, GetLastErrorText()));
+ end;
+
+ local procedure ReceivePaymentDetails(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; PaymentMetadata: Codeunit "Temp Blob"; IDocumentPaymentHandler: Interface IDocumentPaymentHandler)
+ var
+ Payment: Record "E-Document Payment";
+ PaymentContext: Codeunit PaymentContext;
+ begin
+ PaymentContext.SetPaymentStatus("Payment Status"::Received);
+
+ this.RunGetPaymentDetails(EDocument, EDocumentService, PaymentMetadata, IDocumentPaymentHandler, PaymentContext);
+
+ if (PaymentContext.GetAmount() = 0) or (PaymentContext.GetDate() = 0D) then
+ exit;
+
+ Payment.Init();
+ Payment.Validate("E-Document Entry No.", EDocument."Entry No");
+ Payment.Date := PaymentContext.GetDate();
+ Payment.Validate(Amount, PaymentContext.GetAmount());
+ Payment.Status := PaymentContext.GetPaymentStatus();
+ Payment.Insert(true);
+ end;
+
+ local procedure RunGetPaymentDetails(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; PaymentMetadata: Codeunit "Temp Blob"; IDocumentPaymentHandler: Interface IDocumentPaymentHandler; PaymentContext: Codeunit PaymentContext): Boolean
+ var
+ GetPaymentDetails: Codeunit "Get Payment Details";
+ begin
+ // Commit needed for "if codeunit run" pattern when catching errors.
+ Commit();
+
+ GetPaymentDetails.SetInstance(IDocumentPaymentHandler);
+ GetPaymentDetails.SetContext(PaymentContext);
+ GetPaymentDetails.SetParameters(EDocument, EDocumentService, PaymentMetadata);
+ if not GetPaymentDetails.Run() then
+ this.EDocumentErrorHelper.LogErrorMessage(EDocument, Database::"E-Document Payment", EDocument.FieldNo("Paid Amount"), StrSubstNo(this.PaymentReceiveErr, GetLastErrorText()));
+ end;
+
+ local procedure SendPayment(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; Payment: Record "E-Document Payment")
+ var
+ PaymentContext: Codeunit PaymentContext;
+ begin
+ PaymentContext.SetPaymentStatus("Payment Status"::Sent);
+
+ this.RunSendPayment(EDocument, EDocumentService, Payment, EDocumentService."Payment Integration", PaymentContext);
+
+ Payment.Status := PaymentContext.GetPaymentStatus();
+ Payment.Modify(false);
+ end;
+
+ local procedure RunSendPayment(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; Payment: Record "E-Document Payment"; IDocumentPaymentHandler: Interface IDocumentPaymentHandler; PaymentContext: Codeunit PaymentContext): Boolean
+ var
+ SendPayment: Codeunit "Send Payment";
+ begin
+ // Commit needed for "if codeunit run" pattern when catching errors.
+ Commit();
+
+ SendPayment.SetInstance(IDocumentPaymentHandler);
+ SendPayment.SetDocumentAndService(EDocument, EDocumentService);
+ SendPayment.SetContext(PaymentContext);
+
+ if not SendPayment.Run() then
+ this.EDocumentErrorHelper.LogErrorMessage(EDocument, Payment, EDocument.FieldNo("Paid Amount"), StrSubstNo(this.PaymentSendErr, GetLastErrorText()));
+ end;
+
+ var
+ EDocumentErrorHelper: Codeunit "E-Document Error Helper";
+ PaymentSendErr: Label 'Sending payments for this document failed with error: %1', Comment = '%1 - error message';
+ PaymentReceiveErr: Label 'Receiving payments for this document failed with error: %1', Comment = '%1 - error message';
+}
diff --git a/Apps/W1/EDocument/app/src/Integration/Payments/ReceivePayments.Codeunit.al b/Apps/W1/EDocument/app/src/Integration/Payments/ReceivePayments.Codeunit.al
new file mode 100644
index 0000000000..1770e9fc28
--- /dev/null
+++ b/Apps/W1/EDocument/app/src/Integration/Payments/ReceivePayments.Codeunit.al
@@ -0,0 +1,74 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+namespace Microsoft.eServices.EDocument.Integration.Payments;
+
+using System.Utilities;
+using Microsoft.eServices.EDocument;
+using Microsoft.eServices.EDocument.Integration.Interfaces;
+
+codeunit 6106 "Receive Payments"
+{
+ Access = Internal;
+ InherentEntitlements = X;
+ InherentPermissions = X;
+
+ trigger OnRun()
+ begin
+ this.EDocumentService.TestField(Code);
+ this.IDocumentPaymentHandler.Receive(this.EDocument, this.EDocumentService, this.PaymentsMetadata, this.PaymentContext);
+ end;
+
+ ///
+ /// Sets the IDocumentPaymentHandler instance.
+ ///
+ /// IDocumentPaymentHandler implementation used for receiving payments.
+ procedure SetInstance(PaymentHandler: Interface IDocumentPaymentHandler)
+ begin
+ this.IDocumentPaymentHandler := PaymentHandler;
+ end;
+
+ ///
+ /// Sets the global variable PaymentContext.
+ ///
+ /// Payment context codeunit.
+ procedure SetContext(PaymentContext: Codeunit PaymentContext)
+ begin
+ this.PaymentContext := PaymentContext;
+ end;
+
+ ///
+ /// Sets the received payments to Temp Blob List.
+ ///
+ /// Temp Blob List to save received payments.
+ procedure SetPayments(PaymentsMetadata: Codeunit "Temp Blob List")
+ begin
+ this.PaymentsMetadata := PaymentsMetadata
+ end;
+
+ ///
+ /// Sets the E-Document Service used for receiving payments.
+ ///
+ /// Service for receiving payments.
+ procedure SetService(var EDocumentService: Record "E-Document Service")
+ begin
+ this.EDocumentService.Copy(EDocumentService);
+ end;
+
+ ///
+ /// Sets the E-Document for which payments are received.
+ ///
+ /// E-Document for which payments are received.
+ procedure SetDocument(var EDocument: Record "E-Document")
+ begin
+ this.EDocument.Copy(EDocument);
+ end;
+
+ var
+ EDocument: Record "E-Document";
+ EDocumentService: Record "E-Document Service";
+ PaymentsMetadata: Codeunit "Temp Blob List";
+ PaymentContext: Codeunit PaymentContext;
+ IDocumentPaymentHandler: Interface IDocumentPaymentHandler;
+}
diff --git a/Apps/W1/EDocument/app/src/Integration/Payments/SendPayment.Codeunit.al b/Apps/W1/EDocument/app/src/Integration/Payments/SendPayment.Codeunit.al
new file mode 100644
index 0000000000..a4f3a5e55d
--- /dev/null
+++ b/Apps/W1/EDocument/app/src/Integration/Payments/SendPayment.Codeunit.al
@@ -0,0 +1,57 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+namespace Microsoft.eServices.EDocument.Integration.Payments;
+
+using Microsoft.eServices.EDocument;
+using Microsoft.eServices.EDocument.Integration.Interfaces;
+using Microsoft.eServices.EDocument.Payments;
+
+codeunit 6116 "Send Payment"
+{
+ Access = Internal;
+ InherentEntitlements = X;
+ InherentPermissions = X;
+
+ trigger OnRun()
+ begin
+ this.EDocumentService.TestField(Code);
+ this.IPaymentHandler.Send(this.EDocument, this.EDocumentService, this.PaymentContext);
+ end;
+
+ ///
+ /// Sets the IDocumentPaymentHandler instance.
+ ///
+ /// IDocumentPaymentHandler implementation used for sending payments.
+ procedure SetInstance(PaymentHandler: Interface IDocumentPaymentHandler)
+ begin
+ this.IPaymentHandler := PaymentHandler;
+ end;
+
+ ///
+ /// Sets the global variable PaymentContext.
+ ///
+ /// Payment context codeunit.
+ procedure SetContext(PaymentContext: Codeunit PaymentContext)
+ begin
+ this.PaymentContext := PaymentContext;
+ end;
+
+ ///
+ /// Sets the parameters for the payment handler.
+ ///
+ /// Electronic document for which payments are sent.
+ /// Service for sending payments.
+ procedure SetDocumentAndService(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service")
+ begin
+ this.EDocument.Copy(EDocument);
+ this.EDocumentService.Copy(EDocumentService);
+ end;
+
+ var
+ EDocument: Record "E-Document";
+ EDocumentService: Record "E-Document Service";
+ PaymentContext: Codeunit PaymentContext;
+ IPaymentHandler: Interface IDocumentPaymentHandler;
+}
diff --git a/Apps/W1/EDocument/app/src/Integration/Payments/SyncPaymentsJob.Codeunit.al b/Apps/W1/EDocument/app/src/Integration/Payments/SyncPaymentsJob.Codeunit.al
new file mode 100644
index 0000000000..24ebeb9b07
--- /dev/null
+++ b/Apps/W1/EDocument/app/src/Integration/Payments/SyncPaymentsJob.Codeunit.al
@@ -0,0 +1,51 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+namespace Microsoft.eServices.EDocument.Integration.Payments;
+
+using System.Threading;
+using Microsoft.eServices.EDocument;
+
+codeunit 6119 "Sync Payments Job"
+{
+ Access = Internal;
+ TableNo = "Job Queue Entry";
+
+ trigger OnRun()
+ var
+ EDocument: Record "E-Document";
+ EDocumentService: Record "E-Document Service";
+ EDocumentServiceStatus: Record "E-Document Service Status";
+ begin
+ EDocumentService.Get(Rec."Record ID to Process");
+ if EDocumentService."Payment Integration" = EDocumentService."Payment Integration"::"No Integration" then
+ exit;
+
+ EDocumentServiceStatus.SetRange("E-Document Service Code", EDocumentService."Code");
+ if EDocumentServiceStatus.FindSet() then
+ repeat
+ EDocument.Get(EDocumentServiceStatus."E-Document Entry No");
+ if EDocument."Direction" = EDocument.Direction::Incoming then
+ this.SendPayments(EDocument, EDocumentService)
+ else
+ this.ReceivePayments(EDocument, EDocumentService);
+ until EDocumentServiceStatus.Next() = 0;
+ end;
+
+ local procedure SendPayments(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service")
+ var
+ PaymentContext: Codeunit PaymentContext;
+ PaymentIntegrationManagement: Codeunit "Payment Integration Management";
+ begin
+ PaymentIntegrationManagement.SendPayments(EDocument, EDocumentService, PaymentContext);
+ end;
+
+ local procedure ReceivePayments(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service")
+ var
+ PaymentContext: Codeunit PaymentContext;
+ PaymentIntegrationManagement: Codeunit "Payment Integration Management";
+ begin
+ PaymentIntegrationManagement.ReceivePayments(EDocument, EDocumentService, PaymentContext);
+ end;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocument/app/src/Payments/EDocumentPayment.Table.al b/Apps/W1/EDocument/app/src/Payments/EDocumentPayment.Table.al
new file mode 100644
index 0000000000..3e3573d1a8
--- /dev/null
+++ b/Apps/W1/EDocument/app/src/Payments/EDocumentPayment.Table.al
@@ -0,0 +1,113 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+namespace Microsoft.eServices.EDocument.Payments;
+
+using Microsoft.eServices.EDocument;
+
+table 6101 "E-Document Payment"
+{
+ Caption = 'E-Document Payment';
+ DataClassification = CustomerContent;
+ DrillDownPageId = "E-Document Payments";
+ LookupPageId = "E-Document Payments";
+
+ fields
+ {
+ field(1; "E-Document Entry No."; Integer)
+ {
+ Caption = 'E-Document Entry No.';
+ TableRelation = "E-Document"."Entry No";
+ AllowInCustomizations = Always;
+
+ trigger OnValidate()
+ begin
+ this.SetPaymentDirection();
+ end;
+ }
+ field(2; "Payment No."; Integer)
+ {
+ Caption = 'Payment No.';
+ AutoIncrement = true;
+ AllowInCustomizations = Always;
+ }
+ field(20; Date; Date)
+ {
+ Caption = 'Date';
+ ToolTip = 'Specifies the date when the payment was made.';
+ }
+ field(21; Amount; Decimal)
+ {
+ Caption = 'Amount';
+ DecimalPlaces = 2;
+ ToolTip = 'Specifies the total payment amount including VAT.';
+
+ trigger OnValidate()
+ begin
+ this.CalculateVAT();
+ end;
+ }
+ field(22; "VAT Base"; Decimal)
+ {
+ Caption = 'VAT Base';
+ DecimalPlaces = 2;
+ Editable = false;
+ ToolTip = 'Specifies the net amount used as basis for VAT calculation for this payment transaction.';
+ }
+ field(23; "VAT Amount"; Decimal)
+ {
+ Caption = 'VAT Amount';
+ DecimalPlaces = 2;
+ Editable = false;
+ ToolTip = 'Specifies the calculated tax amount for this payment transaction.';
+ }
+ field(24; Status; Enum "Payment Status")
+ {
+ Caption = 'Status';
+ Editable = false;
+ InitValue = Created;
+ ToolTip = 'Specifies the current state of the payment.';
+ }
+ field(25; Direction; Enum "E-Document Direction")
+ {
+ Caption = 'Direction';
+ Editable = false;
+ ToolTip = 'Specifies whether this payment is being received (incoming) or sent (outgoing).';
+ }
+ }
+
+ keys
+ {
+ key(PK; "E-Document Entry No.", "Payment No.")
+ {
+ Clustered = true;
+ }
+ }
+
+ local procedure CalculateVAT()
+ var
+ EDocument: Record "E-Document";
+ EDocumentService: Record "E-Document Service";
+ EDocLog: Codeunit "E-Document Log";
+ begin
+ EDocument.Get(Rec."E-Document Entry No.");
+ EDocumentService := EDocLog.GetLastServiceFromLog(EDocument);
+ if not EDocumentService."Calculate Payment VAT" then
+ exit;
+
+ Rec."VAT Base" := Rec.Amount / (EDocument."Amount Incl. VAT" / EDocument."Amount Excl. VAT");
+ Rec."VAT Amount" := Rec.Amount - Rec."VAT Base";
+ end;
+
+ local procedure SetPaymentDirection()
+ var
+ EDocument: Record "E-Document";
+ begin
+ EDocument.Get(Rec."E-Document Entry No.");
+ if EDocument.Direction = EDocument.Direction::Outgoing then
+ Rec.Direction := Rec.Direction::Incoming
+ else
+ Rec.Direction := Rec.Direction::Outgoing;
+ end;
+}
\ No newline at end of file
diff --git a/Apps/W1/EDocument/app/src/Payments/EDocumentPaymentProgress.Enum.al b/Apps/W1/EDocument/app/src/Payments/EDocumentPaymentProgress.Enum.al
new file mode 100644
index 0000000000..122d29a77f
--- /dev/null
+++ b/Apps/W1/EDocument/app/src/Payments/EDocumentPaymentProgress.Enum.al
@@ -0,0 +1,27 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+namespace Microsoft.eServices.EDocument.Payments;
+
+enum 6104 "E-Document Payment Progress"
+{
+ Extensible = false;
+
+ value(0; " ")
+ {
+ Caption = ' ';
+ }
+ value(1; "Not Paid")
+ {
+ Caption = 'Not Paid';
+ }
+ value(2; "Partially Paid")
+ {
+ Caption = 'Partially Paid';
+ }
+ value(3; Paid)
+ {
+ Caption = 'Paid In Full';
+ }
+}
diff --git a/Apps/W1/EDocument/app/src/Payments/EDocumentPayments.Page.al b/Apps/W1/EDocument/app/src/Payments/EDocumentPayments.Page.al
new file mode 100644
index 0000000000..6953951c15
--- /dev/null
+++ b/Apps/W1/EDocument/app/src/Payments/EDocumentPayments.Page.al
@@ -0,0 +1,54 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+namespace Microsoft.eServices.EDocument.Payments;
+
+page 6101 "E-Document Payments"
+{
+ ApplicationArea = All;
+ Caption = 'E-Document Payments';
+ PageType = List;
+ SourceTable = "E-Document Payment";
+ UsageCategory = Lists;
+
+ layout
+ {
+ area(Content)
+ {
+ repeater(General)
+ {
+ field(Date; Rec.Date)
+ {
+ Editable = this.PaymentEditable;
+ }
+ field(Amount; Rec.Amount)
+ {
+ Editable = this.PaymentEditable;
+ }
+ field("VAT Base"; Rec."VAT Base")
+ {
+ Visible = false;
+ }
+ field("VAT Amount"; Rec."VAT Amount")
+ {
+ Visible = false;
+ }
+ field(Status; Rec.Status)
+ {
+ }
+ field(Direction; Rec.Direction)
+ {
+ }
+ }
+ }
+ }
+
+ var
+ PaymentEditable: Boolean;
+
+ trigger OnAfterGetRecord()
+ begin
+ this.PaymentEditable := Rec.Status <> Rec.Status::Sent;
+ end;
+}
diff --git a/Apps/W1/EDocument/app/src/Payments/PaymentStatus.Enum.al b/Apps/W1/EDocument/app/src/Payments/PaymentStatus.Enum.al
new file mode 100644
index 0000000000..ef7ad64afe
--- /dev/null
+++ b/Apps/W1/EDocument/app/src/Payments/PaymentStatus.Enum.al
@@ -0,0 +1,31 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+namespace Microsoft.eServices.EDocument.Payments;
+
+enum 6103 "Payment Status"
+{
+ Extensible = false;
+
+ value(0; " ")
+ {
+ Caption = ' ';
+ }
+ value(1; Created)
+ {
+ Caption = 'Created';
+ }
+ value(2; Sent)
+ {
+ Caption = 'Sent';
+ }
+ value(3; Received)
+ {
+ Caption = 'Received';
+ }
+ value(4; "Sending Error")
+ {
+ Caption = 'Sending Error';
+ }
+}
diff --git a/Apps/W1/EDocument/app/src/Processing/EDocumentBackgroundJobs.Codeunit.al b/Apps/W1/EDocument/app/src/Processing/EDocumentBackgroundJobs.Codeunit.al
index d688b52eec..33a62d2a04 100644
--- a/Apps/W1/EDocument/app/src/Processing/EDocumentBackgroundJobs.Codeunit.al
+++ b/Apps/W1/EDocument/app/src/Processing/EDocumentBackgroundJobs.Codeunit.al
@@ -6,6 +6,7 @@ namespace Microsoft.eServices.EDocument;
using System.Telemetry;
using System.Threading;
+using Microsoft.eServices.EDocument.Integration.Payments;
codeunit 6133 "E-Document Background Jobs"
{
@@ -104,6 +105,39 @@ codeunit 6133 "E-Document Background Jobs"
Telemetry.LogMessage('0000LC5', EDocumentJobTelemetryLbl, Verbosity::Normal, DataClassification::OrganizationIdentifiableInformation, TelemetryScope::All, TelemetryDimensions);
end;
+ procedure ScheduleRecurrentPaymentSyncJob(var EDocumentService: Record "E-Document Service")
+ var
+ JobQueueEntry: Record "Job Queue Entry";
+ begin
+ if EDocumentService.Code = '' then
+ exit;
+
+ if not this.IsRecurrentJobScheduledForAService(EDocumentService."Payment Sync Recurrent Job Id") then begin
+ JobQueueEntry.ScheduleRecurrentJobQueueEntryWithFrequency(
+ JobQueueEntry."Object Type to Run"::Codeunit,
+ Codeunit::"Sync Payments Job",
+ EDocumentService.RecordId,
+ EDocumentService."Payment Sync Min between runs",
+ EDocumentService."Payment Sync Start Time");
+
+ EDocumentService."Payment Sync Recurrent Job Id" := JobQueueEntry.ID;
+ EDocumentService.Modify(false);
+
+ JobQueueEntry."Rerun Delay (sec.)" := 600;
+ JobQueueEntry."No. of Attempts to Run" := 0;
+ JobQueueEntry."Job Queue Category Code" := this.JobQueueCategoryTok;
+ JobQueueEntry.Modify(false);
+ end else begin
+ JobQueueEntry.Get(EDocumentService."Payment Sync Recurrent Job Id");
+ JobQueueEntry."Starting Time" := EDocumentService."Payment Sync Start Time";
+ JobQueueEntry."No. of Minutes between Runs" := EDocumentService."Payment Sync Min between runs";
+ JobQueueEntry."No. of Attempts to Run" := 0;
+ JobQueueEntry.Modify(false);
+ if not JobQueueEntry.IsReadyToStart() then
+ JobQueueEntry.Restart();
+ end;
+ end;
+
procedure HandleRecurrentBatchJob(var EDocumentService: Record "E-Document Service")
begin
if (EDocumentService."Use Batch Processing") and (EDocumentService."Batch Mode" = EDocumentService."Batch Mode"::Recurrent) then begin
@@ -124,6 +158,16 @@ codeunit 6133 "E-Document Background Jobs"
RemoveJob(EDocumentService."Import Recurrent Job Id");
end;
+ procedure HandleRecurrentPaymentSyncJob(var EDocumentService: Record "E-Document Service")
+ begin
+ if EDocumentService."Auto Sync Payments" then begin
+ EDocumentService.TestField("Payment Sync Start Time");
+ EDocumentService.TestField("Payment Sync Min between runs");
+ this.ScheduleRecurrentPaymentSyncJob(EDocumentService);
+ end else
+ this.RemoveJob(EDocumentService."Payment Sync Recurrent Job Id");
+ end;
+
procedure RemoveJob(JobId: Guid)
var
JobQueueEntry: Record "Job Queue Entry";
diff --git a/Apps/W1/EDocument/app/src/Service/EDocumentService.Table.al b/Apps/W1/EDocument/app/src/Service/EDocumentService.Table.al
index 7f152dd481..cd99201a77 100644
--- a/Apps/W1/EDocument/app/src/Service/EDocumentService.Table.al
+++ b/Apps/W1/EDocument/app/src/Service/EDocumentService.Table.al
@@ -6,6 +6,7 @@ namespace Microsoft.eServices.EDocument;
using Microsoft.Finance.GeneralLedger.Journal;
using System.Privacy;
+using Microsoft.eServices.EDocument.Integration.Payments;
using Microsoft.eServices.EDocument.Integration;
using Microsoft.eServices.EDocument.Integration.Action;
@@ -251,6 +252,50 @@ table 6103 "E-Document Service"
ToolTip = 'Specifies the implementation of actions that can be performed after the document is sent to the service.';
DataClassification = SystemMetadata;
}
+ field(29; "Payment Integration"; Enum "Payment Integration")
+ {
+ Caption = 'Payment Integration';
+ ToolTip = 'Specifies the integration for sending and receiving payments from the service.';
+ DataClassification = SystemMetadata;
+ }
+ field(30; "Calculate Payment VAT"; Boolean)
+ {
+ Caption = 'Calculate Payment VAT';
+ ToolTip = 'Specifies whether the VAT amount should be calculated for the payment.';
+ DataClassification = SystemMetadata;
+ }
+ field(31; "Auto Sync Payments"; Boolean)
+ {
+ Caption = 'Auto Sync Payments';
+ ToolTip = 'Specifies whether the payments should be automatically synchronized with the service.';
+ DataClassification = SystemMetadata;
+
+ trigger OnValidate()
+ begin
+ this.EDocumentBackgroundJobs.HandleRecurrentPaymentSyncJob(Rec);
+ end;
+ }
+ field(32; "Payment Sync Start Time"; Time)
+ {
+ Caption = 'Sync Start Time';
+ ToolTip = 'Specifies the time when the synchronization should start.';
+ DataClassification = SystemMetadata;
+ NotBlank = true;
+ InitValue = 0T;
+ }
+ field(33; "Payment Sync Min Between Runs"; Integer)
+ {
+ Caption = 'Minutes between runs';
+ ToolTip = 'Specifies the time between synchronization runs.';
+ DataClassification = SystemMetadata;
+ InitValue = 1440;
+ }
+ field(34; "Payment Sync Recurrent Job Id"; Guid)
+ {
+ Caption = 'Sync Recurrent Job Id';
+ ToolTip = 'Specifies the ID of the job that is used for the synchronization.';
+ DataClassification = SystemMetadata;
+ }
}
keys
{
diff --git a/Apps/W1/EDocument/app/src/Service/EdocumentService.Page.al b/Apps/W1/EDocument/app/src/Service/EdocumentService.Page.al
index 76d903cfa8..2427643df4 100644
--- a/Apps/W1/EDocument/app/src/Service/EdocumentService.Page.al
+++ b/Apps/W1/EDocument/app/src/Service/EdocumentService.Page.al
@@ -56,6 +56,14 @@ page 6133 "E-Document Service"
{
ToolTip = 'Specifies integration code for sent e-document actions.';
}
+ field("Payment Integration"; Rec."Payment Integration")
+ {
+ Visible = false;
+ }
+ field("Calculate Payment VAT"; Rec."Calculate Payment VAT")
+ {
+ Visible = false;
+ }
field("Use Batch Processing"; Rec."Use Batch Processing")
{
ToolTip = 'Specifies if service uses batch processing for export.';
@@ -177,6 +185,26 @@ page 6133 "E-Document Service"
}
}
}
+ group(Payment)
+ {
+ Caption = 'Payment Settings';
+ Visible = false;
+
+ field("Auto Sync Payments"; Rec."Auto Sync Payments")
+ {
+ }
+ group(PaymentSyncSettings)
+ {
+ ShowCaption = false;
+ Visible = Rec."Auto Sync Payments";
+ field("Payment Sync Start Time"; Rec."Payment Sync Start Time")
+ {
+ }
+ field("Payment Sync Min between runs"; Rec."Payment Sync Min between runs")
+ {
+ }
+ }
+ }
part(EDocumentDataExchDef; "E-Doc. Service Data Exch. Sub")
{
ApplicationArea = All;
diff --git a/Apps/W1/EDocument/test/src/LibraryEDocument.Codeunit.al b/Apps/W1/EDocument/test/src/LibraryEDocument.Codeunit.al
index f331edeb50..32dfade4d7 100644
--- a/Apps/W1/EDocument/test/src/LibraryEDocument.Codeunit.al
+++ b/Apps/W1/EDocument/test/src/LibraryEDocument.Codeunit.al
@@ -759,6 +759,18 @@ codeunit 139629 "Library - E-Document"
end;
#endif
+ procedure CreateTestPaymentServiceForEDoc(var EDocService: Record "E-Document Service"; ServiceIntegration: Enum "Service Integration"; PaymentIntegration: Enum "Payment Integration")
+ begin
+ if not EDocService.Get('TESTPAYMENT') then begin
+ EDocService.Init();
+ EDocService.Code := 'TESTPAYMENT';
+ EDocService."Document Format" := "E-Document Format"::Mock;
+ EDocService."Service Integration V2" := ServiceIntegration;
+ EDocService."Payment Integration" := PaymentIntegration;
+ EDocService.Insert(true);
+ end;
+ end;
+
procedure CreateDirectMapping(var EDocMapping: Record "E-Doc. Mapping"; EDocService: Record "E-Document Service"; FindValue: Text; ReplaceValue: Text)
begin
CreateDirectMapping(EDocMapping, EDocService, FindValue, ReplaceValue, 0, 0);
diff --git a/Apps/W1/EDocument/test/src/Mock/EDocPaymentImplState.Codeunit.al b/Apps/W1/EDocument/test/src/Mock/EDocPaymentImplState.Codeunit.al
new file mode 100644
index 0000000000..7373225eb2
--- /dev/null
+++ b/Apps/W1/EDocument/test/src/Mock/EDocPaymentImplState.Codeunit.al
@@ -0,0 +1,28 @@
+codeunit 139503 "E-Doc. Payment Impl. State"
+{
+ EventSubscriberInstance = Manual;
+
+ [EventSubscriber(ObjectType::Codeunit, Codeunit::"E-Doc Payment Integration Mock", 'OnSendPayment', '', false, false)]
+ local procedure OnSendPayment(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; PaymentContext: Codeunit PaymentContext)
+ begin
+ end;
+
+ [EventSubscriber(ObjectType::Codeunit, Codeunit::"E-Doc Payment Integration Mock", 'OnReceivePayment', '', false, false)]
+ local procedure OnReceivePayment(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var PaymentsMetadata: Codeunit "Temp Blob List"; PaymentContext: Codeunit PaymentContext)
+ var
+ TempBlob: Codeunit "Temp Blob";
+ PaymentText: Text;
+ OutStream: OutStream;
+ begin
+ PaymentText := '{"PaymentId": "123456"}';
+ TempBlob.CreateOutStream(OutStream);
+ OutStream.Write(PaymentText);
+ PaymentsMetadata.Add(TempBlob);
+ end;
+
+ [EventSubscriber(ObjectType::Codeunit, Codeunit::"E-Doc Payment Integration Mock", 'OnGetPaymentDetails', '', false, false)]
+ local procedure OnGetPaymentDetails(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; PaymentMetadata: Codeunit "Temp Blob"; PaymentContext: Codeunit PaymentContext)
+ begin
+ PaymentContext.SetPaymentInformation(Today(), 1);
+ end;
+}
diff --git a/Apps/W1/EDocument/test/src/Mock/EDocPaymentIntegrationMock.Codeunit.al b/Apps/W1/EDocument/test/src/Mock/EDocPaymentIntegrationMock.Codeunit.al
new file mode 100644
index 0000000000..52757ea95a
--- /dev/null
+++ b/Apps/W1/EDocument/test/src/Mock/EDocPaymentIntegrationMock.Codeunit.al
@@ -0,0 +1,34 @@
+codeunit 139502 "E-Doc Payment Integration Mock" implements IDocumentPaymentHandler
+{
+ Access = Internal;
+
+ procedure Send(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; PaymentContext: Codeunit PaymentContext)
+ begin
+ OnSendPayment(EDocument, EDocumentService, PaymentContext);
+ end;
+
+ procedure Receive(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var PaymentsMetadata: Codeunit "Temp Blob List"; PaymentContext: Codeunit PaymentContext)
+ begin
+ OnReceivePayment(EDocument, EDocumentService, PaymentsMetadata, PaymentContext);
+ end;
+
+ procedure GetDetails(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; PaymentMetadata: Codeunit "Temp Blob"; PaymentContext: Codeunit PaymentContext)
+ begin
+ OnGetPaymentDetails(EDocument, EDocumentService, PaymentMetadata, PaymentContext);
+ end;
+
+ [IntegrationEvent(false, false)]
+ procedure OnSendPayment(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; PaymentContext: Codeunit PaymentContext)
+ begin
+ end;
+
+ [IntegrationEvent(false, false)]
+ procedure OnReceivePayment(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var PaymentsMetadata: Codeunit "Temp Blob List"; PaymentContext: Codeunit PaymentContext)
+ begin
+ end;
+
+ [IntegrationEvent(false, false)]
+ procedure OnGetPaymentDetails(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; PaymentMetadata: Codeunit "Temp Blob"; PaymentContext: Codeunit PaymentContext)
+ begin
+ end;
+}
diff --git a/Apps/W1/EDocument/test/src/Mock/EDocPaymentIntegrationMock.EnumExt.al b/Apps/W1/EDocument/test/src/Mock/EDocPaymentIntegrationMock.EnumExt.al
new file mode 100644
index 0000000000..d80d5cf13f
--- /dev/null
+++ b/Apps/W1/EDocument/test/src/Mock/EDocPaymentIntegrationMock.EnumExt.al
@@ -0,0 +1,8 @@
+enumextension 139501 "E-Doc Payment Integration Mock" extends "Payment Integration"
+{
+ value(139500; Mock)
+ {
+ Caption = 'Mock';
+ Implementation = IDocumentPaymentHandler = "E-Doc Payment Integration Mock";
+ }
+}
diff --git a/Apps/W1/EDocument/test/src/Payments/EDocPaymentTest.Codeunit.al b/Apps/W1/EDocument/test/src/Payments/EDocPaymentTest.Codeunit.al
new file mode 100644
index 0000000000..1cba85a023
--- /dev/null
+++ b/Apps/W1/EDocument/test/src/Payments/EDocPaymentTest.Codeunit.al
@@ -0,0 +1,366 @@
+codeunit 139501 "E-Doc. Payment Test"
+{
+ Subtype = Test;
+ TestPermissions = Disabled;
+
+ var
+ Customer: Record "Customer";
+ EDocService: Record "E-Document Service";
+ PurchaseHeader: Record "Purchase Header";
+ PurchaseLine: Record "Purchase Line";
+ Vendor: Record Vendor;
+ Assert: Codeunit "Assert";
+ EDocExportMgt: Codeunit "E-Doc. Export";
+ EDocImplState: Codeunit "E-Doc. Impl. State";
+ EDocLogTest: Codeunit "E-Doc Log Test";
+ EDocPaymentImplState: Codeunit "E-Doc. Payment Impl. State";
+ LibraryEDoc: Codeunit "Library - E-Document";
+ LibraryPurchase: Codeunit "Library - Purchase";
+ LibraryRandom: Codeunit "Library - Random";
+ LibraryInventory: Codeunit "Library - Inventory";
+ PurchOrderTestBuffer: Codeunit "E-Doc. Test Buffer";
+
+ //Create partial payment
+ [Test]
+ procedure CreateOutgoingPartialPaymentTest()
+ var
+ EDocument: Record "E-Document";
+ EDocServicePage: TestPage "E-Document Service";
+ PaymentAmount: Decimal;
+ i: Integer;
+ begin
+ // [FEATURE] [E-Document]
+ // [SCENARIO] Create partial payment for received E-Document
+ this.Initialize();
+
+ // [GIVEN] Create E-Document service setup
+ this.LibraryEDoc.CreateTestPaymentServiceForEDoc(this.EDocService, Enum::"Service Integration"::Mock, Enum::"Payment Integration"::Mock);
+ this.SetDefaultEDocServiceValues(this.EDocService, false);
+ BindSubscription(this.EDocImplState);
+
+ // [GIVEN] Create received E-Document
+ this.LibraryPurchase.CreateVendorWithAddress(this.Vendor);
+ this.Vendor."Receive E-Document To" := this.Vendor."Receive E-Document To"::"Purchase Invoice";
+ this.Vendor.Modify();
+ this.LibraryPurchase.CreatePurchHeader(this.PurchaseHeader, this.PurchaseHeader."Document Type"::Invoice, this.Vendor."No.");
+
+ for i := 1 to 3 do begin
+ this.LibraryPurchase.CreatePurchaseLine(this.PurchaseLine, this.PurchaseHeader, this.PurchaseLine.Type::Item, this.LibraryInventory.CreateItemNo(), this.LibraryRandom.RandInt(100));
+ this.PurchaseLine.Validate("Direct Unit Cost", this.LibraryRandom.RandDecInRange(1, 100, 2));
+ this.PurchaseLine.Modify(true);
+ end;
+
+ this.PurchOrderTestBuffer.ClearTempVariables();
+ this.PurchOrderTestBuffer.AddPurchaseDocToTemp(this.PurchaseHeader);
+
+ // [WHEN] Running Receive
+ EDocServicePage.OpenView();
+ EDocServicePage.Filter.SetFilter(Code, this.EDocService.Code);
+ EDocServicePage.Receive.Invoke();
+ UnbindSubscription(this.EDocImplState);
+
+ // [THEN] Purchase invoice is created with corresponding values
+ EDocument.FindLast();
+
+ // [THEN] Check that Paid Amount for the document is 0
+ this.CheckPaidAmount(EDocument, 0);
+
+ // [GIVEN] Create partial payment for E-Document
+ PaymentAmount := 100;
+ this.CreateEDocumentPayment(EDocument, PaymentAmount);
+
+ // [THEN] Check that Paid Amount for the document is updated
+ this.CheckPaidAmount(EDocument, PaymentAmount);
+
+ // [THEN] Check that Payments Direction is correct
+ this.CheckPaymentDirection(EDocument, Enum::"E-Document Direction"::Outgoing);
+ end;
+
+ //Create full payment
+ [Test]
+ procedure CreateOutgoingFullPaymentTest()
+ var
+ EDocument: Record "E-Document";
+ EDocServicePage: TestPage "E-Document Service";
+ i: Integer;
+ begin
+ // [FEATURE] [E-Document]
+ // [SCENARIO] Send payment for received E-Document
+ this.Initialize();
+
+ // [GIVEN] Create E-Document service setup
+ this.LibraryEDoc.CreateTestPaymentServiceForEDoc(this.EDocService, Enum::"Service Integration"::Mock, Enum::"Payment Integration"::Mock);
+ this.SetDefaultEDocServiceValues(this.EDocService, false);
+ BindSubscription(this.EDocImplState);
+
+ // [GIVEN] Create received E-Document
+ this.LibraryPurchase.CreateVendorWithAddress(this.Vendor);
+ this.Vendor."Receive E-Document To" := this.Vendor."Receive E-Document To"::"Purchase Invoice";
+ this.Vendor.Modify();
+ this.LibraryPurchase.CreatePurchHeader(this.PurchaseHeader, this.PurchaseHeader."Document Type"::Invoice, this.Vendor."No.");
+
+ for i := 1 to 3 do begin
+ this.LibraryPurchase.CreatePurchaseLine(this.PurchaseLine, this.PurchaseHeader, this.PurchaseLine.Type::Item, this.LibraryInventory.CreateItemNo(), this.LibraryRandom.RandInt(100));
+ this.PurchaseLine.Validate("Direct Unit Cost", this.LibraryRandom.RandDecInRange(1, 100, 2));
+ this.PurchaseLine.Modify(true);
+ end;
+
+ this.PurchOrderTestBuffer.ClearTempVariables();
+ this.PurchOrderTestBuffer.AddPurchaseDocToTemp(this.PurchaseHeader);
+
+ // [WHEN] Running Receive
+ EDocServicePage.OpenView();
+ EDocServicePage.Filter.SetFilter(Code, this.EDocService.Code);
+ EDocServicePage.Receive.Invoke();
+ UnbindSubscription(this.EDocImplState);
+
+ // [THEN] Purchase invoice is created with corresponding values
+ EDocument.FindLast();
+
+ // [THEN] Check that Paid Amount for the document is 0
+ this.CheckPaidAmount(EDocument, 0);
+
+ // [GIVEN] Create partial payment for E-Document
+ this.CreateFullEDocumentPayments(EDocument);
+
+ // [THEN] Check that Paid Amount for the document is updated
+ this.CheckPaidAmount(EDocument, EDocument."Amount Incl. VAT");
+
+ // [THEN] Check that Payments Direction is correct
+ this.CheckPaymentDirection(EDocument, Enum::"E-Document Direction"::Outgoing);
+ end;
+
+ //Create partial payment
+ [Test]
+ procedure CreateOutgoingPaymentWithVATCalculationTest()
+ var
+ EDocument: Record "E-Document";
+ EDocServicePage: TestPage "E-Document Service";
+ PaymentAmount: Decimal;
+ i: Integer;
+ begin
+ // [FEATURE] [E-Document]
+ // [SCENARIO] Create partial payment for received E-Document
+ this.Initialize();
+
+ // [GIVEN] Create E-Document service setup and set VAT calculation
+ this.LibraryEDoc.CreateTestPaymentServiceForEDoc(this.EDocService, Enum::"Service Integration"::Mock, Enum::"Payment Integration"::Mock);
+ this.SetDefaultEDocServiceValues(this.EDocService, true);
+ BindSubscription(this.EDocImplState);
+
+ // [GIVEN] Create received E-Document
+ this.LibraryPurchase.CreateVendorWithAddress(this.Vendor);
+ this.Vendor."Receive E-Document To" := this.Vendor."Receive E-Document To"::"Purchase Invoice";
+ this.Vendor.Modify();
+ this.LibraryPurchase.CreatePurchHeader(this.PurchaseHeader, this.PurchaseHeader."Document Type"::Invoice, this.Vendor."No.");
+
+ for i := 1 to 3 do begin
+ this.LibraryPurchase.CreatePurchaseLine(this.PurchaseLine, this.PurchaseHeader, this.PurchaseLine.Type::Item, this.LibraryInventory.CreateItemNo(), this.LibraryRandom.RandInt(100));
+ this.PurchaseLine.Validate("Direct Unit Cost", this.LibraryRandom.RandDecInRange(1, 100, 2));
+ this.PurchaseLine.Modify(true);
+ end;
+
+ this.PurchOrderTestBuffer.ClearTempVariables();
+ this.PurchOrderTestBuffer.AddPurchaseDocToTemp(this.PurchaseHeader);
+
+ // [WHEN] Running Receive
+ EDocServicePage.OpenView();
+ EDocServicePage.Filter.SetFilter(Code, this.EDocService.Code);
+ EDocServicePage.Receive.Invoke();
+ UnbindSubscription(this.EDocImplState);
+
+ // [THEN] Purchase invoice is created with corresponding values
+ EDocument.FindLast();
+
+ // [THEN] Check that Paid Amount for the document is 0
+ this.CheckPaidAmount(EDocument, 0);
+
+ // [GIVEN] Create partial payment for E-Document
+ PaymentAmount := 100;
+ this.CreateEDocumentPayment(EDocument, PaymentAmount);
+
+ // [THEN] Check that Paid Amount for the document is updated
+ this.CheckPaidAmount(EDocument, PaymentAmount);
+
+ // [THEN] Check that VAT amount is calculated
+ this.CheckPaymentVATAmount(EDocument);
+ end;
+
+ //Create incoming partial payment
+ [Test]
+ procedure CreateIncomingPartialPaymentTest()
+ var
+ EDocument: Record "E-Document";
+ PaymentAmount: Decimal;
+ begin
+ // [FEATURE] [E-Document]
+ // [SCENARIO] Receive payment for sent E-Document
+ this.Initialize();
+
+ // [GIVEN] Setup E-Document service to send E-Document and receive payment
+ this.LibraryEDoc.SetupStandardVAT();
+ this.LibraryEDoc.SetupStandardSalesScenario(this.Customer, this.EDocService, Enum::"E-Document Format"::"PEPPOL BIS 3.0", Enum::"Service Integration"::Mock);
+ this.EDocService."Payment Integration" := Enum::"Payment Integration"::Mock;
+ this.EDocService."Calculate Payment VAT" := false;
+ this.EDocService.Modify();
+
+ // [WHEN] Create and post sales invoice to create E-Document
+ this.LibraryEDoc.PostInvoice(this.Customer);
+ EDocument.FindLast();
+
+ // [WHEN] Export EDocument
+ BindSubscription(this.EDocLogTest);
+ this.EDocExportMgt.ExportEDocument(EDocument, this.EDocService);
+ UnbindSubscription(this.EDocLogTest);
+
+ // [THEN] Check that Paid Amount for the document is 0
+ this.CheckPaidAmount(EDocument, 0);
+
+ // [WHEN] Receive payment for E-Document
+ PaymentAmount := 1;
+ this.CreateEDocumentPayment(EDocument, PaymentAmount);
+
+ // [THEN] Check that Paid Amount for the document is updated
+ this.CheckPaidAmount(EDocument, PaymentAmount);
+
+ // [THEN] Check that Payments Direction is correct
+ this.CheckPaymentDirection(EDocument, Enum::"E-Document Direction"::Incoming);
+ end;
+
+ //Receive incoming payment
+ [HandlerFunctions('EDocumentServiceSelectionHandler')]
+ [Test]
+ procedure ReceivePaymentTest()
+ var
+ EDocument: Record "E-Document";
+ begin
+ // [FEATURE] [E-Document]
+ // [SCENARIO] Receive payment for sent E-Document
+ this.Initialize();
+
+ // [GIVEN] Setup E-Document service to send E-Document and receive payment
+ this.LibraryEDoc.SetupStandardVAT();
+ this.LibraryEDoc.SetupStandardSalesScenario(this.Customer, this.EDocService, Enum::"E-Document Format"::"PEPPOL BIS 3.0", Enum::"Service Integration"::Mock);
+ this.EDocService."Payment Integration" := Enum::"Payment Integration"::Mock;
+ this.EDocService."Calculate Payment VAT" := false;
+ this.EDocService.Modify();
+
+ // [WHEN] Create and post sales invoice to create E-Document
+ this.LibraryEDoc.PostInvoice(this.Customer);
+ EDocument.FindLast();
+
+ // [WHEN] Export EDocument
+ BindSubscription(this.EDocLogTest);
+ this.EDocExportMgt.ExportEDocument(EDocument, this.EDocService);
+ UnbindSubscription(this.EDocLogTest);
+
+ // [THEN] Check that Paid Amount for the document is 0
+ this.CheckPaidAmount(EDocument, 0);
+
+ // [WHEN] Receive payment for E-Document
+ this.ReceivePayment(EDocument);
+
+ // [THEN] Check that Paid Amount for the document is updated
+ this.CheckPaidAmount(EDocument, 1);
+
+ // [THEN] Check that Payments Direction is correct
+ this.CheckPaymentDirection(EDocument, Enum::"E-Document Direction"::Incoming);
+ end;
+
+ local procedure Initialize()
+ var
+ EDocument: Record "E-Document";
+ EDocumentPayment: Record "E-Document Payment";
+ begin
+ Clear(this.EDocPaymentImplState);
+ EDocument.DeleteAll(false);
+ EDocumentPayment.DeleteAll(false);
+
+ Clear(this.PurchaseHeader);
+ this.PurchaseHeader.DeleteAll(false);
+
+ Clear(this.EDocService);
+ end;
+
+ local procedure SetDefaultEDocServiceValues(var EDocService: Record "E-Document Service"; CalculateVAT: Boolean)
+ begin
+ EDocService."Lookup Account Mapping" := false;
+ EDocService."Lookup Item GTIN" := false;
+ EDocService."Lookup Item Reference" := false;
+ EDocService."Resolve Unit Of Measure" := false;
+ EDocService."Validate Line Discount" := false;
+ EDocService."Verify Totals" := false;
+ EDocService."Use Batch Processing" := false;
+ EDocService."Calculate Payment VAT" := CalculateVAT;
+ EDocService.Modify(false);
+ end;
+
+ local procedure CreateEDocumentPayment(EDocument: Record "E-Document"; PaymentAmount: Decimal)
+ begin
+ this.CreateEDocumentPaymentRecord(EDocument."Entry No", PaymentAmount)
+ end;
+
+ local procedure CreateFullEDocumentPayments(EDocument: Record "E-Document")
+ begin
+ this.CreateEDocumentPaymentRecord(EDocument."Entry No", 100);
+ this.CreateEDocumentPaymentRecord(EDocument."Entry No", EDocument."Amount Incl. VAT" - 100)
+ end;
+
+ local procedure CreateEDocumentPaymentRecord(EDocumentEntryNo: Integer; Amount: Decimal)
+ var
+ EDocumentPayment: Record "E-Document Payment";
+ begin
+ EDocumentPayment.Init();
+ EDocumentPayment.Validate("E-Document Entry No.", EDocumentEntryNo);
+ EDocumentPayment.Date := Today();
+ EDocumentPayment.Validate(Amount, Amount);
+ EDocumentPayment.Insert(true);
+ end;
+
+ local procedure ReceivePayment(EDocument: Record "E-Document")
+ var
+ EDocumentPage: TestPage "E-Document";
+ begin
+ BindSubscription(this.EDocPaymentImplState);
+ EDocumentPage.OpenView();
+ EDocumentPage.GoToRecord(EDocument);
+ EDocumentPage.ReceivePayments.Invoke();
+ UnbindSubscription(this.EDocPaymentImplState);
+ end;
+
+ local procedure CheckPaidAmount(EDocument: Record "E-Document"; ExpectedPaidAmount: Decimal)
+ begin
+ EDocument.CalcFields("Paid Amount");
+ this.Assert.AreEqual(ExpectedPaidAmount, EDocument."Paid Amount", 'Paid Amount is not updated.');
+ end;
+
+ local procedure CheckPaymentVATAmount(EDocument: Record "E-Document")
+ var
+ EDocumentPayment: Record "E-Document Payment";
+ begin
+ EDocumentPayment.SetRange("E-Document Entry No.", EDocument."Entry No");
+ if EDocumentPayment.FindSet() then
+ repeat
+ this.Assert.AreNotEqual(0, EDocumentPayment."VAT Base", 'Payment Base Amount is not calculated.');
+ this.Assert.AreNotEqual(0, EDocumentPayment."VAT Amount", 'Payment VAT Amount is not calculated.');
+ until EDocumentPayment.Next() = 0;
+ end;
+
+ local procedure CheckPaymentDirection(EDocument: Record "E-Document"; ExpectedDirection: Enum "E-Document Direction")
+ var
+ EDocumentPayment: Record "E-Document Payment";
+ begin
+ EDocumentPayment.SetRange("E-Document Entry No.", EDocument."Entry No");
+ if EDocumentPayment.FindSet() then
+ repeat
+ this.Assert.AreEqual(ExpectedDirection, EDocumentPayment.Direction, 'Payment Direction is not correct.');
+ until EDocumentPayment.Next() = 0;
+ end;
+
+ [ModalPageHandler]
+ procedure EDocumentServiceSelectionHandler(var EDocumentServices: TestPage "E-Document Services")
+ begin
+ EDocumentServices.GoToRecord(this.EDocService);
+ EDocumentServices.OK().Invoke();
+ end;
+}