Web app · Inventory planning

Expiry Hunter

A batch sitting in stock expires and becomes a loss. The risk shows up early in the numbers, but only becomes visible when someone crosses expiry, stock and consumption. I built an app that does this batch by batch, shows how much will be left on the expiry date and suggests an action for each batch.

Lovable · React · RechartsSpecification with ClaudeDemo with fictional data
Expiry Hunter screen with stock value, projected loss and batches that need action

Why it matters

In healthcare, an expired product does not go back on the shelf. It becomes disposal, a loss provision and sometimes a stockout of the same item in another location that would have sold it all in time.

Looking only at the expiry date is not enough. A batch that expires in 60 days can be safe if turnover is high, and a batch that expires in 200 days can be lost if another batch of the same product is ahead in the queue.

How it works

  1. A queue by expiry. For each product and location, batches queue up by expiry date. That is FEFO: first expired, first out.
  2. Consumption works through the queue. Daily consumption empties one batch at a time. The next batch only starts being used when the previous one runs out or expires.
  3. What is left becomes a loss. The quantity not used by the expiry date is the leftover. Leftover times unit cost is the projected loss in reais.
  4. One action per batch. Simple rules suggest what to do, and the planner can change the action and track progress.

On screen you can change the reference date, simulate a consumption change from -50% to +50%, filter by location and import your own CSV. Everything runs in the browser.

Suggested action rules

Tested in this order. The first one that applies is suggested.

Batch situationSuggested action
Already expiredBlock and dispose
Consumption covers the whole batchMonitor
Another location uses at least 20% of the leftover in timeTransfer to that location
Expires within 30 daysProvision the loss and plan disposal
Expires within 90 daysCommercial action: discount or campaign
Expires in more than 90 daysReview the product's purchasing plan

Example with the demo data

Four batches from the fictional dataset, with no change in consumption.

BatchExpires inQuantityConsumptionLeftoverProjected lossAction
L2405 · Painkiller · Southeast DC25 days4,000 units60 units/day2,500 unitsR$ 21,250.00Transfer 1,050 units to South DC
L1120 · Vitamin C · Southeast DC45 days2,500 units30 units/day1,150 unitsR$ 21,160.00Commercial action
L6612 · Children's syrup · Northeast DC95 days1,800 units15 units/day555 unitsR$ 11,821.50Review purchasing plan
L1128 · Vitamin C · Southeast DC160 days3,000 units30 units/day0R$ 0.00Monitor

L6612 expires in 95 days, but batch L6604 of the same syrup is ahead in the queue. That is why it only starts being used on day 12 and 555 units are left over. Looking only at expiry, this batch would seem safe.

How I built it

I wrote the specification with Claude: the sample data, the FEFO formula, the action rules and the numbers the screen had to show. Claude sent that specification to Lovable through the official connector, and Lovable generated the app in React. Then I checked the on-screen totals against the calculation done by hand.

What I learned

About the data: products, batches, costs and locations are fictional. The rules were simplified for the demo; in a real case, transfers and disposal follow health regulations. An imported CSV is processed in the browser and never leaves your computer.