Free operator sheet · Stays in your browser

Daily Sales & Cover
Recap.

End-of-night close-out, one page per shift. Net sales, covers, voids, comps, cash over and short, weather note, manager initials.

Pack: Operations & Margin Cadence: Daily · per shift Private — runs in your browser

Fill it in

Daily Sales & Cover Recap

Type your numbers — the math runs in your browser. Print it, save it as a CSV, or save it to your Workshop.

Worked example 32-seat neighborhood bistro, Tuesday close See what a Tuesday-morning fill-in looks like
Net sales (POS, after sales tax)$3,840
Voids$62
Comps$48
Cash drawer over/short−$11
Voids as a % of sales1.6% · yellow
Comps as a % of sales1.3% · green
Drawer flagWithin $5 — clear

Voids ran a hair high — three of them came from one server who hadn't been re-trained on the comp-vs-void distinction since the spring menu change. The recap stack from the prior two weeks shows the same name on the void column three days running. Wednesday's pre-shift gets a 90-second refresher.

Composite-typical numbers — not a real shop. Use the rhythm, not the figures.

Shift
Sales (net of sales tax)
Voids · Comps · Cash
Notes
Average check $0.00
Voids as % of sales 0.0%
Comps as % of sales 0.0%
Variance vs 14-day average

Type the numbers above. Voids above 1% of sales is the band where theft hides; comps above 3% is the band where over-comping starts pricing your menu.

Read the long version Why daily evidence is what makes the weekly verdict actionable, the four lines that matter most, the patterns that surface over two weeks, and the four lies operators tell themselves about the daily ledger. The trail of evidence — Why the daily recap is what makes the weekly verdict actionable →

+ (Math.round(abs * 100) / 100).toFixed(2); } function fmtPct(v) { return (Math.round(v * 10) / 10).toFixed(1) + '%'; } function recalc() { var f = document.getElementById('sheet-fields'); if (!f) return; var sales = n(f.net_sales.value); var covers = n(f.covers.value); var avg = sales > 0 && covers > 0 ? sales / covers : 0; var voidPct = sales > 0 ? (n(f.voids.value) / sales) * 100 : 0; var compPct = sales > 0 ? (n(f.comps.value) / sales) * 100 : 0; var rolling = n(f.rolling_avg.value); var variance = rolling > 0 ? ((sales - rolling) / rolling) * 100 : null; document.querySelector('[data-output="avg_check"]').textContent = fmt$(avg); var vEl = document.querySelector('[data-output="voids_pct"]'); vEl.textContent = fmtPct(voidPct); // D9 — voids and comps bands route through centralized // benchmarks (data/benchmarks.json). Inline ladder is the // pre-Bench fallback. if (window.Bench && window.Bench.evaluate) { var bv = window.Bench.evaluate('voids_pct_of_sales', voidPct); if (bv && bv.band) vEl.dataset.band = bv.band; } else { vEl.dataset.band = voidPct < 1 ? 'good' : (voidPct < 2 ? 'warn' : 'bad'); } var cEl = document.querySelector('[data-output="comps_pct"]'); cEl.textContent = fmtPct(compPct); if (window.Bench && window.Bench.evaluate) { var bc = window.Bench.evaluate('comps_pct_of_sales', compPct); if (bc && bc.band) cEl.dataset.band = bc.band; } else { cEl.dataset.band = compPct < 2 ? 'good' : (compPct < 4 ? 'warn' : 'bad'); } var varEl = document.querySelector('[data-output="variance"]'); if (variance == null) { varEl.textContent = '—'; varEl.dataset.band = 'idle'; } else { var sign = variance > 0 ? '+' : ''; varEl.textContent = sign + fmtPct(variance); varEl.dataset.band = Math.abs(variance) <= 10 ? 'good' : (Math.abs(variance) <= 20 ? 'warn' : 'bad'); } var callout = document.querySelector('[data-output="callout"]'); if (!callout) return; var bits = []; if (sales <= 0) bits.push('Type the numbers above.'); if (voidPct > 1) bits.push('Voids running above 1% of sales — ' + fmtPct(voidPct) + ' tonight.'); if (compPct > 3) bits.push('Comps running above 3% of sales — review who is comping and why.'); if (variance != null && Math.abs(variance) > 20) bits.push('Tonight landed ' + (variance > 0 ? 'above' : 'below') + ' the 14-day average by more than 20%.'); // D9 — Bench.flag walks data/benchmarks.json's anomalies // for this slug; the drawer-short rule lives there. if (window.Bench && window.Bench.flag) { var flags = window.Bench.flag('daily-sales-recap', { cash_diff: n(f.cash_diff.value) }); for (var fi = 0; fi < flags.length; fi++) bits.push(flags[fi]); } else if (n(f.cash_diff.value) <= -5) { bits.push('Drawer short by ' + fmt$(Math.abs(n(f.cash_diff.value))) + ' — log it tonight, do not let it carry.'); } callout.textContent = bits.length ? bits.join(' ') : 'A clean recap. File it; pull the trend in next week’s review.'; } function collect() { var f = document.getElementById('sheet-fields'); if (!f) return [['Field', 'Value']]; return [ ['Field', 'Value'], ['Date', f.date.value || ''], ['Shift', f.shift.value || ''], ['Manager', f.manager.value || ''], ['Weather', f.weather.value || ''], [], ['Net sales', f.net_sales.value || '0'], ['Covers', f.covers.value || '0'], ['Trailing 14-day average', f.rolling_avg.value || ''], [], ['Voids', f.voids.value || '0'], ['Comps', f.comps.value || '0'], ['Cash over/short', f.cash_diff.value || '0'], [], ['Notes', f.notes.value || ''], [], ['Average check', document.querySelector('[data-output="avg_check"]').textContent], ['Voids %', document.querySelector('[data-output="voids_pct"]').textContent], ['Comps %', document.querySelector('[data-output="comps_pct"]').textContent], ['Variance vs 14-day avg', document.querySelector('[data-output="variance"]').textContent], ['Callout', document.querySelector('[data-output="callout"]').textContent], ]; } if (window.SheetPage) { window.SheetPage.register({ slug: 'daily-sales-recap', collect: collect, recalc: recalc }); } })();

Keyboard: ⌘P print · ⌘S download CSV · ⌘↵ save to Workshop

When to use it

Pull this sheet out when —

  • Right at close, before the manager leaves the building.
  • Comparing tonight to a typical Tuesday — was the dip weather, schedule, or something else?
  • Spotting a void rate that drifts above 1% of sales — that is where theft hides.
Common mistakes

What operators get wrong

  • Logging gross sales instead of net (sales tax included). Use net every time.
  • Skipping the cash over/short field on busy nights — the field exists for the busy nights.
  • Not noting weather. A 30% dip on a clear Saturday is a different problem than the same dip in a snowstorm.
Pairs with

The tools, terms, and articles this sheet sits next to.

Glossary

Reading

  • None yet.

Free, no signup. Your numbers never leave this page.