Saltar a contenido

PDF-010K - B2B Persistence Contract DDL Candidate

Fecha: 2026-06-23

Estado: DDL CANDIDATE + VALIDACION ESTATICA / SIN SQL EJECUTADO / SIN RUNTIME / SIN WRITES

portal_visible = yes

Scope: tenant

tenant_id: alpuntodeventa

Destino funcional: SOURCE-001 Clientes + SOURCE-002 Productos -> PostgreSQL/OpenClaw -> WooCommerce La Directa

Owner: Gabi / Carlos Canu

A. SAFE POINT inicial

Control Resultado
git status -sb ## main...origin/main
git rev-parse HEAD ca424bf4ddd15db86789fd3d78760f82ac2a0853
git rev-parse origin/main ca424bf4ddd15db86789fd3d78760f82ac2a0853
Repo limpio despues de publicar y desplegar PDF-010J

B. Alcance

PDF-010K disena el contrato persistente real para mapping B2B y precios en PostgreSQL/OpenClaw. El paquete es candidate y revisable: no fue ejecutado contra PostgreSQL, no toca WooCommerce API, no modifica runtime, no ejecuta sync, scheduler, cron ni pipelines.

C. Archivos creados

Paquete tecnico:

  • infra/business-observer/production/b2b-pricing/PDF-010K/PDF-010K-B2B-PERSISTENCE-DDL-CANDIDATE.sql
  • infra/business-observer/production/b2b-pricing/PDF-010K/PDF-010K-B2B-PERSISTENCE-ROLLBACK-CANDIDATE.sql
  • infra/business-observer/production/b2b-pricing/PDF-010K/validate_b2b_persistence_contract.py
  • infra/business-observer/production/b2b-pricing/PDF-010K/README.md

Documento oficial:

  • docs/tenants/alpuntodeventa/business-observer/production/PDF-010K-B2B-PERSISTENCE-CONTRACT-DDL-CANDIDATE.md

D. Tabla customer mapping candidate

Tabla propuesta:

  • business_observer.b2b_customer_mapping

Columnas:

  • mapping_id
  • tenant_code
  • wc_customer_id
  • sgc_customer_id
  • price_list_code
  • customer_status
  • mapping_status
  • match_method
  • quality_status
  • source_hash
  • created_at
  • updated_at

Constraints candidate:

  • price_list_code limitado a L1..L9.
  • customer_status limitado a CLIENTE ACTIVO, CLIENTE SUSPENDIDO y CLIENTE DE BAJA.
  • mapping_status limitado a ACTIVE, INACTIVE, BLOCKED, PENDING_REVIEW.
  • quality_status limitado a OK, NEEDS_REVIEW, BLOCKED.
  • unique parcial por tenant_code + wc_customer_id cuando mapping_status = 'ACTIVE'.
  • unique parcial por tenant_code + sgc_customer_id cuando mapping_status = 'ACTIVE'.

Impacto: evita duplicados activos ambiguos para un mismo cliente WooCommerce o cliente SGC dentro del tenant.

E. Tabla product price candidate

Tabla propuesta:

  • business_observer.b2b_product_price

Columnas:

  • price_id
  • tenant_code
  • sku
  • price_list_code
  • applied_price
  • regular_price_reference
  • currency
  • source_hash
  • quality_status
  • valid_from
  • valid_to
  • created_at
  • updated_at

Constraints candidate:

  • price_list_code limitado a L1..L9.
  • applied_price > 0.
  • regular_price_reference >= 0.
  • valid_to IS NULL OR valid_to > valid_from.
  • unique parcial por tenant_code + sku + price_list_code cuando valid_to IS NULL.
  • unique por tenant_code + sku + price_list_code + valid_from.

Impacto: permite resolver precio vigente por tenant, SKU y lista, preservando historial por rango. Para evitar solapamientos temporales completos se propone evaluar constraint/exclusion por rango en un gate posterior si se aprueba usar tipos tstzrange o extensiones disponibles.

