# 03 — Sesiones de caja y configuración

Dos pantallas distintas, para dos perfiles distintos:

- **Mis Cajas** (`/caja/sesiones`) — el cajero: abrir turno, operar, cerrar turno.
- **Gestionar Cajas** (`/caja/configuracion`) — el administrador: crear cajas y asignarles
  usuarios, correlativos y métodos de pago.

## Modelo de sesiones (dos niveles)

```mermaid
erDiagram
    Caja ||--o{ CajaSesion : "tiene"
    CajaSesion ||--o{ CajaSesionUsuario : "contiene turnos"
    Caja ||--o{ CajaUsuario : "usuarios autorizados"
    Caja ||--o{ CajaCorrelativo : "correlativos asignados"
    Caja ||--o{ CajaBanco : "métodos de pago"
    CajaSesion ||--o{ Factura : "cajaSesionId"
```

- **CajaSesion**: la caja física está abierta. Se crea con la primera apertura de usuario
  y se cierra **automáticamente** cuando se cierra el último turno abierto.
- **CajaSesionUsuario**: el turno de una persona. Un usuario no puede tener dos turnos
  abiertos en la misma caja.
- Las facturas se guardan contra `CajaSesionId` (la sesión de la caja, no la del usuario).

## Mis Cajas — flujo del cajero

```mermaid
flowchart TD
    A([Entrar a /caja/sesiones]) --> B[GET /caja/usuario/:codigoUsr]
    B --> C[Por cada caja: GET sesion-usuario-activa/:codigoUsr]
    C --> D{Tiene turno abierto}
    D -->|No| E[Tarjeta gris: Cerrada<br/>botón Abrir Sesión]
    E --> F[Modal: monto de apertura en efectivo]
    F --> G[POST /caja/sesiones/usuario/apertura]
    G --> H[Tarjeta verde: Abierta<br/>muestra fecha y monto de apertura]
    D -->|Sí| H
    H --> I[Botón Abrir Caja]
    H --> J[Menú ⋮ → Cerrar Sesión]
    I --> K{esCajaEmpresarial}
    K -->|false| L["/caja/rapida/:codigo"]
    K -->|true| M["/ventas/facturas/nueva"]
    J --> N[Modal de cierre]
    N --> O[POST /caja/sesiones/usuario/cierre]
    O --> E
```

**Estado vacío**: si el usuario no tiene cajas asignadas ve un `NEmpty` con el texto
"Contacta al administrador para que te asigne acceso a una caja". Buen detalle.

**Coste de la carga**: `cargarMisCajas()` hace **1 + N peticiones secuenciales** (un
`await` dentro del `for`). Con 8 cajas asignadas son 9 viajes en serie. Ver hallazgo UX-09.

### Validaciones del backend al abrir turno

1. La caja existe y está activa
2. El usuario está en `CajaUsuario` (asignado a esa caja)
3. Si no hay `CajaSesion` abierta, se crea; si la hay, se reutiliza
4. El usuario no tiene ya un turno abierto en esa caja

### Cierre de turno

El modal pide **siete valores, todos escritos a mano** y todos inicializados en 0:

| Campo | ¿Lo calcula el sistema? |
|---|---|
| Monto de cierre (efectivo contado) | No — lo cuenta el cajero (correcto) |
| Total ventas | **No** — debería salir de las facturas del turno |
| Total efectivo | **No** — está en `FacturaPagos` |
| Total tarjeta | **No** — ídem |
| Total transferencia | **No** — ídem |
| Total otros | **No** — ídem |
| Motivo de cierre | Texto libre opcional |

No hay comparación esperado vs. contado, ni cálculo de descuadre. Ver hallazgo UX-08.

```mermaid
flowchart LR
    A[Cerrar turno] --> B[POST /caja/sesiones/usuario/cierre]
    B --> C[CajaSesionUsuario.Estado = Cerrado]
    C --> D{Quedan turnos abiertos<br/>en esta CajaSesion}
    D -->|Sí| E[La caja sigue Abierta]
    D -->|No| F[CajaSesion.Estado = Cerrado]
```

## Gestionar Cajas — flujo del administrador

`/caja/configuracion` lista las cajas con filtros y columnas configurables.
`CajaForm.vue` (963 líneas) trabaja en tres modos según la ruta: **nuevo**, **detalle
(solo lectura)** y **editar**.

```mermaid
flowchart TD
    A[Nueva caja] --> B[Datos generales:<br/>sucursal · nombre · flags · activo]
    B --> C[Guardar → POST /caja]
    C --> D[Ya existe codigoCaj]
    D --> E[Asignar métodos de pago<br/>PUT /caja/:cod/bancos]
    D --> F[Asignar correlativos<br/>PUT /caja/:cod/correlativos]
    D --> G[Asignar usuarios<br/>PUT /caja/:cod/usuarios]
```

### Los tres flags de comportamiento

| Flag | Significado pretendido | ¿Se aplica? |
|---|---|---|
| `esCajaEmpresarial` | Decide a qué pantalla entra el cajero | ✅ Sí (`MisCajasIndex:abrirCaja`) |
| `requiereAperturaParaFacturar` | Exigir turno abierto para facturar | ❌ **Se guarda pero nunca se consulta** |
| `requiereAperturaParaCobrar` | Exigir turno abierto para cobrar | ❌ **Se guarda pero nunca se consulta** |
| `permitirFacturarSinTurno` | Permitir facturar sin turno propio | ❌ **Se guarda pero nunca se consulta** |

Confirmado con búsqueda en todo el backend: los tres solo aparecen en el CRUD de `Caja`.
Ver hallazgo UX-10.

Sí hay una protección de coherencia: **no se pueden modificar esos flags ni la sucursal
mientras la caja tenga una sesión abierta** (`CajaRepository:262-267`).

### Asignación de relaciones

Cada bloque (métodos de pago, correlativos, usuarios) funciona igual: un modal de búsqueda
paginado (`MetodoPagoSearchModal`, `CorrelativoSearchModal`, `UsuarioSearchModal`) con
selección múltiple, y una tabla debajo con lo asignado. Los correlativos además pueden
activarse/desactivarse individualmente (`toggleCorrelativoActivo`).

> Las tres asignaciones se persisten con **PUT independientes** después de guardar la caja.
> Si uno de los tres falla, la caja queda guardada con asignaciones parciales.
