WQuestions

Parte V · En la práctica

16

Un sistema de ventas

Hasta aquí, ejemplos de una línea. A partir de ahora, un negocio entero: un spa que vende servicios, emite comprobantes, paga impuestos y cobra en dos monedas. Es donde la teoría se vuelve código que puedes ejecutar.

Son las 18:05 de un jueves en Serena Termas, un spa de barrio. Una clienta (Lucía) acaba de salir de la cámara de vapor, se acerca al mostrador y pide pagar: un circuito termal y un masaje descontracturante. La recepcionista teclea, el sistema calcula el subtotal, le suma el impuesto al consumo, descuenta un cupón de fidelidad, cobra la mitad en efectivo y la mitad con una tarjeta extranjera en otra moneda, e imprime una boleta numerada que esa misma noche viajará al organismo tributario. Toda esa coreografía (servicio, precio, impuesto, comprobante, divisa, fidelidad) ocurre en menos de un minuto y deja un rastro que un contador, un auditor y el dueño tendrán que poder leer meses después. Ese minuto es el examen de este capítulo.

Hasta este punto, el libro te explicó cada decisión de diseño con escenas pequeñas y autocontenidas: una venta de camiseta que se registra, una jugada de fútbol con dos agentes, una ordenanza que entra en vigor a los treinta días. Eran lo bastante chicas para caber en una página. Pero ninguna arquitectura merece llamarse universal si no sostiene un negocio completo, con sus impuestos, sus comprobantes legales y sus monedas. Un spa parece el dominio más inofensivo del mundo (toallas, vapor, música suave) y es justo por eso que conviene empezar aquí: bajo esa superficie relajada se esconde un sistema de ventas con casi todas las exigencias de un comercio formal.

Lo que pone a prueba este capítulo

Un mismo negocio nos obliga a usar, a la vez, casi todas las herramientas de las Partes II y III: los siete ejes, los hechos atómicos, las situaciones reificadas, el catálogo de roles y el lexicon. Y le añade lo que un comercio real no perdona: autoridad tributaria, comprobantes numerados, impuesto al consumo y cobros en varias divisas.

Serena Termas en una página

Fijemos el negocio antes de modelarlo. Serena Termas opera en una sede con dos cámaras de vapor y una cámara seca a 58 °C, una sala de masajes y una pequeña barra de jugos. El catálogo es corto y claro:

♨️

Circuito termal

Veinte minutos por cámara y una ducha helada de cierre. Precio de lista: S/ 80. El producto estrella.

💆

Masaje descontracturante

Cincuenta minutos con una terapeuta. S/ 140. Se vende solo o como complemento del circuito.

🧃

Barra de jugos

Bebidas y fruta. Aquí lo vendido no es un servicio sino un bien: importa para el impuesto, como veremos.

Y, como todo comercio, tiene reglas de negocio que la contabilidad de juguete suele maltratar:

  • Fidelidad. A la décima visita pagada, el circuito de la undécima sale gratis.
  • Impuesto al consumo. Cada venta lleva un impuesto del 18 % que el spa cobra al cliente y luego entrega al fisco. No es ingreso del negocio: es dinero en tránsito.
  • Comprobantes. Toda venta exige un documento numerado (boleta o factura) con una serie correlativa que la autoridad tributaria audita.
  • Multi-divisa. La mitad de la clientela es de paso y paga con tarjetas en dólares; la contabilidad lleva todo en la moneda local.

Usaremos tres clientes para estresar el modelo: Lucía Rentería, fiel y a punto de ganar su sesión gratis; Martín Paredes, un turista que paga en dos monedas; y Noa Cifuentes, que pidió factura a nombre de su empresa. Tres personas bastan para tropezar con casi todos los bordes interesantes.

Paso 1 · Acomodar el negocio en los siete ejes

El primer trabajo de quien modela datos es repartir las entidades del negocio en las coordenadas correctas. Es la decisión que más se paga después: si una cosa cae en el eje equivocado, el sistema cojea para siempre. Así se reparte Serena Termas.

