Deli stall owner-operator - closing-time discount calculator: when to start marking down and by how much, one page of numbers instead of a mood
Build a single-file HTML closing-time discount calculator for a
cooked-food stall, for the owner to glance at in the afternoon:
how much is left on the counter, when to start marking down, how
deep - a decision made daily on gut feel; let it come out of the
arithmetic instead.
Input (typed into the page):
- Items: name, full price per unit weight, current leftover
weight
- Hour bands: each remaining sales window before close (e.g.
5-6 pm, 6-7 pm, 7-8 pm) with "expected sales at full price" -
the recent weekly average sold in that window, typed in;
windows with thin samples are fine, the tool flags them
- Markdown plans: discount rate per step (e.g. 10% off, 20%
off, half price) and the start time of each; one item can
carry a ladder (10% off at 6 pm, half price from 7 pm)
- Spoilage rule: everything left at close counts as spoiled -
this tool has no "carry to tomorrow" option; overnight
product is a quality decision, not a bookkeeping one
- Discount uplift factor: how much sales volume rises in
discounted windows, per item, typed in; blank defaults to 1.0
(discounting sells not one extra portion)
Calculations and output:
- Scenario comparison table (the core): one row per plan -
Projected revenue = sum over windows of (expected sales at
that window's price, capped by remaining stock after any
uplift in discounted windows)
Projected spoilage weight = leftover minus total expected
sales, floor at zero
Versus the "no markdown" baseline: extra revenue, spoilage
avoided
- "Early vs late" block: for the same discount rate, the revenue
difference for each hour the start time moves earlier - this
is the question the tool exists to answer; give it its own
enlarged panel
- Uplift notice bar: whenever any item's factor is 1.0, state
plainly "currently estimating that discounting sells nothing
extra" - the tool would rather show discounting as a loss
than be optimistic on my behalf
- Print view: one A4 page - scenario table plus tomorrow's
stocking suggestion (cut today's spoiled weight by [Z]%,
my coefficient), all arithmetic collapsed
Implementation requirements:
- Single file, no external dependencies, no network calls;
items and hour bands persist in localStorage across refreshes
- Do not embed any "how much discounting usually lifts sales"
rule of thumb - the uplift factor is mine to fill from my own
weeks of data
- Round money to whole currency units and weights to 50-gram
steps - the stall's scale jumps in 50 g and the counter quotes
by weight; nobody feels "3.76 lost," everybody feels "a ladle
of oil"
- No accounts, no cloud sync
Notes for the coding agent:
- Hour-band sales support partial-memory entry: average over
the days actually filled; windows with fewer than [7] days of
sample get a "thin sample" badge but still compute
- When markdown steps overlap in time, the lowest active price
applies; discounts never stack
Why it is written this way
The real failure mode at closing time is not innumeracy - it is mood swinging one way at a time: on a slow day the heart softens and half price goes up at six (margin given away), and on a day that ran on experience the owner holds out to the bitter end (the whole tray spoiled). The two errors alternate, and neither corrects the other. So the tool's core output is not an "optimal discount" - it is scenarios side by side plus the early-versus-late difference, turning "half price at six instead of seven" into a visible daily number that both the soft heart and the hard heart can be measured against.
"Uplift blank means 1.0, stated on the page" is the tool's most important honesty feature. Whether a discount sells more depends entirely on this market's evening foot traffic and this product - any built-in "industry elasticity" is invented. At 1.0 the tool shows discounting as a loss, which is correct behavior: it bounces the question "are you sure marking down sells more?" right back to the only person who can answer it, and pushes them to fill the factor from their own weeks of data. Counting all closing leftovers as spoilage with no overnight option is the same discipline's other half: plenty of stalls "don't lose money" on paper because braised goods get reheated and resold the next day - this tool refuses to book that quality risk as revenue.
The restocking suggestion is only a Z% haircut on today's spoilage rather than a recommended order, because tomorrow's demand still bends to weather, paydays, and the neighbor's stall; the tool converts today's pain into an adjustable starting point, nothing more. Rounding to whole money and 50-gram steps is not formatting fussiness - it matches how the scale ticks and how the counter talks, which is what makes a number felt rather than filed.
Variables
| Variable | Notes |
|---|---|
| Restock haircut Z | How much of today's spoilage weight to cut from tomorrow's prep - decide after two weeks of watching; single days are noise |
| Sample-day threshold | Minimum days behind an hour-band average - below it, badge the number so nobody treats it as settled |