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 @@ -4,6 +4,7 @@
// ------------------------------------------------------------------------------------------------
namespace Microsoft.eServices.EDocument.Formats;

using Microsoft.Bank.BankAccount;
using Microsoft.CRM.Team;
using Microsoft.eServices.EDocument;
using Microsoft.Finance.Currency;
Expand Down Expand Up @@ -349,6 +350,7 @@ codeunit 13917 "Export ZUGFeRD Document"
GetSetups();
FindEDocumentService();
PEPPOLMgt.TransferHeaderToSalesInvoiceHeader(ServiceInvoiceHeader, SalesInvoiceHeader);
SalesInvoiceHeader."Company Bank Account Code" := ServiceInvoiceHeader."Company Bank Account Code";
ServiceInvoiceLine.SetRange("Document No.", ServiceInvoiceHeader."No.");
if ServiceInvoiceLine.FindSet() then
repeat
Expand Down Expand Up @@ -391,6 +393,7 @@ codeunit 13917 "Export ZUGFeRD Document"
GetSetups();
FindEDocumentService();
PEPPOLMgt.TransferHeaderToSalesCrMemoHeader(ServiceCrMemoHeader, SalesCrMemoHeader);
SalesCrMemoHeader."Company Bank Account Code" := ServiceCrMemoHeader."Company Bank Account Code";
ServiceCrMemoLine.SetRange("Document No.", ServiceCrMemoHeader."No.");
if ServiceCrMemoLine.FindSet() then
repeat
Expand Down Expand Up @@ -733,7 +736,7 @@ codeunit 13917 "Export ZUGFeRD Document"
SettlementElement := XmlElement.Create('ApplicableHeaderTradeSettlement', XmlNamespaceRAM);

SettlementElement.Add(XmlElement.Create('InvoiceCurrencyCode', XmlNamespaceRAM, CurrencyCode));
InsertPaymentMethod(SettlementElement);
InsertPaymentMethod(SettlementElement, SalesInvHeader."Company Bank Account Code");
InsertTradeTax(SettlementElement, SalesInvLine, LineAmount, LineVATAmount);
InsertInvDiscountAllowanceCharge(SettlementElement, SalesInvLine, LineDiscAmount, LineAmounts);

Expand All @@ -758,7 +761,7 @@ codeunit 13917 "Export ZUGFeRD Document"
SettlementElement := XmlElement.Create('ApplicableHeaderTradeSettlement', XmlNamespaceRAM);

SettlementElement.Add(XmlElement.Create('InvoiceCurrencyCode', XmlNamespaceRAM, CurrencyCode));
InsertPaymentMethod(SettlementElement);
InsertPaymentMethod(SettlementElement, SalesCrMemoHeader."Company Bank Account Code");
InsertTradeTax(SettlementElement, SalesCrMemoLine, LineAmount, LineVATAmount);
InsertInvDiscountAllowanceCharge(SettlementElement, SalesCrMemoLine, LineDiscAmount, LineAmounts);

Expand Down Expand Up @@ -1042,23 +1045,26 @@ codeunit 13917 "Export ZUGFeRD Document"
RootXMLNode.Add(PaymentTermsElement);
end;

local procedure InsertPaymentMethod(var RootXMLNode: XmlElement)
local procedure InsertPaymentMethod(var RootXMLNode: XmlElement; CompanyBankAccountCode: Code[20])
var
PaymentMethodElement, PaymentMethodTypeCodeElement, PaymentMethodIBANElement, PaymentMethodBICElement : XmlElement;
IBAN: Text[50];
SWIFTCode: Code[20];
begin
GetBankAccountPaymentDetails(CompanyBankAccountCode, IBAN, SWIFTCode);
PaymentMethodElement := XmlElement.Create('SpecifiedTradeSettlementPaymentMeans', XmlNamespaceRAM);
PaymentMethodTypeCodeElement := XmlElement.Create('TypeCode', XmlNamespaceRAM, '58'); //generic for Credit transfer
PaymentMethodElement.Add(PaymentMethodTypeCodeElement);

