Expiry Monitor
Expiry Monitor pulls every batch-tracked product with an expiry date into one urgency-sorted view, so you can act on expired and soon-to-expire stock before it becomes a total loss.
Overview
Batches are grouped into four urgency buckets — Expired, Expires Today, Within 7 Days, Within 30 Days — with a live count on each, and the page auto-opens on the most urgent non-empty bucket.
For each batch you can either create an automatic Clearance Discount (a time-limited markdown so the POS discounts the item until it sells through, with no permanent price change) or Mark Wasted to write the remaining quantity off as a loss.
This is a Stock/Godown page requiring the Advanced plan tier — it is generically mounted in every variant (pointed at /inventory/expiry-monitor), separate from the bakery-specific expiry dashboard used inside the Bakery module.
Before You Start
- Requires the Advanced plan tier or above.
- Only products with batch tracking and an expiry date recorded (via Inventory → ⋮ → Batches, or during a Restock/Adjust with an expiry date entered) will appear here.
Step-by-Step Guide
1 Review batches by urgency
- The alert banner at the top summarises how many batches are already expired and how many expire today.
- Use the four summary cards (Expired / Expires Today / Within 7 Days / Within 30 Days) or the tab bar below them to switch between buckets — each shows its own count.
- Within a bucket, use the table's search box to find a specific product, batch or supplier reference, and sort by any column.
2 Create a clearance discount
- Click Clearance on a batch row.
- Enter a discount percentage (1–99%) when prompted.
- BazaarPOS creates a Clearance Discount rule for that product so POS automatically applies the markdown until the stock sells through — no manual price edit needed, and nothing to remember to undo.
3 Write off expired stock as waste
- Click Mark Wasted on a batch row.
- Confirm the write-off — the remaining batch quantity is deducted from stock immediately with a "WASTE" movement type and a note referencing the batch.
Every Field & Button, Explained
| Field / Button | What it does |
|---|---|
Alert banner | Summarises counts of already-expired and expiring-today batches; only shown when either count is greater than zero. |
Expired / Expires Today / Within 7 Days / Within 30 Days cards | Clickable summary tiles with live counts; clicking one switches the active tab. |
Product column | Product name; searchable together with batch number and supplier reference. |
Batch No. column | The batch/lot number the expiring quantity belongs to. |
Qty Left column | Remaining quantity in that specific batch. |
Expiry Date column | The batch's recorded expiry date. |
Status column | Colour-coded urgency badge with a "days left" or "expired Nd ago" label. |
Supplier Ref column | The supplier reference/PO number recorded against the batch, if any. |
Clearance button | Creates a time-limited clearance discount rule for the product (prompts for a discount %). |
Mark Wasted button | Writes off the remaining batch quantity as waste, deducting stock immediately. |
Tips & Best Practices
- Check the Expired and Expires Today buckets daily — those are the batches losing money right now.
- Use Clearance before Mark Wasted where possible — recovering even a discounted sale is better than a full write-off.
- Combine this page with Batches on the Inventory page: adding accurate expiry dates there is what feeds this monitor.
Troubleshooting & FAQ
The page is empty even though I know some stock is close to expiring.
I don't see Expiry Monitor in my sidebar at all.
Clicking Clearance didn't seem to change the product's price.
Mark Wasted removed stock but I wanted to review it first.
🧑💻 Developer Notes
Source component(s):
frontend-app/packages/pos-react-lib/src/pages/fnb/ExpiryMonitorPage.jsx
Backend endpoints used:
GET /inventory/expiry-monitorPOST /markdown-rulesPUT /inventory/:productId/adjust
Related tables (db-core repositories):
StockBatchProductMarkdownRuleStockMovement
Feature flag key: inventory (requires advanced plan tier or above)
This shared component (pages/fnb/ExpiryMonitorPage.jsx) takes apiPath and wastePath props. The bakery variant uses it with apiPath="/bakery/expiry-monitor" and a real wastage page; every other variant's /expiry-monitor route mounts it generically with apiPath="/inventory/expiry-monitor" and wastePath={null}, which is what makes "Mark Wasted" deduct stock directly instead of navigating to a wastage form. The restaurant and bakery variants instead redirect their own /expiry-monitor route to a variant-specific expiry dashboard.