1. Introducción y principios
Este documento es la referencia técnica integrada del dominio POS / Ticket / Ledger. Consolida el modelo central y el submodelo de promociones en una sola narrativa técnica, incluyendo estructura de datos, reglas de cálculo, ejemplos JSON y lineamientos de implementación. fileciteturn8file0
Jerarquía documental
| Prioridad | Documento | Descripción |
|---|---|---|
| 1 | core.md (202604070108) | Referencia central del modelo POS/Ticket/Ledger. |
| 2 | promociones.md (202604070300) | Complemento específico del motor de promociones. |
| 3 | jsonmodel_optionB_v4 | Ejemplos JSON del modelo corregido. |
| 4 | Documentos históricos | Referencias previas, con menor prioridad ante contradicción. |
2. Agregado raíz: Ticket
Ticket es el agregado raíz y representa el estado completo de una operación POS. Es la unidad principal para cálculo, validación, testing, auditoría y reconciliación. fileciteturn8file0
Estructura base
3. Granos del modelo
El modelo trabaja con tres granos funcionales separados y obligatorios. Esa separación no debe perderse. fileciteturn8file0
Regla de itemización
movimientos[]. items[] es captura comercial;
movimientos[] es impacto económico distribuido. fileciteturn8file0
| Campo | Tipo | Descripción |
|---|---|---|
| id | integer | Identificador incremental del movimiento |
| concepto | enum | VENTA_ITEM · PROMOCION · PAGO |
| origenid | integer | Referencia al registro maestro origen |
| movimientoid | integer/null | Referencia al VENTA_ITEM afectado; null para excedentes y vuelto |
| nucleoimpositivo[] | array | Importes e impuestos del movimiento |
4. Objetos del dominio
NucleoImpositivo
Es la estructura central de importes e impuestos. Se utiliza en artículos, movimientos y datos referenciales. No debe asumirse que todo impuesto sea porcentual. fileciteturn8file0
Articulo
| Campo | Descripción |
|---|---|
| ean / plu | Identificación comercial del producto |
| descripcion | Nombre visible del artículo |
| pesable | Indica si admite cantidades decimales |
| preciolista | Precio base para cálculo de promociones |
| rubro / depto / marca | Atributos comerciales para filtros |
| nucleoimpositivo[] | Composición impositiva base |
TipoDePago y Pago
TipoDePago es catálogo/configuración externo al ticket. Pago es el registro maestro operativo dentro del ticket y su monto puede ser positivo o negativo. Un pago negativo es válido cuando participa como vuelto. fileciteturn8file0
montoingresado o montoaplicado a la versión base.
El modelo conservador usa solo monto. fileciteturn8file0
5. Modelo de promociones
El modelo promocional distingue tres capas obligatorias: definición en listapromociones,
registro maestro aplicado en promociones[] y efecto económico final en
movimientos[]. fileciteturn8file0
Catálogos auxiliares
| Catálogo | Valores | Descripción |
|---|---|---|
| promocionalcance | ITEM · PAGO | Etapa funcional donde aplica la promoción |
| promocionbeneficio | PORCENTAJE · MONTO · NUEVOPRECIOITEM | Cómo interpretar valor |
| promocionmetodo | CANTIDAD · COMBO | Lógica base de resolución |
| promociondecision | NOACUMULATIVA · ACUMULATIVA | Base de cálculo del precio |
| promocionestado | POSIBLE · APLICADA · NOAPLICA · ANULADA | Estado de una promoción aplicada |
| promocionlistatype | INCLUSION · EXCLUSION | Tipo de entrada de lista |
| promocionlistanumber | LISTA1 · LISTA2 | Agrupa listas lógicas |
promociontipoelemento
Incluye valores como EAN, PLU, DEPTO, RUBRO, CODIGOCLASIFICACION, PROVEEDOR, MARCA,
MEDIODEPAGO, SUCURSAL, TICKET y CANTIDAD_MAX_PROMOS, que limita la cantidad
de aplicaciones de una promoción dentro del ticket y siempre se informa con
valordeelemento. fileciteturn8file0
Definición de promoción
6. Motor de promociones
MODO ITEM
Se ejecuta una sola vez por ticket. Cada invocación resetea promociones previamente calculadas,
evalúa solo promociones con alcance ITEM, genera registros en promociones[] y
distribuye su efecto en movimientos[]. No devuelve promociones de medio de pago. fileciteturn8file0
MODO PAGO
Puede invocarse múltiples veces por ticket. Evalúa promociones con alcance PAGO y opera en dos sub-etapas: CONSULTA y APLICAR. Los pagos se comparan siempre contra el saldo real luego de promociones e impuestos. fileciteturn8file0
Escenarios de monto
| Escenario | Condición | Comportamiento |
|---|---|---|
| Pago parcial | monto < saldo neto | Promoción proporcional; queda saldo pendiente |
| Pago exacto | monto = saldo neto | Promoción completa; ticket saldado |
| Pago con excedente | monto > saldo neto | Excedente resuelto como vuelto según tiposdepago |
Lógica de vuelto
| Caso | davuelto | vueltomediodepago | Resultado |
|---|---|---|---|
| A | true | — | Vuelto en el mismo medio; operación aceptada |
| B | false | null | No se permite vuelto; operación denegada |
| C | false | id_medio | Vuelto en medio alternativo indicado; aceptada |
7. Ledger — movimientos[]
El ledger distribuido es la fuente de verdad fiscal y contable. Las convenciones de signo son obligatorias para que la operación cierre algebraicamente en 0. fileciteturn8file0
| Concepto | origenid | movimientoid |
|---|---|---|
| VENTA_ITEM | items[].id | null |
| PROMOCION | promociones[].id | id del VENTA_ITEM afectado |
| PAGO contra ítem | pagos[].id | id del VENTA_ITEM cancelado |
| PAGO excedente | pagos[].id | null |
| PAGO vuelto | pagos[].id (vuelto) | null |
nucleoimpositivo en movimientos[] debe dar exactamente 0 al cierre final del ticket. fileciteturn8file0
8. Ejemplo completo integrado
Escenario: 3 unidades de ARROZ a $1310, promoción 2x1 (50% sobre dos unidades, máximo una aplicación), pago con CHEQUE por $3000 y vuelto $380 en EFECTIVO. fileciteturn8file0
Resultado MODO ITEM
Resultado MODO PAGO
Verificación de reconciliación
| Verificación | Cálculo | Resultado |
|---|---|---|
| Items bruto | 3 × $1310 | $3930.00 ✓ |
| Promo maestro | promociones[1].monto | −$1310.00 ✓ |
| Movs PROMOCION | mov4 + mov5 | −$1310.00 ✓ |
| Neto ticket | $3930 − $1310 | $2620.00 ✓ |
| Pagado neto | $3000 − $380 | $2620.00 ✓ |
| Suma ledger total | Σ mov1..10 | $0.00 ✓ |
9. Orden base de cálculo
| Paso | Acción | Observación |
|---|---|---|
| 1 | Identificar cliente | Determina tipo de comprobante y alícuotas aplicables |
| 2 | Ingresar ítems | Deduplicar articulos[], crear items[] |
| 3 | Resolver referencias | Cada item referencia su articuloid |
| 4 | Determinar bases iniciales | preciolista × unidades |
| 5–6 | Aplicar promociones ITEM | MODO ITEM |
| 7 | Calcular impuestos y núcleo | nucleoimpositivo del ticket |
| 8 | Determinar total | datosreferenciales.total |
| 9 | Pre-consulta promos de pago | MODO PAGO CONSULTA |
| 10 | Registrar pagos | MODO PAGO APLICAR |
| 11 | Calcular excedente y vuelto | Movimientos PAGO null |
| 12 | Distribuir pagos en ledger | Contra VENTA_ITEM |
| 13 | Calcular saldo final | datosreferenciales.saldo |
| 14 | Validar reconciliación | Σ movimientos[] = 0 |
10. Convenciones de implementación Java 8
La implementación objetivo es Java 8 clásico: POJOs simples, campos privados, getters/setters explícitos, constructor por defecto, sin Lombok, sin records y sin features posteriores a Java 8. fileciteturn8file0
Paquetes sugeridos
com.tipre.ruleengine.modelcom.tipre.ruleengine.model.enumscom.tipre.ruleengine.model.catalogcom.tipre.ruleengine.logiccom.tipre.ruleengine.validationcom.tipre.ruleengine.example
POJO ejemplo — Item
11. Decisiones diferidas y extensiones futuras
Hay áreas reconocidas por el modelo que todavía no están definidas en esta versión y requieren decisión explícita. fileciteturn8file0
| Área | Estado | Impacto esperado |
|---|---|---|
| Filtros por tipo de cliente / convenio / fidelización | Diferido | Nuevo atributo en listapromociones y filtro extra en el motor |
| Orden de evaluación / prioridad entre promociones | Diferido | Campo prioridad y cambio en algoritmo |
| NUEVOPRECIOITEM | Definido en catálogo | Manejo especial en acumulación |
| COMBO como método de cómputo | Definido en catálogo | Lógica combinatoria aún no especificada |
| LISTA3, LISTA4... | Extensible | Agregar valores sin cambios estructurales |
| IDs externos vs internos en artículos | Pendiente | Diferenciar ids locales y externos |