Saltar a contenido

PDF-010H - B2B Runtime Dry-Run Design

Fecha: 2026-06-23

Estado: DISENO + DRY-RUN / SIN WRITES / SIN RUNTIME / B2B_RUNTIME_NOT_IMPLEMENTED

portal_visible = yes

Scope: tenant

tenant_id: alpuntodeventa

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

Owner: Gabi / Carlos Canu

A. SAFE POINT inicial

Control Resultado
git status -sb ## main...origin/main
git rev-parse HEAD d17fb945b0dc724c390b4fc3723b1fd9b5553e8f
git rev-parse origin/main d17fb945b0dc724c390b4fc3723b1fd9b5553e8f
git log -3 --oneline d17fb94 docs: add pdf-010g b2b commercial price rules approval; 979c919 docs: add pdf-010f b2b commercial pricing design; bd9fe78 docs: add pdf-010e b2b customer price dry-run
git diff --check inicial PASS

Safe point esperado confirmado:

  • HEAD coincide con d17fb945b0dc724c390b4fc3723b1fd9b5553e8f.
  • origin/main coincide con d17fb945b0dc724c390b4fc3723b1fd9b5553e8f.
  • repo limpio al inicio.
  • ultimo commit esperado confirmado.

Alcance de este gate:

  • disenar runtime B2B futuro;
  • simular catalogo, carrito, checkout y orden sin ejecutar runtime;
  • no tocar WooCommerce API;
  • no tocar PostgreSQL con writes;
  • no ejecutar SQL write;
  • no crear clientes ni productos;
  • no modificar precios reales;
  • no instalar plugins ni modificar theme;
  • no ejecutar sync, scheduler, cron ni pipelines;
  • no hacer push, deploy ni commit.

B. Documentacion leida

Documentacion base revisada:

  • docs/tenants/alpuntodeventa/business-observer/production/PDF-010A-B2B-PRICE-LISTS-CUSTOMER-SYNC-CONTRACT.md
  • docs/tenants/alpuntodeventa/business-observer/production/PDF-010B-B2B-PRICE-LIST-AUTHORITY-READ-ONLY-VALIDATION.md
  • docs/tenants/alpuntodeventa/business-observer/production/PDF-010D-SOURCE-001-VCLIENTES-READ-ONLY-SNAPSHOT.md
  • docs/tenants/alpuntodeventa/business-observer/production/PDF-010E-B2B-CUSTOMER-PRICE-DRY-RUN.md
  • docs/tenants/alpuntodeventa/business-observer/production/PDF-010F-B2B-COMMERCIAL-PRICE-RULES-SERVER-SIDE-PRICING-DESIGN.md
  • docs/tenants/alpuntodeventa/business-observer/production/PDF-010G-B2B-COMMERCIAL-PRICE-RULES-APPROVAL.md
  • docs/tenants/alpuntodeventa/business-observer/production/PDF-009M-WOOCOMMERCE-PRODUCT-DRAFT-PILOT-WRITE.md
  • docs/PROJECT-STATE.md
  • docs/ROADMAP.md
  • docs/governance/ACTIVE-CONTEXT.md
  • docs/tenants/alpuntodeventa/business-observer/production/README.md
  • mkdocs.yml

C. Diseno matching wc_customer_id -> sgc_customer_id

Objetivo futuro: vincular el usuario WooCommerce logueado con el cliente SGC sin crear clientes ni inferir automaticamente por datos debiles.

Autoridad fuerte:

  • sgc_customer_id debe provenir de SOURCE-001.Codigo canonicalizado.
  • wc_customer_id es identificador externo WooCommerce.
  • el mapping valido debe quedar persistido en OpenClaw/PostgreSQL en un gate futuro autorizado.

Fuente candidate principal:

  • metadata de usuario WooCommerce con una clave futura candidate, por ejemplo _apv_sgc_customer_id.
  • esa metadata debe apuntar a un unico sgc_customer_id activo y auditable.
  • en este gate no se lee ni escribe metadata real de WooCommerce.

Fallbacks solo como candidatos de conciliacion:

  • email normalizado;
  • CUIT / tax id normalizado;
  • WhatsApp / telefono normalizado.

Reglas:

  • email, CUIT y WhatsApp no son claves unicas primarias.
  • si una senal candidata matchea mas de un cliente SGC, el caso queda BLOCKED_CUSTOMER_MAPPING.
  • si un wc_customer_id apunta a mas de un sgc_customer_id, queda BLOCKED_CUSTOMER_MAPPING.
  • si un sgc_customer_id activo queda asociado a mas de un wc_customer_id, queda PENDING_REVIEW_CUSTOMER_MAPPING, salvo regla futura explicita.
  • cliente suspendido o de baja se bloquea antes de resolver precio.

