3.9 KiB
3.9 KiB
F-144 — Implementer evidence
What
F-144 build evidence: an additive schema migration 048_* adds the store/VAT/cost/shipping snapshot columns to orders_orders / orders_items, plus DB integration test reporting-snapshots.itest.ts. Backend-only, no API or user-facing behavior change (reporting routes are unchanged from F-143).
Design recap (architect-approved — see architect.md)
orders_orders.store_iduuid NOT NULL DEFAULT <default store>with guarded FK →pos_stores(id)+ index(store_id, created_at). Column DEFAULT backfills existing rows and future inserts without a table rewrite and without app-layer changes to the order INSERT path. FK resolución por request se posterga a F-146.orders_orders.shipping_centsinteger NOT NULL DEFAULT 0separa envío del total (sin sobreescritura: históricos → 0,total_centsintacto).orders_items.cost_at_sale_centsbigintyorders_items.vat_ratetext, nullable (snapshots → NULL hasta poblados; margen/IVA-por-tipo permanecenunavailable, nunca 0).up()idempotente:ADD COLUMN IF NOT EXISTS(PG>=9.6) +DO $$ IF NOT EXISTS ... $$guard para el FK (PG16 no admiteADD CONSTRAINT IF NOT EXISTS).down()reversible (índice/constraint/columnas).
Files
project/migrations/048_reporting_store_shipping_snapshots.js(created) —up/downidempotent/reversible. El FK usaDO $$guard (convención 047/046) tras confirmar via psql que el bloque DO es SQL válido en PG16.15.project/src/app/tests/reporting-snapshots.itest.ts(created) — recrea la DB (drop+recreate), migra001→048, verifica schema víainformation_schema/pg_constraint/pg_indexes, e inserta revertindo el CHECK de 047.
Tests
- NEW
reporting-snapshots.itest.ts(3, real PostgreSQL): AC1 (store_id col NOT NULL + DEFAULT + FK contype='f' + índice + INSERT backfill store_id=DEFAULT_STORE_ID), AC2 (shipping_cents NOT NULL DEFAULT 0 + backfill=0), AC3 (cost_at_sale_cents bigint nullable / vat_rate text nullable).- Adaptación: el
INSERTusaINSERT INTO orders_orders (source) VALUES ('pos')en lugar deDEFAULT VALUESporque el CHECK de 047 (source='pos' OR user_id IS NOT NULL) rechaza una fila 100% NULL;store_id/shipping_centssiguen backfilliándose por el column DEFAULT → el intento de AC1/AC2 se verifica.
- Adaptación: el
Verification
- Migration 048 applies clean (dev + test DB):
node-pg-migrate up --verbose→ "Migrations complete!";048_reporting_store_shipping_snapshots (UP)log; columns/FK/index presentes enmercadodevidadev. (Raw psql confirmó el DO-block FK válido en PG16.15.) TEST_DATABASE_URL=... npx vitest run src/app/tests/reporting-snapshots.itest.ts→ 3 passed, 0 skipped, exit 0 (crea DB, migra 048, verifica todo).npx tsc --noEmit→ 0 errors (incluye el itest .ts; estricto, noUncheckedIndexedAccess).node scripts/check-module-boundaries.mjs src→ 0 NEW violations (única infracción R1 preexistentesecurity.routes.ts → log-broadcaster, no introducida por F-144, fuera del diff)../scripts/verify.sh→ green (F-144 in_progress, runtime-consistent; 270 features válidos).- Re-run up() idempotente → no-op (DDL
IF NOT EXISTS+ DO guard);down()revierte todo.
AC traceability
| AC | Estado | Evidencia |
|---|---|---|
| AC1 store_id NOT NULL + DEFAULT + FK + idx + backfill | ✅ | itest col/is_nullable=NO/default+FK contype='f'+índice+INSERT backfill |
| AC2 shipping_cents NOT NULL DEFAULT 0 | ✅ | itest col + INSERT backfill=0 |
| AC3 cost_at_sale/vat_rate nullable | ✅ | itest is_nullable=YES en orders_items |
| AC4 idempotent/reversible | ✅ | IF NOT EXISTS + DO guard; down() drops all (PG16 raw check válida DO-block) |
| AC5 itest DB | ✅ | 3/3 (dev + test DB fresh) |
| AC6 gates | ✅ | tsc 0; itest 3/3; 0 boundaries nuevas |
| AC7 no regressión | ✅ | orders_orders INSERT sin store_id explícito sigue válido (column DEFAULT) |