← back to index

U9 — Product Import (XLSX/CSV)PROD

Bulk-create products + variants via Narong's canonical XLSX template. Source: Notion test-run doc item #12 "Product Import". Client-side parse via SheetJS keeps bytes off the Worker; per-row transactions so one bad row doesn't roll back the rest. 3-stage UI (Upload → Mapping → Result).

Summary

Status
11/11 prod · 51/51 regression = 62/62 · shipped
Commits
nix-outdoor-sales-backend a8ac8ab · nix-cafe 80fc8fc
Files
1 new migration · 5 new + 2 modified nix-cafe files · 1 new dep (xlsx@^0.18.5) · ~1,400 LOC
Migration
Add cafe.product_template.track_inventory BOOLEAN NOT NULL DEFAULT false. Verified on prod across get-coffee + demo + lumiere.

11/11 prod checks

Prod: cafe.product_template.track_inventory column exists, default false, NOT NULL (direct Supabase information_schema query)
SSO login on lumiere-coffee.nixtech.app
/cafe/products renders + "+ New ▾" dropdown trigger visible
"+ New ▾" dropdown opens with 4 items: New record, Import records, Export All (disabled), Spreadsheet (disabled)
Click "Import records" → routes to /cafe/products/import; Upload stage + template download link + drop zone render
setInputFiles → mapping stage renders with 9 mapping rows; first column auto-maps to sku
Click Test → green validation-ok banner ("3 rows ready to import")
Click Import → result stage renders + summary tiles: 1 template / 3 variants / 0 skipped / 1 category / 1 attribute / 3 values
DB verify on prod Supabase: 1 template (track_inventory=false, is_hidden=false from show_on_pos=TRUE) + 3 variants (prices "1.25" / "1.75" / "2.00") + 1 category (id matches template.category_id) + 1 attribute + 3 values (HOT / ICE / FRAPPE)
Re-upload same XLSX → result stage shows 0 templates created, 0 variants added, 3 variantsSkipped — skip-existing dedup confirmed end-to-end
No 5xx during the suite

Screenshots

Regression sweep — 51/51

11/11 + 51/51 = 62/62 prod tests green on the karouna-dev branch.
test-phase1-prod.mjs11/11
test-phase2-sso-outdoor-prod.mjs6/6
test-m1-prod.mjs10/10
test-r7-prod.mjs14/14
test-r8-prod.mjs4/4
test-phase2-cafe-multishop-prod.mjs (solo)6/6

Mid-Gate-2 notes