GET/api/packing/reports/missing

What is still owed (PK-6)

The night's "what do we still owe people", asked at either end of the shift.

when=after — ordered vs actually packed. Unambiguous: both sides are order lines. This is the sheet the shipping team works from.

when=before — ordered vs what the floor has produced (production records plus the night bake log), to predict the shortfall before picking starts.

Only shortfalls appear — a report of everything the bakery got right is not a report anyone reads at 4am. missing floors at zero per item, so an over-supply of one item can never mask a shortfall on another.

shape=section regroups exactly the rows shape=total returns, and still carries rows, so a caller never has to ask twice.

⚠️ productionLive is false when the day has no production record and no logged bake — which today is always, because the platform has no recipes and no productions yet. When it is false the numbers mean "not yet made", not "short": the screen and the printed sheet both say so (PK-4). There is also an unresolved unit question — recipes output base items while orders are for variants — so production counts only where a recipe's output item IS the ordered item. Revisit when the floor goes live.

3 parameters
datestringrequired
Montreal business day, `yyyy-mm-dd`. Required. Day-scoped endpoints filter on the **delivery** date (D-14).
whenstringrequired
Which end of the shift.
Allowed:beforeafter
shapestringoptional
Flat list, or grouped by production section. Defaults to `total`.
Allowed:totalsection

4 status codes
200What is still owed.
datestringoptional
whenstringoptional
Allowed:beforeafter
shapestringoptional
Allowed:totalsection
productionLivebooleanoptional
False when the day has NO production record and NO logged bake anywhere. The numbers then mean "not yet made", NOT "short" — both the screen and the printed sheet must say so (PK-4). ⚠️ **This is a DAY-level flag and it is true as soon as ONE record exists.** It cannot express "true, but for one item out of forty", which is the state a real day is usually in. Read `rowsWithoutProduction` with it, never instead of it.
rowsWithoutProductionintegeroptional
How many of `rows` have NO production record — their `available` is a default, not a count. Zero on `when=after`, which measures what was packed. Added 2026-08-18 after a production day where one bake-log row flipped `productionLive` true, suppressed the PK-4 banner, and let the sheet state **6,637 items missing across 39 rows that had nothing recorded against them**.
totalMissingnumberoptional
rowsarray<object>optional
Always present, in both shapes.
sectionsarray<object>optional
Populated only when `shape=section`. Regroups exactly the rows above.
400Invalid input — the `error` string says what was wrong.
errorstringrequired
401Not authenticated. Sign in first (see the Auth tag).
errorstringrequired
500Unexpected server error.
errorstringrequired

Error handling

A 400 is returned: Invalid input — the error string says what was wrong. A 401 is returned: Not authenticated. Sign in first (see the Auth tag). A 500 is returned: Unexpected server error.