Flow
One setting, one function, every file
Every route asks the same function.
1Amount setting
The claim by default; shopper savings only when asked for.
2Amount function
Takes a row and the setting and returns cents.
3Grouped files
Rows get the chosen amount before grouping.
4Line-item file and PDF
Call the function row by row.
5Label table
Headings and total lines come from the setting.
Flow
The pieces of the amount change
Each piece is covered above.
1One setting
Picks which number; the claim by default.
2Label table
A heading and total line for each choice.
3Cards
Normal cards show the claim; savings sit on an audit card.
4Bulk export script
Writes down which number it used.
5Row limit
Rows are hidden first; the limit runs last.
The discounts card in my supplier report and the export file for the same panel carried the same title. They showed different numbers, and neither one told you which.
This report lives in the ordering system. I use it to ask suppliers to pay back their part of a sale or a return. Each sale on promotion has two true numbers. One is what the shopper saved at the register. The other is what I can claim, based on what the item cost me wholesale. The claim is much smaller. In one test, the shopper's savings were about eight times the claim.
The labels didn't match the sums
Most cards added up the shopper's savings. The credits card next to them added up the claim. The export file used the same title as the discounts card but held the claim, under a generic amount heading. The grouped file and the PDF used two more names for it. Every sum was right. You just couldn't tell what any of them meant.
The real problem: each screen and file chose its own number and wrote its own label. No one place made the call.
How the export code picks the number now
I gave the export code one setting for which number to use, with the claim as the default. A small table holds the heading and total line for each choice. One function picks the amount for a row. The grouped files run every row through it before grouping.
The grouped files first rewrite each row with the amount for the chosen measure.
The line-item file and PDF call that same function row by row.
Every normal card now shows the claim and says so. The shopper's savings live on a separate audit card that says it isn't for credit requests. The bulk export script writes down which number it used, so the next tool doesn't have to guess. Tests check the labels and the values for both choices.
If you build something like this, rename old fields instead of changing what they mean. Then any code still using the old name breaks loudly.
Filters run before the row limit
I also added ways to hide a whole category or a single item. Category is only known after a row is matched to a product. The old code cut the list to the row limit before that match. With a category filter, that would drop rows after the cut and return fewer than asked. So the limit now counts only rows that survive the category filter.
What's still loose
If a row has no register amount, the savings file falls back to the claim, so it can mix the two. And nothing checks that a new caller says which number it wants. It just gets the claim.