Backend AutoCompraMod¶
Referencia técnica del backend: stack, layout, build, datos y seguridad. Para el porqué del diseño, mirá El monolito modular; acá están los datos exactos.
Stack¶
| Pieza | Versión / valor |
|---|---|
| Lenguaje | Java 21 (enforcer fuerza [21,22)) |
| Framework | Spring Boot 3.4.0 |
| Modularidad | Spring Modulith 1.3.0 |
| Persistencia | Spring Data JPA / Hibernate, SQL Server (mssql-jdbc) |
| Auditoría | Hibernate Envers (entidad Vale) |
| Cache | Caffeine (catálogo ~100k) |
| Async externo | Spring WebFlux WebClient + Reactor Netty (gateways de pago) |
| Seguridad | OAuth2 Resource Server (JWT / Keycloak) |
| QR | ZXing |
| Voucher / impresión | escpos-coffee (ESC/POS) + OpenPDF (reemplazó iText 5 AGPL) |
| Frontend Cockpit | React 18 + Vite + TypeScript (build vía frontend-maven-plugin) |
| Context-path | /autocompras/v1 |
Layout de paquetes¶
com.tipre.autocompras
├── tickets/ orquestador (API del POS)
├── catalogo/ artículos por EAN/sucursal
├── pagos/ intent/pay/check/cancel (stateless)
├── promos/ cálculo de promociones
├── envases/ vales y depósitos retornables
├── shared/ kernel OPEN (ResponseMessage, enums, NucleoImpositivoDto)
├── security/ SecurityConfig + JwtAuthConverter (app-wide)
└── monitoring/ Cockpit (observabilidad)
Cada módulo se declara con un package-info.java anotado @ApplicationModule (shared es type = OPEN). El detalle de roles y reglas está en Los módulos.
Datos: schema-por-módulo¶
No hay una base única: cada módulo con persistencia define su propio DataSource (hbm2ddl.auto=none — el schema no lo maneja la app). Cero foreign keys cruzadas entre módulos.
| Módulo | Config | Base | Notas |
|---|---|---|---|
tickets |
TicketsDataSourceConfig (@Primary) |
TsAutoCompra (SQL Server) |
Entidades Trx, PaymentAttempt, PosConfig, DeviceConfig. |
catalogo |
CatalogoDataSourceConfig |
TipreRetail |
Read-only, cache Caffeine ~100k. |
promos |
PromosDataSourceConfig |
TsPromos |
Promos + auditoría de cálculos. |
envases |
EnvasesDataSourceConfig |
TsEnvases |
Vale (@Audited, Envers → tablas _AUD), Envase. |
pagos |
— | — | Stateless: no persiste, usa WebClient a gateways. |
monitoring |
MonitoringDataSourceConfig |
DB de observabilidad separada | ErrorEvent, retención 30 días. |
Entidades principales¶
Trx(tickets) — el ticket persistido. Estados:OPEN,PAGADO,VOUCHERPENDING,CLOSE,CANCELED_USER,CANCELED_INACTIVITY,ERROR.Articulo(catalogo) —@Table(name = "dm_Artic"). Campos:cEan,cDescripcion,fPrecio,iTax,bPeso,bEnvase,iNroSuc, etc.Vale(envases) —@Entity @Audited. Campos:nroVale,codVale,nroSucursal,fechaCreacion,fechaVto,terminalOrigen, estado. GeneraVales_AUD.Envase(envases) —ean,plu,descripcion,nroSucursal,imagen(@Lob),habilitado,orden.
Seguridad¶
App-wide: un único SecurityFilterChain y JwtAuthConverter en el paquete security (SecurityConfig.java).
| Propiedad | Default | Efecto |
|---|---|---|
app.security.enabled |
false |
false → anyRequest().permitAll(). true → política de roles (resource server JWT/Keycloak). |
app.security.admin-role |
ADMIN |
Rol exigido en mutaciones admin (espera authority ROLE_<admin-role>). |
Con seguridad activa:
permitAll:/actuator/health,/actuator/info,/*/dummy, swagger.hasRole(adminRole):POST /promociones/update,POST /cache/refresh,POST /catalogo/cache/refresh.authenticated(): el resto (incluido el runtime del POS, para no romper el checkout).
Toggle en false = todo abierto
Con app.security.enabled=false todos los endpoints quedan permitAll, incluidas las mutaciones admin. Es sólo para dev / parallel-run; se loguea un WARN al armar el filter chain. En producción con Keycloak: enabled=true y admin-role al rol real del realm.
Build y guardrail¶
# Build + verificación de boundaries de módulos. Requiere JDK 21.
mvn test
# Levantar (con los DataSource configurados)
mvn spring-boot:run
ModularityTestscorreApplicationModules.of(...).verify()y rompe el build si se viola una frontera o aparece un ciclo. Ver El monolito modular.- CI: GitHub Actions corre
mvn testcon JDK 21 en cada push/PR (~411 tests; 22 deshabilitados por requerir infra de DB). - Cockpit: el profile
frontendde Maven instala Node local (frontend-maven-plugin), correnpm ci && npm run buildy copiadist/asrc/main/resources/static/cockpit, servido por Spring como SPA.
Por dónde seguir¶
- Los módulos — qué hace cada uno y su API pública.
- API REST — endpoints concretos.
- Cockpit — el panel de operación y
/monitoring/*.