F. Tabla decision log candidate

Tabla propuesta:

  • business_observer.b2b_pricing_decision_log

Columnas:

  • decision_id
  • tenant_code
  • wc_customer_id
  • sgc_customer_id
  • sku
  • price_list_code
  • pricing_status
  • applied_price
  • regular_price_reference
  • source_hash
  • decision_context
  • created_at

Decision: queda como tabla real candidate para auditoria minima de decisiones de pricing, pero su activacion operativa queda bloqueada hasta un gate separado de volumen, retencion, privacidad y performance. Alternativa futura: vista o log particionado si el runtime requiere alto volumen.

G. Vista effective price candidate

Vista propuesta:

  • business_observer.v_b2b_customer_effective_price

Resuelve:

  • cliente WooCommerce activo y mapeado;
  • cliente SGC asociado;
  • lista L1..L9;
  • SKU;
  • precio vigente por valid_from <= now() y valid_to IS NULL OR valid_to > now();
  • solo mappings y precios con quality_status = 'OK'.

El runtime WooCommerce/headless deberia leer solo el precio final necesario, sin exponer costos, margenes, proveedor ni datos sensibles.

H. RLS y permisos candidate

Roles esperados:

  • business_observer_reader
  • business_observer_writer
  • business_observer_admin

Regla candidate:

  • reader: SELECT sobre tablas necesarias y vista effective price.
  • writer: SELECT/INSERT/UPDATE sobre mappings y precios; SELECT/INSERT sobre decision log.
  • admin: privilegios completos para administracion controlada.

RLS queda habilitado como candidate. Las policies finales deben definirse en un gate de ejecucion con matriz tenant/rol antes de tocar PostgreSQL real.

I. Rollback candidate

Rollback candidate:

  • revoca grants candidate;
  • elimina vista v_b2b_customer_effective_price;
  • elimina tablas b2b_pricing_decision_log, b2b_product_price y b2b_customer_mapping;
  • se mantiene como texto no ejecutado.

J. Validador estatico

Validador:

  • infra/business-observer/production/b2b-pricing/PDF-010K/validate_b2b_persistence_contract.py

Controles:

  • tablas esperadas presentes;
  • columnas esperadas presentes;
  • unique/constraints minimos presentes;
  • vista candidate presente;
  • roles reader/writer/admin presentes;
  • no contiene DROP DATABASE;
  • no contiene TRUNCATE;
  • no contiene patrones peligrosos de DML, extensiones, sistema o secretos.

Resultado esperado:

text PDF-010K B2B persistence contract validation: PASS

K. Riesgos

  • RLS requiere policies finales antes de ejecucion real.
  • La no superposicion total de rangos vigentes puede requerir exclusion constraint o validacion transaccional adicional.
  • Decision log puede crecer rapido si se activa en runtime sin retencion.
  • El contrato no debe exponer costos, margenes ni proveedor a WooCommerce.
  • Cualquier ejecucion real exige backup, preflight y aprobacion separada.

L. Bloqueos

  • No ejecutar DDL hasta gate separado.
  • No conectar runtime WooCommerce hasta tener lectura controlada y pruebas.
  • No cargar mappings reales sin fuente aprobada y validacion de duplicados.
  • No cargar precios reales sin snapshot/versionado y estrategia de rollback.
  • No activar sync, scheduler, cron ni pipelines.

M. Proximos pasos

  1. Revisar DDL candidate y definir policies RLS concretas por tenant/rol.
  2. Preparar preflight read-only de roles/schema existentes.
  3. Crear gate PDF-010L para ejecucion controlada, con backup y rollback probado, si se aprueba.
  4. Mantener WooCommerce API y runtime sin cambios hasta el gate posterior.

N. Cierre

No se ejecuto SQL. No hubo writes. No se toco PostgreSQL real. No se toco WooCommerce API. No se leyo ni modifico .env. No se imprimieron secretos. No se modifico runtime WooCommerce. No se ejecuto sync, scheduler, cron ni pipelines.