← All tests

Multi-register Bundle 1 — schema + backfill PROD

2026-05-13 on Supabase prod. First of two bundles toward multi-register per shop + UUID-decoupling from Odoo's bigint. Bundle 1 is migration + backfill ONLY, zero code change, zero behavior change. No code on prod reads the new pos_config_uuid column yet — legacy int pos_config_id stays authoritative until Bundle 2 ships.

15/15 prod data-integrity probe PASS. 51/51 regression green. 66/66 total.

Prod backfill log (from node migrate.js output)

  - cafe.pos_configs Pro shop_id enriched: 0 rows
  - cafe.pos_configs 'Register 1' seeded for shops without a row: 7 rows
  - cafe.sessions.pos_config_uuid backfilled: 440 rows
  - cafe.orders.pos_config_uuid backfilled: 181 rows
  - cafe.shop_pos_configs.pos_config_uuid backfilled: 0 (Pro) + 4 (fallback)
  - cafe.pos_sequences.pos_config_uuid backfilled: 10 (Pro) + 368 (Starter)
Migrations complete.

Diagnostic counts (prod)

Loading…

Per-tenant breakdown

Loading…

⚠ Data shape finding — affects Bundle 2 plan

get-coffee has 6 cafe.pos_configs but only 1 commerce.shops row:
  - 5 Pro rows (Bakery Shop, Get Coffee CM/TK/TSP, Fresh Clean Shop — Odoo ids 4-8)
    all with shop_id=NULL (no shop_pos_configs entry ever linked them).
  - 1 'Register 1' auto-seeded by THIS migration — redundant for get-coffee.
The migration's "auto-seed if no pos_configs row exists FOR this shop" check
treated the shop as unlinked (correct — no shop_id was set yet) and inserted.

Implication for Bundle 2:
  - Single-shop tenants (get-coffee + demo) need a one-shot enrichment:
      UPDATE cafe.pos_configs SET shop_id=(...)
       WHERE shop_id IS NULL
         AND tenant has exactly 1 commerce.shops row
  - Then delete the redundant auto-seeded 'Register 1' on get-coffee.
  - Bundle 2's /cafe/settings/registers will show this cleanly: 5 Pro registers
    under the one get-coffee shop, named after the Odoo pos.configs.

Why this happens: R6.5 created cafe.shop_pos_configs as an optional scoping
link table — Pro tenants can use it to restrict which shop sees which Odoo
register. Narong never populated it for get-coffee (only lumiere has 4 rows).
So the auto-enrichment-from-JOIN path returned 0 rows for get-coffee.

Probe still passes — every pos_config_uuid resolves correctly, every session +
order has the right UUID. The issue is purely cosmetic until Bundle 2's admin
UI tries to list "registers per shop". Fix lands as the first step of
Bundle 2's migration step.

Regression sweep — 51/51

SuiteResult
test-multi-register-bundle1-prod.mjs (NEW)15/15
test-phase1-prod.mjs11/11
test-phase2-sso-outdoor-prod.mjs6/6
test-phase2-cafe-multishop-prod.mjs6/6
test-m1-prod.mjs10/10
test-r7-prod.mjs14/14
test-r8-prod.mjs4/4
Total66/66

Bundle 2 prep (next gate cycle)

Migration step 1 (Bundle 2 starts here):
  Enrich shop_id on pos_configs for tenants with exactly 1 shop +
  delete redundant auto-seeded Register 1 rows where Pro rows exist.

Then code cutover (~30-40 files):
  - Read pos_config_uuid in every DAO/route/action/test
  - Set NOT NULL + FK on pos_config_uuid → cafe.pos_configs.id
  - /cafe/settings/registers admin (per-shop dropdown, CRUD, sequence_prefix)
  - Starter POS landing renders N cards per shop (currently 1:1)
  - StarterTopBar register picker when shop has > 1 register
  - formatPosOrderNumber extended with sequence_prefix
  - settings-nav.tsx adds "Registers" entry

Out of scope (separate future task):
  - Odoo connector to push NIX-created Pro registers via pos.config.create.
    Bundle 2 sets sync_state='pending_create' on those rows; the connector
    drain mirrors R11.5's session-close-move shape.