Skip to content

BR-28: Make the item gross price zero or positive

The gross price in cbc:BaseAmount of a line price discount must not be below zero. A credit or correction takes its sign from the quantity.

EN 16931Fatal: the document is invalidLines and prices

The short answer

BR-28 fails when cac:Price/cac:AllowanceCharge/cbc:BaseAmount on a line is below zero. That element is the item gross price, the unit price before the price discount, and it cannot be negative. Correct the sign at source so that the gross price is positive and the net price in cbc:PriceAmount equals it minus the discount.

In the recorded example the negative gross price no longer agrees with the net price either, so PEPPOL-EN16931-R046 comes with it.

What the rule checks

For each cac:InvoiceLine or cac:CreditNoteLine, the rule reads the cbc:BaseAmount of the cac:AllowanceCharge inside cac:Price, if there is one, and requires it to be zero or more.

With no price-level cac:AllowanceCharge, or none with a cbc:BaseAmount, no gross price is stated and the rule passes. When tried, deleting the gross price from the recorded line left a valid invoice.

Zero is accepted by this rule. When tried, a gross price of 0 was not reported by BR-28; only PEPPOL-EN16931-R046 objected, because 0 minus 2.5 is not the net price of 12.5.

The sign test stands on its own. With a gross price of -15 and a discount of -27.5, which keeps the net price at 12.5, BR-28 was still reported when tried, and nothing else was.

The discount amount, the net price and the quantity are not read. A negative net price is a separate rule, BR-27.

TermMeaningUBL element
BT-148Item gross pricecac:InvoiceLine/cac:Price/cac:AllowanceCharge/cbc:BaseAmount (cac:CreditNoteLine in a credit note)
BT-147Item price discountcac:InvoiceLine/cac:Price/cac:AllowanceCharge/cbc:Amount
BT-146Item net pricecac:InvoiceLine/cac:Price/cbc:PriceAmount

How an integration ends up here

Possible causes, from the shape of the rule rather than from measured usage:

  • A credit or return line is built by negating every price field, the gross price included.
  • The sign of the line net amount is copied onto the unit prices when a return is mapped.
  • The gross price is derived from the net price and the discount with the operands the wrong way round, such as discount minus net price.
  • A price-level entry is used to carry a credit that belongs on the line or the document.

How to fix it

  1. Find the line from the finding location and read cbc:PriceAmount, and the cbc:Amount and cbc:BaseAmount inside cac:Price/cac:AllowanceCharge.
  2. Write the gross price as the positive unit price before discount. If the line is a credit or correction, express that through a negative cbc:InvoicedQuantity (or cbc:CreditedQuantity) and line net amount, not through the prices.
  3. Make sure net price = gross price - discount holds exactly, since PEPPOL-EN16931-R046 tests it with no tolerance.
  4. If the source has no reliable gross price, leave out the whole price-level cac:AllowanceCharge and send the net price alone.

The recorded line has a net price of 12.5 and a price discount of 2.5.

Failing: gross price -15 - discount 2.5 = -17.5, net price sent 12.5, so BR-28 and PEPPOL-EN16931-R046 both fail
Corrected: gross price 15 - discount 2.5 = 12.5, which is the net price sent

Validate your corrected invoice

Before and after

These are fragments, not complete documents. The complete synthetic documents they come from are linked below.

Fragment of the failing invoice: the gross price is -15

<cac:Price>
  <cbc:PriceAmount currencyID="GBP">12.5</cbc:PriceAmount>
  <cbc:BaseQuantity unitCode="C62">1</cbc:BaseQuantity>
  <cac:AllowanceCharge>
    <cbc:ChargeIndicator>false</cbc:ChargeIndicator>
    <cbc:Amount currencyID="GBP">2.5</cbc:Amount>
    <cbc:BaseAmount currencyID="GBP">-15</cbc:BaseAmount>
  </cac:AllowanceCharge>
</cac:Price>

Fragment of the corrected invoice: the gross price is 15, and 15 minus 2.5 is the net price

<cac:Price>
  <cbc:PriceAmount currencyID="GBP">12.5</cbc:PriceAmount>
  <cbc:BaseQuantity unitCode="C62">1</cbc:BaseQuantity>
  <cac:AllowanceCharge>
    <cbc:ChargeIndicator>false</cbc:ChargeIndicator>
    <cbc:Amount currencyID="GBP">2.5</cbc:Amount>
    <cbc:BaseAmount currencyID="GBP">15</cbc:BaseAmount>
  </cac:AllowanceCharge>
</cac:Price>

The gross price in cbc:BaseAmount is -15 in the failing invoice and 15 in the corrected one; nothing else changes. The failing document also reports PEPPOL-EN16931-R046 on the price discount, because -15 minus 2.5 is -17.5 while the net price is 12.5. With the sign corrected, 15 minus 2.5 gives 12.5 and both findings clear.

What the validator reported

Recorded on phive 12.1.0 / phive-rules-peppol 4.5.6 / Saxon-HE 12.10, the engine behind the free validator, using synthetic data. A recorded result is regression evidence for these documents; it is not a certification.

Where it applies

  • Applies to cac:InvoiceLine and cac:CreditNoteLine. A credit note line with the same gross price of -15 reported BR-28 and PEPPOL-EN16931-R046 when tried.
  • Reported by the EN 16931 layer; the companion finding, PEPPOL-EN16931-R046, comes from the Peppol layer.
  • The gross price feeds no total. The line net amount is worked out from the net price, so the negative figure disturbed nothing beyond the price itself.

Scope and source

Written for Peppol BIS Billing 3.0.21 (May 2026), EN 16931 1.3.16, as applied to UBL 2.1 Invoice and CreditNote documents. Other profiles, syntaxes and releases can define this identifier differently. Guidance version 2026-09-24.1: source checked 2026-09-24, explanation last updated 2026-09-24.

The official definition of BR-28 carries the normative wording and test. This page is our explanation of it, not a copy.

Guidance does not change the engine verdict. Fixing this finding does not mean the document passes every layer, and validation does not certify legal or tax compliance or transmit a document over Peppol.