Parte V · En la práctica
Un ERP multi-módulo
El banco demostró que el modelo resiste el peso del dinero. El ERP plantea un reto distinto: una sola venta que, en el mismo instante, cuenta como cuatro cosas a la vez. La prueba ya no es la presión, sino la interoperabilidad interna.
Son las 11:20 de un martes en Viento Norte, una fábrica mediana de bombas de riego. La vendedora Ortiz cierra un pedido por teléfono: ocho bombas del modelo K7 para Ferrocom, nueve mil seiscientos dólares. Cuelga, teclea una línea en el sistema y se va a almorzar. En ese gesto de quince segundos acaban de ocurrir cuatro cosas distintas, y ninguna es la venta entera. El almacén del norte debe descontar ocho unidades de su stock. Contabilidad debe registrar un ingreso de nueve mil seiscientos dólares con su asiento. A Ortiz le corresponde una comisión del cuatro por ciento. Y, río arriba, alguien tendrá que reponer ocho bombas, lo que disparará una orden de producción que consumirá cobre y horas de taller. Una frase, cuatro módulos. El examen de este capítulo es lograr que los cuatro vean el mismo hecho sin que nadie lo copie.
En los capítulos anteriores de esta parte, el modelo enfrentó adversarios de un solo frente. El spa nos exigió agilidad; el taxi, velocidad; el historial clínico, repartir la verdad entre varios custodios; el banco añadió al regulador. El ERP no sube ninguno de esos picos en particular. Su dificultad es de otra clase: la convivencia simultánea de módulos que la industria siempre construyó como mundos aparte. Lo que aquí se pone a prueba no es cuánto aguanta el modelo, sino si los módulos pueden hablarse sin un traductor en el medio.
La maldición de los módulos que no se hablan
Quien haya trabajado cerca de un SAP, un Oracle o un Dynamics reconocerá la escena. Un ERP tradicional es una federación de subsistemas, cada uno con su propio esquema, sus propias tablas y sus propios procesos:
RR. HH.
Empleados, jerarquías, salarios, evaluaciones de desempeño, comisiones.
Finanzas
Asientos, presupuestos, cuentas por pagar y por cobrar, cierres.
Inventario
Stocks, movimientos de almacén, valorizaciones, reposición.
Ventas
Pedidos, clientes, listas de precios, comisiones de fuerza de ventas.
Compras
Órdenes a proveedores, aprobaciones, recepciones, vencimientos.
Manufactura
Lista de materiales (BOM), órdenes de producción, consumos de insumos.
Cada uno de esos módulos vive, históricamente, en su propio archipiélago de tablas. Y la consecuencia es bien conocida por cualquier consultor: las integraciones entre módulos son el grueso del proyecto. Se estima que conectar los subsistemas (lograr que la venta «avise» al inventario, que el inventario «avise» a contabilidad, que contabilidad «avise» a recursos humanos) consume del orden del 60 al 70 por ciento del esfuerzo total de una implementación. No se paga por modelar la venta; se paga por coserla a todo lo demás.
La razón profunda de ese costo es que cada módulo bautiza la realidad a su manera. Para
ventas, la operación de Ortiz es un pedido con un cliente_id; para
inventario, es un movimiento con un sku y un signo negativo; para
contabilidad, es un asiento con un haber. Tres nombres, tres
tablas, tres identidades para el mismo suceso. Y para volver a juntarlos (para
responder «¿cuánta comisión generó la venta que vació ocho bombas del almacén norte?») hace
falta cruzar tres bases de datos con claves foráneas frágiles y, casi siempre, un proceso
ETL nocturno mantenido a mano.
Esto debería sonarte familiar. Es la misma torre de Babel del primer capítulo, pero esta vez no entre empresas distintas: dentro de una sola, entre sus propios departamentos. La diferencia es que aquí la cura es más limpia, porque todos los módulos pertenecen al mismo dueño y pueden, de entrada, hablar el mismo idioma.
La apuesta del ERP
La integración entre módulos no exige ningún sistema de
unificación. Cuando todos los hechos del negocio comparten la estructura atómica
(sujeto, rol, valor), el grafo ya es la integración. Una venta no
genera «registros en tres tablas distintas»: genera una situación reificada con
varias sub-situaciones ligadas por parte_de, y todas viven en el
mismo grafo. Nadie copia el hecho; cada módulo lo mira desde su rol.
El ERP sobre las siete coordenadas
Antes de los escenarios, repartamos las piezas de la fábrica en los ejes de valor. El ejercicio ordena, en seis preguntas, lo que en un ERP tradicional son docenas de tablas inconexas.
Q quién · agentes
Empleados, clientes y proveedores, y —decisivo— la
empresa misma. vientonorte_sa es una persona jurídica: un agente tan válido
como la vendedora Ortiz (D5). El director reporta a la empresa, no al vacío.
O qué · entidades y eventos
Productos, órdenes, asientos, comisiones, evaluaciones de desempeño, movimientos de almacén. Todo lo que tiene fecha de creación, historia y trazabilidad es una entidad de primera clase.
L dónde · lugares
Departamentos, almacenes, plantas, sucursales. Forman
una jerarquía territorial-organizacional que se arma con parte_de, igual que
cualquier otra.
T cuándo · tiempos
Fechas de pedido, períodos contables, vencimientos de órdenes de compra, vigencias de salario. El tiempo gobierna los estados que cambian.
N cuánto · magnitudes
Unidades vendidas, montos, horas-hombre, kilos de
insumo. Cada número arrastra su unidad anclada en K: nada anda suelto.
K cuál · clases
Tipos de producto, categorías de empleado, estados de orden, monedas. El zócalo categórico que da sentido a las magnitudes y los estados.
Y atravesando las seis cajas, los predicados del séptimo eje (M,
el cómo) son los cables que articulan todo: agente, parte_de,
reporta_a, motivado_por. Las decisiones de diseño que el ERP más
ejercita son cuatro, y conviene tenerlas a mano porque reaparecerán en cada escenario: la
D3 (todo es tripleta atómica), la D4 (una operación que
tocaría varios módulos se reifica como una situación con sub-situaciones), la
D6 (los estados, salarios y precios que cambian guardan su historial) y la
D7 (cada acción lleva su motivado_por y su
justificado_por: la auditoría es nativa, no un añadido).
Caso 1 · El organigrama es un solo cable
Todo ERP empieza por el organigrama. Una empresa tiene un director, sus gerentes, sus
equipos. En SAP esa estructura vive en una tabla llamada HRP1001 con un esquema
gimnástico de «relaciones» genéricas que hay que decodificar con catálogos auxiliares. En
WQuestions es un único rol de dominio, reporta_a, y la jerarquía completa de
Viento Norte cabe en cuatro tripletas:
(vendedora_ortiz, reporta_a, gerente_duarte)
(jefe_planta_cordero, reporta_a, gerente_duarte)
(gerente_duarte, reporta_a, directora_salas)
(directora_salas, reporta_a, vientonorte_sa)
La última línea es la que delata la potencia del eje Q: la empresa también es
un agente. La directora no reporta a la nada; reporta a la persona jurídica
vientonorte_sa, que firma contratos y rinde cuentas igual que un humano (D5). La
pregunta «¿quién es el jefe del jefe de Ortiz?» es un recorrido transitivo de dos saltos
sobre reporta_a; «todo el árbol bajo Duarte» es la relación inversa recorrida en
forma recursiva. No hace falta una tabla de cierre transitivo: el motor la calcula
al vuelo.
Asignar a cada empleado un departamento físico es igual de directo, y aquí el departamento
es un lugar del eje L:
(vendedora_ortiz, trabaja_en, dpto_ventas) # dpto_ventas ∈ L
(jefe_planta_cordero, trabaja_en, dpto_produccion) # dpto_produccion ∈ L
(dpto_ventas, parte_de, sede_central) # la jerarquía territorial
(almacen_norte, parte_de, sede_central) # se arma con parte_de
Si más adelante un departamento contuviera sub-departamentos, o una planta agrupara varias
líneas, usarías parte_de exactamente igual. La jerarquía de personas y la de
lugares se modelan con la misma maquinaria; solo cambia el eje sobre el que viven los nodos.
Caso 2 · La lista de materiales (BOM) es parte_de recursivo
Aquí el modelo luce. Una lista de materiales (el BOM, por bill of
materials) es la descomposición jerárquica de un producto en sus subproductos y, al
final, en su materia prima. Es uno de los conceptos más notoriamente incómodos de
implementar en bases relacionales: los MRP clásicos lo resuelven con tablas como
mast, matl y caps unidas por joins que pocos
disfrutan escribir.
Modelemos la bomba de riego K7. Tiene una carcasa de acero, un motor y un impulsor; el motor, a su vez, lleva un bobinado de cobre. Cuatro niveles de anidamiento:
bomba_riego_k7 ────┬─── carcasa_acero
├─── impulsor_bronce
└─── motor_electrico ───┬─── eje_motor
└─── bobinado_cobre ─── mp_cobre
En WQuestions, cada arista de ese árbol es una sola tripleta con
parte_de:
(carcasa_acero, parte_de, bomba_riego_k7)
(impulsor_bronce, parte_de, bomba_riego_k7)
(motor_electrico, parte_de, bomba_riego_k7)
(eje_motor, parte_de, motor_electrico)
(bobinado_cobre, parte_de, motor_electrico)
(mp_cobre, parte_de, bobinado_cobre)
¿Y cuántas unidades de cada subproducto entran? Esa cantidad no es del producto: es del enlace. Por eso se modela como un atributo de la relación, con su número y su unidad ancladas:
u.assert_fact(bobinado_cobre, "cantidad_en_bom",
n(2, "unidades", "n_2_uds_bobinado"))
u.assert_fact(mp_cobre, "cantidad_en_bom",
n(0.4, "kg", "n_04_kg_cobre"))
Para responder «¿qué materia prima necesita la bomba?» basta con recorrer
parte_de en forma recursiva hasta tocar las hojas del árbol. El recorrido no
conoce la profundidad de antemano y no le importa: la misma maquinaria sirve para una bomba
de cuatro niveles, un electrodoméstico de seis o un tablero electrónico de diez.
Una sola regla, dos jerarquías distintas
Fíjate en que parte_de ya hizo dos trabajos en este
capítulo: armó la jerarquía de lugares (el almacén es parte de la sede) y la de
componentes (el cobre es parte del bobinado). No son dos mecanismos parecidos:
son el mismo cable del eje M, recorrido sobre nodos de
distinto eje. La recursión arbitraria del BOM no pide ningún esquema especial; es un caso
particular de algo que el modelo ya tenía.
Caso 3 · La venta cross-módulo: el patrón que vale oro
Llegamos al caso emblemático, el que da título al capítulo. Volvamos a la llamada de las 11:20: ocho bombas K7 para Ferrocom por nueve mil seiscientos dólares. Ese único hecho toca, a la vez, tres módulos:
- Inventario: hay que descontar 8 unidades del almacén del norte.
- Contabilidad: hay que registrar el ingreso de 9.600 USD con su asiento.
- Recursos humanos: a Ortiz le corresponde una comisión del 4 % sobre la venta: 384 USD.
En un ERP tradicional, esta venta dispara tres procesos separados que escriben en tres tablas distintas, unidas por claves foráneas y convenciones de nombres. La pregunta de auditoría más simple («explícame qué pasó con esta venta») obliga a cruzar las tres bases. En WQuestions el modelado es directo: una situación reificada con tres sub-situaciones. Esto es exactamente la D4 en acción (la operación que tocaría varios módulos se reifica) y la figura lo muestra antes que el código.
venta_4417 como
situación central, referida por tres sub-situaciones que cuelgan de ella por
parte_de: el movimiento de inventario, el asiento contable y la comisión. Tres
módulos miran el mismo hecho desde su rol —ninguno lo copia—. En un ERP clásico,
esto serían tres tablas y un ETL nocturno para volver a juntarlas.Primero declaramos la situación articuladora con sus roles principales; luego colgamos de
ella, por parte_de, una sub-situación por módulo:
venta = ingest_situation(u, lex, "vender", roles={
"agente": vendedora_ortiz,
"tema": bomba_riego_k7,
"cliente": cliente_ferrocom,
"monto": n(9600, "USD"),
"momento": at("2026-07-15T11:20"),
"lugar_de": dpto_ventas,
}, sit_id="venta_4417")
# Sub-situación 1 — INVENTARIO: descuenta 8 unidades del almacén norte
u.assert_fact(mov_inventario, "parte_de", venta)
u.assert_fact(mov_inventario, "tema", bomba_riego_k7)
u.assert_fact(mov_inventario, "cantidad", n(8, "unidades"))
u.assert_fact(mov_inventario, "origen", almacen_norte)
# Sub-situación 2 — CONTABILIDAD: registra el ingreso
u.assert_fact(asiento_venta, "parte_de", venta)
u.assert_fact(asiento_venta, "monto", n(9600, "USD"))
u.assert_fact(asiento_venta, "tipo_movimiento", ingreso_por_venta)
# Sub-situación 3 — RR. HH.: comisión del 4 % para Ortiz
u.assert_fact(comision_ortiz, "parte_de", venta)
u.assert_fact(comision_ortiz, "beneficiario", vendedora_ortiz)
u.assert_fact(comision_ortiz, "monto", n(384, "USD"))
u.assert_fact(comision_ortiz, "calculado_segun", politica_comisiones_v2)
Tres sub-situaciones, una situación articuladora, ningún cruce de tablas
necesario. Y como cada sub-situación tiene su propia identidad, podemos hacer
preguntas finas que en un ERP clásico exigirían su propio reporte. «Explícame todo lo que
pasó con la venta 4417» es una proyección directa por parte_de:
sub_situaciones = [
f.subject for f in u.facts_with_role("parte_de")
if f.value.id == "venta_4417"
]
# → [mov_inventario_4417, asiento_venta_4417, comision_ortiz_4417]
«¿Qué comisión generó esta venta?», «¿cuál es su asiento contable?», «¿de qué almacén salió la mercancía?»: todas son recorridos de un salto sobre el mismo nodo central. Sin ETL, sin sistema intermedio, sin tabla de unificación. Lo que en un ERP tradicional es un proyecto de integración, aquí es la forma normal de escribir el hecho.
La venta no se reparte en tres registros que después hay que volver a unir. Es un solo hecho que cada módulo mira desde su rol: el grafo ya es la integración.La lección del Caso 3
De la venta 4417 al cierre de mes
Acompañamos una venta que cruzó inventario, contabilidad y compras. La gerencia
no mira la venta_4417: mira el cierre de mes. Cuánto facturó cada línea de
producto, qué margen dejó cada sede, cuántas bombas K7 quedan en el almacén norte, qué
comisiones acumuló Ortiz en el trimestre. Lo notable es que ninguno de esos reportes vive en
un módulo. Son cortes distintos del mismo grafo de situaciones —cada uno fija una coordenada
y deja libre el resto—, y todos los sumandos ya estaban escritos cuando cerró el pedido de las
11:20. Sumar las ventas de una línea es el corte más simple del consolidado:
# Facturación de una línea de producto — un corte; el cierre de mes recorre todas
suma(u, "monto", Pattern(fixed={"tema": u.ind("bomba_riego_k7")},
type_constraint=u.ind("vender")))
Caso 4 · La orden de compra y su aprobación bitemporal
Río arriba de la venta hay que reponer stock, y eso dispara compras. Las órdenes grandes (digamos 48.000 USD de cobre al proveedor) no se ejecutan al instante: pasan por un ciclo. Alguien la redacta, alguien la manda a aprobación, alguien con autoridad la aprueba o la rechaza. Cada estado tiene su fecha de entrada y su fecha de salida.
En sistemas tradicionales, esto vive en una columna estado que se
sobrescribe en cada transición. Cuando alguien pregunta «¿en qué estado estaba esta
orden el 20 de julio a la una de la tarde?», hay que rebuscar en la tabla de auditoría (si
existe) o estimarlo a partir de los logs. En WQuestions, el estado es un hecho con
vigencia temporal (D6): no se pisa, se acumula.
D6 Vigencia: el estado se acumula, no se pisa
Ningún atributo que pueda cambiar se guarda como un valor desnudo, sino
con un intervalo [inicio, fin). Cambiar de estado no es modificar una celda:
es cerrar el intervalo vigente y abrir uno nuevo. La consecuencia es que
el grafo conserva, gratis, toda la trayectoria del atributo a lo largo del tiempo.
u.assert_fact(oc_2208, "estado", borrador,
valid_from=t_creacion, valid_to=t_envio_aprob)
u.assert_fact(oc_2208, "estado", pendiente_aprobacion,
valid_from=t_envio_aprob, valid_to=t_aprobacion)
u.assert_fact(oc_2208, "estado", aprobada,
valid_from=t_aprobacion)
Tres tripletas en lugar de tres update destructivos. La consulta bitemporal
«¿en qué estado estaba el 20 de julio a las 13:00?» devuelve pendiente_aprobacion;
«¿y el 22 de julio?», devuelve aprobada. El historial completo es nativo, no un
módulo aparte. La aprobación misma, además, no es una simple marca: es una situación reificada
con su agente y su justificación normativa.
aprobacion = ingest_situation(u, lex, "aprobar", roles={
"agente": gerente_duarte,
"tema": oc_2208,
"momento": at("2026-07-21T15:30"),
"justificado_por": politica_aprobacion_oc_v4,
}, sit_id="aprobacion_oc_2208")
Duarte no aprueba «porque sí»: aprueba porque la política corporativa lo autoriza
para órdenes mayores a 30.000 USD. Aquí asoma la D7: el «por qué» no es un eje, sino una
relación entre hechos. La autorización se ata por justificado_por al documento
normativo, que es a su vez otro objeto reificado con su umbral y su vigencia. Y esto tiene una
consecuencia elegante: si mañana cambia el umbral, la política se reifica como versión nueva y
las aprobaciones viejas siguen apuntando a la anterior, sin alterar el historial.
Caso 5 · La orden de producción que consume insumos
Las ocho bombas que salieron del almacén hay que reponerlas: la planta de Cordero va a producir cincuenta. Cada bomba consume cierta cantidad de cobre (para el bobinado) y cierta cantidad de horas-hombre de taller. El ERP necesita registrar tres cosas (la orden como evento principal, el consumo de insumos y el consumo de mano de obra) y el patrón es, felizmente, el mismo de la venta cross-módulo:
op = ingest_situation(u, lex, "producir", roles={
"agente": jefe_planta_cordero,
"tema": bomba_riego_k7,
"cantidad": n(50, "unidades"),
"lugar_de": dpto_produccion,
}, sit_id="op_3390")
# Consumo de materia prima
u.assert_fact(consumo_cobre, "parte_de", op)
u.assert_fact(consumo_cobre, "tema", mp_cobre)
u.assert_fact(consumo_cobre, "cantidad", n(20, "kg"))
# Consumo de mano de obra
u.assert_fact(consumo_hh, "parte_de", op)
u.assert_fact(consumo_hh, "cantidad", n(160, "horas"))
u.assert_fact(consumo_hh, "ejecutado_por", jefe_planta_cordero)
Lo notable es que la misma estructura que modela una bomba producida por
un equipo humano podría modelar, sin cambiar una línea, una reacción química industrial donde
no hay agente humano y los reactivos se transforman solos siguiendo su
estequiometría. El catálogo ya admite que el rol agente sea opcional cuando el
verbo lo permite (D5); por eso el mismo molde sirve para «Cordero ensambla» y para «la
mezcla reacciona». Ese caso límite (química sin agente) se explora en el
capítulo 25.
La consulta «¿cuántos kilos de cobre consumió esta orden?» es, otra vez, una proyección:
encuentra las sub-situaciones de op_3390, filtra por tema = mp_cobre
y suma sus cantidad. Tres operaciones simples sobre el grafo. Cero ETL.
Y nota lo que acaba de pasar entre bastidores: el cobre que esta orden consume es el mismo
mp_cobre que el BOM del Caso 2 declaró como hoja del árbol de la bomba. Inventario
de insumos y lista de materiales no son dos módulos que haya que sincronizar: son el mismo
nodo, visto desde dos preguntas.
Caso 6 · El rastro bitemporal de un salario
Cerramos con una situación que en cualquier ERP es notoriamente difícil. Ortiz fue contratada el 10 de enero con un salario de 2.500 USD. El 1 de abril le subieron a 2.800. El 1 de agosto, tras una evaluación de desempeño con calificación «excelente», le subieron de nuevo a 3.200. La pregunta que el modelo tiene que responder sin esfuerzo es la que hace todo auditor laboral al revisar un legajo: ¿cuál era el salario de Ortiz el 15 de marzo? ¿Y el 15 de junio? ¿Y el 15 de septiembre?
En un ERP tradicional, esto exige una tabla histórica auxiliar (emp_salary_hist
y parientes) que la mitad de las implementaciones nunca termina de mantener al día. En
WQuestions, es la misma D6 del Caso 4 aplicada a un número: tres tripletas
que conviven en el grafo.
u.assert_fact(vendedora_ortiz, "salario_mensual", n(2500, "USD"),
valid_from=t_contrato, valid_to=t_aumento1)
u.assert_fact(vendedora_ortiz, "salario_mensual", n(2800, "USD"),
valid_from=t_aumento1, valid_to=t_aumento2)
u.assert_fact(vendedora_ortiz, "salario_mensual", n(3200, "USD"),
valid_from=t_aumento2)
La consulta query(..., at=fecha) filtra por vigencia y devuelve el valor que
regía en ese instante, no el de hoy:
marzo → 2 500 USD
junio → 2 800 USD
septiembre → 3 200 USD
Y el último aumento no flota suelto: se conecta con su causa. La evaluación de desempeño es
un objeto reificado propio, y el ajuste de salario lleva un motivado_por que
apunta a ella (D7). Si el auditor pregunta «¿por qué le subieron el salario a Ortiz en
agosto?», el grafo responde sin gimnasia: porque evaluacion_ortiz_2026, con
calificación excelente, lo motivó.
El antes y el después: del esquema fragmentado al grafo único
Pongamos las dos arquitecturas frente a frente con una pregunta transversal deliberadamente incómoda: ¿cuántas horas-hombre de producción demandó cada unidad que Ortiz vendió este trimestre, y cuánto cobró ella de comisión por esa venta?
Antes, en el modelo relacional. La información vive en islas:
employees y emp_salary_hist en RR. HH.; sales_orders
y sales_commissions en Ventas; production_orders y
wh_stock_movements en Manufactura e Inventario. La pregunta obliga a cruzar
cuatro tablas de tres módulos distintos con joins frágiles, claves foráneas de
convención y, casi siempre, una vista ETL que el equipo de inteligencia de negocio
mantiene a mano. Cualquier cambio de esquema en un módulo rompe el reporte en silencio.
-- Antes: cuatro tablas, tres módulos, joins por convención.
-- Y la venta vive partida en tres registros que hay que volver a unir.
SELECT so.id AS venta,
sc.monto AS comision,
SUM(wh.horas) AS horas_hombre
FROM sales_orders so
JOIN sales_commissions sc ON sc.order_id = so.id
JOIN production_orders po ON po.product_id = so.product_id
JOIN wh_stock_movements wh ON wh.po_id = po.id -- FK frágil
WHERE so.seller_id = 'ORTIZ'
AND so.fecha BETWEEN '2026-07-01' AND '2026-09-30'
GROUP BY so.id, sc.monto;
-- Si Manufactura renombra wh.po_id, el reporte calla y miente.
Después, en WQuestions. La misma información ya existe como un único
grafo de hechos atómicos. La venta_4417 es una situación reificada que
contiene, por parte_de, la comisión de Ortiz, el movimiento de inventario y
(a través de la orden de producción que repuso el stock) el consumo de horas-hombre. La
pregunta transversal es una proyección de unos pocos saltos: localiza las ventas de Ortiz
del trimestre, recorre sus sub-situaciones, lee monto en la comisión y
cantidad en el consumo de mano de obra.
No hay join de cuatro tablas, no hay vista ETL paralela, y sobre todo no hay silos, porque nunca hubo fronteras de módulo: hubo una sola venta, y el grafo la modeló entera. Un cambio de vocabulario en un módulo no rompe nada, porque no existe el módulo como tabla separada: existe el rol, mapeado una sola vez en el lexicon. La consulta que antes era un proyecto pasa a ser una sola pregunta bien formada.
El veredicto del dominio multi-módulo
El ERP es, probablemente, el dominio donde la promesa de WQuestions paga su dividendo más concreto: la integración entre módulos deja de ser un proyecto y se vuelve gratuita. Repasemos qué pidió cada escena y con qué la pagó el modelo, porque la lista entera cae sobre maquinaria que el libro ya tenía construida:
Lo que el ERP puso a prueba
- La venta cross-módulo. No genera «registros en tres
tablas»: genera una situación con tres sub-situaciones ligadas por
parte_de(D4). Cada módulo la mira desde su rol, ninguno la copia. - La lista de materiales. No necesita esquemas
auxiliares; es
parte_derecorrido en forma recursiva, el mismo cable que arma la jerarquía de lugares. - El rastro bitemporal. Estados de órdenes y salarios que cambian no se sobrescriben; conservan su historial nativo con vigencia (D6). El auditor reconstruye cualquier instante sin tablas paralelas.
- La aprobación y el aumento. No son workflows ni banderas externas: son
situaciones reificadas con su
justificado_pory sumotivado_por(D7). La auditoría es nativa, no un añadido.
Y todo se modeló con los mismos roles canónicos del catálogo (D8) más un puñado de roles de
dominio (reporta_a, trabaja_en, calculado_segun,
cantidad_en_bom, ejecutado_por) admitidos por la política liberal.
El motor no creció ni una línea para absorber el ERP. Lo único que creció fue el lexicon,
con un puñado de verbos nuevos (vender, ordenar_compra,
aprobar, producir, contratar,
ajustar_salario) y sus signaturas.
Si el banco demostró que el modelo soporta el peso del dinero, el ERP demuestra que soporta el peso de la coordinación: muchas voces internas describiendo, cada una a su manera, hechos que en el fondo son uno solo. El próximo capítulo cambia de terreno (de la fábrica al aula) y trae un grafo de otra naturaleza: una universidad, donde los prerrequisitos forman cadenas que el modelo deberá recorrer como un dependiente al que nunca le faltó un eslabón.