A shop that sells by weight eventually fails to tie out at closing.
The stack of labels adds up to a few hundred won different from the till total, and nobody can find where it came from. And it happens a little every day.
Why it happens
Because the price is calculated twice.
- When the label prints — it is rounded to something a customer can pay. A 3,444.5-won item prints as 3,440.
- When it goes into the ledger — it is recalculated from the weight. 3,444.5 won.
Neither is wrong. And they differ. And the difference is 4 or 5 won per item, so it only becomes visible after a day.
Make the price in one place
This sample's answer is one function.
/// The only place a price is made.
///
/// Rounds to what somebody can pay, once. Every other number in this server
/// — the label, the ledger, the day total — comes from this and never from
/// a second pass over the weight.
static int priceFor(Product p, int grams) {
final exact = p.wonPer100g * grams / 100;
return (exact / _payableStep).round() * _payableStep;
}
And when the label prints, the result of that one call goes into the ledger unchanged.
// One call, one number. The label and the ledger row are the same
// integer, so there is nothing for them to disagree about.
final won = priceFor(_product, _grams);
_sales.add(Sale(_product.code, _product.name, _grams, won));
What the customer paid is what stays in the ledger. There is no reason for the ledger to say "well, strictly it was 3,444.5" — the customer did not pay that.
On the pan

The label says how much the rounding was.
pan: Pork belly 347 g — exact 10340.6 won, label 10340 won (rounded -0.6 won to the nearest 10)
// What the rounding actually did, in won, said out loud. A shop
// that rounds without showing it is a shop that argues later.
This is not for the customer, it is for the shop. Hide the rounding and nobody can answer "why did it come out like this" later. Show it and the question ends there.
Five items, then closing
label 1: 347 g -> 10340 won (exact 10340.6, rounded -0.6)
label 2: 512 g -> 21250 won (exact 21248.0, rounded +2.0)
label 3: 210 g -> 2600 won (exact 2604.0, rounded -4.0)
label 4: 1000 g -> 29800 won (exact 29800.0, rounded 0.0)
label 5: 83 g -> 3440 won (exact 3444.5, rounded -4.5)
Some round up, some round down, one lands exactly. Chosen deliberately — test with data that rounds the same direction every time and this class of bug does not surface.

ledger says 5 labels, total 67430 won
harness added the labels itself: 67430 won
ledger total minus watched labels: 0 won
This content requires Developer or above
Sign in and upgrade your plan to continue reading.
View Plans