-
Notifications
You must be signed in to change notification settings - Fork 441
[FR E-Reporting] Add payment and invoice lifecycle messages #10437
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 24 commits
08c3cc0
31b4bb0
dc09a12
31387e6
161edf4
53b2023
bcef50b
54fcc33
6cff425
6a85318
19a729b
7a454d7
dc578d2
c55c5d4
70ca478
80c8837
67d718e
05f4c34
f5b8567
62dd4e4
ad98e96
bb53620
2e6e4e3
e3a91c8
372c19e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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.Formats; | ||
|
|
||
| using Microsoft.eServices.EDocument; | ||
|
|
||
| permissionset 10988 "E-Reporting FR User" | ||
| { | ||
| Assignable = true; | ||
| Caption = 'E-Reporting FR - User'; | ||
|
|
||
| IncludedPermissionSets = "E-Doc. Core - User"; | ||
|
|
||
| Permissions = | ||
| table "FR E-Invoice Message" = X, | ||
| tabledata "FR E-Invoice Message" = RIMD, | ||
| table "FR E-Invoice Message VAT" = X, | ||
| tabledata "FR E-Invoice Message VAT" = R, | ||
| codeunit "FR E-Invoice Message Mgt." = X, | ||
| codeunit "FR E-Invoice Message Builder" = X, | ||
| codeunit "FR E-Invoice Profile Validator" = X, | ||
| codeunit "FR E-Invoice Message API" = X, | ||
| page "FR E-Invoice Refusal Dialog" = X, | ||
| page "FR E-Invoice Messages" = X; | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -158,6 +158,7 @@ codeunit 10978 "CII XML Builder" | |||||||||||||||
|
|
||||||||||||||||
| AddSellerTradeParty(AgreementElement, CompanyInformation); | ||||||||||||||||
| AddBuyerTradeParty(AgreementElement, SourceDocumentHeader); | ||||||||||||||||
| AddInvoiceReferencedDocument(AgreementElement, SourceDocumentHeader); | ||||||||||||||||
|
|
||||||||||||||||
| // BT-13 Purchase order reference | ||||||||||||||||
| if FREDocHelpers.FindFieldByName(SourceDocumentHeader, 'Order No.', FieldRefVar) then | ||||||||||||||||
|
|
@@ -175,6 +176,35 @@ codeunit 10978 "CII XML Builder" | |||||||||||||||
| TransactionElement.Add(AgreementElement); | ||||||||||||||||
| end; | ||||||||||||||||
|
|
||||||||||||||||
| local procedure AddInvoiceReferencedDocument(var AgreementElement: XmlElement; var SourceDocumentHeader: RecordRef) | ||||||||||||||||
| var | ||||||||||||||||
| SalesInvoiceHeader: Record "Sales Invoice Header"; | ||||||||||||||||
| FREDocHelpers: Codeunit "EDoc. Helpers"; | ||||||||||||||||
| AppliesToDocumentNoFieldRef: FieldRef; | ||||||||||||||||
| DateStringElement: XmlElement; | ||||||||||||||||
| FormattedIssueDateElement: XmlElement; | ||||||||||||||||
| InvoiceReferenceElement: XmlElement; | ||||||||||||||||
| AppliesToDocumentNo: Code[20]; | ||||||||||||||||
| begin | ||||||||||||||||
| if SourceDocumentHeader.Number() <> Database::"Sales Cr.Memo Header" then | ||||||||||||||||
| exit; | ||||||||||||||||
| if not FREDocHelpers.FindFieldByName(SourceDocumentHeader, 'Applies-to Doc. No.', AppliesToDocumentNoFieldRef) then | ||||||||||||||||
| exit; | ||||||||||||||||
|
|
||||||||||||||||
| AppliesToDocumentNo := AppliesToDocumentNoFieldRef.Value(); | ||||||||||||||||
| if (AppliesToDocumentNo = '') or not SalesInvoiceHeader.Get(AppliesToDocumentNo) then | ||||||||||||||||
| exit; | ||||||||||||||||
|
Comment on lines
+194
to
+196
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AddInvoiceReferencedDocument loads the full Sales Invoice Header row even though it only reads "Document Date". This is the partial-record anti-pattern on a wide posted-document table; call SetLoadFields before Get so the credit-memo reference lookup does not transfer unused columns.
Suggested change
Knowledge: 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.35.4 |
||||||||||||||||
|
|
||||||||||||||||
| InvoiceReferenceElement := XmlElement.Create('InvoiceReferencedDocument', RamNamespaceTok); | ||||||||||||||||
| InvoiceReferenceElement.Add(XmlElement.Create('IssuerAssignedID', RamNamespaceTok, AppliesToDocumentNo)); | ||||||||||||||||
| FormattedIssueDateElement := XmlElement.Create('FormattedIssueDateTime', RamNamespaceTok); | ||||||||||||||||
| DateStringElement := XmlElement.Create('DateTimeString', QdtNamespaceTok, FormatDate(SalesInvoiceHeader."Document Date")); | ||||||||||||||||
| DateStringElement.SetAttribute('format', '102'); | ||||||||||||||||
| FormattedIssueDateElement.Add(DateStringElement); | ||||||||||||||||
| InvoiceReferenceElement.Add(FormattedIssueDateElement); | ||||||||||||||||
| AgreementElement.Add(InvoiceReferenceElement); | ||||||||||||||||
| end; | ||||||||||||||||
|
|
||||||||||||||||
| local procedure AddSellerTradeParty(var AgreementElement: XmlElement; CompanyInformation: Record "Company Information") | ||||||||||||||||
| var | ||||||||||||||||
| SellerElement: XmlElement; | ||||||||||||||||
|
|
@@ -268,6 +298,31 @@ codeunit 10978 "CII XML Builder" | |||||||||||||||
| AgreementElement.Add(BuyerElement); | ||||||||||||||||
| end; | ||||||||||||||||
|
|
||||||||||||||||
| procedure TryGetBuyerElectronicAddress(Customer: Record Customer; var BuyerElectronicAddress: Text): Boolean | ||||||||||||||||
| var | ||||||||||||||||
| VATRegistrationNo: Text; | ||||||||||||||||
| begin | ||||||||||||||||
| if Customer."FR Electronic Address" <> '' then begin | ||||||||||||||||
| BuyerElectronicAddress := Customer."FR Electronic Address"; | ||||||||||||||||
| exit(true); | ||||||||||||||||
| end; | ||||||||||||||||
|
|
||||||||||||||||
| if Customer."Registration Number" <> '' then begin | ||||||||||||||||
| BuyerElectronicAddress := CopyStr(Customer."Registration Number", 1, 14); | ||||||||||||||||
| exit(true); | ||||||||||||||||
| end; | ||||||||||||||||
|
|
||||||||||||||||
| VATRegistrationNo := UpperCase(DelChr(Customer."VAT Registration No.", '=', ' ')); | ||||||||||||||||
| if (StrLen(VATRegistrationNo) = 13) and (CopyStr(VATRegistrationNo, 1, 2) = 'FR') and | ||||||||||||||||
| (DelChr(CopyStr(VATRegistrationNo, 3), '=', '0123456789') = '') | ||||||||||||||||
| then begin | ||||||||||||||||
| BuyerElectronicAddress := CopyStr(VATRegistrationNo, 5, 9); | ||||||||||||||||
| exit(true); | ||||||||||||||||
| end; | ||||||||||||||||
|
|
||||||||||||||||
| exit(false); | ||||||||||||||||
| end; | ||||||||||||||||
|
|
||||||||||||||||
| local procedure GetHeaderFieldText(var SourceDocumentHeader: RecordRef; PrimaryFieldName: Text; FallbackFieldName: Text): Text | ||||||||||||||||
| var | ||||||||||||||||
| FREDocHelpers: Codeunit "EDoc. Helpers"; | ||||||||||||||||
|
|
||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,158 @@ | ||
| // ------------------------------------------------------------------------------------------------ | ||
| // 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.Formats; | ||
|
|
||
| using Microsoft.eServices.EDocument; | ||
|
|
||
| table 10970 "FR E-Invoice Message" | ||
| { | ||
| Caption = 'FR E-Invoice Message'; | ||
| DataClassification = CustomerContent; | ||
| InherentEntitlements = X; | ||
| InherentPermissions = X; | ||
| ReplicateData = false; | ||
|
|
||
| fields | ||
| { | ||
| field(1; "Entry No."; Integer) | ||
| { | ||
| AutoIncrement = true; | ||
| Caption = 'Entry No.'; | ||
| DataClassification = SystemMetadata; | ||
| } | ||
| field(2; "E-Document Entry No."; Integer) | ||
| { | ||
| Caption = 'E-Document Entry No.'; | ||
| DataClassification = SystemMetadata; | ||
| TableRelation = "E-Document"."Entry No"; | ||
| } | ||
| field(3; Type; Enum "FR E-Invoice Message Type") | ||
| { | ||
| Caption = 'Type'; | ||
| DataClassification = SystemMetadata; | ||
| } | ||
| field(4; "Source Occurrence ID"; Guid) | ||
| { | ||
| Caption = 'Source Occurrence ID'; | ||
| DataClassification = SystemMetadata; | ||
| } | ||
| field(5; "Original Entry No."; Integer) | ||
| { | ||
| Caption = 'Original Entry No.'; | ||
| DataClassification = SystemMetadata; | ||
| TableRelation = "FR E-Invoice Message"."Entry No."; | ||
| } | ||
| field(6; Amount; Decimal) | ||
| { | ||
| AutoFormatExpression = Rec."Currency Code"; | ||
| AutoFormatType = 1; | ||
| Caption = 'Amount'; | ||
| DataClassification = CustomerContent; | ||
| } | ||
| field(7; "Currency Code"; Code[10]) | ||
| { | ||
| Caption = 'Currency Code'; | ||
| DataClassification = CustomerContent; | ||
| } | ||
| field(8; "Event Date"; Date) | ||
| { | ||
| Caption = 'Event Date'; | ||
| DataClassification = CustomerContent; | ||
| } | ||
| field(9; "Detailed Ledger Entry No."; Integer) | ||
| { | ||
| Caption = 'Detailed Ledger Entry No.'; | ||
| DataClassification = SystemMetadata; | ||
| } | ||
| field(10; "Reason Code"; Code[20]) | ||
| { | ||
| Caption = 'Reason Code'; | ||
| DataClassification = CustomerContent; | ||
| } | ||
| field(11; "Reason Description"; Text[500]) | ||
| { | ||
| Caption = 'Reason Description'; | ||
| DataClassification = CustomerContent; | ||
| } | ||
| field(12; "E-Document Message Entry No."; Integer) | ||
|
djukicmilica marked this conversation as resolved.
|
||
| { | ||
| Caption = 'E-Document Message Entry No.'; | ||
| DataClassification = SystemMetadata; | ||
| } | ||
|
djukicmilica marked this conversation as resolved.
|
||
| field(13; "Created At"; DateTime) | ||
| { | ||
| Caption = 'Created At'; | ||
| DataClassification = SystemMetadata; | ||
| } | ||
| field(14; "External Message ID"; Text[250]) | ||
| { | ||
| Caption = 'External Message ID'; | ||
| DataClassification = CustomerContent; | ||
| } | ||
| field(15; "Received At"; DateTime) | ||
| { | ||
| Caption = 'Received At'; | ||
| DataClassification = SystemMetadata; | ||
| } | ||
| field(16; "Sender Platform ID"; Text[50]) | ||
| { | ||
| Caption = 'Sender Platform ID'; | ||
| DataClassification = OrganizationIdentifiableInformation; | ||
| } | ||
| field(17; "Sender Platform Scheme"; Code[4]) | ||
| { | ||
| Caption = 'Sender Platform Scheme'; | ||
| DataClassification = SystemMetadata; | ||
| } | ||
| field(18; "Sender Platform Name"; Text[100]) | ||
| { | ||
| Caption = 'Sender Platform Name'; | ||
| DataClassification = OrganizationIdentifiableInformation; | ||
| } | ||
| field(19; "Invoice Issue Date"; Date) | ||
| { | ||
| Caption = 'Invoice Issue Date'; | ||
| DataClassification = CustomerContent; | ||
| } | ||
| field(20; "Invoice Receipt At"; DateTime) | ||
| { | ||
| Caption = 'Invoice Receipt At'; | ||
| DataClassification = CustomerContent; | ||
| } | ||
| field(21; "Invoice Issuer ID"; Text[50]) | ||
| { | ||
| Caption = 'Invoice Issuer ID'; | ||
| DataClassification = OrganizationIdentifiableInformation; | ||
| } | ||
| field(22; "Invoice Issuer Scheme"; Code[4]) | ||
| { | ||
| Caption = 'Invoice Issuer Scheme'; | ||
| DataClassification = SystemMetadata; | ||
| } | ||
| field(23; "Invoice Issuer Name"; Text[100]) | ||
| { | ||
| Caption = 'Invoice Issuer Name'; | ||
| DataClassification = OrganizationIdentifiableInformation; | ||
| } | ||
| } | ||
|
|
||
| keys | ||
| { | ||
| key(PK; "Entry No.") | ||
| { | ||
| Clustered = true; | ||
| } | ||
| key(Occurrence; "E-Document Entry No.", "Source Occurrence ID", Type) | ||
| { | ||
| Unique = true; | ||
| } | ||
| key(DetailedLedgerEntry; Type, "Detailed Ledger Entry No.") | ||
| { | ||
| } | ||
| key(EDocumentMessage; "E-Document Message Entry No.") | ||
| { | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The French user role grants RIMD directly on "FR E-Invoice Message", even though the table is consumed through a read-only page and message-management codeunits. That lets assigned users bypass the lifecycle workflow and alter or delete refusal reasons, received message metadata, and sent-status records directly through any client surface that honors table permissions. This table should be readable directly at most, with writes reserved for code-mediated paths.
Knowledge:
👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.35.4