[Bug]: [DE] XRechnung/ZUGFeRD — no posting-time error when SELLER CONTACT (BG-6) source data is incomplete, producing non-compliant e-invoices#9646
Conversation
…ZUGFeRD documents The SELLER CONTACT group (BG-6) is filled from the assigned salesperson, or from Company Information when no salesperson resolves. Neither source was validated at posting time, so a document with incomplete contact data posted successfully and produced XML that fails XRechnung validation (BR-DE-2, BR-DE-5, BR-DE-6, BR-DE-7). Add "E-Document DE Helper".CheckSellerContactMandatory and call it from the Check of the XRechnung and ZUGFeRD formats. It mirrors the resolution order the export uses: the salesperson supplies BT-41, BT-42 and BT-43 only when the code is set and the record exists, otherwise Company Information supplies them. The error names the missing field and the source it was expected from. The Company Information E-Mail is deliberately not checked there. It is the same field that supplies the seller electronic address (BT-34), which CheckCompanyInfoMandatory already requires, so the BG-6 fallback cannot be blank once that check passes. CheckCompanyInfoMandatory now documents that BT-34 relationship and runs before the seller contact check. PEPPOL BIS 3.0 DE is not wired to the new check, so its behaviour is unchanged. Tests: 11 mirrored tests in each of the XRechnung and ZUGFeRD suites, covering both branches, every mandatory field, the fallback when the assigned salesperson no longer exists, service documents and the positive cases. The suites are kept in sync deliberately: the check logic is shared, but each format wires it up in its own Check, so a format-specific regression is only caught by that format's own tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
| exit; | ||
|
|
||
| SalespersonCode := GetSalespersonCode(SourceDocumentHeader); | ||
| if SalespersonCode <> '' then begin |
There was a problem hiding this comment.
CheckSellerContactMandatory hand-builds Error() calls with FieldCaption()/TableCaption() to report a mandatory-field violation on Salesperson/Purchaser (Name, Phone No., E-Mail) and Company Information (Contact Person, Phone No.), instead of using TestField or FieldError. Both built-ins already attach the field caption and the record's primary-key context automatically, so this reimplements behavior the platform provides for free and risks the manual composition drifting from the built-in format over time. Since the extra business context here ("required for the seller contact (BG-6)") is a genuine custom reason beyond a generic mandatory-field message, FieldError(FieldNo, CustomMessage) on the record itself is the better fit: it keeps the custom BG-6 reasoning while reusing the platform's caption/record-context formatting instead of assembling it manually with FieldCaption/TableCaption/SalespersonCode.
Knowledge:
👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.13.4
|
The new XML doc comment on ZUGFeRDFormat.Codeunit.al's CheckCompanyInfoMandatory says "which XRechnung requires (PEPPOL-EN16931-R020)", but this is the ZUGFeRD format codeunit, not XRechnung. This is a copy-paste artifact from XRechnungFormat.Codeunit.al's identical comment and misattributes the requirement to the wrong format when read by IntelliSense or generated docs. Recommend changing "XRechnung" to "ZUGFeRD" in the comment. Suggested fix (apply manually — could not be anchored as a one-click suggestion): /// <summary>
/// Checks the Company Information data that the electronic document requires.
/// The E-Mail supplies the seller electronic address (BT-34), which ZUGFeRD requires
/// (PEPPOL-EN16931-R020). BT-34 is a party level routing address and is always taken from Company
/// Information, never from the salesperson, so it is independent of the seller contact (BG-6).
/// </summary>Agent judgement — not directly backed by a BCQuality knowledge article. Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.13.4 |
What & why
The SELLER CONTACT group (BG-6) is filled from the assigned salesperson, or from Company Information when no salesperson resolves. Neither source was validated at posting time, so a document with incomplete contact data posted successfully and produced XML that fails XRechnung validation (BR-DE-2, BR-DE-5, BR-DE-6, BR-DE-7).
Add "E-Document DE Helper".CheckSellerContactMandatory and call it from the Check of the XRechnung and ZUGFeRD formats. It mirrors the resolution order the export uses: the salesperson supplies BT-41, BT-42 and BT-43 only when the code is set and the record exists, otherwise Company Information supplies them. The error names the missing field and the source it was expected from.
The Company Information E-Mail is deliberately not checked there. It is the same field that supplies the seller electronic address (BT-34), which CheckCompanyInfoMandatory already requires, so the BG-6 fallback cannot be blank once that check passes. CheckCompanyInfoMandatory now documents that BT-34 relationship and runs before the seller contact check.
Tests: 11 mirrored tests in each of the XRechnung and ZUGFeRD suites, covering both branches, every mandatory field, the fallback when the assigned salesperson no longer exists, service documents and the positive cases. The suites are kept in sync deliberately: the check logic is shared, but each format wires it up in its own Check, so a format-specific regression is only caught by that format's own tests.
Linked work
Fixes #8416
How I validated this
What I tested and the outcome (required — be specific: scenarios, commands, screenshots for UI changes)
I have tried posting invoices with missing data with and without Salesperson assigned.
Risk & compatibility
Risk & compatibility
Breaking: posting XRechnung/ZUGFeRD documents now fails when the salesperson
(Name / Phone No. / E-Mail) or Company Information (Contact Person / Phone No.)
is incomplete. Intended by the issue, but it surfaces as a new posting failure on
existing data — worth a release note.
Wider than posting: the check sits in the format's
Checkand ignoresEDocumentProcessingPhase, so it also blocks export of documents posted beforethis change. Same behaviour as the existing IBAN and buyer-reference checks.
No opt-out:
OnBeforeCheckhas noIsHandled, so extensions cannot suppressthe check. Adding it would be the follow-up if customers with incomplete master
data need an escape hatch.
Untested:
GetSalespersonCoderesolves the field number the same wayCheckBankAccountIBANMandatoryalready does, but tests only coverSales Headerand
Service Header— not the four posted-document tables.No impact: no schema, upgrade, permission, telemetry or feature-flag changes.
Translations are build-generated. PEPPOL BIS 3.0 DE is untouched.