How it was built
YB
Back to the overview
DESTOCK

How this demo was built

Every number you see comes from twelve months of operations at a simulated restaurant. Two things below: how that data was built, and what we do with it.

1

Part 1 — Where the data comes from

Why not just use a real restaurant’s books

We do have real books, and we do serve real restaurants. But they don’t work for a demo, for three reasons:

01

Real books are incomplete

Most restaurants only have monthly totals: revenue in, purchases out. No daily sales, no prep log, no itemised waste. Half the product would show "no data" on that.

02

Someone else’s numbers aren’t ours to show

Purchase prices, margin structure, supplier terms — that is a restaurant’s commercial position. Not something to put in front of third parties.

03

And the one that matters most: real books have no answer key

The braised beef sold out at 12:35. What was real demand that day? The till will never know — the people who wanted it turned around and left. You cannot check whether any forecast was right, because the thing to check against does not exist.

So we built a restaurant

Not a set of good-looking tables dropped into a UI. A full year of trading was simulated first, and every page of the product reads off it. That difference matters: invented numbers only have to look right on one screen, whereas a simulated operation has to reconcile across all of them. The 4.3 kg of brown rice on the waste page comes off the stock ledger, lands in the cost figure, and traces back to how many pots were cooked that morning.

The generation chain

  1. 1

    Outside conditions

    Day of week, public holidays, office-tower occupancy, temperature and rain, platform promos

  2. 2

    Footfall

    Trend + season + correlated noise (negative binomial, not an average with jitter on top)

  3. 3

    What they ordered

    Preferences drift slowly; three menu changes across the year

  4. 4

    True demand that day

    This is the answer key. Stored, and kept away from the product

  5. 5

    Spread across the day

    Lunch 78%, peak 12:00–12:45; dinner 19%

  6. 6

    What the owner actually prepped

    Four-week same-weekday average × 0.95 — by feel, and systematically short

  7. 7

    Sold out, so demand gets cut off

    The demand turned away is booked separately; it never appears in sales

  8. 8

    Leftovers, carryover, expiry

    Produces the waste log

  9. 9

    How the owner ordered

    Produces purchase orders, with late deliveries, substitutions, handwritten dockets

  10. 10

    How stock moved

    Produces the daily ledger and monthly counts, with counting error

Each step follows from the one above it. Nothing in here was typed in by hand.

What the restaurant looks like

Yummy BowlSimulated store

Fast-casual grain bowls & salads, office district

Menu items
23
Raw SKUs
75
Prep items
19
Suppliers
6
Orders / day
281
Revenue / month
¥273,831
Hours
10:00–20:00
Data window
365 days
2025-09-01 → 2026-08-31

Why this format

Nothing is cooked to order — everything is prepped ahead and assembled at the counter, so prep is the whole business. And prepped shelf life runs from 4 hours to 5 days, which is the full range needed to make "how much to prep" a real question.

What got generated

17 tables, 100k rows. Three kinds: master data (what this restaurant has), transactions (what happened each day), and a calendar.

17tables102,696rows365days8weeks of ticket detail

Master data

TableRowsContents
bom_dish211Recipes: which ingredients go in each dish, and how many grams
bom_prep80Prep recipes: how much raw material goes into one batch
dim_alias37Aliases: four different names on four dockets, all the same lettuce
dim_calendar365Calendar: weekday, holidays, temperature, rain, platform promos
dim_dish23Dishes: price, category, launch and delist dates. The menu changed three times
dim_ingredient94Ingredients: shelf life, storage, supplier, batch size, yield
dim_supplier6Suppliers: which days they deliver, lead time, minimum order

Transactions

TableRowsContents
fact_inventory_daily25,511Stock ledger: opening, received, consumed, expired, closing — daily, per item
fact_order_line19,007Order lines: every dish on every ticket
fact_prep_log6,549Prep log: what was cooked when, how many batches, yield, raw cost
fact_price20,359Purchase prices: daily unit price per ingredient, with seasonality and shocks
fact_purchase_header696Purchase orders: with late deliveries and substitutions; 12% handwritten
fact_purchase_line4,404Purchase lines: what came in, how much, at what price
fact_sales_daily7,665Daily sales: units, revenue and delivery share per dish per day
fact_sales_order14,669Orders: every ticket for 8 weeks, with timestamp, channel, discount, void
fact_stock_count813Stock counts: monthly, and the book never quite matches the shelf
fact_waste2,207Waste log: line by line, split into "prepped, not used" and "raw stock expired"

The data is messy on purpose

Real dockets are not clean. A demo on tidy data would skip the step that eats the most time in this business. So the generator lays a mess on top of the clean version:

Mixed units

The same item is kg on one docket, jin on another, "two cases" on a third

Inconsistent names

One kind of lettuce goes by four names across dockets

Missing paperwork

About 3% of purchase orders simply cannot be found

Handwritten dockets

About 12% are handwritten, with looser fields

Book vs shelf

Every stock count has a batch of SKUs that do not tie out

We kept the clean version too. So "how much of the mess did it read correctly" is a measurable number, not a claim we make about ourselves.

Three acceptance tests, all passing

The accounting identity

Every item, every day: opening + received − consumed − wasted + count adjustment = closing. Twenty-five thousand ledger rows, and not one is allowed to break.

Statistical health check

How much daily sales swing, how correlated consecutive days are, how often a slow dish sells zero — all have to land inside the range of a real restaurant. This is the most effective guard against data that is too clean.

Blind test

Mix the generated daily sales in with a real restaurant’s and show someone. If they can pick them out at a glance, it is not good enough.

We know the answer key — the one thing simulated data buys you

Because we built this restaurant, we hold a copy of the things a real one can never measure:

What demand really was on a day that sold out — including the part turned away

The tower’s occupancy that day, and what that promo genuinely lifted

Inside the cost gap: how much was over-portioning, prep loss, expiry, staff meals

93.7%

of true demand met

6,872

covers turned away by stockouts

11.9%

of purchases became waste

That answer key is locked outside the product, and the model cannot read it while it is being built — a script checks this every single time, because a model that can see the answers is just proving it can guess what we wrote. The key is used at the end, to mark the work: the model says 8 kg tomorrow, the answer says 8.6, and the difference gets written down.

Fields the product side can never reach

true_demandcensored_qtysellout_timeoffice_occupancypromo_liftlocal_eventgap_overportiongap_prep_lossgap_expiredgap_staff_meal
2

Part 2 — What the product does with it

Six features below. Each one states three things: which of your records it reads, what it computes, and what decision it lets you make in the morning.

01

Daily prep plan

First thing every morning

The front door of the product. 19 prep items, one number each: prep to this much, cook this many batches, and here is why.

Reads

Sales history, recipes, prep log, waste log, weather forecast, calendar

Computes

Forecast how many of each dish sells tomorrow, convert that into kilos of each prep item, then set the quantity from that item’s own cost of over- versus under-prepping.

What you do with it

The head chef works off the sheet instead of guessing.

The point is that over-prepping costs a different amount per item

Caesar dressing keeps five days — what is left today gets used tomorrow, so an extra batch costs almost nothing. Prep it wide. Guacamole dies today; leftovers are a total loss. Prep it tight and make more at lunch if you need it. Nobody can eyeball that difference, and it is exactly the line between making money and losing it.

Three completely different kinds of answer on one page

Braised beef

"Prep to 8 kg, good through tomorrow lunch" — it carries over, so we give a total

Brown rice

Keeps 4 hours. The answer is not a quantity, it is a timetable: 2 pots at 10:00, 2 more at 11:30

Sweet potato fries

"Don’t prep. Fry to order."

All three on the same page is itself the proof that we are not applying one formula.

02

The cost gap

The page that needs no faith in our algorithm

The card that matters most on the home page: what the recipes say you should have spent, what the ledger says you did, and the difference.

Reads

Sales history, recipes, stock ledger

Computes

One side is dishes sold × recipe quantity × that day’s purchase price. The other is what actually came off the stock ledger. Subtract.

What you do with it

A specific monthly figure, and a thread to pull.

This page argues differently from the rest

Forecasting asks you to trust us. This asks you to look at your own books. You do not have to believe our model, only arithmetic — both numbers come from your own records.

In this dataset, pulling that thread found two things

The scoop has been running heavy

Three braised items consume 14% more than the recipe calls for. Derived from prep log minus waste log, against units sold. It has been that way since last November. Nine months, nobody caught it.

Braised beef yield slipped

From 62% to 55%. Same pot, more raw material going in. The recipe never changed — the supplier changed the cut. Back-derived from purchased weight versus finished weight. Nobody weighed it, but the books could not hide it.

Both of these had been bleeding continuously, and neither appeared on any report.

03

Demand forecast

How many covers for each of the next seven days, and why each day lands where it does.

Reads

Sales history, weather forecast, public holidays, promos you signed up for