D. Customer matching matrix

Caso Fuente candidate Resultado Regla
wc_customer_id con metadata _apv_sgc_customer_id unica metadata Woo usuario MAPPING_OK aplicar si SGC existe y esta activo
metadata apunta a cliente inexistente metadata Woo usuario BLOCKED_CUSTOMER_MAPPING no aplicar precio B2B
metadata apunta a cliente suspendido/de baja metadata Woo usuario + SOURCE-001 Estado BLOCKED_CUSTOMER_STATUS bloquear antes de precio
sin metadata, email unico candidate email PENDING_REVIEW_CUSTOMER_MAPPING no automatico; requiere conciliacion
sin metadata, CUIT unico candidate CUIT PENDING_REVIEW_CUSTOMER_MAPPING sensible; no automatico
sin metadata, WhatsApp unico candidate WhatsApp PENDING_REVIEW_CUSTOMER_MAPPING no automatico
email/CUIT/WhatsApp duplicado fallback candidates BLOCKED_CUSTOMER_MAPPING no elegir cliente por inferencia
sin ninguna senal ninguna BLOCKED_CUSTOMER_MAPPING no aplicar precio B2B

E. Diseno catalogo B2B

Regla vigente aprobada por PDF-010G:

  • visitante no logueado ve regular_price vigente en WooCommerce.
  • regular_price vigente queda respaldado por PrecioListaFinal.
  • PrecioL1 no es default publico.
  • cliente logueado activo con mapping valido usa precio segun Lista_Precio.
  • Lista_Precio 1..9 -> PrecioL1..PrecioL9 queda APPROVED.

Flujo candidate de catalogo:

  1. Detectar si el usuario esta logueado.
  2. Si no esta logueado, mostrar regular_price.
  3. Si esta logueado, resolver wc_customer_id -> sgc_customer_id.
  4. Validar Estado = CLIENTE ACTIVO.
  5. Normalizar Lista_Precio n a price_list_code = Ln.
  6. Resolver precio por sku + price_list_code.
  7. Si el precio falta, es nulo o <= 0, devolver BLOCKED_PRICE_MISSING.
  8. No reemplazar silenciosamente por regular_price cuando el cliente B2B ya esta identificado.

F. Catalog price matrix

Actor Estado cliente Lista SKU Precio visual candidate Resultado
visitante no aplica no aplica 2442 regular_price = 2020.901 PUBLIC_DEFAULT
cliente activo CLIENTE ACTIVO 1 / L1 2442 PrecioL1 = 2020.900 B2B_PRICE_OK
cliente activo CLIENTE ACTIVO 5 / L5 2442 PrecioL5 = 2020.900 B2B_PRICE_OK
cliente suspendido CLIENTE SUSPENDIDO cualquier lista 2442 no aplicar BLOCKED_CUSTOMER_STATUS
cliente de baja CLIENTE DE BAJA cualquier lista 2442 no aplicar BLOCKED_CUSTOMER_STATUS
cliente activo CLIENTE ACTIVO 1 / L1 3995 0.000 BLOCKED_PRICE_MISSING
cliente activo CLIENTE ACTIVO 5 / L5 4010 0.000 BLOCKED_PRICE_MISSING

G. Diseno carrito server-side

Regla: el carrito nunca debe confiar solamente en el precio visual del catalogo.

Flujo candidate:

  1. En cada recalculo de carrito, detectar usuario y wc_customer_id.
  2. Resolver mapping vigente wc_customer_id -> sgc_customer_id.
  3. Validar cliente activo.
  4. Para cada item, resolver sku.
  5. Resolver price_list_code desde Lista_Precio.
  6. Obtener applied_price desde sku + price_list_code.
  7. Comparar contra cualquier precio visual recibido solo como referencia.
  8. Reemplazar el precio de linea en servidor.
  9. Guardar metadata candidate de item/carrito.
  10. Bloquear carrito si hay inconsistencia no recuperable.

Metadata candidate por item/carrito:

  • sku
  • sgc_customer_id o referencia interna no sensible
  • price_list_code
  • price_source
  • applied_price
  • regular_price_reference
  • source_hash
  • pricing_status

H. Cart recalculation matrix

Caso Entrada carrito Recalculo server-side Metadata candidate Resultado
visitante con SKU valido sku=2442 usar regular_price price_source=PUBLIC_DEFAULT CART_PRICE_OK
cliente L1 activo sku=2442 aplicar PrecioL1 price_list_code=L1, price_source=SOURCE-002 CART_PRICE_OK
cliente L5 activo sku=2442 aplicar PrecioL5 price_list_code=L5, price_source=SOURCE-002 CART_PRICE_OK
cliente suspendido/de baja cualquier SKU no aplicar precio pricing_status=BLOCKED_CUSTOMER_STATUS CART_BLOCKED
cliente activo + SKU 3995 sku=3995 precio 0.000 pricing_status=BLOCKED_PRICE_MISSING CART_BLOCKED
cliente activo + mapping duplicado cualquier SKU no calcular pricing_status=BLOCKED_CUSTOMER_MAPPING CART_BLOCKED

