Files
sap-intercompany-worker/docs/TABLAS.md
T
GeorgeandClaude Sonnet 5 ca57403663 Initial commit: sap-intercompany-worker
Motor de escenarios de replicacion entre bases SAP Business One
(Service Layer). Poll periodico sobre webhook_events, escenarios
configurables via Prisma (filter + transform por escenario).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 07:45:57 -05:00

9.1 KiB
Raw Blame History

Referencia de tablas

Todas viven en la base Postgres compartida (docker-compose.yml en la raíz del workspace), definidas en prisma/schema.prisma. Los ejemplos de esta página usan datos reales de la config actual del ambiente de desarrollo (bases HQ01/SUB_01.."SUB_04", escenario BP_PROVEEDORES).

webhook_events

Bandeja de entrada. sap-webhook-api inserta una fila acá por cada notificación real que recibe de SAP (además de guardar el .json local). No se toca a mano — el worker es el único que la actualiza.

Columna Tipo Notas
id String (PK) El id del CloudEvent que manda SAP.
business_object String 'BusinessPartners', 'SalesPersons', 'ProfitCenters', ...
operation String 'Created' | 'Updated'.
subject String Clave del registro en la base que lo generó (CardCode, SalesEmployeeCode, CenterCode, según el objeto).
payload Json El CloudEvent completo tal cual llegó — incluye source (/default/sap.b1/<CompanyDB>), que el motor usa para la protección contra loops (ver ARQUITECTURA.md).
status EventStatus pending → processing → done | partial | failed | filtered.
received_at DateTime

databases

Registro único de toda base SAP alcanzable por Service Layer. Sin distinción HQ/subsidiaria — ver ARQUITECTURA.md.

Columna Tipo Notas
id Int (PK, autoincremental) Identificador interno, no se usa como referencia legible.
code String (único) Mnemónico corto y estable, asignado una sola vez al crear (ej. HQ01, SUB_01). No autoincremental — es lo que aparece en los logs.
name String Descriptivo, solo para mostrar.
base_url String URL del Service Layer, ej. https://sap10:50000/b1s/v2.
company_db String CompanyDB de esa base.
username / password String Credenciales de login del Service Layer.
active Boolean Una base inactiva no se usa como origen ni destino en ningún escenario.

Ejemplo (ambiente de desarrollo actual):

code name base_url company_db active
HQ01 HQ DemoCL https://sap10:50000/b1s/v2 SBODemoCL true
SUB_01 SUB 01 DemoCL https://sap10:50000/b1s/v2 SUBDemoCL_01 true
SUB_02 SUB 02 DemoCL https://sap10:50000/b1s/v2 SUBDemoCL_02 true
SUB_03 SUB 03 DemoCL https://sap10:50000/b1s/v2 SUBDemoCL_03 true
SUB_04 SUB 04 DemoCL https://sap10:50000/b1s/v2 SUBDemoCL_04 true

scenarios

Una fila por escenario. Ver ESCENARIOS.md para cómo armar uno con el CLI.

Columna Tipo Notas
id Int (PK)
code String (único) Identificador legible del escenario, en mayúsculas (ej. BP_PROVEEDORES). Determina el nombre de su archivo (filter + transform) en minúsculas: src/scenarios/<code en minúsculas>.ts (ej. bp_proveedores.ts) — ver scenarioFileSlug en src/scenarioTransform.ts.
name String Descriptivo.
business_object String Objeto que dispara el escenario: con qué se matchea webhook_events y con qué se lee el registro del origen.
destination_business_object String? Objeto a usar en el GET/POST/PATCH del destino, si es distinto al de origen (ej. origen PurchaseOrders → destino Orders, típico de comercio intercompañía). null ⇒ mismo objeto que business_object (el caso común).
origin_database_code String (FK → databases.code) De dónde se lee el registro completo.
destination_mode ScenarioDestinationMode fixed (lista fija en scenario_destinations) | payload (destino resuelto por routing_field — ambos implementados).
key_field String Campo clave del registro, ej. CardCode, SalesEmployeeCode.
key_type ScenarioKeyType string (va entre comillas en la URL OData) | number (sin comillas — un campo numérico con comillas da HTTP 400).
key_strategy ScenarioKeyStrategy portable (la clave vale lo mismo en origen y destino) | udfLink (SAP asigna la clave por base; se busca por match_field).
match_field String? Solo si key_strategy = udfLink: nombre del UDF en el destino que guarda la clave de origen (ej. U_ITC_Source_JdtNum).
routing_field String? Solo si destination_mode = payload: UDF en el origen cuyo valor es el code de la base destino (ej. U_ITC_Target).
active Boolean