if CompanyInformation.IBAN <> '' then begin
if IBAN <> '' then begin
PaymentMethodIBANElement := XmlElement.Create('PayeePartyCreditorFinancialAccount', XmlNamespaceRAM);
PaymentMethodIBANElement.Add(XmlElement.Create('IBANID', XmlNamespaceRAM, GetIBAN(CompanyInformation.IBAN)));
PaymentMethodIBANElement.Add(XmlElement.Create('IBANID', XmlNamespaceRAM, GetIBAN(IBAN)));
PaymentMethodElement.Add(PaymentMethodIBANElement);
end;

if CompanyInformation."SWIFT Code" <> '' then begin
if SWIFTCode <> '' then begin
PaymentMethodBICElement := XmlElement.Create('PayeeSpecifiedCreditorFinancialInstitution', XmlNamespaceRAM);
PaymentMethodBICElement.Add(XmlElement.Create('BICID', XmlNamespaceRAM, GetIBAN(CompanyInformation."SWIFT Code")));
PaymentMethodBICElement.Add(XmlElement.Create('BICID', XmlNamespaceRAM, GetIBAN(SWIFTCode)));
PaymentMethodElement.Add(PaymentMethodBICElement);
end;
RootXMLNode.Add(PaymentMethodElement);
Expand Down Expand Up @@ -1376,6 +1382,21 @@ codeunit 13917 "Export ZUGFeRD Document"
if EDocumentService.FindLast() then;
OnAfterFindEDocumentService(EDocumentService);
end;

local procedure GetBankAccountPaymentDetails(BankAccountCode: Code[20]; var IBAN: Text[50]; var SWIFTCode: Code[20])
var
BankAccount: Record "Bank Account";
begin
if BankAccountCode <> '' then
if BankAccount.Get(BankAccountCode) then begin
IBAN := BankAccount.IBAN;
SWIFTCode := BankAccount."SWIFT Code";
exit;
end;

IBAN := CompanyInformation.IBAN;
SWIFTCode := CompanyInformation."SWIFT Code";
end;
#endregion

[IntegrationEvent(false, false)]
Expand Down
46 changes: 42 additions & 4 deletions Apps/DE/EDocumentDE/app/src/ZUGFeRD/ZUGFeRDFormat.Codeunit.al
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// ------------------------------------------------------------------------------------------------
namespace Microsoft.eServices.EDocument.Formats;

using Microsoft.Bank.BankAccount;
using Microsoft.eServices.EDocument;
using Microsoft.eServices.EDocument.IO.Peppol;
using Microsoft.Foundation.Company;
Expand All @@ -27,9 +28,12 @@ codeunit 13920 "ZUGFeRD Format" implements "E-Document"
EDocImportZUGFeRD: Codeunit "Import ZUGFeRD Document";

procedure Check(var SourceDocumentHeader: RecordRef; EDocumentService: Record "E-Document Service"; EDocumentProcessingPhase: Enum "E-Document Processing Phase")
var
CompanyInformation: Record "Company Information";
begin
OnBeforeCheck(SourceDocumentHeader, EDocumentService, EDocumentProcessingPhase);
CheckCompanyInfoMandatory();
CheckCompanyInfoMandatory(CompanyInformation);
CheckBankAccountIBANMandatory(SourceDocumentHeader, CompanyInformation);
CheckBuyerReferenceMandatory(EDocumentService, SourceDocumentHeader);
EDocPEPPOLValidationDE.SetBuyerReference(EDocumentService."Buyer Reference");
BindSubscription(EDocPEPPOLValidationDE);
Expand Down Expand Up @@ -141,14 +145,48 @@ codeunit 13920 "ZUGFeRD Format" implements "E-Document"
FileExtension := PDFFileTypeTok;
end;

local procedure CheckCompanyInfoMandatory()
var
CompanyInformation: Record "Company Information";
local procedure CheckCompanyInfoMandatory(var CompanyInformation: Record "Company Information")
begin
CompanyInformation.Get();
CompanyInformation.TestField("E-Mail");
end;