Q quién · agentes Lucía, Martín, Noa (clientes) la recepcionista, la terapeuta la empresa Serena Termas, el fisco O qué · eventos y objetos la venta_4471, cada sesión los cobros, la boleta_4471 el cupón, el contrato de fidelidad L dónde · lugares la sede, la cámara_vapor_2 la sala de masajes, las duchas la barra de jugos T cuándo · tiempo la hora de cada venta la vigencia de cada promoción el tipo de cambio del día N cuánto · magnitudes S/ 80, S/ 140, el 18 % 58 °C, el contador de 10 visitas US$ 22.50, la tasa 3.72 K cuál · clases circuito_termal, masaje tipo_boleta, tipo_factura estados: pagada, anulada · soles, dólares M cómo · los predicados que enlazan los seis ejes cliente · comprende · cubierto_por · grava · documentado_por · pagado_con Una venta no vive en ningún eje aislado: es el nudo donde todos se cruzan. Serena Termas, repartido en sus siete coordenadas
Figura 16.1. El dominio del spa sobre los siete ejes. Nota un detalle: la empresa Serena Termas y el propio fisco viven en Q, porque ambos son agentes que cobran y reciben dinero. Las cámaras viven en L (son lugares donde ocurre la sesión) pero también en O (son máquinas con temperatura y mantenimiento): una misma cosa puede habitar dos ejes según la pregunta. La banda inferior, el eje M, no contiene entidades sino los cables que las conectan.

Repara en la barra de jugos. Un servicio y un jugo parecen lo mismo en la caja registradora, pero el fisco los trata distinto: el servicio es prestación, el jugo es bien, y de eso depende qué impuesto aplica. Modelarlos como clases distintas en K (servicio_spa frente a bien_consumible) no es pedantería: es lo que permite, más tarde, declarar el impuesto correcto sin un solo if incrustado en el código de la caja.

El nudo central · la venta

Si tuviéramos que elegir el evento alrededor del cual orbita todo el negocio, sería la venta. Quién la hizo, qué incluyó, dónde, cuándo, cuánto sumó, qué impuesto gravó, qué comprobante la respalda y cómo se pagó: la venta es el punto donde los siete ejes se cruzan. Tal como vimos al tratar el hecho atómico (D3), no la guardamos como una fila gorda, sino como una constelación de tripletas tipadas que se apilan.

La venta de las 18:05 a Lucía (un circuito más un masaje) se reifica como una situación en O (D4: lo merece, porque agrupa varias partes, tiene fecha y participa en otras relaciones) y se describe con esta lista de hechos atómicos:

tripletas
(venta_4471) ∈ O
  instancia_de     : transaccion_venta            # K · qué clase de cosa es
  cliente          : lucia_renteria               # Q · quién compró
  vendido_por      : serena_termas                # Q · qué agente vendió
  lugar_de         : sede_central                 # L · dónde ocurrió
  inicio           : 2026-06-11T18:05-05:00       # T · cuándo
  comprende        : item_4471_a                  # O · una línea de la venta
  comprende        : item_4471_b                  # O · otra línea
  moneda_base      : soles                         # K · la moneda de la contabilidad
  subtotal         : 220.00                        # N · antes de impuesto
  impuesto_total   : 39.60                         # N · el 18 % del gravado
  total            : 259.60                        # N · lo que se cobra
  documentado_por  : boleta_4471                   # O · el comprobante legal
  estatus_factual  : pagada                         # K · su estado

Cada línea de la venta es a su vez un objeto en O, porque cada una tiene su propio precio, su propia clase de producto y —esto es lo importante— su propio tratamiento tributario. El masaje y el jugo no se gravan igual; meterlos en el mismo campo perdería esa distinción para siempre.

tripletas
(item_4471_a, instancia_de,   circuito_termal)     # un servicio
(item_4471_a, parte_de,       venta_4471)
(item_4471_a, precio_unitario, 80.00)              # N · soles
(item_4471_a, gravado_con,    impuesto_consumo_18) # K · le aplica el 18 %

(item_4471_b, instancia_de,   masaje_descontracturante)
(item_4471_b, parte_de,       venta_4471)
(item_4471_b, precio_unitario, 140.00)
(item_4471_b, gravado_con,    impuesto_consumo_18)

El cable parte_de hace de hilo: cada línea cuelga de su venta, y la venta de su comprobante. Recorriendo ese hilo, el sistema reconstruye la jerarquía completa sin un solo JOIN. Visto como tripleta, ese andamiaje se lee de un vistazo:

item_4471_aO parte_deM(O→O) venta_4471O documentado_porM(O→O) boleta_4471O

Y en el código real del prototipo, construir esa venta no exige redactar las tripletas a mano: una llamada de pocas líneas consulta el lexicon, desambigua el verbo, crea la situación y le enchufa los cables: validando que ninguno esté mal puesto.