No hay columnas de filtro: el filtro es la función filter() del archivo del escenario (ver ARQUITECTURA.md).

Ejemplo (los 5 escenarios activos hoy en desarrollo):

code business_object destination_business_object origin destinations key_field key_strategy
BP_PROVEEDORES BusinessPartners — HQ01 SUB_01, SUB_02 CardCode portable
CHARTOFACCOUNTS ChartOfAccounts — HQ01 SUB_01, SUB_02 Code portable
JOURNALENTRIES JournalEntries — HQ01 (payload: U_ITC_Target) JdtNum udfLink (U_ITC_Source_JdtNum)
PROFITCENTERS ProfitCenters — HQ01 SUB_01, SUB_02, SUB_03 CenterCode portable
SALESPERSONS SalesPersons — HQ01 SUB_01, SUB_03 SalesEmployeeCode udfLink (U_HQ_SlpCode)

Ninguno usa todavía destination_business_object (ninguno lo necesita por ahora) — quedaría, por ejemplo, PurchaseOrders → Orders en un futuro escenario de compras intercompañía.

scenario_destinations

Destinos fijos de un escenario (solo aplica a destination_mode = fixed). Único por (scenario_id, database_code).

Columna Tipo Notas
scenario_id Int (FK → scenarios.id)
database_code String (FK → databases.code)

scenario_value_mappings

Datos puros que el archivo de transformación de un escenario consulta vía ctx.mapValue(fieldName, sourceValue) — ver ARQUITECTURA.md. El código decide QUÉ campo mapear y QUÉ hacer si falta el valor (tirar error, dejar sin traducir, etc.); acá solo vive la equivalencia. Escopada por escenario (no global por objeto+campo) porque el mismo campo puede tener dominios de valores distintos según el escenario (ej. GroupCode de clientes vs. de proveedores).

Columna Tipo Notas
scenario_id Int (FK)
field_name String Ej. GroupCode.
database_code String (FK → databases.code) El destino al que aplica esta traducción puntual.
source_value String Valor tal como viene de la base origen.
target_value String Valor a usar en ese destino.

Único por (scenario_id, field_name, database_code, source_value).

Ejemplo real (BP_PROVEEDORES, GroupCode, hoy 1:1 en ambas subsidiarias):

scenario field_name database_code source_value target_value
BP_PROVEEDORES GroupCode SUB_01 101 101
BP_PROVEEDORES GroupCode SUB_01 110 110
BP_PROVEEDORES GroupCode SUB_02 101 101
... (7 códigos × 2 destinos = 14 filas)

replication_attempts

Log de auditoría inmutable. Una fila por cada intento de un escenario hacia una base destino.

Columna Tipo Notas
event_id String (FK → webhook_events.id)
scenario_id Int (FK → scenarios.id) Imprescindible porque un evento puede pasar por varios escenarios a la vez.
origin_database String Código de la base origen usada en este intento — texto libre, no FK: sobrevive si la base se borra o renombra después.
destination_database String Ídem para el destino. 'N/A' si el intento falló antes de resolver un destino (ej. error leyendo el origen).
verb_used String POST | PATCH | SKIPPED (falta mapeo, o transform tiró error) | N/A (error antes de llamar al destino).
http_status Int?
error_message String?
payload_sent Json? El payload ya transformado enviado al destino — se guarda siempre, en éxito y en falla.
result_key String? Para key_strategy=udfLink: la clave propia del destino (encontrada o recién asignada por SAP en un POST). null en key_strategy=portable y en datos maestros sin esta estrategia.
attempted_at DateTime

Índices sobre event_id, scenario_id y attempted_at, pensados para la futura UI de consulta (sap-intercompany-viewer, ver ARQUITECTURA.md).

Ejemplo real (SALESPERSONS, vendedor nuevo SalesEmployeeCode=7 en HQ01, POST en ambas subsidiarias — SAP le asignó el mismo número por coincidencia, pero el motor no lo asume, lo captura del response):

event_id scenario destination_database verb_used http_status result_key
149be29e-... SALESPERSONS SUB_01 POST 201 7
149be29e-... SALESPERSONS SUB_03 POST 201 7