Closes the H4 arc completely. View-ifies cafe.products; migrates
order_lines.product_id FK; refactors all DAOs that wrote to
cafe.products into singular-table writes; adds name_kh on attribute
model; adds per-variant edit UI; adds global branded 404.
0b8aaa7 + nix-cafe 0482893. Migration applied to prod Supabase via
node migrate.js — 5 phases A-E completed atomically. 35,084 cafe.order_lines
rows had their product_id retargeted from cafe.products → cafe.product_product.
DAO probe verified createProduct/updateProduct/deleteProduct round-trip through the new view +
per-variant updateVariant + Khmer Unicode name_kh round-trip (កម្តៅ / ក្តៅ).
/cafe/settings/attributes renders with name_kh fields visible in attr-form/cafe/settings/modifiers still retired (R10 UI absent)Raw: 01-prod-dao-probe.json · result.json
| test-phase1-prod.mjs | 11/11 |
| test-phase2-sso-outdoor-prod.mjs | 6/6 |
| test-phase2-cafe-multishop-prod.mjs (parallel on demo) | 6/6 |
| test-m1-prod.mjs | 10/10 |
| test-r7-prod.mjs | 14/14 |
| test-r8-prod.mjs | 4/4 |
| Plus prod feature test (above) | 8/8 |
| Total | 59/59 |
First prod-test run had 7/8 — the /cafe/settings/attributes attr-form check
timed out waiting for the new attr-name-kh testid. Re-ran after a 60-second
delay (CF Pages deploy was still propagating the new client bundle) and got 8/8. The
backfill + FK migration + view recreation completed on the migrate.js run; only the client
bundle deploy lagged.
P1 (2026-05-19) — schema (7 dark singular tables)
P2+P3 (2026-05-19→20) — Attributes admin + R10/products backfill + Cartesian generator
P4 (2026-05-20) — POS read-path cutover + multi-variant backfill
P5 (2026-05-20) — Retire R10 + cafe.products sync hooks
X (2026-05-20) — View-ify cafe.products + name_kh + per-variant edit + not-found + reverse sync via direct singular writes
The data model now matches Odoo's product.template / product.product convention end-to-end. Order history works via the back-compat view. Admin manages attributes + variants at template level. POS reads from singular tables directly. Pro Odoo sync writes singular (via refactored backfill scripts + lib/db/odoo_push.ts mark*Synced/Failed).
New:
nix-outdoor-sales-backend/migrations/20260520140000_h4_x_viewify_cafe_products.ts ·
nix-cafe/app/(authed)/not-found.tsx
Modified:
nix-outdoor-sales-backend/migrate.js ·
nix-cafe/lib/db/schema.ts ·
nix-cafe/lib/db/products.ts ·
nix-cafe/lib/db/odoo_push.ts ·
nix-cafe/lib/db/product_attribute.ts ·
nix-cafe/lib/actions/product_attribute.ts ·
nix-cafe/app/(authed)/settings/attributes/attributes-client.tsx ·
nix-cafe/scripts/backfill-pro-tenant-products.ts ·
nix-cafe/scripts/backfill-pro-tenant-categories.ts ·
nix-cafe/scripts/backfill-pro-tenant-product-images.ts
Deleted:
nix-cafe/lib/db/product_template_sync.ts
Migrations: 1 (5 phases, idempotent).