local procedure CheckBankAccountIBANMandatory(SourceDocumentHeader: RecordRef; var CompanyInformation: Record "Company Information")
var
BankAccount: Record "Bank Account";
SalesInvoiceHeader: Record "Sales Invoice Header";
ServiceInvoiceHeader: Record "Service Invoice Header";
BankAccountCodeFieldRef: FieldRef;
CheckBankAccount: Boolean;
BankAccountCode: Code[20];
BankAccFieldNo: Integer;
begin
if not (SourceDocumentHeader.Number() in
[Database::"Sales Header",
Database::"Sales Invoice Header",
Database::"Sales Cr.Memo Header",
Database::"Service Header",
Database::"Service Invoice Header",
Database::"Service Cr.Memo Header"])
then
exit;

BankAccFieldNo := SalesInvoiceHeader.FieldNo("Company Bank Account Code");
if SourceDocumentHeader.Number() in [Database::"Service Header", Database::"Service Invoice Header", Database::"Service Cr.Memo Header"] then
BankAccFieldNo := ServiceInvoiceHeader.FieldNo("Company Bank Account Code");

BankAccountCodeFieldRef := SourceDocumentHeader.Field(BankAccFieldNo);
BankAccountCode := BankAccountCodeFieldRef.Value();

if BankAccountCode <> '' then
CheckBankAccount := BankAccount.Get(BankAccountCode);

if CheckBankAccount then
BankAccount.TestField(IBAN)
else
CompanyInformation.TestField(IBAN);
end;

local procedure CheckBuyerReferenceMandatory(EDocumentService: Record "E-Document Service"; SourceDocumentHeader: RecordRef)
var
SalesInvoiceHeader: Record "Sales Invoice Header";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,40 @@ codeunit 13922 "ZUGFeRD XML Document Tests"
// [WHEN] Export ZUGFeRD Electronic Document.
ExportInvoice(SalesInvoiceHeader, TempXMLBuffer);

// [THEN] ZUGFeRD Electronic Document is created with bank informarion as payment means
// [THEN] ZUGFeRD Electronic Document is created with bank information as payment means
VerifyPaymentMeans(TempXMLBuffer, '/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement', SalesInvoiceHeader."Currency Code");
end;

[Test]
procedure ExportPostedSalesInvoiceInZUGFeRDFormatVerifyBankAccountPaymentMeans();
var
BankAccount: Record "Bank Account";
SalesInvoiceHeader: Record "Sales Invoice Header";
TempXMLBuffer: Record "XML Buffer" temporary;
BankAccountIBAN: Code[50];
BankAccountSWIFT: Code[20];
begin
// [SCENARIO 496414] Export posted sales invoice uses Bank Account IBAN and SWIFT Code when Company Bank Account Code is specified
Initialize();

// [GIVEN] Create Bank Account with specific IBAN and SWIFT Code
BankAccountIBAN := LibraryUtility.GenerateMOD97CompliantCode();
BankAccountSWIFT := LibraryUtility.GenerateGUID();
LibraryERM.CreateBankAccount(BankAccount);
BankAccount.IBAN := BankAccountIBAN;
BankAccount."SWIFT Code" := BankAccountSWIFT;
BankAccount.Modify(true);

// [GIVEN] Create and Post Sales Invoice with Bank Account Code
SalesInvoiceHeader.Get(CreateAndPostSalesDocumentWithBankAccount("Sales Document Type"::Invoice, Enum::"Sales Line Type"::Item, BankAccount."No."));

// [WHEN] Export ZUGFeRD Electronic Document.
ExportInvoice(SalesInvoiceHeader, TempXMLBuffer);

// [THEN] ZUGFeRD Electronic Document uses Bank Account IBAN and SWIFT Code
VerifyPaymentMeans(TempXMLBuffer, '/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement', BankAccountIBAN, BankAccountSWIFT);
end;

[Test]
procedure ExportPostedSalesInvoiceInZUGFeRDFormatVerifyPaymentTerms();
var
Expand Down Expand Up @@ -574,10 +604,40 @@ codeunit 13922 "ZUGFeRD XML Document Tests"
// [WHEN] Export ZUGFeRD Electronic Document.
ExportCreditMemo(SalesCrMemoHeader, TempXMLBuffer);

// [THEN] ZUGFeRD Electronic Document is created with bank informarion as payment means
// [THEN] ZUGFeRD Electronic Document is created with bank information as payment means
VerifyPaymentMeans(TempXMLBuffer, '/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement', SalesCrMemoHeader."Currency Code");
end;

