BR-CO-13Tax-exclusive total is missing from the document totals
Mutabiq checks Saudi ZATCA Phase 2 e-invoice XML before you submit it: pre-validation against published ZATCA requirements, not an approval by the authority. This page explains one rule, BR-CO-13.
Five checks a month on the Free plan. The file is checked in memory and is never stored.
The message ZATCA prints
[BR-CO-13]-Invoice total amount without VAT (BT-109) = Σ Invoice line net amount (BT-131) - Sum of allowances on document level (BT-107) + Sum of charges on document level (BT-108).
Also cited in this report
BR-CO-13
[BR-CO-13]-Invoice total amount without VAT (BT-109) = Σ Invoice line net amount (BT-131) - Sum of allowances on document level (BT-107) + Sum of charges on document level (BT-108).
What Mutabiq reports
One entry for each way this rule can be reported.
Reported as
What kind of value was found — empty, not_15_digits and the like — never the value itself.
Tax-exclusive total is missing from the document totals
Reported astotal_missingthe total is missing
What is wrong
The document totals block, cac:LegalMonetaryTotal, carries no cbc:TaxExclusiveAmount. That field is the invoice total before VAT (BT-109), and EN 16931 rule BR-CO-13, which ZATCA runs, requires it to equal the line total plus any charges less any allowances. With no value written there is nothing to compare and the rule fails.
What to check in your ERP
Check the export template in your e-invoicing module: this is normally a mapping that writes the total including VAT and the payable amount but omits the one before VAT. The element is required by the UBL schema as well, so a document in this state is usually reported here and by the schema check together.
Tax-exclusive total does not match the lines, charges and allowances
Reported asnot_lines_plus_charges_less_allowancesnot the lines plus charges less allowances
What is wrong
The cbc:TaxExclusiveAmount in cac:LegalMonetaryTotal is not the line total plus the charge total less the allowance total. EN 16931 rule BR-CO-13, which ZATCA runs, checks whichever of those two optional totals your document carries, rounds the result to two decimals and requires an exact match. One case is stricter than the rest and catches people out: when the document has neither a charge total nor an allowance total, ZATCA requires the tax-exclusive amount to equal the line total with no rounding applied at all - so a line total written as 100.001 against a tax-exclusive amount of 100.00 fails, where in every other branch it would have been rounded first.
What to check in your ERP
Start by checking that the amounts entering this sum are the ones ZATCA expects: cbc:LineExtensionAmount for the lines, cbc:ChargeTotalAmount for document charges, cbc:AllowanceTotalAmount for document discounts. Then check the number of decimal places your system writes. If any amount carries three or more decimals, write it to two - the strict branch above compares those digits exactly, and a third decimal that rounds away in your reports does not round away here.
Sum of document-level charges is empty, so the total without VAT cannot be checked
Reported ascharge_total_blankthe charge total is present but empty
What is wrong
cbc:ChargeTotalAmount is present in cac:LegalMonetaryTotal but empty. BR-CO-13, which checks that the invoice total without VAT (BT-109) equals the sum of the line amounts minus document-level allowances plus document-level charges, reports this case on its own before any arithmetic. ZATCA flags this as a warning, which does not by itself reject the document. BR-CO-12 reports the same empty element as an error.
What to check in your ERP
Either write the charge total - 0.00 when the document has no document-level charge - or leave the element out. An empty element usually comes from a template that always writes the tag and fills it only when a charge exists.
The clause that runs
Quoted from the validation-rule stylesheet ZATCA publishes, at the file and line named below. The executed guard is what the check runs; the reported test is what it prints when it fails, and the two are not always the same.
Executed guard
exists (cbc:ChargeTotalAmount) and normalize-space(cbc:ChargeTotalAmount)=''
Reported test
((cbc:ChargeTotalAmount) and (cbc:AllowanceTotalAmount) and (xs:decimal(cbc:TaxExclusiveAmount) = round((xs:decimal(cbc:LineExtensionAmount) + xs:decimal(cbc:ChargeTotalAmount) - xs:decimal(cbc:AllowanceTotalAmount)) * 10 * 10) div 100 )) or (not(cbc:ChargeTotalAmount) and (cbc:AllowanceTotalAmount) and (xs:decimal(cbc:TaxExclusiveAmount) = round((xs:decimal(cbc:LineExtensionAmount) - xs:decimal(cbc:AllowanceTotalAmount)) * 10 * 10 ) div 100)) or ((cbc:ChargeTotalAmount) and not(cbc:AllowanceTotalAmount) and (xs:decimal(cbc:TaxExclusiveAmount) = round((xs:decimal(cbc:LineExtensionAmount) + xs:decimal(cbc:ChargeTotalAmount)) * 10 * 10 ) div 100)) or (not(cbc:ChargeTotalAmount) and not(cbc:AllowanceTotalAmount) and (xs:decimal(cbc:TaxExclusiveAmount) = xs:decimal(cbc:LineExtensionAmount)))
Evaluated against
cac:LegalMonetaryTotal
Source
vendor/zatca/schematron/CEN-EN16931-UBL.xsl:470
As shipped in ZATCA SDK 3.4.8: the copy quoted here is, byte for byte, the file that release ships. The date in the file name is the name ZATCA gives the file; the rules in it are those of SDK 3.4.8.
A worked example
A synthetic document from the measured test corpus that trips this rule, shown where it differs from one that passed. Mutabiq's report names the class of the value, never the value itself.