Saltar a contenido

PDF-010B - B2B Price List Authority Read-Only Validation

Fecha: 2026-06-23

Estado: VALIDACION READ-ONLY / SIN WRITES / SIN SYNC / PENDING_VALIDATE

portal_visible = yes

Scope: tenant

tenant_id: alpuntodeventa

Destino funcional: SGC -> 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 24ad2aa14364ca0867693fcf94011095bb3f4ae8
git rev-parse origin/main 24ad2aa14364ca0867693fcf94011095bb3f4ae8
git log -3 --oneline 24ad2aa docs: add pdf-010a b2b price lists customer sync contract; 06979f2 docs: add pdf-009m product draft pilot write; f9e54f0 docs: add pdf-009l categories controlled write
git diff --check inicial PASS

Safe point esperado confirmado:

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

B. Documentacion leida

Documentacion base revisada:

  • docs/PROJECT-STATE.md
  • docs/ROADMAP.md
  • docs/governance/ACTIVE-CONTEXT.md
  • docs/tenants/alpuntodeventa/business-observer/production/PDF-010A-B2B-PRICE-LISTS-CUSTOMER-SYNC-CONTRACT.md
  • docs/tenants/alpuntodeventa/business-observer/production/PDF-009M-WOOCOMMERCE-PRODUCT-DRAFT-PILOT-WRITE.md
  • docs/tenants/alpuntodeventa/business-observer/BUSINESS-OBSERVER-DATA-CONTRACT-001.md
  • docs/tenants/alpuntodeventa/business-observer/SOURCE-002-FUTURE-LAYER-MAPPING.md
  • docs/tenants/alpuntodeventa/business-observer/SOURCE-002-ECONOMIC-LAYER.md
  • docs/tenants/alpuntodeventa/business-observer/source-authority/SOURCE-002-PRODUCTOS-PRODUCTS-AUTHORITY.sql
  • docs/tenants/alpuntodeventa/business-observer/source-authority/SOURCE-001-CLIENTES-VCLIENTES-AUTHORITY.md
  • docs/tenants/alpuntodeventa/business-observer/source-authority/SOURCE-AUTHORITY-REGISTRY.md
  • docs/tenants/alpuntodeventa/business-observer/blueprints/PRODUCT-BLUEPRINT.md
  • docs/tenants/alpuntodeventa/business-observer/blueprints/CUSTOMER-BLUEPRINT.md
  • docs/tenants/alpuntodeventa/business-observer/mappings/SOURCE-001-CLIENTES-MAPPING.md
  • snapshots/source-002/SOURCE-002-PRODUCTS-RUNTIME-PREFLIGHT-20260620-173614.csv

Evidencia local de snapshots:

  • snapshots/source-002/ existe y contiene snapshot CSV con 314 filas documentadas en PDF-009M y 81 columnas observadas.
  • snapshots/source-001/ no existe en este repo al momento de la validacion.

C. Inventario de campos de precio

El snapshot local SOURCE-002 expone 81 columnas. El bloque de precios observado incluye:

Familia Campos observados Lectura
precio base neto PrecioListaNeto precio base neto antes de IVA
precio base final PrecioListaFinal precio final de referencia calculado desde costo, markup e IVA
descuento permitido PrecioCDescPermitidoFinal precio final calculado desde Price_L1 y MaxDctoArticulo
oferta PrecioOfertaFinal precio promocional vigente, no equivalente a lista base
listas finales PrecioL1 a PrecioL9 precios finales por lista
listas netas PrecioNetoL1 a PrecioNetoL9 netos por lista
IVA por lista IVAPrecioL1 a IVAPrecioL9 componente fiscal por lista
margen por lista MargenL1 a MargenL9 margen vigente por lista
origen SQL preservado Price_L1..Price_L9, Margen_L1..Margen_L9 nombres fuente del patron repetible

No se encontro evidencia de campos destino llamados literalmente priceL1..priceL9. La autoridad SQL y la documentacion vigente usan PrecioL1..PrecioL9 como aliases de salida y Price_L1..Price_L9 como campos fuente.

D. Validacion L1 vs PrecioListaFinal

Veredicto: PENDING_VALIDATE.

Evidencia confirmada:

  • PDF-009M uso PrecioListaFinal como regular_price para los 10 productos draft creados.
  • PDF-009E dejo PrecioListaFinal como regular_price candidate.
  • SOURCE-002-FUTURE-LAYER-MAPPING define PrecioListaFinal como precio final de referencia.
  • SOURCE-002-FUTURE-LAYER-MAPPING define PrecioCDescPermitidoFinal como calculado desde Price_L1, pero no declara que L1 sea precio publico default.
  • SOURCE-002-ECONOMIC-LAYER confirma que L1..L9 son listas normalizables, pero no cierra semantica comercial de L1 como precio publico.

Conclusiones:

  • no hay evidencia suficiente para reemplazar regular_price por PrecioL1;
  • WooCommerce debe conservar el regular_price default vigente basado en PrecioListaFinal hasta validacion humana o evidencia SGC;
  • L1 sigue como PENDING_VALIDATE para precio publico/default.

E. Ejemplo SKU/listas/clientes

Ejemplo desde snapshot local source-002:

Campo Valor
SKU 2442
Articulo Pudding de Choco c/chip x300 grs
regular_price vigente documentado en PDF-009M 2020.901
PrecioListaFinal snapshot 2020.901
PrecioL1 2020.900
PrecioL2 2020.900
PrecioL3 2020.900
PrecioNetoL1/L2/L3 1670.165
IVAPrecioL1/L2/L3 350.735
MargenL1/L2/L3 0.000

Ejemplo funcional documentado:

Actor / contexto Lista Precio esperado Regla
visitante no logueado default WooCommerce 2020.901 usa regular_price vigente
cliente SGC CANDIDATE-001 asignado a L1 L1 2020.900 aplica precio final de lista si mapping validado
cliente SGC CANDIDATE-002 asignado a L2 L2 2020.900 aplica precio final de lista si mapping validado
cliente SGC CANDIDATE-003 asignado a L3 L3 2020.900 aplica precio final de lista si mapping validado
carrito/pedido de cliente L2 L2 2020.900 recalculo server-side, no solo display visual

La igualdad numerica entre PrecioL1, PrecioL2 y PrecioL3 para este SKU no prueba equivalencia comercial entre listas. Solo documenta el valor observado para el ejemplo.

F. Evidencia SOURCE-001 Clientes

SOURCE-001 existe como autoridad documental preservada en:

  • source-authority/SOURCE-001-CLIENTES-VCLIENTES-AUTHORITY.md
  • mappings/SOURCE-001-CLIENTES-MAPPING.md
  • sources/SOURCE-001-SGC-CLIENTES.md

Campos confirmados:

Necesidad Evidencia Estado
identificador cliente SGC RTRIM([Codigo]) AS codigo_cliente confirmado
clave logica recomendada tenant_id + codigo_cliente confirmado
lista asignada RTRIM([Lista_Precio]) AS lista_precio campo existe; catalogo real pendiente
destino recomendado lista price_list_code_raw en customers_commercial confirmado documentalmente
Telefono como WhatsApp RTRIM([Telefono]) AS whatsapp confirmado
CUIT/DNI RTRIM([Cuit]) AS cuit; mapeado a tax_id_raw confirmado como CUIT; DNI no confirmado
email RTRIM([mail]) AS email; mapeado a email_raw confirmado
estado activo/inactivo RTRIM([Estado]) AS estado confirmado
estados preservados CLIENTE ACTIVO, CLIENTE SUSPENDIDO, CLIENTE DE BAJA confirmado documentalmente

Pendientes:

  • no existe snapshot local snapshots/source-001/ para validar catalogo real de Lista_Precio;
  • no se ejecuto SQL read-only contra SGC porque requeriria autorizacion separada segun alcance;
  • no se puede cerrar si los valores de Lista_Precio vienen como L1, 1, nombres comerciales u otro codigo hasta validar la fuente real.

G. Modelo B2B precios candidate

Tabla candidate: b2b_product_price_lists

Grano:

  • una fila por tenant_id;
  • una fila por sku;
  • una fila por price_list_code;
  • una fila por vigencia observada.

Campos minimos:

Campo Tipo sugerido Regla
tenant_id text obligatorio; esperado alpuntodeventa
sku text obligatorio; ancla con SOURCE-002
price_list_code text obligatorio; L1, L2, ..., futuras listas
price_total numeric(18,3) precio final con impuestos, derivado de PrecioLn
currency text default candidate ARS, pendiente de validacion final
valid_from timestamptz inicio de vigencia observada
valid_to timestamptz nullable; cierre de vigencia
source_hash text hash de fila o valor fuente para detectar cambios
quality_status text validated, observed, pending_validate, blocked

Reglas:

  • price_list_code no debe depender de que existan exactamente 9 listas.
  • price_total debe ser el precio final aplicable al cliente.
  • valid_to IS NULL representa vigencia abierta.
  • JSON puede existir como cache o auditoria secundaria, no como fuente primaria de verdad B2B.

H. Modelo B2B clientes candidate

Tabla candidate: b2b_customer_price_list_mapping

Grano:

  • una fila vigente por tenant_id + sgc_customer_id;
  • historizacion futura por cambio de lista si negocio lo requiere.

Campos minimos:

Campo Tipo sugerido Origen / regla
tenant_id text obligatorio; esperado alpuntodeventa
sgc_customer_id text SOURCE-001.Codigo canonicalizado
customer_name text cliente_nombre
cuit_dni text Cuit / tax_id_raw; sensible; DNI no confirmado
email text email_raw o normalizado si aplica
whatsapp text whatsapp_raw o normalizado; no es clave unica
price_list_code text lista_precio / price_list_code_raw
wc_customer_id bigint nullable; se completa al matchear o crear cliente Woo
status text active, suspended, inactive, unknown
source_hash text hash de fila fuente o bloque comercial
quality_status text validated, observed, pending_validate, blocked

Reglas:

  • tenant_id + sgc_customer_id es la clave logica fuerte.
  • WhatsApp, email y CUIT no son clave unica primaria.
  • clientes suspendidos o de baja se preservan.
  • cliente sin lista debe quedar bloqueado o pendiente segun regla comercial, no recibir lista inventada.

I. Reglas WooCommerce B2B

Reglas candidate obligatorias:

Caso Regla
visitante no logueado usar regular_price default de WooCommerce
cliente logueado con mapping validado resolver wc_customer_id -> sgc_customer_id -> price_list_code
cliente con lista vigente mostrar y aplicar precio de sku + price_list_code
cliente sin lista BLOCKED / PENDING_PRICE_LIST; fallback solo si negocio lo aprueba
SKU sin precio para lista BLOCKED_PRICE_MISSING; no reemplazar silenciosamente
carrito recalculo server-side con lista del cliente
checkout recalculo server-side antes de crear orden
orden guardar evidencia de lista usada por linea

Metadata minima recomendada para orden/linea:

  • sku
  • price_list_code
  • price_total
  • source_hash
  • calculated_at
  • sgc_customer_id o referencia interna no sensible

WooCommerce no debe ser fuente maestra de listas multiples. Puede almacenar el precio efectivo cobrado y metadata minima de trazabilidad, pero la autoridad de listas debe vivir en PostgreSQL/OpenClaw.

J. Riesgos y bloqueos

Riesgo / bloqueo Impacto Control recomendado
L1 no validado como publico precio default incorrecto mantener PrecioListaFinal como regular_price hasta evidencia
cache de precios cliente ve precio viejo invalidar por customer_id, price_list_code, SKU y hash
performance frontend catalogo lento por consultas por linea cache precomputada por lista y SKU, indices por sku + price_list_code
precio visual distinto al cobrado reclamo y perdida de confianza recalculo server-side en carrito y checkout
cliente sin email matching WooCommerce incompleto usar workflow de conciliacion; no crear clientes sin gate
clientes duplicados lista asignada a cliente incorrecto matching por SGC ID y revision de CUIT/email/WhatsApp como senales, no claves unicas
CUIT/DNI duplicado riesgo fiscal/comercial tratar tax_id_raw como sensible y no como primary key
telefono/WhatsApp duplicado automatizacion al contacto equivocado no usar WhatsApp como clave unica
seguridad comercial de listas exposicion de precios sensibles no exponer costos, margenes ni listas completas publicamente
SKU sin precio para lista venta con precio incorrecto bloquear linea o pedido hasta regla aprobada
cliente suspendido/de baja venta no permitida derivar can_sell=false desde Estado

Bloqueos vigentes:

  • validar catalogo real de Lista_Precio en SOURCE-001;
  • confirmar si L1 es precio publico/default;
  • definir matching sgc_customer_id <-> wc_customer_id;
  • definir fallback comercial explicito;
  • preparar dry-run B2B sin writes.

K. Archivos creados/modificados

Creado:

  • docs/tenants/alpuntodeventa/business-observer/production/PDF-010B-B2B-PRICE-LIST-AUTHORITY-READ-ONLY-VALIDATION.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:

  • se agrega evidencia documental read-only de autoridad de precios B2B;
  • se publica el documento en la navegacion MkDocs;
  • se actualiza el estado rector sin habilitar sync, API, SQL ni runtime.

L. Validaciones ejecutadas

Validaciones documentadas para este gate:

  • git status -sb
  • git rev-parse HEAD
  • git rev-parse origin/main
  • git log -3 --oneline
  • git diff --check
  • lectura local de documentos y snapshot source-002
  • confirmacion de ausencia local de snapshots/source-001/

Validacion final requerida al cierre:

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

M. Estado final Git

Estado esperado al cierre:

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

N. Recomendacion de commit

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

docs: add pdf-010b b2b price list authority validation

No hacer commit sin autorizacion posterior.

O. Proximo paso recomendado

Abrir gate separado read-only para:

  1. validar catalogo real de Lista_Precio en SOURCE-001;
  2. confirmar con negocio si L1 es precio publico/default;
  3. definir matching seguro sgc_customer_id <-> wc_customer_id;
  4. armar dry-run B2B por cliente, catalogo, carrito y checkout sin writes.

Si se necesita SQL read-only contra SGC o PostgreSQL, debe pedirse autorizacion separada antes de ejecutarlo.

P. Restricciones preservadas

Durante este gate:

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