[Test]
procedure ExportPostedSalesCrMemoInZUGFeRDFormatVerifyBankAccountPaymentMeans();
var
BankAccount: Record "Bank Account";
SalesCrMemoHeader: Record "Sales Cr.Memo Header";
TempXMLBuffer: Record "XML Buffer" temporary;
BankAccountIBAN: Code[50];
BankAccountSWIFT: Code[20];
begin
// [SCENARIO 496414] Export posted sales credit memo uses Bank Account IBAN and SWIFT Code when Company Bank Account Code is specified
Initialize();

// [GIVEN] Create Bank Account with specific IBAN and SWIFT Code
BankAccountIBAN := LibraryUtility.GenerateMOD97CompliantCode();
BankAccountSWIFT := LibraryUtility.GenerateGUID();
LibraryERM.CreateBankAccount(BankAccount);
BankAccount.IBAN := BankAccountIBAN;
BankAccount."SWIFT Code" := BankAccountSWIFT;
BankAccount.Modify(true);

// [GIVEN] Create and Post Sales Credit Memo with Bank Account Code
SalesCrMemoHeader.Get(CreateAndPostSalesDocumentWithBankAccount("Sales Document Type"::"Credit Memo", Enum::"Sales Line Type"::Item, BankAccount."No."));

// [WHEN] Export ZUGFeRD Electronic Document.
ExportCreditMemo(SalesCrMemoHeader, TempXMLBuffer);

// [THEN] ZUGFeRD Electronic Document uses Bank Account IBAN and SWIFT Code
VerifyPaymentMeans(TempXMLBuffer, '/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement', BankAccountIBAN, BankAccountSWIFT);
end;

[Test]
procedure ExportPostedSalesCrMemoInZUGFeRDFormatVerifyPaymentTerms();
var
Expand Down Expand Up @@ -1345,6 +1405,17 @@ codeunit 13922 "ZUGFeRD XML Document Tests"
exit(LibrarySales.PostSalesDocument(SalesHeader, true, true));
end;

local procedure CreateAndPostSalesDocumentWithBankAccount(DocumentType: Enum "Sales Document Type"; LineType: Enum "Sales Line Type"; BankAccountCode: Code[20]): Code[20];
var
SalesHeader: Record "Sales Header";
begin
CreateSalesHeader(SalesHeader, DocumentType);
SalesHeader.Validate("Company Bank Account Code", BankAccountCode);
SalesHeader.Modify(true);
CreateSalesLine(SalesHeader, LineType, false);
exit(LibrarySales.PostSalesDocument(SalesHeader, true, true));
end;

local procedure CreateAndPostServiceDocument(): Code[20]
var
ServiceHeader: Record "Service Header";
Expand Down Expand Up @@ -1931,6 +2002,20 @@ codeunit 13922 "ZUGFeRD XML Document Tests"
Assert.AreEqual(GetIBAN(CompanyInformation.IBAN), GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path));
end;

local procedure VerifyPaymentMeans(var TempXMLBuffer: Record "XML Buffer" temporary; DocumentTok: Text; ExpectedIBAN: Code[50]; ExpectedSWIFT: Code[20])
var
Path: Text;
begin
Path := DocumentTok + '/ram:SpecifiedTradeSettlementPaymentMeans/ram:TypeCode';
Assert.AreEqual('58', GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path));
Path := DocumentTok + '/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayeePartyCreditorFinancialAccount/ram:IBANID';
Assert.AreEqual(GetIBAN(ExpectedIBAN), GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path));
if ExpectedSWIFT <> '' then begin
Path := DocumentTok + '/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayeeSpecifiedCreditorFinancialInstitution/ram:BICID';
Assert.AreEqual(GetIBAN(ExpectedSWIFT), GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path));
end;
end;

local procedure VerifyPaymentTerms(PaymentTermsCode: Code[10]; DueDate: Date; var TempXMLBuffer: Record "XML Buffer" temporary; DocumentTok: Text);
var
PaymentTerms: Record "Payment Terms";
Expand Down
Loading