python
venta = ingest_situation(u, lex, "vender",
    roles={
        "cliente":     lucia,
        "vendido_por": serena_termas,
        "lugar_de":    sede_central,
        "inicio":      t_venta,
    },
    complements=["circuito", "masaje"],     # el lexicon arma las dos líneas
    extra={
        "moneda_base":     soles,
        "estatus_factual": pagada,
    },
    sit_id="venta_4471",
)

El sistema se niega a aceptar disparates

Si un programador distraído intentara poner a lucia en el rol lugar_de, o un texto donde va una cantidad, ingest_situation aborta de inmediato con un error de firma (SignatureError). El rol lugar_de exige un habitante del eje L; una persona no lo es. La validación no es opcional: es la frontera que impide que la basura entre al grafo.

El impuesto al consumo · dinero que solo está de paso

Aquí es donde un sistema de ventas se separa de un cuaderno de apuntes. Ese 18 % que aparece en la boleta no es ingreso del spa: es dinero que el negocio cobra por cuenta del fisco y que tendrá que entregarle. Confundir ambas cosas (tratar el impuesto como ganancia) es uno de los errores contables más caros que existen. El modelo lo mantiene separado por construcción.

El impuesto no se guarda como un número suelto pegado a la venta, sino como un objeto con identidad: sabe cuánto es, sobre qué base se calculó, qué tasa aplicó y a quién se le debe.

tripletas
(impuesto_4471) ∈ O
  instancia_de   : impuesto_consumo_18    # K · qué tributo es
  grava          : venta_4471             # O · sobre qué venta recae
  base_imponible : 220.00                 # N · el subtotal gravado
  tasa           : 0.18                   # N · la alícuota vigente
  monto          : 39.60                  # N · lo que se debe
  acreedor       : fisco                  # Q · a quién se le entrega
  estatus_factual: por_remitir           # K · cobrado, aún no entregado

Modelarlo así tiene una consecuencia inmediata y deliciosa: la pregunta del contador «¿cuánto impuesto debo entregar este mes?» deja de ser un cálculo que alguien reprograma cada vez que cambia la ley, y pasa a ser una simple suma sobre los objetos cuyo acreedor es el fisco y cuyo estado sigue en por_remitir. Y cuando la tasa cambie del 18 % al 16 %, las ventas viejas conservan su tasa congelada: se calcularon con la alícuota que regía ese día, y esa verdad histórica no se reescribe.

El comprobante · cuando la ley pide un número correlativo

Un comercio formal no puede limitarse a saber que vendió: debe emitir un documento numerado, de una serie correlativa que la autoridad tributaria audita. Si la boleta 4470 existe y la 4472 existe, la 4471 tiene que existir; un hueco en la numeración es, para un auditor, una venta sospechosamente desaparecida. El comprobante, por tanto, no es un adorno de la venta: es un objeto de pleno derecho, con su propia clase, su propio número y su propio destino regulatorio.

tripletas
(boleta_4471) ∈ O
  instancia_de   : tipo_boleta_venta      # K · boleta (consumidor final)
  serie          : B001                    # K · la serie correlativa
  numero         : 4471                    # N · correlativo dentro de la serie
  respalda       : venta_4471             # O · qué venta documenta
  emitido_por    : serena_termas          # Q · el emisor
  receptor       : lucia_renteria         # Q · a nombre de quién
  emitido_el     : 2026-06-11T18:06-05:00 # T
  estatus_factual: emitida                 # K · emitida, anulada, etc.

La distinción entre boleta y factura (una para el consumidor final, otra a nombre de una empresa que descontará el impuesto) es, en el modelo, nada más que dos clases distintas en K: tipo_boleta_venta y tipo_factura_venta. Cuando Noa pidió factura a nombre de su empresa, el sistema no necesitó otra tabla ni otro flujo: la misma maquinaria emitió un objeto de otra clase, con un campo extra para el identificador tributario del receptor.

Comprobante de venta

Documento legal, numerado en serie correlativa, que respalda una transacción ante la autoridad tributaria. En WQuestions es un objeto en O con su clase (tipo_boleta, tipo_factura), su número, su emisor, su receptor y un cable respalda hacia la venta. La numeración correlativa es una invariante auditable: el grafo permite verificar que no falta ninguno.

Multi-divisa · dos monedas, una contabilidad

