Skip to content

[29.0] Fix item charge unit codes in XRechnung/ZUGFeRD - #11100

Open
Milica Đukić (djukicmilica) wants to merge 1 commit into
microsoft:releases/29.0from
djukicmilica:backport-9860-to-releases/29.0
Open

[29.0] Fix item charge unit codes in XRechnung/ZUGFeRD#11100
Milica Đukić (djukicmilica) wants to merge 1 commit into
microsoft:releases/29.0from
djukicmilica:backport-9860-to-releases/29.0

Conversation

@djukicmilica

@djukicmilica Milica Đukić (djukicmilica) commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Backport of #9860.

Why

Item charges exported as synthetic invoice lines can carry an empty or invalid unit code on BT-130, causing EN16931 BR-23 / BR-CL-23 validation failures in XRechnung and ZUGFeRD documents.

Summary

  • Added configurable item-charge mapping to document-level, line-level, or fallback invoice-line structures.
  • Updated XRechnung and ZUGFeRD exports to emit semantically correct allowance/charge structures and valid fallback unit codes.
  • Added regression coverage for invoice and credit memo item-charge scenarios.

Fixes
AB#649224

…valid unit of measure code (BR-CL-23 / BR-23 on BT-130) (microsoft#9860)

<!--
Thanks for contributing to BCApps!

A few things before you hit "Create pull request":
- Your PR must link to an approved issue. New here? See CONTRIBUTING.md.
- You must have built and run your change yourself. CI is a safety net,
not a substitute.
- If you used AI or an agent to write this PR, you are still the author.
Read the diff,
  build it, and try it before requesting review.

Contributing guide:
https://github.com/microsoft/BCApps/blob/main/CONTRIBUTING.md
Local dev environment:
https://github.com/microsoft/BCApps/blob/main/LOCAL_DEV_ENV.md
-->

Item charge lines (Type = Charge (Item)) were exported as synthetic
invoice lines carrying an empty unit code or PCE on BT-130, which fails
EN 16931 validation with BR-23 and BR-CL-23. Semantically most item
charges are allowances or charges and belong in the allowance/charge
structures rather than in a fabricated invoice line.

E-Document Core gains the classification:

- Enum "Item Charge E-Invoice Mapping" with Automatic (default),
Document Allowance/Charge, Line Allowance/Charge and Line with Unit
Code, held on E-Document Service.
- A per-item-charge override (mapping, reason text, reason code,
fallback unit code) on a table extension of Item Charge.
- Codeunit "E-Doc. Item Charge Mapping" resolves the structure for
posted sales invoices and credit memos. Automatic exports a charge as
line-level when it is assigned to exactly one line whose VAT calculation
type and rate match, as document-level when the assignment is absent or
ambiguous, and as a regular line otherwise. The assignment is recovered
from Value Entry, because item charge assignments no longer exist once
the document is posted.
- Integration events let subscribers override the resolved structure.

The controls are hidden in Core. E-Document for Germany makes them
visible, and both German exporters consume the classification:

- XRechnung emits cac:AllowanceCharge under Invoice or inside the target
cac:InvoiceLine; ZUGFeRD emits ram:SpecifiedTradeAllowanceCharge in the
header or line settlement.
- A document-level allowance/charge carries its tax category, a
line-level one does not.
- Negative amounts are exported as allowances with a positive amount.
- The fallback line reports quantity 1 with unit code C62; a negative
charge uses a negative quantity with a non-negative net price so that
BR-27 holds.
- A document whose only lines are item charges keeps a regular line, so
BR-16 is not violated.

Document and line totals are corrected so that the monetary totals and
tax subtotals still add up once charges leave the line set.

Also removes a duplicate "features" key from the DE demo data manifest,
which prevented that app from compiling.

<!-- Required: link an approved GitHub issue using "Fixes #<number>".
Microsoft contributors: also link the ADO work item with "AB#<number>"
if you have one. -->

Fixes microsoft#8417

[AB#641600](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/641600)

- [x] I read the full diff and it contains only changes I intended.
- [x] I built the affected app(s) locally with no new analyzer warnings.
- [x] I ran the change in Business Central and confirmed it behaves as
expected.
- [x] I added or updated tests for the new behavior, or explained below
why none are needed.

**What I tested and the outcome** *(required — be specific: scenarios,
commands, screenshots for UI changes)*

Manual, against a BC 29 DE container (bc29de), validating every exported
document
with online EN 16931 / XRechnung validators (KoSIT):

- Exported a posted sales invoice with item charges under **all four**
values of the
new **Item Charge Mapping** service setting — Automatic, Document Level
Allowance/Charge, Invoice Line Allowance/Charge and Invoice Line with
Unit Code.
All four produce documents that pass XSD, EN 16931 Schematron and the
XRechnung
  CIUS rules.
- Overrode the setting per item charge on the **Item Charges** page and
confirmed the
per-charge **E-Invoice Mapping** takes precedence over the service-level
setting,
  including a blank override falling through to the service setting.

Automated (all executed against the container, not just compiled):

| Test codeunit | Result |
|---|---|
| `E-Doc. Item Charge Tests` (139520) | 27 / 0 |
| `E-Doc. Item Charge UI Tests` (139522) | 3 / 0 |
| `Item Charge UI DE Tests` (13927) | 5 / 0 |
| `XRechnung XML Document Tests` (13918) | 93 / 2 |
| `ZUGFeRD XML Document Tests` (13922) | 93 / 2 |

73 tests were added in total. The 2 + 2 failures are **pre-existing and
unrelated** —
`AdditionalDocumentReference` counts in two attachment tests, and
`ram:GlobalID` in two
ZUGFeRD tests. They were measured as failing on an unmodified tree
before this work
started, and the failure sets are unchanged by this PR.

Coverage was verified by mutation: each classification branch, the sign
convention, the
totals corrections and the fallback quantity/unit code were deliberately
broken and
confirmed to fail a specific test. Two genuine bugs were caught this way
— a signed
amount reaching `AllowanceCharge`, and a missing guard that let a
charge-only document
export zero invoice lines (BR-16).

<!-- Anything reviewers should watch for: breaking changes, upgrade/data
impact, permissions,
telemetry, feature flags, follow-up work. Write "None" if there's
nothing to call out. -->

- **Behaviour changes by default.** `Automatic` is the default mapping,
so existing
services start exporting item charges as document- or line-level
allowances/charges
instead of synthetic invoice lines. This is the point of the fix — the
old output was
invalid — but the XML shape changes for anyone already exporting item
charges, and
  downstream systems that parse charges out of `cac:InvoiceLine` /
`ram:IncludedSupplyChainTradeLineItem` will see them move. Reviewers
should confirm
  this is acceptable as a default rather than opt-in.
- **Schema change.** New field on `E-Document Service`, and a table
extension on
`Item Charge` with four new fields. Requires a schema sync; no data
migration, all
fields default to blank/`Automatic`, which preserves the intended
behaviour.
- **Monetary totals are recomputed.** `cac:LegalMonetaryTotal` /
`ram:...HeaderMonetarySummation` and the tax subtotals are adjusted when
charges leave
the line set. Tax base and payable amounts are unchanged by construction
and asserted
  in tests, but this is the area most worth a careful read.
- **Known limitation:** a PEPPOL BIS 3.0 DE service shows the Item
Charge Mapping
setting, but that format's export ignores it — it delegates XML
generation to the W1
PEPPOL BIS 3.0 implementation, which is deliberately out of scope here.
Follow-up work
  if PEPPOL BIS DE should honour the setting.
- **Deliberately out of scope:** the generic W1 PEPPOL BIS 3.0 export is
untouched, and
  service documents keep opting out (they cannot carry item charges).
- **New public surface:** integration events allow subscribers to
override the resolved
structure for invoices and credit memos. Once shipped these are a
compatibility
  commitment.
- **Permissions:** the new `E-Doc. Item Charge Mapping` codeunit is
granted execute in
`E-Doc. Core - Objects`, which flows to Read/User/Basic/Edit/Admin and
the D365
permission set extensions. The codeunit itself elevates the table reads
it needs
(`Item Charge`, `Value Entry`, posted sales lines) via its `Permissions`
property.

<!-- Example:
- Ran the new "Post and Send" action on a sales invoice in a fresh
container; document posted and email queued (see screenshot).
- New unit tests in MyFeatureTest.Codeunit.al pass locally; full module
test suite green.
- No tests added because change is comment-only / refactor with existing
coverage. -->

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: djukicmilica <milicadjukic@microsoft.com>
@github-actions github-actions Bot added AL: Apps (W1) Add-on apps for W1 From Fork Pull request is coming from a fork Ownership: Needs Review Ownership is Other, low confidence, or needs manual correction Team: Other GitHub request for other area than SCM, Finance or Integration labels Sep 6, 2026
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Could not find linked issues in the pull request description. Please make sure the pull request description contains a line that contains 'Fixes #' followed by the issue number being fixed. Use that pattern for every issue you want to link.

@github-actions github-actions Bot added the ADO: Sync Creates an Azure DevOps work item if needed and indicates that one is linked label Sep 6, 2026
@github-actions github-actions Bot added this to the Version 29.0 milestone Sep 6, 2026
auto-merge was automatically disabled September 6, 2026 10:25

Pull request was closed

auto-merge was automatically disabled September 9, 2026 21:10

Pull request was closed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ADO: Sync Creates an Azure DevOps work item if needed and indicates that one is linked AL: Apps (W1) Add-on apps for W1 From Fork Pull request is coming from a fork Ownership: Needs Review Ownership is Other, low confidence, or needs manual correction Team: Other GitHub request for other area than SCM, Finance or Integration

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants