Skip to content

Modulo Convenio

Jose Navarro edited this page Aug 12, 2026 · 1 revision

Módulo convenio

Contratos administrativos (compra/venta/intercambio/servicio) con proveedor y/o bodega opcionales. No tiene ningún efecto sobre inventario — confirmado por grep, cero referencias a Inventario en todo el paquete. El campo tipo es puramente descriptivo.

Endpoints

Todo el path /api/convenios/** exige ROLE_ADMIN.

Método Path Request Response
GET /api/convenios query: estado, tipo, nombre RespuestaPagina<RespuestaConvenio>
GET /api/convenios/{id} RespuestaConvenio
POST /api/convenios CuerpoConvenio RespuestaConvenio (201)
PUT /api/convenios/{id} CuerpoConvenio RespuestaConvenio
PATCH /api/convenios/{id}/estado ?valor=EstadoConvenio RespuestaConvenio

CuerpoConvenio: nombre, tipo(TipoConvenio), proveedorId?, bodegaId?, fechaInicio, fechaFin?, valorTotal, responsable, descripcion.

Flujo de negocio

flowchart TD
    POST["POST /api/convenios"] --> CODE["codigo = CNV-%06d (secuencia SQL)"]
    CODE --> APLICAR["aplicarCuerpo()"]
    APLICAR --> FECHAS{"fechaFin < fechaInicio?"}
    FECHAS -->|"sí"| E1["FechasConvenioInvalidasException (400)"]
    FECHAS -->|"no"| PROV{"proveedorId presente?"}
    PROV -->|"sí, no existe"| E2["ProveedorNoEncontradoException (404)"]
    PROV -->|"sí existe / no viene"| BOD{"bodegaId presente?"}
    BOD -->|"sí, no existe"| E3["BodegaNoEncontradaException (404)"]
    BOD -->|"sí existe / no viene"| SETALL["setea resto de campos directo,\nincluyendo valorTotal (sin cálculo)"]
    SETALL --> SAVE["convenioRepository.save()\nestado default = ACTIVO"]
    SAVE --> ISLA["FIN — sin ninguna llamada a InventarioService,\nsin importar tipo=COMPRA/VENTA/INTERCAMBIO/SERVICIO"]

    PUT["PUT /api/convenios/{id}"] --> APLICAR

    ESTADO["PATCH /{id}/estado"] --> FREE["set directo, SIN validar transición\n(ACTIVO/INACTIVO/VENCIDO/SUSPENDIDO,\ncualquier valor aceptado)"]

    style ISLA fill:#f4d4d4
    style FREE fill:#fde9c8
Loading

Secuencia HTTP: crear convenio

sequenceDiagram
    participant C as Cliente (ADMIN)
    participant CC as ConvenioController
    participant CS as ConvenioServiceImpl
    participant PR as ProveedorRepository
    participant BR as BodegaRepository
    participant CR as ConvenioRepository

    C->>CC: POST /api/convenios {nombre, tipo=VENTA, proveedorId?, bodegaId?, valorTotal}
    CC->>CS: crear(cuerpo)
    CS->>CR: siguienteConsecutivo() → codigo "CNV-000017"
    CS->>CS: aplicarCuerpo(): valida fechas
    opt proveedorId presente
        CS->>PR: findById(proveedorId)
    end
    opt bodegaId presente
        CS->>BR: findById(bodegaId)
    end
    CS->>CR: save(convenio, estado=ACTIVO)
    CR-->>CS: Convenio persistido
    CS-->>CC: RespuestaConvenio
    CC-->>C: 201
    Note over CS: Ningún paso llama a InventarioService,<br/>independientemente de "tipo".
Loading

Notas

  • TipoConvenio (COMPRA, VENTA, INTERCAMBIO, SERVICIO) y EstadoConvenio (ACTIVO, INACTIVO, VENCIDO, SUSPENDIDO) no disparan ninguna lógica condicional en el código actual — son metadatos de negocio para reportes/consulta manual, no automatización.
  • Si el negocio espera que un convenio de tipo VENTA descuente stock, ese comportamiento no existe hoy en el backend — sería una brecha real a cerrar, no un bug de UI.

Clone this wiki locally