Martín, el turista, pagó su circuito en dos partes: la mitad en efectivo, en moneda local, y la mitad con una tarjeta en dólares. La trampa clásica es guardar «pagó 22.50» sin decir de qué moneda hablamos (el pecado capital de los sistemas que asumen una sola divisa). En WQuestions, un monto nunca viaja solo: siempre arrastra su unidad, que es un habitante de K. Y un pago en otra moneda guarda, además, la tasa de cambio con la que se convirtió, fechada en el día de la operación.

tripletas
(cobro_4480_efectivo) ∈ O
  instancia_de  : pago_recibido
  paga          : venta_4480              # la venta de Martín
  monto         : 40.00
  moneda        : soles                   # K · moneda local
  medio         : efectivo

(cobro_4480_tarjeta) ∈ O
  instancia_de  : pago_recibido
  paga          : venta_4480
  monto         : 10.75                   # N · lo que se cobró
  moneda        : dolares                 # K · ¡otra unidad!
  tasa_cambio   : 3.72                    # N · soles por dólar, ese día
  equiv_base    : 40.00                   # N · su valor en moneda local
  medio         : tarjeta_credito

Como cada cantidad declara su unidad, el sistema nunca suma peras con manzanas. Para totalizar la caja del día convierte cada cobro a la moneda base usando la tasa que ya quedó guardada con él —no la de hoy, sino la del momento del cobro—, y la contabilidad cierra al centavo aunque hayan entrado cuatro monedas distintas. La unidad como ciudadano de primera clase, que el capítulo del eje cuantitativo defendió en abstracto, aquí se cobra su sueldo.

El lexicon del spa · enseñarle a la máquina el idioma del negocio

Para que la recepcionista no tenga que aprender jerga de bases de datos, configuramos el lexicon con las palabras exactas del spa. El lexicon es el compilador del que habló la Parte IV: traduce el vocabulario humano a los roles canónicos del modelo, y de paso resuelve la polisemia. El verbo «tomar», por ejemplo, significa cosas distintas según lo que lo acompañe:

python
lex.register(LexiconEntry(
    verb="tomar",
    situation_type="servicio_spa",
    obligatory=["cliente", "lugar_de"],
    pattern=("sesion",),            # "tomar una sesión" → activa esta regla
))

lex.register(LexiconEntry(
    verb="tomar",
    situation_type="accion_decidir",
    obligatory=["agente", "objeto"],
    pattern=("una_decision",),      # "tomar una decisión" → otra regla
))

Y le instalamos el «dialecto corporativo» del spa (D8/D9): un mapa entre las palabras que el personal usa de verdad y las etiquetas canónicas que el catálogo conoce. El usuario final nunca toca esas etiquetas internas; el sistema traduce por debajo.

python
lex.register_domain_dialect("serena_termas", {
    "cliente":        "agente",
    "sesion":         "servicio_spa",
    "boleta":         "tipo_boleta_venta",
    "factura":        "tipo_factura_venta",
    "sesion_gratis":  "beneficio_fidelidad",
    "igv":            "impuesto_consumo_18",
})

Gracias a esto, la recepcionista puede escribirle al sistema «emítele una boleta a Lucía por una sesión, con su sesión gratis aplicada» y el grafo lo traduce a sus identificadores internos sin que ella sepa que existen.

La interfaz es el lexicon, no el catálogo

El catálogo canónico (impuesto_consumo_18, tipo_boleta_venta) es invisible para quien usa el negocio. Lo que ve es su propio idioma: «IGV», «boleta», «sesión gratis». Dos spas con vocabularios distintos pueden compartir el mismo catálogo y aun así cada uno hablar como siempre habló.

Tres preguntas de negocio, resueltas como recorridos del grafo

El valor de un sistema se mide por la facilidad con que responde las preguntas que de verdad importan a fin de mes. Veamos tres clásicas de este spa y cómo el código las resuelve recorriendo tripletas en vez de encadenar tablas.

Pregunta 1 · ¿Cuántos circuitos pagados lleva Lucía? ¿Le toca el gratis?
No hay JOIN que escribir: el motor busca un patrón en el grafo (todas las ventas de clase circuito_termal cuyo cliente sea Lucía y cuyo estado sea pagada) y las cuenta.

python
n = count(u, Pattern(
    fixed={"cliente": lucia, "estatus_factual": u.ind("pagada")},
    type_constraint=u.ind("circuito_termal"),
))
le_toca_gratis = n >= 10        # la regla de fidelidad, en una línea

El modelo no ejecuta la regla de negocio por su cuenta (para eso hace falta un motor externo o una IA); lo que hace es entregar el dato prístino y estructurado para que ese motor decida sin equivocarse. La división del trabajo es deliberada: el grafo guarda la verdad, la lógica vive afuera.

Pregunta 2 · ¿Cuánto impuesto debo entregarle al fisco este mes?
Una suma sobre todos los objetos impuesto cuyo acreedor es el fisco y que siguen pendientes de remitir. La ley puede cambiar la tasa: las ventas viejas no se tocan, cada una ya guardó la suya.

python
deuda_fiscal = suma(u, "monto", Pattern(
    fixed={"acreedor": fisco, "estatus_factual": u.ind("por_remitir")},
    type_constraint=u.ind("impuesto_consumo_18"),
))

Pregunta 3 · ¿Quedó algún hueco en la numeración de boletas?
La auditoría más temida del negocio se vuelve trivial: pide al grafo todos los números de la serie B001 y verifica que sean correlativos. Un salto delata una boleta extraviada —o un fraude.

Pregunta: ¿cuánto impuesto debo entregar este mes? → suma sobre N El patrón fija… Q acreedor = fisco K estado = por_remitir + tipo: impuesto_consumo_18 imp_ 4471 39.60 imp_ 4480 7.20 imp_ 4492 25.20 N se proyecta y se suma = 72.00 soles El patrón restringe; el motor recorre los hechos atómicos; la proyección agrega. Sin un solo JOIN. Los colores son los ejes: Q acreedor · K estado y tipo · O los objetos impuesto · N el monto que se agrega.
Figura 16.2. Cómo se resuelve una pregunta saltando tripletas. El patrón fija dos roles (acreedor en Q, estado en K) y restringe por tipo; el motor recorre los objetos impuesto que encajan y proyecta su campo monto sobre el eje N, donde los agrega. La misma mecánica responde «cuántos circuitos» (un conteo) o «cuánto facturé» (otra suma): cambia la proyección, no la maquinaria.

Detente un segundo aquí, porque esa suma es la primera aparición de algo que volverá en cada dominio del libro. No preguntamos por una venta del spa: preguntamos por todo el impuesto del mes a la vez. Modelar con cuidado la venta de un circuito de aguas termales fue, sin proponérnoslo, dejar listo el reporte fiscal del negocio entero.

El «por qué» de una venta · los cuatro cables

En un negocio real, saber qué pasó no basta; a menudo hace falta saber por qué. Tal como argumentó el capítulo del «por qué» (D7), no existe un eje «por qué»: el porqué se reparte en cuatro cables distintos, y un sistema de ventas los necesita a casi todos. Dos ejemplos del spa lo dejan claro.

El descuento que tiene una causa normativa. A Lucía se le aplicó su circuito gratis de la décima visita. Ese descuento no es un capricho de la recepcionista: está justificado por el contrato de fidelidad, una regla del negocio. El cable justificado_por ata el descuento a la norma que lo autoriza, de modo que cualquier auditor pueda rastrear por qué esa venta cobró menos —y comprobar que fue legítimo, no un robo.

El cliente que casi compra. Noa quiso contratar el plan mensual, pero no cerró ese día. En una caja registradora común, ese dato se pierde. En WQuestions se guarda como una intención: una situación con modalidad volitiva y estado intencionado, no real. Cuando marketing pregunte «¿a quién llamamos para ofrecer el plan?», Noa salta a la lista; cuando contabilidad pregunte «¿qué planes están activos?», Noa no aparece y nadie le cobra por error.

tripletas
(descuento_4471, aplica_a,        venta_4471)
(descuento_4471, justificado_por, contrato_fidelidad_lucia)   # ← regla normativa

(intencion_noa_01, instancia_de,    contrato_plan_mensual)
(intencion_noa_01, cliente,         noa_cifuentes)
(intencion_noa_01, modalidad,       volitiva)                 # ← lo quería
(intencion_noa_01, estatus_factual, intencionado)             # ← aún no es real

La distinción entre lo intencionado y lo real es la misma que separa, en banca, una solicitud de un préstamo desembolsado, o en una clínica un diagnóstico de sospecha de uno confirmado. Que un spa la necesite tanto como un banco es, en sí mismo, una pequeña confirmación de que el modelo capturó algo general.

El antes y el después · del esquema fragmentado al grafo único

Antes, en SQL. En un esquema relacional clásico, Serena Termas vive repartido en media docena de tablas que no se hablan solas: clientes, ventas, lineas_venta, pagos, comprobantes, impuestos. Responder «¿cuánto IGV debo este mes, descontando las ventas anuladas y convertido todo a moneda local?» obliga a encadenar cinco JOIN frágiles, filtrar por estado, cruzar tasas de cambio y dejar la mitad de la lógica enterrada en código de aplicación que nadie documenta y que se rompe cada vez que cambia una regla.

