Los módulos¶
El backend está dividido en módulos Spring Modulith. Cada uno tiene una API pública (lo que está en la raíz de su paquete) e internals privados. Acá: qué hace cada uno, su API pública y a quién llama. El porqué de esta estructura está en El monolito modular.
Mapa rápido¶
graph TD
TICKETS["tickets<br/>orquestador"] --> CAT["catalogo"]
TICKETS --> PAG["pagos"]
TICKETS --> PRO["promos"]
TICKETS --> ENV["envases"]
SHARED["shared<br/>(kernel OPEN)"]
MON["monitoring<br/>(Cockpit)"]
SEC["security<br/>(app-wide)"]
| Módulo | Rol | Llama a |
|---|---|---|
tickets |
Orquestador. La API que ve el POS. | catalogo, pagos, promos, envases |
catalogo |
Artículos por EAN/sucursal + búsqueda. | — (hoja) |
pagos |
intent/pay/check/cancel. Stateless. | — (hoja, sale a gateways) |
promos |
Calcula promociones del ticket. | — (hoja) |
envases |
Vales y depósitos retornables. | — (hoja) |
shared |
Kernel OPEN: lengua común. | — |
security |
Seguridad app-wide. | — |
monitoring |
Cockpit / observabilidad. | — (lee APIs públicas) |
tickets — el orquestador¶
El corazón del backend: la API que consume la terminal y la que coordina a los demás módulos para armar, calcular y cerrar un ticket.
- Servicios:
TicketService(ciclo de vida del ticket),VoucherService(generación e impresión del comprobante),EanDecodeService(decodifica el EAN escaneado),TerminalSessionService(vestigio STOMP, muerto). - Controllers:
TicketRestController(open/close/validate),PosRestController,TerminalSessionRestController,CacheRestController,EnvasesRestController,TemplateController,TestToolController. - Datos:
Trx(el ticket),PaymentAttempt,PosConfig,DeviceConfigen la baseTsAutoCompra.
Dos issues conocidos en VoucherService
- Thread-safety (plan 007): un campo de config mutable compartido entre requests puede hacer que un thread pise la config de otro mientras imprime. La solución es aislar por thread.
getFirst()sin guarda (plan 008): un.getFirst()sobre lista vacía tiraNoSuchElementExceptionopaca si falta config; conviene fallar explícito con mensaje.
catalogo — artículos¶
Resuelve artículos por EAN y sucursal, y ofrece búsqueda paginada. Read-only sobre la base TipreRetail, con cache Caffeine de ~100k artículos.
- Servicios:
ArticuloService,ArticuloCacheService. - Controller:
ArticuloRestController—GET /searchBy(porid/codigoInterno/ean/descripcion/sucursal, paginado, máx. 200 ítems por página). - Admin:
ArticuloCacheAdminController—POST /catalogo/cache/refresh(rol admin si la seguridad está activa). - Datos:
Articulo(dm_Artic),Envase(projection).
pagos — cobros¶
Maneja el ciclo de pago contra los gateways. Stateless: no persiste, sale por WebClient a MercadoPago / RouterQR.
- Servicios:
PagoService,RealPaymentProcessorService,RouterQRBuilder. - Controller:
PagoRestController—POST /payment-intent(async, devuelveMono<ResponseEntity>), pay, check-status. - Borde externo: la salida a MercadoPago es red real; ahí viven la reconciliación durable y el manejo del estado indeterminado. Ver Pagos.
promos — promociones¶
Calcula las promociones aplicables a un ticket. Hoja, con cache propia.
- Servicios:
PromoService,PromosCacheService. - Controller:
PromoController—GET /promociones,POST /promociones/update(rol admin),POST /cache/refresh(rol admin). - Datos: promociones + auditoría de cálculos en
TsPromos.
envases — vales y retornables¶
Gestiona envases retornables y los vales asociados.
- Servicios:
ValeService,EnvaseService. - Controllers:
ValeController(@RequestMapping("/vales")—GET /vales?codVale=, alta, update),EnvaseController. - Datos:
Vale(@Auditedcon Envers →Vales_AUD),EnvaseenTsEnvases.
shared — kernel OPEN¶
La lengua común que cualquier módulo puede usar sin violar fronteras: ResponseMessage (la envoltura unificada de respuestas), los enums de pago y NucleoImpositivoDto (info impositiva). No tiene lógica de negocio.
security — app-wide¶
Un único SecurityFilterChain + JwtAuthConverter. Detalle en Backend → Seguridad.
monitoring — el Cockpit¶
Observabilidad del backend y del parque de terminales. Lee las APIs públicas de los demás módulos (no sus internals) y expone /monitoring/*. Ver Cockpit.