1 Latte = 18g espresso bean + 200ml fresh milk + 1 paper cup. When the order is paid, a PostgreSQL trigger deducts each ingredient from inventory_item.qty_remaining. The refund-with-restore option re-adds stock if the item gets returned.

Every inventory_item can have a par level (e.g. minimum 2kg coffee beans). When qty_remaining ≤ par, the dashboard flags it red. Procurement sees the re-order list first thing in the morning.

Each outlet has its own inventory pool. Senopati can run out of croissants without affecting Dago. Recipes & master menu are central, but stock is counted at outlet level.

Quarterly stock-take? Tap "Adjust" on the inventory_item, enter the physical qty, give a reason (e.g. "Spoilage Mar 2026"). Every adjust writes an audit row so the owner sees who, when, and why.

When you receive stock, optionally fill in the per-unit cost (e.g. Rp 145,000/kg) — Posz recomputes the weighted-average automatically. Result: the Dashboard's Profit report (gross / COGS / gross-profit) uses cost that's accurate across batches, not just the last receipt's price.