sql
-- Antes: venta, línea, impuesto y comprobante viven en tablas distintas;
-- la pregunta tributaria obliga a encadenarlas con JOINs frágiles.
CREATE TABLE ventas       (id INTEGER PRIMARY KEY, cliente_id INT, estado TEXT, moneda TEXT);
CREATE TABLE lineas_venta (id INTEGER PRIMARY KEY, venta_id INT, producto_id INT, precio NUMERIC);
CREATE TABLE impuestos    (id INTEGER PRIMARY KEY, venta_id INT, tasa NUMERIC, monto NUMERIC);
CREATE TABLE comprobantes (id INTEGER PRIMARY KEY, venta_id INT, serie TEXT, numero INT);

SELECT SUM(i.monto) AS igv_por_pagar
FROM impuestos i
JOIN ventas v       ON v.id = i.venta_id
JOIN comprobantes c ON c.venta_id = v.id
WHERE v.estado = 'pagada'              -- ojo: ¿y las anuladas?
  AND c.numero IS NOT NULL;           -- la lógica de moneda… vive en otra parte

Después, en WQuestions. La misma información es un grafo único de hechos atómicos: cada impuesto es un objeto con su cable acreedor → fisco y su estatus_factual. La pregunta se vuelve una suma sobre un patrón (sin migrar esquema, sin JOIN, sin lógica escondida en procedimientos almacenados). Y cuando la tasa cambie, se edita un solo hecho en el catálogo; las ventas pasadas conservan la suya y el resto del sistema ni se entera.

python
# Después: la misma pregunta, como un patrón sobre el grafo de hechos.
igv_por_pagar = suma(u, "monto", Pattern(
    fixed={"acreedor": fisco, "estatus_factual": u.ind("por_remitir")},
    type_constraint=u.ind("impuesto_consumo_18")))

En un sistema de ventas, el impuesto no es un número: es una deuda con un acreedor, una base y una fecha. Tratarlo como un objeto, y no como una columna, es lo que convierte la auditoría en una consulta.La lección del spa

Cuánto se vendió · el negocio en una barra

Un sistema de ventas que no sabe responder «¿qué se vendió más?» no merece el nombre. Como cada línea de venta es un objeto con su clase de producto, totalizar por servicio es —otra vez— una agregación sobre el grafo. Este fue el desglose de ingresos de un mes en Serena Termas:

Figura 16.3. Ingresos del mes por línea de producto, en miles de soles. El circuito termal sostiene el negocio; los planes mensuales aportan más que la barra de jugos. Ninguna de estas cifras se calculó con una consulta nueva: las cuatro son la misma suma sobre el grafo, agrupada por la clase del producto en K.

Balance · el spa fue un cliente amable

Cerremos repasando qué demostró el prototipo al absorber este negocio de punta a punta:

El veredicto del primer dominio industrial

  • Los siete ejes funcionan juntos. Clientes y fisco en Q, ventas y comprobantes en O, cámaras en L, momentos y vigencias en T, precios, impuestos y tasas en N, tipos y estados en K, y los predicados de M cosiéndolo todo.
  • El sistema de ventas, completo. Comprobantes numerados auditables, impuesto al consumo como dinero en tránsito, cobros en dos divisas con su tasa fechada. Nada de esto pidió ingeniería nueva: cayó sobre la maquinaria existente.
  • La historia se preserva (D6). Una tasa de impuesto que cambia no reescribe las boletas viejas; cada comprobante sigue siendo coherente con la ley que regía el día en que se emitió.
  • Cero parches. Todo el negocio se modeló con los roles base de la arquitectura y un puñado de clases en el catálogo. Donde un sistema tradicional pediría media docena de tablas y procedimientos almacenados, aquí bastaron tripletas y un lexicon.

El spa parecía el dominio más inofensivo del libro y resultó ser un sistema de ventas completo, con su autoridad tributaria mirando por encima del hombro. El modelo lo absorbió sin doblarse. Pero un comercio de barrio opera a su propio ritmo: las ventas no llegan por miles ni cambian de estado cada segundo. En el próximo capítulo subimos la apuesta hacia la velocidad y la concurrencia: un servicio on-demand, donde un viaje en taxi cambia de estado una docena de veces en quince minutos y miles ocurren a la vez.