Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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 @@ -119,7 +120,7 @@ codeunit 13916 "Export XRechnung Document"
InsertAccountingSupplierParty(SalesInvoiceHeader."Responsibility Center", SalesInvoiceHeader."Salesperson Code", RootXMLNode);
InsertAccountingCustomerParty(RootXMLNode, SalesInvoiceHeader);
InsertDelivery(RootXMLNode, SalesInvoiceHeader);
InsertPaymentMeans(RootXMLNode, '68', 'PayeeFinancialAccount', SalesInvoiceHeader."Company Bank Account Code");
InsertPaymentMeans(RootXMLNode, '58', 'PayeeFinancialAccount', SalesInvoiceHeader."Company Bank Account Code");
InsertPaymentTerms(RootXMLNode, SalesInvoiceHeader."Payment Terms Code");
InsertVATAmounts(SalesInvLine, LineVATAmount, LineAmount, LineDiscAmount, SalesInvoiceHeader."Prices Including VAT", Currency);
InsertInvDiscountAllowanceCharge(LineAmounts, SalesInvLine, CurrencyCode, RootXMLNode, LineDiscAmount, LineAmount, Currency."Amount Rounding Precision");
Expand Down Expand Up @@ -164,7 +165,7 @@ codeunit 13916 "Export XRechnung Document"
InsertAccountingSupplierParty(SalesCrMemoHeader."Responsibility Center", SalesCrMemoHeader."Salesperson Code", RootXMLNode);
InsertAccountingCustomerParty(RootXMLNode, SalesCrMemoHeader);
InsertDelivery(RootXMLNode, SalesCrMemoHeader);
InsertPaymentMeans(RootXMLNode, '68', '', SalesCrMemoHeader."Company Bank Account Code");
InsertPaymentMeans(RootXMLNode, '58', '', SalesCrMemoHeader."Company Bank Account Code");
InsertPaymentTerms(RootXMLNode, SalesCrMemoHeader."Payment Terms Code");
InsertVATAmounts(SalesCrMemoLine, LineVATAmount, LineAmount, LineDiscAmount, SalesCrMemoHeader."Prices Including VAT", Currency);
InsertInvDiscountAllowanceCharge(LineAmounts, SalesCrMemoLine, CurrencyCode, RootXMLNode, LineDiscAmount, LineAmount, Currency."Amount Rounding Precision");
Expand Down Expand Up @@ -388,22 +389,23 @@ codeunit 13916 "Export XRechnung Document"
local procedure InsertPayeeFinancialAccount(var PaymentMeansElement: XmlElement; PayeeFinancialAccount: Text[30]; CompanyBankAccountCode: Code[20]);
var
PayeeFinancialAccountElement: XmlElement;
IBAN: Text[50];
SWIFTCode: Code[20];
begin
PayeeFinancialAccountElement := XmlElement.Create(PayeeFinancialAccount, XmlNamespaceCAC);
if CompanyBankAccountCode <> '' then
PayeeFinancialAccountElement.Add(XmlElement.Create('ID', XmlNamespaceCBC, CompanyBankAccountCode))
else
PayeeFinancialAccountElement.Add(XmlElement.Create('ID', XmlNamespaceCBC, CompanyInformation."Bank Account No."));
InsertFinancialInstitutionBranch(PayeeFinancialAccountElement);
GetBankAccountPaymentDetails(CompanyBankAccountCode, IBAN, SWIFTCode);
PayeeFinancialAccountElement.Add(XmlElement.Create('ID', XmlNamespaceCBC, GetIBAN(IBAN)));
if SWIFTCode <> '' then
InsertFinancialInstitutionBranch(PayeeFinancialAccountElement, SWIFTCode);
PaymentMeansElement.Add(PayeeFinancialAccountElement);
end;

local procedure InsertFinancialInstitutionBranch(var RootElement: XmlElement);
local procedure InsertFinancialInstitutionBranch(var RootElement: XmlElement; SWIFTCode: Code[20]);
var
FinancialInstitutionBranchElement: XmlElement;
begin
FinancialInstitutionBranchElement := XmlElement.Create('FinancialInstitutionBranch', XmlNamespaceCAC);
FinancialInstitutionBranchElement.Add(XmlElement.Create('ID', XmlNamespaceCBC, CompanyInformation."Bank Branch No."));
FinancialInstitutionBranchElement.Add(XmlElement.Create('ID', XmlNamespaceCBC, GetIBAN(SWIFTCode)));
RootElement.Add(FinancialInstitutionBranchElement);
end;

Expand Down Expand Up @@ -1291,6 +1293,38 @@ codeunit 13916 "Export XRechnung Document"
GeneralLedgerSetup.Get();
OnAfterGetSetups(CompanyInformation, GeneralLedgerSetup);
end;

local procedure GetIBAN(IBAN: Text[50]) IBANFormatted: Text[50]
begin
// Format IBAN to remove spaces and ensure it is in uppercase
if IBAN = '' then
exit('');
IBANFormatted := UpperCase(DelChr(IBAN, '=', ' '));
exit(CopyStr(IBANFormatted, 1, 50));
end;

local procedure GetBankAccountPaymentDetails(BankAccountCode: Code[20]; var IBAN: Text[50]; var SWIFTCode: Code[20])
var
BankAccount: Record "Bank Account";
begin
Clear(IBAN);
Clear(SWIFTCode);

if BankAccountCode = '' then begin
IBAN := CompanyInformation.IBAN;
SWIFTCode := CompanyInformation."SWIFT Code";
exit;
end;

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
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 @@ -30,6 +31,7 @@ codeunit 13914 "XRechnung Format" implements "E-Document"
begin
OnBeforeCheck(SourceDocumentHeader, EDocumentService, EDocumentProcessingPhase);
CheckCompanyInfoMandatory();
CheckBankAccountIBANMandatory(SourceDocumentHeader);
CheckBuyerReferenceMandatory(EDocumentService, SourceDocumentHeader);
BindSubscription(EDocPEPPOLValidationDE);
EDocPEPPOLBIS30.Check(SourceDocumentHeader, EDocumentService, EDocumentProcessingPhase);
Expand Down Expand Up @@ -85,10 +87,40 @@ codeunit 13914 "XRechnung Format" implements "E-Document"
CompanyInformation.TestField("E-Mail");
end;

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

BankAccountCodeFieldRef := SourceDocumentHeader.Field(SalesInvoiceHeader.FieldNo("Company Bank Account Code"));
BankAccountCode := BankAccountCodeFieldRef.Value();

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

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

local procedure CheckBuyerReferenceMandatory(EDocumentService: Record "E-Document Service"; SourceDocumentHeader: RecordRef)
var
Customer: Record Customer;
SalesInvoiceHeader: Record "Sales Invoice Header";
CustomerNoFieldRef: FieldRef;
YourReferenceFieldRef: FieldRef;
begin
Expand Down
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.Integration;
using Microsoft.Finance.Currency;
Expand Down Expand Up @@ -190,7 +191,37 @@ codeunit 13918 "XRechnung XML Document Tests"
ExportInvoice(SalesInvoiceHeader, TempXMLBuffer);

// [THEN] XRechnung Electronic Document is created with bank informarion as payment means
VerifyPaymentMeans(TempXMLBuffer, '/ubl:Invoice/cac:PaymentMeans');
VerifyPaymentMeans(TempXMLBuffer, '/ubl:Invoice/cac:PaymentMeans', CompanyInformation.IBAN, CompanyInformation."SWIFT Code");
end;

[Test]
procedure ExportPostedSalesInvoiceInXRechnungFormatVerifyBankAccountPaymentMeans();
var
BankAccount: Record "Bank Account";
SalesInvoiceHeader: Record "Sales Invoice Header";
TempXMLBuffer: Record "XML Buffer" temporary;
BankAccountIBAN: Text;
BankAccountSWIFT: Text;
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 XRechnung Electronic Document.
ExportInvoice(SalesInvoiceHeader, TempXMLBuffer);

