Rule at a Glance
| ID | Severity | Context (XPath) |
|---|---|---|
| Series ref. BR-39 | Fatal (error) | cac:AllowanceCharge |
Schematron ID: ibr-082 | Field: cbc:ChargeIndicator |
||
Classification
Syntax & Integration — unlike BR-31 through BR-38, which each govern a specific allowance or charge field, BR-39 governs the single boolean flag that every one of those rules depends on. Every AllowanceCharge block on a PINT-AE invoice — document-level or line-level, allowance or charge — carries a ChargeIndicator, and its value is what determines whether the block reduces the invoice total or adds to it.
What the Rule Is Checking
For every AllowanceCharge element on the invoice, the rule requires that cbc:ChargeIndicator, when normalised, reads exactly as the literal string "true" or "false". No other value — including a numeric 1 or 0, a capitalised variant, or an empty element — satisfies the rule. This is a structural check on the field's content, applied uniformly wherever an AllowanceCharge block appears in the document.
Why This Rule Exists
Every rule that governs allowance and charge amounts and reasons — BR-31 through BR-38 — distinguishes an allowance from a charge purely by testing the value of ChargeIndicator. If that field carries anything other than a clean "true" or "false", the downstream logic that classifies the block, and every calculation that sums allowances separately from charges, has no reliable basis to work from. A malformed indicator does not just fail in isolation; it undermines every rule that reads it.
This matters more in practice than it might appear, because ChargeIndicator is exactly the kind of field that ERP export logic gets wrong silently. A system that internally represents the flag as a numeric 1 or 0, or as "Y" and "N", and does not convert it correctly during UBL generation, will produce an invoice that looks structurally complete but fails validation on a field most implementation teams do not think to check directly.
UAE Data Example
PASSES ✓: AllowanceCharge block with ChargeIndicator = "true", representing a delivery charge. Value matches exactly; rule passes.
PASSES ✓: AllowanceCharge block with ChargeIndicator = "false", representing an early-payment discount. Value matches exactly; rule passes.
FAILS ✗: AllowanceCharge block with ChargeIndicator = "1". Fatal error — a numeric flag is not an accepted substitute for the literal string value.
What Your ERP / IT Team Must Ensure
- Trace how your ERP or billing system internally represents the allowance-versus-charge distinction, and confirm the mapping layer converts it to the literal lowercase strings "true" or "false" — not a Boolean type that serialises differently, and not a Y/N or 1/0 flag left unconverted.
- Test this specifically rather than assuming it is covered by general schema validation. A field can be schema-valid as a boolean type while still failing this schematron rule if the serialised text does not match exactly.
- Check every code path that generates an
AllowanceChargeblock — document-level and line-level, allowance and charge — since a mapping error introduced in one part of the invoice generation logic will typically affect all of them identically. - Add this as an early check in your pre-submission validation sequence. Because every allowance and charge rule depends on this field, catching a malformed indicator first avoids a batch of confusing secondary errors on the amount and reason fields that trace back to the same root cause.
Related Rules
BR-31 (ibr-031) and BR-33 (ibr-033) depend on this indicator reading "false" to identify a document-level allowance. BR-35 (ibr-036) and BR-37 (ibr-038) depend on it reading "true" to identify a document-level charge. BR-32, BR-34, BR-36, and BR-38 apply the same dependency at line level.
