For Managers · 5-minute read
Data export
Two reports in PrepTable have an Export CSV button — the inventory-usage report and the low-stock panel. The CSV is the format you hand to the business office, attach to a vendor conversation, or paste into a spreadsheet to re-pivot. This page explains how to get them, what the columns mean, and how the export relates to what's on screen.
What's exportable today
| Report | Endpoint | On-screen view | CSV download |
|---|---|---|---|
| Inventory usage | GET /api/v1/stores/{storeID}/usage | /stores/{id}/usage | usage-report.csv |
| Low-stock items | GET /api/v1/items/low | inventory page → low-stock panel | low-stock-report.csv |
That's the full export surface. There is no raw stock_movements ledger export, no audit-log export, and no POS/sales export — pricing and transaction data are Saavor's per the boundary in the overview, and the per-transaction detail isn't useful for a campus manager's weekly review.
If you need a third export and don't see it here, raise it through your administrator — adding a new export to the same pattern is a one-day change.
How to download
In the app:
- Inventory usage: go to
/stores/{id}/usage, set your date range and which reasons to include, click Run report, then click Export CSV. The file downloads asusage-report.csv. - Low-stock: open the inventory view at your campus. The low-stock panel has an Export CSV button next to its existing store/location filter. Click it; the file downloads as
low-stock-report.csv.
The buttons are <a download> links, not JavaScript fetches. That means the browser does a normal same-origin navigation with your session cookie attached, the server streams the CSV back with Content-Disposition: attachment, and the browser saves the file. There's no Blob construction, no FileSaver, no race condition — session-cookie auth flows through the same mechanism that loads the page itself.
The export is disabled when the report has zero rows. There's no point in an empty CSV.
The CSV format (exact columns)
Inventory usage report
item_name,unit,total_used,used_waste,used_adjust,used_count_correction,used_receive,unit_cost_cents,value_used_centsitem_name,unit— straight from the item recordtotal_used— sum of absolute quantity consumed in the window (across all selected reasons)used_waste,used_adjust,used_count_correction,used_receive— same total broken out by reason. Reasons not selected, or zero for that item, write0.unit_cost_cents— the current item cost (the value preferred-vendor pricing computes). The CSV values usage at current cost, not the cost at the time of the movement. This matches what's on screen, which uses the same value.value_used_cents—total_used × unit_cost_cents, rounded to cents
A reason that's not in the filter writes 0 in that column — the CSV always has the same shape regardless of which reasons are selected. The total reasons column is the rollup; the per-reason columns are how you'd re-pivot in a spreadsheet.
Low-stock report
item_name,item_sku,unit,current_stock,par_level,deficititem_name,item_sku— duplicated (item_name is for human reading, item_sku is for the reorder conversation with the vendor)current_stock— the on-hand quantity at the time of exportpar_level— the par configured at the campusdeficit—par_level - current_stock, rounded. Items above par don't appear in this report at all (they're not "low stock").
The low-stock CSV is read-only and idempotent: re-running it twenty minutes apart gives nearly the same file (modulo movements between the runs).
How the export stays in sync with what's on screen
The export uses the same query as the on-screen report. No duplication. There's no "we built the JSON path then built a separate CSV path" — there's one path that switches serialization based on ?format=csv. That has two important consequences:
- Filters carry through identically. If you filter the on-screen usage report to
Wasteonly, the CSV that comes out of Export CSV is the same set of rows. The CSV does not give you everything despite the on-screen filter, and it does not give you a subset based on a separate UI. - The CSV cannot silently drift from the JSON. It's the same computation. If we ever fix a bug in the usage rollup, the CSV updates in lockstep — there's no second implementation to keep in sync.
If a column on the CSV looks wrong, the same number on screen is also wrong. The fix lives in the rollup, not in the export code.
What to do with the CSV
Two common downstream uses:
Hand it to the business office
The business office typically wants weekly usage by item valued at cost (the value_used_cents column) for cost-of-goods reporting. Filter the on-screen report to the week, click Export CSV, email it. They can pivot on the by_reason columns to attribute cost to spoilage vs. adjustment vs. receiving-error.
A weekly cadence is the right rhythm — daily exports produce noisy data and monthly exports mask trends you'd want to react to mid-week.
Share the low-stock with a vendor
When an item is structurally low at multiple campuses, the low-stock CSV across all of those campuses reads as one conversation with your vendor. The item_sku column is the key — paste it into an email subject line and the vendor's rep knows exactly what you're talking about. Include current_stock and deficit so they can quote a fill quantity without asking back.
Drop it into a spreadsheet and re-pivot
If you want to look at "waste by item by week over the last quarter," pull the CSV per week, concatenate in a sheet (copy/paste or a small loader script), pivot on item_name × week, sum used_waste. The by_reason columns give you the breakdown for free without re-pivoting the JSON.
What's deliberately not in the CSV
- The raw
stock_movementsledger. We expose the rollup, not the per-event feed. Each row in the ledger is one item-store change; the rollup adds them up by reason for the window. If you need the per-event feed (for a deep investigation), ask your admin — the audit log captures every event, which is more authoritative for that purpose than a CSV export. - The audit log. Audit-log export is a separately deferred item; admins reading the log on-screen is the supported path right now.
- Pricing data. Sell prices are Saavor's domain. The CSV values usage at the prepTable-side cost (
unit_cost_cents); no margin, no sell price. - Other formats. CSV only. No Excel, no PDF, no "export-as-email" integration. Each is a different downstream feature; CSV was the one the RFP asked for.
Where to go next
- Par levels & low-stock alerts — the source of the low-stock CSV
- Waste tracking — the source of the
used_wastecolumn in the usage CSV