// [THEN] XRechnung Electronic Document uses Bank Account IBAN and SWIFT Code
VerifyPaymentMeans(TempXMLBuffer, '/ubl:Invoice/cac:PaymentMeans', BankAccountIBAN, BankAccountSWIFT);
end;

[Test]
Expand Down Expand Up @@ -514,7 +545,37 @@ codeunit 13918 "XRechnung XML Document Tests"
// [WHEN] Export XRechnung Electronic Document.
ExportCreditMemo(SalesCrMemoHeader, TempXMLBuffer);

// [THEN] XRechnung Electronic Document is created with bank informarion as payment means
// [THEN] XRechnung Electronic Document is created with payment means code
VerifyPaymentMeans(TempXMLBuffer, '/ns0:CreditNote/cac:PaymentMeans');
end;

[Test]
procedure ExportPostedSalesCrMemoInXRechnungFormatVerifyBankAccountPaymentMeans();
var
BankAccount: Record "Bank Account";
SalesCrMemoHeader: Record "Sales Cr.Memo Header";
TempXMLBuffer: Record "XML Buffer" temporary;
BankAccountIBAN: Text;
BankAccountSWIFT: Text;
begin
// [SCENARIO 496414] Export posted sales cr. 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 cr. memo with Bank Account Code
SalesCrMemoHeader.Get(CreateAndPostSalesDocumentWithBankAccount("Sales Document Type"::"Credit Memo", Enum::"Sales Line Type"::Item, BankAccount."No."));

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

// [THEN] XRechnung Electronic Document has payment means code
VerifyPaymentMeans(TempXMLBuffer, '/ns0:CreditNote/cac:PaymentMeans');
end;

Expand Down Expand Up @@ -751,6 +812,17 @@ codeunit 13918 "XRechnung 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 CreatePurchDocument(var PurchaseHeader: Record "Purchase Header"; DocumentType: Enum "Purchase Document Type")
var
PurchaseLine: Record "Purchase Line";
Expand Down Expand Up @@ -1027,7 +1099,20 @@ codeunit 13918 "XRechnung XML Document Tests"
Path: Text;
begin
Path := DocumentTok + '/cbc:PaymentMeansCode';
Assert.AreEqual('68', GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path));
Assert.AreEqual('58', GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path));
end;

local procedure VerifyPaymentMeans(var TempXMLBuffer: Record "XML Buffer" temporary; DocumentTok: Text; ExpectedIBAN: Text; ExpectedSWIFT: Text);
var
Path: Text;
begin
VerifyPaymentMeans(TempXMLBuffer, DocumentTok);
Path := DocumentTok + '/cac:PayeeFinancialAccount/cbc:ID';
Assert.AreEqual(ExpectedIBAN, GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path));
if ExpectedSWIFT <> '' then begin
Path := DocumentTok + '/cac:PayeeFinancialAccount/cac:FinancialInstitutionBranch/cbc:ID';
Assert.AreEqual(ExpectedSWIFT, GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path));
end;
end;

local procedure VerifyPaymentTerms(PaymentTermsCode: Code[10]; var TempXMLBuffer: Record "XML Buffer" temporary; DocumentTok: Text);
Expand Down Expand Up @@ -1465,6 +1550,9 @@ codeunit 13918 "XRechnung XML Document Tests"
LibraryTestInitialize.OnBeforeTestSuiteInitialize(Codeunit::"XRechnung XML Document Tests");
IsInitialized := true;
CompanyInformation.Get();
CompanyInformation.IBAN := LibraryUtility.GenerateMOD97CompliantCode();
CompanyInformation."SWIFT Code" := LibraryUtility.GenerateGUID();
CompanyInformation.Modify();
GeneralLedgerSetup.Get();
EDocumentService.DeleteAll();
EDocumentService.Get(LibraryEdocument.CreateService("E-Document Format"::XRechnung, "Service Integration"::"No Integration"));
Expand Down
Loading