I. Diseno checkout/orden

Regla: checkout debe validar nuevamente antes de crear la orden.

Flujo candidate:

  1. Releer usuario, mapping y estado cliente.
  2. Releer lista vigente.
  3. Recalcular cada linea por sku + price_list_code.
  4. Comparar contra metadata de carrito.
  5. Bloquear la orden si cambio la lista, falta precio, cambia source_hash de forma no aceptada o el cliente ya no esta activo.
  6. Crear orden solo si todas las lineas pasan validacion.
  7. Guardar evidencia por linea.

Metadata minima por linea de orden:

  • sku
  • price_list_code
  • applied_price
  • regular_price_reference
  • source_hash

Metadata adicional recomendada:

  • pricing_mode
  • price_source
  • sgc_customer_ref
  • calculated_at
  • pricing_status

J. Checkout/order metadata matrix

Campo Nivel Fuente candidate Requerido Regla
sku linea producto Woo / SOURCE-002 si identifica precio aplicado
price_list_code linea SOURCE-001 Lista_Precio normalizada si L1..L9 para B2B
applied_price linea SOURCE-002 PrecioLn si precio final cobrado
regular_price_reference linea Woo regular_price / PrecioListaFinal si referencia publica/default
source_hash linea snapshot/fuente OpenClaw si trazabilidad e invalidacion
price_source linea/carrito OpenClaw/PostgreSQL futuro recomendado no exponer costos/margenes
pricing_status linea/carrito/orden motor pricing futuro recomendado OK o bloqueo explicito
sgc_customer_ref orden mapping B2B recomendado referencia no sensible

K. Dry-run de muestra

La simulacion usa evidencia documental previa, sin leer WooCommerce API, sin consultar PostgreSQL y sin ejecutar runtime.

Clientes sanitizados SOURCE-001 usados como referencia:

Cliente sanitizado Estado Lista_Precio price_list_code Resultado sample
SOURCE-001-L1-ACTIVE-CANDIDATE CLIENTE ACTIVO 1 L1 B2B_PRICE_OK simulado
SOURCE-001-L5-ACTIVE-CANDIDATE CLIENTE ACTIVO 5 L5 B2B_PRICE_OK simulado
SOURCE-001-SUSPENDED-CANDIDATE CLIENTE SUSPENDIDO 1..9 Ln BLOCKED_CUSTOMER_STATUS
SOURCE-001-INACTIVE-CANDIDATE CLIENTE DE BAJA 1..9 Ln BLOCKED_CUSTOMER_STATUS

SKUs piloto de PDF-009M:

SKU Producto regular_price PrecioL1 PrecioL5 Resultado
2442 Pudding de Choco c/chip x300 grs 2020.901 2020.900 2020.900 PRICE_OK
2443 Pudding Gales C/Nuez x300 grs 2020.901 2020.900 2020.900 PRICE_OK
2444 Pudding Limon c/ semilla de Amapolla x300 grs 2020.901 2020.900 2020.900 PRICE_OK
2847 Pudding Naranja c/ cascara x350 grs 2020.901 2020.900 2020.900 PRICE_OK
2446 Pudding Vainila capa frutos secos x300 grs 2020.901 2020.900 2020.900 PRICE_OK
2814 Chips Papas x 80gr Alwa 1081.151 1081.150 1081.150 PRICE_OK
2815 Chips Batata x 80gr Alwa 1081.151 1081.150 1081.150 PRICE_OK
2816 Pochoclo dulce x 75gr Alwa 946.940 946.940 946.940 PRICE_OK
3514 Nachos con Chia x80gr Alwa 1153.947 1153.950 1153.950 PRICE_OK
0269 Arrocitas C/Sal x 101gr Ce 1015.718 1015.720 1015.720 PRICE_OK

Casos negativos:

SKU Producto PrecioListaFinal PrecioL1..PrecioL9 Resultado
3995 Saldos Clientes 0.000 todos 0.000 BLOCKED_PRICE_MISSING
4010 Asesoramiento de servicios de marketing 0.000 todos 0.000 BLOCKED_PRICE_MISSING

L. Dry-run runtime B2B

