Skip to main content

High Level Design (HLD) - Employee Revenue Microservice

1. Resumen Ejecutivo

Propósito del microservicio

El microservicio alpura-back-msa-transactions (identificado como módulo de Arquitectura Base ex en pom.xml) tiene como propósito principal la gestión y consulta de saldos y redención de productos para empleados. Actúa como el backend transaccional que permite visualizar el balance disponible de beneficios (productos) y ejecutar el canje de los mismos en tiendas.

Funcionalidad principal

  • Consulta de Saldo: Permite obtener el balance detallado de productos disponibles para un empleado, buscando por su número de nómina.
  • Redención de Productos: Procesa transacciones de canje, validando disponibilidad de saldo, descontando inventario virtual del empleado y registrando la transacción para auditoría.
  • Sincronización de Eventos: Publica eventos de negocio (Tickets) hacia el ecosistema (Pub/Sub) para notificar creaciones de trabajos/procesos.

Tipo de consumidores

  • Frontends: Aplicaciones Web o Móviles (App de Empleados) que consumen la API REST.
  • Sistemas Internos: Otros microservicios o sistemas legacy que requieran verificar disponibilidad de beneficios.

Rol en la arquitectura

Pertenece al Dominio de Empleados / Beneficios. Es un servicio "Core" de negocio que orquesta la lógica transaccional de los beneficios de productos, aislando la complejidad del cálculo de saldos y manteniendo la integridad de las transacciones de canje.


2. Contexto Arquitectónico

Descripción del Ecosistema

El servicio reside en un entorno de microservicios Spring Boot, desplegado probablemente en contenedores (referencia a Dockerfile). Interactúa con una infraestructura de nube (Pub/Sub y Artifact Registry).

Relaciones

  • Bases de Datos:
    • Primaria (PostgreSQL): Almacena la información transaccional de ingresos de empleados (EmployeeRevenue), transacciones de redención (RedemptionTransaction) y catálogos (Category).
  • Brokers / Mensajería:
    • Google Cloud Pub/Sub: Publica eventos en el topic uat.sienpro.sync.tickets configurado vía properties.
  • Librerías Internas:
    • Depende fuertemente de librerías com.alpura para modelos (model-ex, model-sienpro), utilidades (common-utilities) y auditoría (common-telemetry).

Responsabilidades (Bounded Context)

El contexto delimitado de este servicio es "Gestión de Saldo de Beneficios de Empleados".

  • IN: Gestión del saldo, reglas de redención, histórico de transacciones.
  • OUT: Gestión de usuarios (Identity), Catálogo maestro de productos (solo lectura), Nómina general.

3. Arquitectura de Alto Nivel (HLD)

Diagrama de Arquitectura

Componentes Principales

  • Controller: EmployeeController (API REST).
  • Facade: EmployeeRevenueImpl (Orquestación simple y delegación).
  • Service: EmployeeRevenueServiceImpl (Lógica de negocio core: validación de saldos, transaccionalidad, lógica JSON).
  • Persistence: Repositorios JPA (IEmployeeRevenueRepository, etc.) interactuando con entidades externas.
  • Listener: JobEventListener para manejo de eventos transaccionales (JobCreatedEventVO).

Patrones

  • Layered Architecture: Controller -> Facade -> Service -> Repository.
  • Transactional Script: Lógica de negocio procedural dentro del Servicio.
  • DTO/VO Pattern: Uso extensivo de VOs (RedeemRequestVO, BalanceResponseVO) para desacoplar la API del modelo de dominio.
  • JSON Column: Uso de columnas JSON en BD para almacenar estructuras dinámicas de saldo (Flexibilidad vs Normalización).

4. Contrato de API y Endpoints

1. Consultar Saldo de Empleado

  • Método: GET
  • Path: /api/v1/employees/{payrollNumber}/balance
  • Descripción: Obtiene el saldo disponible de productos para un empleado.

Response (202 Accepted): SingleResponseVO<BalanceResponseVO>

{
"success": true,
"data": {
"payrollNumber": 12345,
"employeeName": "Juan Perez",
"products": [
{
"code": "PROD01",
"productName": "Leche Entera",
"quantity": 5
}
],
"photo": "/9j/4AAQSk..."
},
"errors": []
}

2. Redimir Productos

  • Método: POST
  • Path: /api/v1/employees/{payrollNumber}/redeem
  • Descripción: Ejecuta el canje de productos. Valida saldo y descuenta inventario.

