4-level supply model
Each supply now has 4 layers of identity (gh#878):
| Level | What | Source |
|---|---|---|
| 1. Parsed name | What the receipt parser extracted from the raw receipt line | Receipt OCR/parse |
| 2. Corrected name | Human-readable canonical name | LLM canonicalize / operator edit |
| 3. Product type | The functional category (e.g. coffee_capsule, dishwasher_tab, toilet_paper_roll) |
Operator or LLM |
| 4. Category | The high-level consumption-model bucket (Guest Consumables / Cleaning Supplies / Stay Essentials / Reusables) | Operator |
Why four levels
The historical model conflated all four — every receipt line became its own supply row, names drifted, two "CAFISSIMO 70g FINE AROMA" lines from different receipts didn't merge.
The 4-level model lets supplies merge by product type across receipts:
- Receipt A: parsed
CAFISSIMO 70g FINE AROMA, correctedCAFISSIMO 70g FINE AROMA capsules, typecoffee_capsule. - Receipt B: parsed
CAFISSIMO STR INTENSO, correctedCAFISSIMO Intenso capsules, typecoffee_capsule.
If you've set merge_by_product_type=true on coffee_capsule, both feed the same Coffee Capsules supply row. If you've left it false (e.g. you track CAFISSIMO Aroma vs Intenso separately for variety counts), they stay distinct rows.
Editor: Pack Sizes + Correct-names unified (gh#824)
The Pack Sizes admin and the new corrected-names editor merge into one product table. Each row has all 4 levels editable in one slide-over (gh#824 — earlier two separate surfaces).
Rows with unidentifiable parsed names (no product-type, no category) hide by default — the editor shows actionable rows first. A Show unidentified toggle reveals them.
Type-match restock (gh#878 Part E)
The low-stock monitor now considers ALL rows of the same product_type when checking restock. Receipt-add to any row of type coffee_capsule resolves a low-stock task on the Coffee Capsules supply, regardless of which CAFISSIMO SKU the receipt was for.
AI canonical (gh#808)
When the operator opens a parsed row in the editor, an AI canonicalize button proposes:
- Suggested corrected name (online product lookup)
- Suggested product type (from a catalog of operator-defined types)
- Suggested category
Operator accepts each independently. Suggestions persist; future receipts mentioning the same parsed name auto-apply.
Corrected-name property (gh#837)
The corrected-name field is operator-editable + drives deterministic future-receipt matching. Set it once; every future receipt with the same parsed name resolves to your corrected name automatically.
What gh#878 + gh#824 supersede
- gh#515's
product_pack_sizestable merged into the unified product table. - gh#673's per-row category filter now operates over level 4 (Category), with rollups by level 3 (Product type) available.
- gh#825 (over-generalized parsed names) — operator can correct at level 2 without losing the original parse at level 1.
- gh#743 (receipt-derived supply names include the purchased quantity) — strip-quantity logic operates at parse time + corrected-name overrides.
Ignore list (gh#815)
A separate Ignore list keeps non-inventory items (carrier bags, packaging, plastic wrap) out of stock + receipt re-ingestion. Add a product type to the ignore list → matching receipt lines never spawn supply rows.
Implements: gh#878 (4-level model + merge-by-product-type + type-match restock), gh#824 (unified Pack Sizes + Correct-names editor with drawer), gh#808 (AI canonical management in Pack Sizes view), gh#837 (corrected parsed-product-name property), gh#815 (ignore list), gh#825 (parsed-name overgeneralization fix), gh#743 (strip purchased-quantity from supply names). Related: Pack Sizes, History, Stock tracking.