Skip to content
Reports·Prophet 21

When P21 invoices print the wrong number above $1,000

A Prophet 21 form that prints correct figures on small lines and wrong ones on large lines is almost never a data problem. It is the datastream and the report's numeric handling disagreeing about the thousands separator.

A distributor reports that some invoices print wrong. Not all of them. The totals in P21 are right, the order is right, and the customer's copy shows a figure that does not match anything in the system. Reprint it and the same line is wrong the same way.

The instinct is to go looking for bad data. That is usually the wrong first move, and it can burn a day.

The tell

Sort the failing invoices by line value. If every line under a threshold prints correctly and the failures start above it, you are not looking at data. You are looking at number formatting crossing a boundary.

The two boundaries worth checking first:

  • $1,000, where a thousands separator first appears in the formatted value
  • $10,000, where a fixed-precision numeric field can overflow its declared width

Both produce the same user-visible symptom: a printed figure that is not the stored figure, on some lines but not others.

Why the separator matters

P21 form reports are driven by a datastream. The report does not query the database for these values, it receives them. If a platform change starts pushing a formatted string where the report expects a plain number, every value without a separator continues to parse cleanly and every value with one does not. Under $1,000 there is no comma, so nothing breaks. At $1,000 the comma appears and the parse silently produces something else.

The report will not error. It will print.

The reason this survives for years before anyone notices is that it needs two conditions at once: a formatting change on the platform side, and a line big enough to carry a separator. A shop whose lines rarely cross the threshold can run for a very long time before the first wrong invoice.

Why the precision boundary matters

The second class is different. A fixed-precision numeric with too few digits for the value assigned to it cannot represent the number. Where the separator bug corrupts the parse, this one corrupts the storage, and it appears at a hard boundary rather than a formatting one.

If exactly one line on the invoice is wrong and it is the only line over $10,000, stop looking at the rest of the invoice.

How to confirm it in an hour

  1. Pull the same values two ways. Read the invoice through the OData views and compare against what printed. If the stored value is right and the printed value is wrong, the defect is downstream of the data, which eliminates the entire data-cleanup theory.
  2. Find the threshold empirically. Take the failing invoices, sort by line extended value, and find where correct becomes incorrect. A clean boundary at a round number is the answer. A scatter is something else.
  3. Check whether it is the first time. Query for historical lines above the threshold. If there are thousands of them across prior years and they were fine, a platform or report change is the trigger and you should be looking at what moved. If this is genuinely the first line that large, the defect was always there and simply had never been reachable.

That third check is the one people skip, and it is the one that decides whether you are hunting a regression or a latent bug. They call for completely different fixes.

The fix

For the separator class, the fix belongs in the report's handling of the incoming value, not in the data and not in the platform. Parse defensively or receive the raw numeric.

For the precision class, the field has to be widened, which means the change lands in the report's own definitions rather than anywhere in P21.

In both cases: reprint a known-bad invoice as the acceptance test. A form fix that has not been proven against the exact document that failed is not finished. Keep that invoice number in the ticket.

The general lesson

A report that is right for small values and wrong for large ones is a formatting or precision defect, essentially always. The size dependency is the diagnosis. Data problems do not respect numeric thresholds.

Seeing this on your system?

Describe the symptom in your own words. Diagnosing it is our job, and an engineer replies within one business day.