Request Body: RedeemRequestVO

{
"storeId": "99",
"productsToRedeem": {
"PROD01": 2,
"PROD02": 1
}
}

Response (202 Accepted): SingleResponseVO<RedeemResponseVO>

{
"success": true,
"data": {
"message": "Redención exitosa",
"payrollNumber": 12345,
"newBalance": {
"PROD01": 3,
"PROD02": 5
}
}
}

5. Flujos Funcionales

Flujo: Redención de Productos

Este es el flujo crítico del negocio que garantiza la consistencia del saldo.


6. Integraciones Técnicas

Bases de Datos

  • Motor: PostgreSQL (según PrimaryDataConfig y dialect).
  • ORM: Hibernate / Spring Data JPA.
  • Configuración:
    • hbm2ddl.auto = none (Esquema debe existir previamente).
    • Datos almacenados en columnas tipo JSON (manipulados via Jackson JsonNode).

Mensajería (Pub/Sub)

  • Provider: Google Cloud Pub/Sub.
  • Topic: projects/alpura-hub-uat/topics/uat.sienpro.sync.tickets (Hardcoded en JobEventListener, aunque existe código comentado para leer de properties).
  • Evento: JobCreatedEventVO -> Se publica tras el commit de una transacción (TransactionPhase.AFTER_COMMIT).

7. Seguridad

  • Mecanismos:
    • El código analizado no contiene configuración explícita de Spring Security (filtros, roles, JWT decoder).
    • Sin embargo, ExApplication realiza un @ComponentScan({"com.alpura.security.*"}). Esto indica que la seguridad es provista por una librería compartida (alpura-lib u similar) que autoconfigura la seguridad.
    • Suposición: Se asume seguridad vía Token OAuth2/JWT estándar en la organización, inyectada por la librería común.

8. Observabilidad

  • Telemetría:
    • Uso de anotación propia @IAuditable en métodos de negocio (EmployeeRevenueServiceImpl), lo que sugiere un aspecto (AOP) que intercepta y registra auditoría.
    • Dependencia back-java-lib-common-telemetry.
  • Métricas:
    • Dependencia micrometer-registry-prometheus presente en pom.xml, habilitando endpoint para scraping de Prometheus.
    • Actuator presente (spring-boot-starter-actuator).

9. Modelo de Datos (ERD)

Diccionario de Datos

EntidadTabla (est.)ColumnaTipo JavaTipo SQL (est.)Descripción
EmployeeRevenueDOemployee_revenuepayroll_numberLongBIGINTLlave primaria. Número de nómina.
totalJsonNodeJSONBObjeto JSON con saldo: {"PROD1": 10, "PROD2": 5}
RedemptionTransactionDOredemption_transactionidLongBIGINTID autogenerado.
payroll_numberLongBIGINTReferencia al empleado.
balance_beforeJsonNodeJSONBSnapshot saldo antes.
balance_afterJsonNodeJSONBSnapshot saldo después.
redeemed_amountJsonNodeJSONBCantidad redimida.

10. Consideraciones No Funcionales

  • Concurrencia: El método redeemProducts recupera el registro, valida en memoria y guarda. Riesgo: Si no existe un bloqueo pesimista en base de datos (@Lock(LockModeType.PESSIMISTIC_WRITE)) o optimista (@Version), existe riesgo de condición de carrera (lost update) si dos redenciones ocurren simultáneamente. El repositorio tiene imports de LockModeType, pero no se observó la anotación @Lock en el método findByPayrollNumber usado en el service (solo estaba definido en la interfaz sin anotación visible en el snippet mostrado, aunque se vió el import).
  • Performance:
    • El uso de columnas JSON evita joins complejos para obtener el saldo completo.
    • Data Sources: Configuración de Primary y Secondary data sources sugiere separación de carga o conexión a múltiples esquemas.
  • Mantenibilidad:
    • Alta dependencia de librerías internas (com.alpura.*). Esto estandariza pero acopla el ciclo de vida del servicio a las librerías base.

11. Estructura del Proyecto

src/main/java/com/alpura/java/arch
├── ExApplication.java # Main Entry Point
├── common
│ ├── listener # Event Listeners (Pub/Sub)
│ └── vo # Value Objects (DTOs)
├── config
│ └── database # Configuración de Datasources (Primary/Secondary)
├── facade # Capa intermedia (Interface + Impl)
├── persistence # Repositorios JPA
├── service # Lógica de Negocio (Interface + Impl)
└── web # Controllers REST