diff --git a/Apps/DE/EDocumentDE/app/src/XRechnung/ExportXRechnungDocument.Codeunit.al b/Apps/DE/EDocumentDE/app/src/XRechnung/ExportXRechnungDocument.Codeunit.al index 8ba3aaf48e..6801a60561 100644 --- a/Apps/DE/EDocumentDE/app/src/XRechnung/ExportXRechnungDocument.Codeunit.al +++ b/Apps/DE/EDocumentDE/app/src/XRechnung/ExportXRechnungDocument.Codeunit.al @@ -4,6 +4,7 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.eServices.EDocument.Formats; +using Microsoft.CRM.Team; using Microsoft.eServices.EDocument; using Microsoft.Finance.Currency; using Microsoft.Finance.GeneralLedger.Setup; @@ -14,6 +15,7 @@ using Microsoft.Foundation.Company; using Microsoft.Foundation.PaymentTerms; using Microsoft.Foundation.Reporting; using Microsoft.Foundation.UOM; +using Microsoft.Inventory.Location; using Microsoft.Sales.Customer; using Microsoft.Sales.Document; using Microsoft.Sales.History; @@ -114,7 +116,7 @@ codeunit 13916 "Export XRechnung Document" InsertEmbeddedDocument(RootXMLNode, SalesInvoiceHeader); InsertAttachment(RootXMLNode, Database::"Sales Invoice Header", SalesInvoiceHeader."No."); CalculateLineAmounts(SalesInvoiceHeader, SalesInvLine, Currency, LineAmounts); - InsertAccountingSupplierParty(RootXMLNode); + InsertAccountingSupplierParty(SalesInvoiceHeader."Responsibility Center", SalesInvoiceHeader."Salesperson Code", RootXMLNode); InsertAccountingCustomerParty(RootXMLNode, SalesInvoiceHeader); InsertDelivery(RootXMLNode, SalesInvoiceHeader); InsertPaymentMeans(RootXMLNode, '68', 'PayeeFinancialAccount', SalesInvoiceHeader."Company Bank Account Code"); @@ -159,7 +161,7 @@ codeunit 13916 "Export XRechnung Document" InsertEmbeddedDocument(RootXMLNode, SalesCrMemoHeader); InsertAttachment(RootXMLNode, Database::"Sales Cr.Memo Header", SalesCrMemoHeader."No."); CalculateLineAmounts(SalesCrMemoHeader, SalesCrMemoLine, Currency, LineAmounts); - InsertAccountingSupplierParty(RootXMLNode); + InsertAccountingSupplierParty(SalesCrMemoHeader."Responsibility Center", SalesCrMemoHeader."Salesperson Code", RootXMLNode); InsertAccountingCustomerParty(RootXMLNode, SalesCrMemoHeader); InsertDelivery(RootXMLNode, SalesCrMemoHeader); InsertPaymentMeans(RootXMLNode, '68', '', SalesCrMemoHeader."Company Bank Account Code"); @@ -285,12 +287,12 @@ codeunit 13916 "Export XRechnung Document" until SalesCrMemoLine.Next() = 0; end; - local procedure InsertAccountingSupplierParty(var RootXMLNode: XmlElement) + local procedure InsertAccountingSupplierParty(RespCenterCode: Code[10]; SalespersonCode: Code[20]; var RootXMLNode: XmlElement) var AccountingSupplierPartyElement: XmlElement; begin AccountingSupplierPartyElement := XmlElement.Create('AccountingSupplierParty', XmlNamespaceCAC); - InsertSupplierParty(AccountingSupplierPartyElement); + InsertSupplierParty(RespCenterCode, SalespersonCode, AccountingSupplierPartyElement); RootXMLNode.Add(AccountingSupplierPartyElement); end; @@ -348,6 +350,7 @@ codeunit 13916 "Export XRechnung Document" local procedure InsertAddress(var RootElement: XmlElement; ElementName: Text; Address: Record "Standard Address"); var AddressElement: XmlElement; + IdentificationCode: Code[2]; begin AddressElement := XmlElement.Create(ElementName, XmlNamespaceCAC); AddressElement.Add(XmlElement.Create('StreetName', XmlNamespaceCBC, Address.Address)); @@ -355,7 +358,8 @@ codeunit 13916 "Export XRechnung Document" AddressElement.Add(XmlElement.Create('AdditionalStreetName', XmlNamespaceCBC, Address."Address 2")); AddressElement.Add(XmlElement.Create('CityName', XmlNamespaceCBC, Address.City)); AddressElement.Add(XmlElement.Create('PostalZone', XmlNamespaceCBC, Address."Post Code")); - InsertCountry(AddressElement, GetCountryRegionCode(Address."Country/Region Code")); + IdentificationCode := GetCountryISOCode(GetCountryRegionCode(Address."Country/Region Code")); + InsertCountry(AddressElement, IdentificationCode); RootElement.Add(AddressElement); end; @@ -530,18 +534,46 @@ codeunit 13916 "Export XRechnung Document" RootElement.Add(ContactElement); end; - local procedure InsertContact(var RootElement: XmlElement); + local procedure InsertSupplierContact(SalespersonCode: Code[20]; var RootElement: XmlElement) var ContactElement: XmlElement; + ContactName: Text; + EmailAddress: Text; + PhoneNumber: Text; begin + if not SetSupplierContactFromSalesPerson(SalespersonCode, ContactName, PhoneNumber, EmailAddress) then + SetSupplierContactFromCompanyInformation(ContactName, PhoneNumber, EmailAddress); + ContactElement := XmlElement.Create('Contact', XmlNamespaceCAC); - ContactElement.Add(XmlElement.Create('Name', XmlNamespaceCBC, CompanyInformation."Contact Person")); - ContactElement.Add(XmlElement.Create('Telephone', XmlNamespaceCBC, CompanyInformation."Phone No.")); - ContactElement.Add(XmlElement.Create('ElectronicMail', XmlNamespaceCBC, CompanyInformation."E-Mail")); + ContactElement.Add(XmlElement.Create('Name', XmlNamespaceCBC, ContactName)); + ContactElement.Add(XmlElement.Create('Telephone', XmlNamespaceCBC, PhoneNumber)); + ContactElement.Add(XmlElement.Create('ElectronicMail', XmlNamespaceCBC, EmailAddress)); RootElement.Add(ContactElement); end; - local procedure InsertSupplierParty(var AccountingSupplierPartyElement: XmlElement); + local procedure SetSupplierContactFromSalesPerson(SalespersonCode: Code[20]; var ContactName: Text; var PhoneNumber: Text; var EmailAddress: Text): Boolean + var + Salesperson: Record "Salesperson/Purchaser"; + begin + if SalesPersonCode = '' then + exit(false); + Salesperson.SetLoadFields(Name, "Phone No.", "E-Mail"); + if not Salesperson.Get(SalesPersonCode) then + exit(false); + ContactName := Salesperson.Name; + PhoneNumber := Salesperson."Phone No."; + EmailAddress := Salesperson."E-Mail"; + exit(true); + end; + + local procedure SetSupplierContactFromCompanyInformation(var ContactName: Text; var PhoneNumber: Text; var EmailAddress: Text) + begin + ContactName := CompanyInformation."Contact Person"; + PhoneNumber := CompanyInformation."Phone No."; + EmailAddress := CompanyInformation."E-Mail"; + end; + + local procedure InsertSupplierParty(RespCenterCode: Code[10]; SalespersonCode: Code[20]; var AccountingSupplierPartyElement: XmlElement); var TempCompanyAddress: Record "Standard Address" temporary; PartyElement: XmlElement; @@ -555,10 +587,11 @@ codeunit 13916 "Export XRechnung Document" InsertPartyIdentification(PartyElement, GetVATRegistrationNo(CompanyInformation."VAT Registration No.", CompanyInformation."Country/Region Code")); InsertPartyName(PartyElement, CompanyInformation.Name); TempCompanyAddress.CopyFromCompanyInformation(CompanyInformation); + UpdateSellerAddressFromResponsibilityCenter(RespCenterCode, TempCompanyAddress); InsertAddress(PartyElement, 'PostalAddress', TempCompanyAddress); InsertPartyTaxScheme(PartyElement, CompanyInformation."VAT Registration No.", CompanyInformation."Country/Region Code"); InsertPartyLegalEntity(PartyElement); - InsertContact(PartyElement); + InsertSupplierContact(SalespersonCode, PartyElement); AccountingSupplierPartyElement.Add(PartyElement); end; @@ -1088,6 +1121,24 @@ codeunit 13916 "Export XRechnung Document" TotalAmounts.Set(VATPercent, TotalAmounts.Get(VATPercent) + NewAmount); end; + local procedure UpdateSellerAddressFromResponsibilityCenter(RespCenterCode: Code[10]; var TempCompanyAddress: Record "Standard Address" temporary) + var + RespCenter: Record "Responsibility Center"; + begin + if RespCenterCode = '' then + exit; + if not RespCenter.Get(RespCenterCode) then + exit; + + TempCompanyAddress.Address := RespCenter.Address; + TempCompanyAddress."Address 2" := RespCenter."Address 2"; + TempCompanyAddress.City := RespCenter.City; + TempCompanyAddress."Country/Region Code" := RespCenter."Country/Region Code"; + TempCompanyAddress."Post Code" := RespCenter."Post Code"; + TempCompanyAddress.County := RespCenter.County; + TempCompanyAddress.Modify(false); + end; + local procedure FindEDocumentService(EDocumentFormat: Code[20]) begin if EDocumentFormat = '' then @@ -1170,6 +1221,14 @@ codeunit 13916 "Export XRechnung Document" end; end; + local procedure GetCountryISOCode(CountryRegionCode: Code[10]): Code[2] + var + CountryRegion: Record "Country/Region"; + begin + CountryRegion.Get(CountryRegionCode); + exit(CountryRegion."ISO Code"); + end; + local procedure GetCountryRegionCode(CountryRegionCode: Code[10]): Code[10] begin if CountryRegionCode <> '' then diff --git a/Apps/DE/EDocumentDE/app/src/ZUGFeRD/ExportZUGFeRDDocument.Codeunit.al b/Apps/DE/EDocumentDE/app/src/ZUGFeRD/ExportZUGFeRDDocument.Codeunit.al index ff59cb3320..5b7ab06e6e 100644 --- a/Apps/DE/EDocumentDE/app/src/ZUGFeRD/ExportZUGFeRDDocument.Codeunit.al +++ b/Apps/DE/EDocumentDE/app/src/ZUGFeRD/ExportZUGFeRDDocument.Codeunit.al @@ -4,20 +4,23 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.eServices.EDocument.Formats; -using System.Telemetry; using Microsoft.eServices.EDocument; -using Microsoft.Foundation.PaymentTerms; -using Microsoft.Finance.VAT.Setup; -using Microsoft.Sales.Customer; -using System.Utilities; -using Microsoft.Foundation.Reporting; -using System.IO; -using Microsoft.Sales.History; -using Microsoft.Foundation.UOM; +using Microsoft.CRM.Team; using Microsoft.Finance.Currency; using Microsoft.Finance.GeneralLedger.Setup; +using Microsoft.Finance.VAT.Setup; +using Microsoft.Foundation.Address; using Microsoft.Foundation.Company; +using Microsoft.Foundation.PaymentTerms; +using Microsoft.Foundation.Reporting; +using Microsoft.Foundation.UOM; +using Microsoft.Inventory.Location; +using Microsoft.Sales.Customer; +using Microsoft.Sales.History; +using System.IO; using System.Reflection; +using System.Telemetry; +using System.Utilities; codeunit 13917 "Export ZUGFeRD Document" { @@ -305,6 +308,15 @@ codeunit 13917 "Export ZUGFeRD Document" Contact: Text[100]; CustomerEmail: Text[250]; PhoneNumber: Text[30]; + SellerStreetName: Text; + SellerAdditionalStreetName: Text; + SellerCityName: Text; + SellerContactName: Text; + SellerEmailAddress: Text; + SellerPhoneNumber: Text; + SellerPostalZone: Text; + SellerCountryCode: Code[2]; + RespCentrCode: Code[10]; begin if not DataTypeManagement.GetRecordRef(RecordVariant, HeaderRecordRef) then exit; @@ -325,6 +337,8 @@ codeunit 13917 "Export ZUGFeRD Document" ReportSelections.FindEmailBodyUsageForCust("Report Selection Usage"::"S.Invoice", CustomerNo, TempBodyReportSelections); CustomerEmail := ReportSelections.GetEmailAddressExt("Report Selection Usage"::"S.Invoice".AsInteger(), RecordVariant, CustomerNo, TempBodyReportSelections); PhoneNumber := SalesInvoiceHeader."Sell-to Phone No."; + RespCentrCode := SalesInvoiceHeader."Responsibility Center"; + GetSellerContactInfo(SalesInvoiceHeader, SellerContactName, SellerPhoneNumber, SellerEmailAddress); end; Database::"Sales Cr.Memo Header": begin @@ -342,9 +356,12 @@ codeunit 13917 "Export ZUGFeRD Document" ReportSelections.FindEmailBodyUsageForCust("Report Selection Usage"::"S.Cr.Memo", CustomerNo, TempBodyReportSelections); CustomerEmail := ReportSelections.GetEmailAddressExt("Report Selection Usage"::"S.Cr.Memo".AsInteger(), RecordVariant, CustomerNo, TempBodyReportSelections); PhoneNumber := SalesCrMemoHeader."Sell-to Phone No."; + RespCentrCode := SalesCrMemoHeader."Responsibility Center"; + GetSellerContactInfo(SalesCrMemoHeader, SellerContactName, SellerPhoneNumber, SellerEmailAddress); end; end; + GetSellerPostalAddr(RespCentrCode, SellerStreetName, SellerAdditionalStreetName, SellerCityName, SellerPostalZone, SellerCountryCode); HeaderTradeAgreementElement := XmlElement.Create('ApplicableHeaderTradeAgreement', XmlNamespaceRAM); HeaderTradeAgreementElement.Add(XmlElement.Create('BuyerReference', XmlNamespaceRAM, GetBuyerReference(YourReference, CustomerNo))); @@ -357,26 +374,26 @@ codeunit 13917 "Export ZUGFeRD Document" SellerTradePartyElement.Add(XmlElement.Create('Name', XmlNamespaceRAM, CompanyInformation.Name)); // Seller Contact - if CompanyInformation."Phone No." <> '' then begin + if SellerPhoneNumber <> '' then begin ContactElement := XmlElement.Create('DefinedTradeContact', XmlNamespaceRAM); - ContactElement.Add(XmlElement.Create('PersonName', XmlNamespaceRAM, CompanyInformation."Contact Person")); + ContactElement.Add(XmlElement.Create('PersonName', XmlNamespaceRAM, SellerContactName)); ContactElement.Add(XmlElement.Create('TelephoneUniversalCommunication', XmlNamespaceRAM, - XmlElement.Create('CompleteNumber', XmlNamespaceRAM, CompanyInformation."Phone No."))); - if CompanyInformation."E-Mail" <> '' then + XmlElement.Create('CompleteNumber', XmlNamespaceRAM, SellerPhoneNumber))); + if SellerEmailAddress <> '' then ContactElement.Add(XmlElement.Create('EmailURIUniversalCommunication', XmlNamespaceRAM, - XmlElement.Create('URIID', XmlNamespaceRAM, CompanyInformation."E-Mail"))); + XmlElement.Create('URIID', XmlNamespaceRAM, SellerEmailAddress))); SellerTradePartyElement.Add(ContactElement); end; // Seller Address PostalTradeAddressElement := XmlElement.Create('PostalTradeAddress', XmlNamespaceRAM); - PostalTradeAddressElement.Add(XmlElement.Create('PostcodeCode', XmlNamespaceRAM, CompanyInformation."Post Code")); - PostalTradeAddressElement.Add(XmlElement.Create('LineOne', XmlNamespaceRAM, CompanyInformation.Address)); - if CompanyInformation."Address 2" <> '' then - PostalTradeAddressElement.Add(XmlElement.Create('LineTwo', XmlNamespaceRAM, CompanyInformation."Address 2")); - PostalTradeAddressElement.Add(XmlElement.Create('CityName', XmlNamespaceRAM, CompanyInformation.City)); - PostalTradeAddressElement.Add(XmlElement.Create('CountryID', XmlNamespaceRAM, GetCountryRegionCode(CompanyInformation."Country/Region Code"))); + PostalTradeAddressElement.Add(XmlElement.Create('PostcodeCode', XmlNamespaceRAM, SellerPostalZone)); + PostalTradeAddressElement.Add(XmlElement.Create('LineOne', XmlNamespaceRAM, SellerStreetName)); + if SellerAdditionalStreetName <> '' then + PostalTradeAddressElement.Add(XmlElement.Create('LineTwo', XmlNamespaceRAM, SellerAdditionalStreetName)); + PostalTradeAddressElement.Add(XmlElement.Create('CityName', XmlNamespaceRAM, SellerCityName)); + PostalTradeAddressElement.Add(XmlElement.Create('CountryID', XmlNamespaceRAM, GetCountryISOCode(SellerCountryCode))); SellerTradePartyElement.Add(PostalTradeAddressElement); //Seller E-Mail @@ -386,7 +403,7 @@ codeunit 13917 "Export ZUGFeRD Document" if CompanyInformation."VAT Registration No." <> '' then begin SellerIDAttr := XmlAttribute.Create('schemeID', 'VA'); - IDElement := XmlElement.Create('ID', XmlNamespaceRAM, SellerIDAttr, GetVATRegistrationNo(CompanyInformation."VAT Registration No.", CompanyInformation."Country/Region Code")); + IDElement := XmlElement.Create('ID', XmlNamespaceRAM, SellerIDAttr, GetVATRegistrationNo(CompanyInformation."VAT Registration No.", SellerCountryCode)); SpecifiedTaxRegistrationElement := XmlElement.Create('SpecifiedTaxRegistration', XmlNamespaceRAM); SpecifiedTaxRegistrationElement.Add(IDElement); SellerTradePartyElement.Add(SpecifiedTaxRegistrationElement); @@ -417,7 +434,7 @@ codeunit 13917 "Export ZUGFeRD Document" if Address2 <> '' then PostalTradeAddressElement.Add(XmlElement.Create('LineTwo', XmlNamespaceRAM, Address2)); PostalTradeAddressElement.Add(XmlElement.Create('CityName', XmlNamespaceRAM, City)); - PostalTradeAddressElement.Add(XmlElement.Create('CountryID', XmlNamespaceRAM, GetCountryRegionCode(CountryCode))); + PostalTradeAddressElement.Add(XmlElement.Create('CountryID', XmlNamespaceRAM, GetCountryISOCode(GetCountryRegionCode(CountryCode)))); BuyerTradePartyElement.Add(PostalTradeAddressElement); // Buyer E-Mail @@ -449,7 +466,7 @@ codeunit 13917 "Export ZUGFeRD Document" PostalAddressElement.Add(XmlElement.Create('PostcodeCode', XmlNamespaceRAM, SalesInvoiceHeader."Sell-to Post Code")); PostalAddressElement.Add(XmlElement.Create('LineOne', XmlNamespaceRAM, SalesInvoiceHeader."Sell-to Address")); PostalAddressElement.Add(XmlElement.Create('CityName', XmlNamespaceRAM, SalesInvoiceHeader."Sell-to City")); - PostalAddressElement.Add(XmlElement.Create('CountryID', XmlNamespaceRAM, GetCountryRegionCode(SalesInvoiceHeader."Sell-to Country/Region Code"))); + PostalAddressElement.Add(XmlElement.Create('CountryID', XmlNamespaceRAM, GetCountryISOCode(GetCountryRegionCode(SalesInvoiceHeader."Sell-to Country/Region Code")))); ShipToPartyElement.Add(PostalAddressElement); DeliveryElement.Add(ShipToPartyElement); @@ -469,7 +486,7 @@ codeunit 13917 "Export ZUGFeRD Document" PostalAddressElement.Add(XmlElement.Create('PostcodeCode', XmlNamespaceRAM, SalesCrMemoHeader."Sell-to Post Code")); PostalAddressElement.Add(XmlElement.Create('LineOne', XmlNamespaceRAM, SalesCrMemoHeader."Sell-to Address")); PostalAddressElement.Add(XmlElement.Create('CityName', XmlNamespaceRAM, SalesCrMemoHeader."Sell-to City")); - PostalAddressElement.Add(XmlElement.Create('CountryID', XmlNamespaceRAM, GetCountryRegionCode(SalesCrMemoHeader."Sell-to Country/Region Code"))); + PostalAddressElement.Add(XmlElement.Create('CountryID', XmlNamespaceRAM, GetCountryISOCode(GetCountryRegionCode(SalesCrMemoHeader."Sell-to Country/Region Code")))); ShipToPartyElement.Add(PostalAddressElement); DeliveryElement.Add(ShipToPartyElement); @@ -954,6 +971,62 @@ codeunit 13917 "Export ZUGFeRD Document" IBANFormatted := UpperCase(DelChr(IBAN, '=', ' ')); exit(CopyStr(IBANFormatted, 1, 50)); end; + + local procedure GetSellerPostalAddr(RespCentercode: Code[10]; var StreetName: Text; var SupplierAdditionalStreetName: Text; var CityName: Text; var PostalZone: Text; var CountryRegionCode: Code[10]) + var + RespCenter: Record "Responsibility Center"; + begin + if RespCenter.Get(RespCentercode) then begin + StreetName := RespCenter.Address; + SupplierAdditionalStreetName := RespCenter."Address 2"; + CityName := RespCenter.City; + PostalZone := RespCenter."Post Code"; + CountryRegionCode := GetCountryRegionCode(RespCenter."Country/Region Code"); + exit; + end; + StreetName := CompanyInformation.Address; + SupplierAdditionalStreetName := CompanyInformation."Address 2"; + CityName := CompanyInformation.City; + PostalZone := CompanyInformation."Post Code"; + CountryRegionCode := CompanyInformation."Country/Region Code"; + end; + + local procedure GetSellerContactInfo(SalesInvoiceHeader: Record "Sales Invoice Header"; var ContactName: Text; var PhoneNumber: Text; var EmailAddress: Text) + begin + if SetSellerContactFromSalesPerson(SalesInvoiceHeader."Salesperson Code", ContactName, PhoneNumber, EmailAddress) then + exit; + SetSellerContactFromCompanyInformation(ContactName, PhoneNumber, EmailAddress); + end; + + local procedure GetSellerContactInfo(SalesCrMemoHeader: Record "Sales Cr.Memo Header"; var ContactName: Text; var PhoneNumber: Text; var EmailAddress: Text) + begin + if SetSellerContactFromSalesPerson(SalesCrMemoHeader."Salesperson Code", ContactName, PhoneNumber, EmailAddress) then + exit; + SetSellerContactFromCompanyInformation(ContactName, PhoneNumber, EmailAddress); + end; + + local procedure SetSellerContactFromSalesPerson(SalesPersonCode: Code[20]; var ContactName: Text; var PhoneNumber: Text; var EmailAddress: Text): Boolean + var + Salesperson: Record "Salesperson/Purchaser"; + begin + if SalesPersonCode = '' then + exit(false); + Salesperson.SetLoadFields(Name, "Phone No.", "E-Mail"); + if not Salesperson.Get(SalesPersonCode) then + exit(false); + ContactName := Salesperson.Name; + PhoneNumber := Salesperson."Phone No."; + EmailAddress := Salesperson."E-Mail"; + exit(true); + end; + + local procedure SetSellerContactFromCompanyInformation(var ContactName: Text; var PhoneNumber: Text; var EmailAddress: Text) + begin + ContactName := CompanyInformation."Contact Person"; + PhoneNumber := CompanyInformation."Phone No."; + EmailAddress := CompanyInformation."E-Mail"; + end; + #region CommonFunctions local procedure GetSetups() begin @@ -1014,6 +1087,14 @@ codeunit 13917 "Export ZUGFeRD Document" exit(CompanyInformation."Country/Region Code"); end; + local procedure GetCountryISOCode(CountryRegionCode: Code[10]): Code[2] + var + CountryRegion: Record "Country/Region"; + begin + CountryRegion.Get(CountryRegionCode); + exit(CountryRegion."ISO Code"); + end; + procedure GetVATRegistrationNo(VATRegistrationNo: Text[20]; CountryRegionCode: Code[10]): Text[30]; begin if CountryRegionCode = '' then diff --git a/Apps/DE/EDocumentDE/test/src/XRechnungXMLDocumentTests.Codeunit.al b/Apps/DE/EDocumentDE/test/src/XRechnungXMLDocumentTests.Codeunit.al index 00bce42a3c..e56b46833e 100644 --- a/Apps/DE/EDocumentDE/test/src/XRechnungXMLDocumentTests.Codeunit.al +++ b/Apps/DE/EDocumentDE/test/src/XRechnungXMLDocumentTests.Codeunit.al @@ -18,6 +18,7 @@ using Microsoft.Finance.Currency; using Microsoft.eServices.EDocument.Integration; using Microsoft.Finance.GeneralLedger.Setup; using Microsoft.Foundation.PaymentTerms; +using Microsoft.Inventory.Location; codeunit 13918 "XRechnung XML Document Tests" { @@ -346,6 +347,29 @@ codeunit 13918 "XRechnung XML Document Tests" // [THEN] PDF is embedded in the XML VerifyInvoicePDFEmbeddedToXML(TempXMLBuffer); end; + + [Test] + procedure ExportPostedSalesInvoiceInXRechnungFormatVerifySellerAddressFromRespCenter(); + var + ResponsibilityCenter: Record "Responsibility Center"; + SalesInvoiceHeader: Record "Sales Invoice Header"; + TempXMLBuffer: Record "XML Buffer" temporary; + begin + // [SCENARIO] Export posted sales invoice creates electronic document in XRechnung format with seller info from responsibility center + Initialize(); + + // [GIVEN] Responsibility Center + CreateResponsibilityCenter(ResponsibilityCenter); + + // [GIVEN] Create and Post Sales Invoice. + SalesInvoiceHeader.Get(CreateAndPostSalesDocumentWithRespCenter("Sales Document Type"::Invoice, Enum::"Sales Line Type"::Item, ResponsibilityCenter.Code)); + + // [WHEN] Export XRechnung Electronic Document. + ExportInvoice(SalesInvoiceHeader, TempXMLBuffer); + + // [THEN] XRechnung Electronic Document is created with company data as accounting supplier party + VerifyAccountingSupplierParty(TempXMLBuffer, '/ubl:Invoice/cac:AccountingSupplierParty/cac:Party', ResponsibilityCenter); + end; #endregion #region SalesCreditMemo @@ -629,6 +653,29 @@ codeunit 13918 "XRechnung XML Document Tests" // [THEN] PDF is embedded in the XML VerifyCrMemoPDFEmbeddedToXML(TempXMLBuffer); end; + + [Test] + procedure ExportPostedSalesCrMemoInXRechnungFormatVerifySellerAddressFromRespCenter(); + var + ResponsibilityCenter: Record "Responsibility Center"; + SalesCrMemoHeader: Record "Sales Cr.Memo Header"; + TempXMLBuffer: Record "XML Buffer" temporary; + begin + // [SCENARIO] Export posted sales credit memo creates electronic document in XRechnung format with seller info from responsibility center + Initialize(); + + // [GIVEN] Responsibility Center + CreateResponsibilityCenter(ResponsibilityCenter); + + // [GIVEN] Create and Post Sales Invoice. + SalesCrMemoHeader.Get(CreateAndPostSalesDocumentWithRespCenter("Sales Document Type"::"Credit Memo", Enum::"Sales Line Type"::Item, ResponsibilityCenter.Code)); + + // [WHEN] Export XRechnung Electronic Document. + ExportCreditMemo(SalesCrMemoHeader, TempXMLBuffer); + + // [THEN] XRechnung Electronic Document is created with company data as accounting supplier party + VerifyAccountingSupplierParty(TempXMLBuffer, '/ns0:CreditNote/cac:AccountingSupplierParty/cac:Party', ResponsibilityCenter); + end; #endregion #region PurchaseInvoice @@ -695,6 +742,14 @@ codeunit 13918 "XRechnung XML Document Tests" exit(LibrarySales.PostSalesDocument(SalesHeader, true, true)); end; + local procedure CreateAndPostSalesDocumentWithRespCenter(DocumentType: Enum "Sales Document Type"; LineType: Enum "Sales Line Type"; RespCenterCode: Code[10]): Code[20]; + var + SalesHeader: Record "Sales Header"; + begin + SalesHeader.Get(DocumentType, CreateSalesDocumentWithLine(DocumentType, LineType, false, RespCenterCode)); + 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"; @@ -716,11 +771,20 @@ codeunit 13918 "XRechnung XML Document Tests" PurchaseHeader.Modify(true); end; - local procedure CreateSalesDocumentWithLine(DocumentType: Enum "Sales Document Type"; LineType: Enum "Sales Line Type"; InvoiceDiscount: Boolean): Code[20]; + local procedure CreateSalesDocumentWithLine(DocumentType: Enum "Sales Document Type"; LineType: Enum "Sales Line Type"; InvoiceDiscount: Boolean): Code[20] + begin + exit(CreateSalesDocumentWithLine(DocumentType, LineType, InvoiceDiscount, '')); + end; + + local procedure CreateSalesDocumentWithLine(DocumentType: Enum "Sales Document Type"; LineType: Enum "Sales Line Type"; InvoiceDiscount: Boolean; RespCenterCode: Code[20]): Code[20] var SalesHeader: Record "Sales Header"; begin CreateSalesHeader(SalesHeader, DocumentType); + if RespCenterCode <> '' then begin + SalesHeader.Validate("Responsibility Center", RespCenterCode); + SalesHeader.Modify(true); + end; CreateSalesLine(SalesHeader, LineType, false); if InvoiceDiscount then @@ -796,6 +860,20 @@ codeunit 13918 "XRechnung XML Document Tests" exit(Customer."No.") end; + local procedure CreateResponsibilityCenter(var ResponsibilityCenter: Record "Responsibility Center") + begin + ResponsibilityCenter.Init(); + ResponsibilityCenter.Validate(Code, LibraryUtility.GenerateRandomCode(ResponsibilityCenter.FieldNo(Code), DATABASE::"Responsibility Center")); + ResponsibilityCenter.Validate(Name, ResponsibilityCenter.Code); // Validating Code as Name because value is not important. + ResponsibilityCenter.Insert(true); + ResponsibilityCenter.Address := CopyStr(LibraryUtility.GenerateRandomText(10), 1, MaxStrLen(ResponsibilityCenter.Address)); + ResponsibilityCenter."Address 2" := CopyStr(LibraryUtility.GenerateRandomText(10), 1, MaxStrLen(ResponsibilityCenter."Address 2")); + ResponsibilityCenter."Post Code" := CopyStr(LibraryUtility.GenerateRandomText(10), 1, MaxStrLen(ResponsibilityCenter."Post Code")); + ResponsibilityCenter.City := CopyStr(LibraryUtility.GenerateRandomText(10), 1, MaxStrLen(ResponsibilityCenter.City)); + ResponsibilityCenter."Country/Region Code" := CompanyInformation."Country/Region Code"; + ResponsibilityCenter.Modify(true); + end; + local procedure CreateSalesLine(SalesHeader: Record "Sales Header"; LineType: Enum "Sales Line Type"; LineDiscount: Boolean); var SalesLine: Record "Sales Line"; @@ -892,16 +970,30 @@ codeunit 13918 "XRechnung XML Document Tests" Assert.AreEqual(BuyerReference, GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path)); end; - local procedure VerifyAccountingSupplierParty(var TempXMLBuffer: Record "XML Buffer" temporary; DocumentTok: Text); + local procedure VerifyAccountingSupplierParty(var TempXMLBuffer: Record "XML Buffer" temporary; DocumentTok: Text) + var + Path: Text; + begin + VerifyAccountingSupplierParty(TempXMLBuffer, DocumentTok, CompanyInformation.Address, CompanyInformation."Post Code", CompanyInformation.City); + end; + + local procedure VerifyAccountingSupplierParty(var TempXMLBuffer: Record "XML Buffer" temporary; DocumentTok: Text; ResponsibilityCenter: Record "Responsibility Center") + var + Path: Text; + begin + VerifyAccountingSupplierParty(TempXMLBuffer, DocumentTok, ResponsibilityCenter.Address, ResponsibilityCenter."Post Code", ResponsibilityCenter.City); + end; + + local procedure VerifyAccountingSupplierParty(var TempXMLBuffer: Record "XML Buffer" temporary; DocumentTok: Text; Address: Text; PostCode: Code[20]; City: Text[30]) var Path: Text; begin Path := DocumentTok + '/cac:PostalAddress/cbc:StreetName'; - Assert.AreEqual(CompanyInformation.Address, GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path)); + Assert.AreEqual(Address, GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path)); Path := DocumentTok + '/cac:PostalAddress/cbc:CityName'; - Assert.AreEqual(CompanyInformation.City, GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path)); + Assert.AreEqual(City, GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path)); Path := DocumentTok + '/cac:PostalAddress/cbc:PostalZone'; - Assert.AreEqual(CompanyInformation."Post Code", GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path)); + Assert.AreEqual(PostCode, GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path)); Path := DocumentTok + '/cac:PartyTaxScheme/cbc:CompanyID'; Assert.AreEqual(GetVATRegistrationNo(CompanyInformation."VAT Registration No.", CompanyInformation."Country/Region Code"), GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path)); diff --git a/Apps/DE/EDocumentDE/test/src/ZUGFeRDXMLDocumentTests.Codeunit.al b/Apps/DE/EDocumentDE/test/src/ZUGFeRDXMLDocumentTests.Codeunit.al index 0b010d877b..399faba73c 100644 --- a/Apps/DE/EDocumentDE/test/src/ZUGFeRDXMLDocumentTests.Codeunit.al +++ b/Apps/DE/EDocumentDE/test/src/ZUGFeRDXMLDocumentTests.Codeunit.al @@ -21,6 +21,7 @@ using Microsoft.eServices.EDocument.Integration; using Microsoft.Finance.GeneralLedger.Setup; using Microsoft.Foundation.PaymentTerms; using Microsoft.Foundation.Reporting; +using Microsoft.Inventory.Location; codeunit 13922 "ZUGFeRD XML Document Tests" { @@ -156,6 +157,29 @@ codeunit 13922 "ZUGFeRD XML Document Tests" VerifySellerData(TempXMLBuffer, '/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty'); end; + [Test] + procedure ExportPostedSalesInvoiceInZUGFeRDFormatWithRespCenterVerifySellerDataApplicableHeaderTradeAgreement(); + var + ResponsibilityCenter: Record "Responsibility Center"; + SalesInvoiceHeader: Record "Sales Invoice Header"; + TempXMLBuffer: Record "XML Buffer" temporary; + begin + // [SCENARIO] Export posted sales invoice creates electronic document in ZUGFeRD format with responsibility center data as seller in applicable header trade agreement + Initialize(); + + // [GIVEN] Responsibility Center + CreateResponsibilityCenter(ResponsibilityCenter); + + // [GIVEN] Create and Post Sales Invoice. + SalesInvoiceHeader.Get(CreateAndPostSalesDocumentWithRespCenter("Sales Document Type"::Invoice, Enum::"Sales Line Type"::Item, ResponsibilityCenter.Code)); + + // [WHEN] Export ZUGFeRD Electronic Document. + ExportInvoice(SalesInvoiceHeader, TempXMLBuffer); + + // [THEN] ZUGFeRD Electronic Document is created with responsibility data as seller in applicable header trade agreement + VerifySellerData(TempXMLBuffer, '/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty', ResponsibilityCenter); + end; + [Test] procedure ExportPostedSalesInvoiceInZUGFeRDFormatVerifyBuyerDataApplicableHeaderTradeAgreement(); var @@ -509,6 +533,29 @@ codeunit 13922 "ZUGFeRD XML Document Tests" VerifySellerData(TempXMLBuffer, '/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty'); end; + [Test] + procedure ExportPostedSalesCrMemoInZUGFeRDFormatWithRespCenterVerifySellerDataApplicableHeaderTradeAgreement(); + var + ResponsibilityCenter: Record "Responsibility Center"; + SalesCrMemoHeader: Record "Sales Cr.Memo Header"; + TempXMLBuffer: Record "XML Buffer" temporary; + begin + // [SCENARIO] Export posted sales cr. memo creates electronic document in ZUGFeRD format with responsibility center data as seller in applicable header trade agreement + Initialize(); + + // [GIVEN] Responsibility Center + CreateResponsibilityCenter(ResponsibilityCenter); + + // [GIVEN] Create and Post sales cr. memo. + SalesCrMemoHeader.Get(CreateAndPostSalesDocumentWithRespCenter("Sales Document Type"::"Credit Memo", Enum::"Sales Line Type"::Item, ResponsibilityCenter.Code)); + + // [WHEN] Export ZUGFeRD Electronic Document. + ExportCreditMemo(SalesCrMemoHeader, TempXMLBuffer); + + // [THEN] ZUGFeRD Electronic Document is created with responsibility data as seller in applicable header trade agreement + VerifySellerData(TempXMLBuffer, '/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty', ResponsibilityCenter); + end; + [Test] procedure ExportPostedSalesCrMemoInZUGFeRDFormatVerifyBuyerDataApplicableHeaderTradeAgreement(); var @@ -750,6 +797,14 @@ codeunit 13922 "ZUGFeRD XML Document Tests" exit(LibrarySales.PostSalesDocument(SalesHeader, true, true)); end; + local procedure CreateAndPostSalesDocumentWithRespCenter(DocumentType: Enum "Sales Document Type"; LineType: Enum "Sales Line Type"; RespCenterCode: Code[10]): Code[20]; + var + SalesHeader: Record "Sales Header"; + begin + SalesHeader.Get(DocumentType, CreateSalesDocumentWithLine(DocumentType, LineType, false, RespCenterCode)); + 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"; @@ -771,11 +826,20 @@ codeunit 13922 "ZUGFeRD XML Document Tests" PurchaseHeader.Modify(true); end; - local procedure CreateSalesDocumentWithLine(DocumentType: Enum "Sales Document Type"; LineType: Enum "Sales Line Type"; InvoiceDiscount: Boolean): Code[20]; + local procedure CreateSalesDocumentWithLine(DocumentType: Enum "Sales Document Type"; LineType: Enum "Sales Line Type"; InvoiceDiscount: Boolean): Code[20] + begin + exit(CreateSalesDocumentWithLine(DocumentType, LineType, InvoiceDiscount, '')); + end; + + local procedure CreateSalesDocumentWithLine(DocumentType: Enum "Sales Document Type"; LineType: Enum "Sales Line Type"; InvoiceDiscount: Boolean; RespCenterCode: Code[20]): Code[20] var SalesHeader: Record "Sales Header"; begin CreateSalesHeader(SalesHeader, DocumentType); + if RespCenterCode <> '' then begin + SalesHeader.Validate("Responsibility Center", RespCenterCode); + SalesHeader.Modify(true); + end; CreateSalesLine(SalesHeader, LineType, false); if InvoiceDiscount then @@ -856,6 +920,20 @@ codeunit 13922 "ZUGFeRD XML Document Tests" exit(Customer."No.") end; + local procedure CreateResponsibilityCenter(var ResponsibilityCenter: Record "Responsibility Center") + begin + ResponsibilityCenter.Init(); + ResponsibilityCenter.Validate(Code, LibraryUtility.GenerateRandomCode(ResponsibilityCenter.FieldNo(Code), DATABASE::"Responsibility Center")); + ResponsibilityCenter.Validate(Name, ResponsibilityCenter.Code); // Validating Code as Name because value is not important. + ResponsibilityCenter.Insert(true); + ResponsibilityCenter.Address := CopyStr(LibraryUtility.GenerateRandomText(10), 1, MaxStrLen(ResponsibilityCenter.Address)); + ResponsibilityCenter."Address 2" := CopyStr(LibraryUtility.GenerateRandomText(10), 1, MaxStrLen(ResponsibilityCenter."Address 2")); + ResponsibilityCenter."Post Code" := CopyStr(LibraryUtility.GenerateRandomText(10), 1, MaxStrLen(ResponsibilityCenter."Post Code")); + ResponsibilityCenter.City := CopyStr(LibraryUtility.GenerateRandomText(10), 1, MaxStrLen(ResponsibilityCenter.City)); + ResponsibilityCenter."Country/Region Code" := CompanyInformation."Country/Region Code"; + ResponsibilityCenter.Modify(true); + end; + local procedure CreateSalesLine(SalesHeader: Record "Sales Header"; LineType: Enum "Sales Line Type"; LineDiscount: Boolean); var SalesLine: Record "Sales Line"; @@ -962,15 +1040,28 @@ codeunit 13922 "ZUGFeRD XML Document Tests" end; local procedure VerifySellerData(var TempXMLBuffer: Record "XML Buffer" temporary; DocumentTok: Text); + begin + VerifySellerData(TempXMLBuffer, DocumentTok, CompanyInformation.Address, CompanyInformation."Post Code", CompanyInformation.City); + end; + + local procedure VerifySellerData(var TempXMLBuffer: Record "XML Buffer" temporary; DocumentTok: Text; ResponsibilityCenter: Record "Responsibility Center"); + begin + VerifySellerData(TempXMLBuffer, DocumentTok, ResponsibilityCenter.Address, ResponsibilityCenter."Post Code", ResponsibilityCenter.City); + end; + + local procedure VerifySellerData(var TempXMLBuffer: Record "XML Buffer" temporary; DocumentTok: Text; Address: Text[100]; PostCode: Code[20]; City: Text[30]) var Path: Text; begin Path := DocumentTok + '/ram:Name'; Assert.AreEqual(CompanyInformation.Name, GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path)); + + Path := DocumentTok + '/ram:PostalTradeAddress/ram:LineOne'; + Assert.AreEqual(Address, GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path)); Path := DocumentTok + '/ram:PostalTradeAddress/ram:PostcodeCode'; - Assert.AreEqual(CompanyInformation."Post Code", GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path)); + Assert.AreEqual(PostCode, GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path)); Path := DocumentTok + '/ram:PostalTradeAddress/ram:CityName'; - Assert.AreEqual(CompanyInformation.City, GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path)); + Assert.AreEqual(City, GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path)); Path := DocumentTok + '/ram:URIUniversalCommunication/ram:URIID'; Assert.AreEqual(CompanyInformation."E-Mail", GetNodeByPathWithError(TempXMLBuffer, Path), StrSubstNo(IncorrectValueErr, Path));