Escenario Cliente SKU Catalogo Carrito Checkout/orden
visitante no logueado 2442 PUBLIC_DEFAULT 2020.901 CART_PRICE_OK con regular orden publica sin price_list_code B2B
cliente Lista_Precio 1 SOURCE-001-L1-ACTIVE-CANDIDATE 2442 PrecioL1 2020.900 recalcula L1 server-side guarda sku, L1, 2020.900, regular ref, hash
cliente Lista_Precio 5 SOURCE-001-L5-ACTIVE-CANDIDATE 2442 PrecioL5 2020.900 recalcula L5 server-side guarda sku, L5, 2020.900, regular ref, hash
cliente suspendido SOURCE-001-SUSPENDED-CANDIDATE 2442 bloqueado carrito bloqueado orden bloqueada
cliente de baja SOURCE-001-INACTIVE-CANDIDATE 2442 bloqueado carrito bloqueado orden bloqueada
precio faltante L1 SOURCE-001-L1-ACTIVE-CANDIDATE 3995 BLOCKED_PRICE_MISSING carrito bloqueado orden bloqueada
precio faltante L5 SOURCE-001-L5-ACTIVE-CANDIDATE 4010 BLOCKED_PRICE_MISSING carrito bloqueado orden bloqueada

M. Blocked cases matrix

Bloqueo Donde se detecta Resultado Regla
BLOCKED_CUSTOMER_MAPPING catalogo/carrito/checkout no aplicar B2B mapping ausente, ambiguo o duplicado
BLOCKED_CUSTOMER_STATUS catalogo/carrito/checkout bloquear venta B2B CLIENTE SUSPENDIDO o CLIENTE DE BAJA
BLOCKED_PRICE_LIST catalogo/carrito/checkout bloquear linea/pedido lista ausente o fuera de 1..9
BLOCKED_PRICE_MISSING catalogo/carrito/checkout bloquear linea/pedido precio nulo, ausente o <= 0
BLOCKED_ORDER_INCONSISTENCY checkout bloquear orden precio/hash/lista difiere del recalculo final
PUBLIC_DEFAULT catalogo/carrito publico permitir flujo publico visitante usa regular_price

N. Impacto documental

Este documento:

  • traduce las reglas aprobadas de PDF-010G a diseno runtime B2B;
  • define matching seguro wc_customer_id -> sgc_customer_id;
  • define catalogo, carrito, checkout y metadata de orden;
  • simula visitantes, clientes Lista_Precio 1, clientes Lista_Precio 5, clientes suspendidos/de baja y SKUs sin precio;
  • no implementa runtime;
  • no habilita writes.

O. Archivos creados/modificados

Creado:

  • docs/tenants/alpuntodeventa/business-observer/production/PDF-010H-B2B-RUNTIME-DRY-RUN-DESIGN.md

Actualizados:

  • docs/tenants/alpuntodeventa/business-observer/production/README.md
  • docs/PROJECT-STATE.md
  • docs/ROADMAP.md
  • docs/governance/ACTIVE-CONTEXT.md
  • mkdocs.yml

Impacto:

  • publica el gate documental PDF-010H en el Knowledge Portal;
  • actualiza estado y roadmap para reflejar que el proximo paso B2B ya tiene diseno/dry-run de runtime;
  • no modifica codigo, runtime, WooCommerce ni PostgreSQL.

P. Validaciones requeridas

Validaciones de cierre de este gate:

  • git diff --check
  • .\.venv-portal\Scripts\mkdocs.exe build --strict

Q. Estado final Git

Estado esperado al cierre:

  • cambios documentales locales sin commit;
  • sin push;
  • sin deploy.

R. Recomendacion de commit

Si la revision humana aprueba este gate documental, commit sugerido:

docs: add pdf-010h b2b runtime dry-run design

No hacer commit sin autorizacion posterior.

S. Proximo paso recomendado

Abrir gate separado de implementacion tecnica sin writes iniciales:

  1. definir tabla o store real de mapping wc_customer_id -> sgc_customer_id;
  2. definir hook/plugin o capa headless para catalogo, carrito y checkout;
  3. preparar tests unitarios y dry-run local del motor de pricing;
  4. ejecutar cualquier read real de WooCommerce o PostgreSQL solo con autorizacion explicita;
  5. ejecutar cualquier write solo en gate posterior separado.

T. Restricciones preservadas

Durante este gate:

  • no se toco WooCommerce API;
  • no se toco PostgreSQL con writes;
  • no se ejecuto SQL write;
  • no se crearon clientes;
  • no se crearon productos;
  • no se modificaron precios reales;
  • no se instalaron plugins;
  • no se modifico theme;
  • no se modifico runtime;
  • no se imprimieron secretos;
  • no se hizo push;
  • no se hizo deploy;
  • no se ejecuto sync;
  • no se activo scheduler, cron ni pipelines.