Computes

Decomposes demand into weekday, trend, holiday, weather and promo factors that multiply together. Days that sold out get reconstructed separately — running out does not mean that was all the demand.

What you do with it

A seven-day ingredient requirement you can order straight off.

Why we insist on a model that can explain itself

"Heavy rain tomorrow. Delivery historically climbs, dine-in drops, net +11%, so braised beef goes from 8 kg to 9.5 kg." That sentence is the reason an owner actually follows the advice. A black box cannot produce it — it can only hand you a number and ask for trust.

The comparison stays on screen

Measured against your current method

The dashed line is the four-week same-weekday average — what most restaurants use today. We do not claim to be accurate in the abstract, only better than that line by a stated amount.

Walk-forward, not hindsight

The number for any given day is fitted only on data from before it. Otherwise every "forecast" in the demo is written after the fact and collapses under the first question.

04

Inventory

How many days of cover each item has, and which ones will not make it to the next delivery.

Reads

Stock ledger, last four weeks of consumption, supplier delivery schedule

Computes

Closing stock ÷ daily consumption = days of cover. Set against which days that supplier delivers and how long the order takes.

What you do with it

A list of what must be ordered today, and how much.

You never key in a par level

Most inventory software asks you to set a par level for every item first — dozens or hundreds of SKUs, which nobody finishes, and which nobody updates when the season turns. Here the line is computed: consumption is in the ledger, delivery rhythm is in the supplier terms, and you already have both. The seafood supplier comes daily, the dry-goods one every three days — the same two days of stock is fine for one and a problem for the other.

05

Waste log

What went in the bin, what it was worth, and why.

Reads

Waste log, ingredient master, calendar

Computes

Totals it by cause, category, item, weekday and month.

What you do with it

Knowing which thing to fix first.

The two kinds of waste get fixed in different places

"Prepped, not used" is a prep-quantity problem — fixed on the prep page. "Raw stock expired" is a purchase-quantity problem — fixed on the forecast page. Rolling them into one waste total makes the number unactionable, so this page keeps them apart throughout.

By weekday, you see things the totals hide

Monday and Sunday carry the weight — what gets prepped for the weekend does not get eaten on the weekend. You cannot find that pattern without cutting by weekday.

06

Menu costing

Every dish costed to the cent, and changing one quantity recomputes the margin live.

Reads

Recipes, daily purchase prices, prep log, sales

Computes

Costs each dish at today’s prices. Prep items are priced from what the kitchen actually spends per finished kilo, not from the recipe on paper.

What you do with it

Knowing which dish is losing money, and whether portion or price is the fix.

Why prep items are not costed from the paper recipe

On paper, 13 kg of chuck makes an 8 kg batch of braised beef. Once yield slips to 55%, the same 8 kg takes 14.5 kg going in. Cost it on paper and this dish never moves, while money leaves every day. Cost it from the actual prep log and the number moves — which is the only way you get to see it.

How accurate is the forecast

42.0%

error · four-week weekday average

36.4%

error · DESTOCK

−13%

error reduced

Measured across 274 days of walk-forward replay, each day using only data from before it. The comparison is what most restaurants do today. We do not quote an accuracy figure on its own — a number without a baseline means nothing.

How the gap on the home page is computed

recipes say

25.1%

→

ledger says

27.8%

=

unaccounted gap

2.7 pts

¥9,059 / mo

Both sides cover the last 30 days and both exclude packaging (that runs a separate 3.4% — the industry definition of food cost has never included it). Left is every dish sold × recipe grams × that day's purchase price. Right is what actually came off the stock ledger. Both come from the restaurant's own records, with none of our assumptions in between.

In one paragraph

Most restaurant software helps you keep books — recording what already happened. DESTOCK is aimed at the decision every morning that has not happened yet: how much to prep today. That decision is made by feel, and getting it wrong costs on both sides — prep too much and it goes in the bin tonight, prep too little and the customer turns around and leaves. You see the first one. You never see the second. Which is why most restaurants are quietly under-prepping.

The restaurant in this dataset bins ¥133,910 a year, and carries another ¥9,059 a month it cannot account for between its two ledgers. Neither figure appears on any report it produces — not because nobody cares, but because nobody can see them.

Disclaimer

"Yummy Bowl" in this demo is a simulated restaurant. All data is program-generated and is not any real restaurant’s trading results. Unit prices for common ingredients such as rice, chicken, lettuce and cooking oil reference a real set of books; the rest are industry benchmarks.