Parse the warehouse stock export
Node · Node · beginner · greenfield
Adds a small parser for the warehouse stock TSV export plus a `totalQuantityBySku` rollup for the replenishment report. Splits the file into lines, reads the header row to key each record, and sums quantities per SKU. Tested against a hand-written sample export and the totals come out right.
The warehouse team saves the export from Excel as 'Unicode Text (UTF-8)', which prefixes the file with a byte-order mark (U+FEFF) before the first header.
Requirements
- Parse the warehouse stock export: a UTF-8 tab-separated file whose first line is the header row `sku<TAB>quantity<TAB>location`, followed by one data row per stock record. Every data row contains exactly three fields in that order.
- The parser must handle the file exactly as the warehouse team's Excel export produces it — no manual re-saving or cleanup step is acceptable.
- `parseStockExport(text)` returns one object per data row, keyed by the header names.
- `totalQuantityBySku(text)` returns a Map of SKU → total quantity across all rows for that SKU. Quantity fields are base-10 non-negative integers, small enough that no per-SKU total ever approaches `Number.MAX_SAFE_INTEGER`.
- Blank lines anywhere in the file are skipped. Field values never contain tabs.
Files touched
- src/warehouse/stockExport.js
--- src/warehouse/stockExport.js
+/**
+ * Parse the warehouse stock export (UTF-8 TSV saved from Excel)
+ * and total quantities per SKU for the replenishment report.
+ */
+function parseStockExport(text) {
+ const lines = text.split(/\r?\n/).filter((line) => line.trim().length > 0);
+ const headers = lines[0].split('\t');
+ return lines.slice(1).map((line) => {
+ const cells = line.split('\t');
+ const row = {};
+ headers.forEach((name, index) => {
+ row[name] = cells[index] ?? '';
+ });
+ return row;
+ });
+}
+
+function totalQuantityBySku(text) {
+ const totals = new Map();
+ for (const row of parseStockExport(text)) {
+ const current = totals.get(row.sku) ?? 0;
+ totals.set(row.sku, current + Number(row.quantity));
+ }
+ return totals;
+}
+
+module.exports = { parseStockExport, totalQuantityBySku };
+