# Sistema de Reserva de Cajas - Flujo de Trabajo Completo

## 📋 Resumen del Flujo

```mermaid
graph TD
    A[Inicio] --> B[Usuario Web: Crear Reserva]
    B --> C[Seleccionar Cliente]
    C --> D[Guardar Reserva]
    D --> E{¿Cómo agregar cajas?}
    
    E -->|Opción 1| F[Descargar Inventario Completo]
    E -->|Opción 2| G[Descargar Plantilla Simple]
    
    F --> H[Marcar Cajas en Excel]
    G --> H
    
    H --> I[Subir Excel]
    I --> J[Sistema Importa Cajas]
    J --> K[Reserva Estado: PENDING]
    
    K --> L[Operario: Módulo Preparar Pedido]
    L --> M[Seleccionar Reserva]
    M --> N[Estado: IN_PROGRESS]
    
    N --> O[Escanear Caja]
    O --> P{¿Caja en reserva?}
    
    P -->|Sí| Q[Marcar como CONFIRMED]
    P -->|No| R{¿Agregar?}
    
    R -->|Sí| S[Agregar a Reserva]
    R -->|No| O
    
    Q --> T{¿Todas confirmadas?}
    S --> T
    
    T -->|No| O
    T -->|Sí| U[Completar Reserva]
    
    U --> V[Crear Orden Automáticamente]
    V --> W[Actualizar Inventario: DESPACHADO]
    W --> X[Estado: COMPLETED]
    X --> Y[Fin]
```

## 👥 Actores del Sistema

### 1. Usuario Administrativo (Web)
- Crea reservas
- Descarga inventario
- Importa cajas seleccionadas
- Cancela reservas

### 2. Operario (Preparación de Pedidos)
- Confirma reservas físicamente
- Escanea códigos de barras
- Agrega cajas adicionales
- Completa despacho

## 🔄 Flujo Detallado Paso a Paso

### FASE 1: Creación de Reserva (Web) 🖥️

#### Paso 1.1: Crear Reserva
```
URL: /reservations/create
Actor: Usuario Administrativo
Acción: 
  1. Seleccionar cliente del dropdown
  2. Agregar notas (opcional)
  3. Click "Crear Reserva"
  
Sistema:
  - Genera código único: RES-YYYYMMDD-0001
  - Estado inicial: PENDING
  - Guarda en BD: box_reservations
  
Resultado: Redirige a /reservations/{id}
```

#### Paso 1.2: Descargar Inventario
```
Opción A - Inventario Completo:
  URL: /reservations/inventory/available
  Descarga: inventario_disponible_2025-12-14.xlsx
  Contenido:
    - BOX_NUMBER (número de caja)
    - CLIENTE_ORIGINAL
    - MARCA
    - SECCION
    - FAMILIA
    - CANTIDAD
    - UBICACION
    - CONTENEDOR
    - FECHA_ENTRADA
    - SELECCIONAR (vacío - para marcar)

Opción B - Plantilla Simple:
  URL: /reservations/template/download
  Descarga: plantilla_reserva_2025-12-14.xlsx
  Contenido:
    - BOX_NUMBER
    - SELECCIONAR
```

#### Paso 1.3: Marcar Cajas en Excel
```
Actor: Usuario Administrativo
Acción:
  1. Abrir Excel descargado
  2. Revisar cajas disponibles
  3. En columna SELECCIONAR:
     - Poner "X" para cajas deseadas
     - O poner "1" 
     - O poner "SI"
  4. Guardar archivo
  
Ejemplo:
  BOX_NUMBER | MARCA | SELECCIONAR
  CAJA001    | ZARA  | X
  CAJA002    | ZARA  | 
  CAJA003    | ZARA  | 1
  CAJA004    | ZARA  | X
```

#### Paso 1.4: Importar Cajas
```
URL: /reservations/{id}/import
Actor: Usuario Administrativo
Acción:
  1. Click "Importar Cajas"
  2. Seleccionar archivo Excel
  3. Click "Importar"
  
Sistema:
  1. Lee Excel fila por fila
  2. Busca cajas marcadas (SELECCIONAR = X o 1)
  3. Valida que cajas existan y estén disponibles
  4. Para cada caja válida:
     - Crea box_reservation_items
     - Actualiza inventory:
       * reservation_status = 'reserved'
       * reserved_for_client_id = {client_id}
       * reservation_id = {reservation_id}
  5. Retorna estadísticas:
     - Cajas importadas: 15
     - Cajas no encontradas: 2
     
Estado BD:
  box_reservations:
    - status = 'pending'
    - total cajas = 15
    
  box_reservation_items:
    - 15 registros con status = 'reserved'
    
  inventory:
    - 15 cajas con reservation_status = 'reserved'
```

### FASE 2: Confirmación Física (Operario) 📦

#### Paso 2.1: Acceder a Reservas
```
URL: /order-preparation
Actor: Operario
Acción:
  1. Navegar a módulo "Preparar Pedido"
  2. Click en pestaña "Reservas"
  3. Ver lista de reservas pendientes
  
Sistema muestra:
  - Código de reserva
  - Cliente
  - Total de cajas
  - Cajas confirmadas / pendientes
  - Progreso %
```

#### Paso 2.2: Iniciar Confirmación
```
API: POST /api/order-preparation/start-box-reservation
Actor: Operario
Acción:
  1. Seleccionar reserva de la lista
  2. Click "Iniciar Confirmación"
  
Request:
  {
    "reservation_id": 1
  }

Sistema:
  1. Actualiza estado: IN_PROGRESS
  2. Carga lista de cajas reservadas
  3. Muestra interfaz de escaneo
  
Response:
  {
    "reservation": {
      "id": 1,
      "reservation_code": "RES-20251214-0001",
      "client_name": "Cliente ABC",
      "status": "in_progress"
    },
    "boxes": [
      {
        "box_number": "CAJA001",
        "status": "reserved",
        "marca": "ZARA",
        "ubicacion": "A-01-05"
      },
      ...
    ],
    "stats": {
      "total": 15,
      "confirmed": 0,
      "pending": 15
    }
  }
```

#### Paso 2.3: Escanear Cajas
```
API: POST /api/order-preparation/confirm-box-scan
Actor: Operario
Acción:
  1. Escanear código de barras de caja
  2. Sistema valida automáticamente
  
Request:
  {
    "reservation_id": 1,
    "box_number": "CAJA001"
  }

Escenario A - Caja está en reserva:
  Sistema:
    1. Busca en box_reservation_items
    2. Actualiza status = 'confirmed'
    3. Actualiza scanned_at = now()
    4. Actualiza inventory.reservation_status = 'confirmed'
    
  Response:
    {
      "status": "confirmed",
      "message": "Caja confirmada correctamente",
      "is_from_reservation": true,
      "stats": {
        "total": 15,
        "confirmed": 1,
        "pending": 14
      }
    }
  
  UI: ✅ Marca caja como confirmada en verde

Escenario B - Caja NO está en reserva:
  Sistema:
    1. Busca en inventory
    2. Verifica que esté disponible
    
  Response:
    {
      "status": "not_in_reservation",
      "message": "¿Desea agregar esta caja a la reserva?",
      "box": {
        "n_carton": "CAJA999",
        "marca": "ZARA",
        "ubicacion": "B-02-10"
      },
      "is_from_reservation": false
    }
  
  UI: ⚠️ Muestra diálogo de confirmación
```

#### Paso 2.4: Agregar Caja Extra
```
API: POST /api/order-preparation/add-extra-box
Actor: Operario
Acción:
  1. Confirmar agregar caja no reservada
  2. Click "Sí, agregar"
  
Request:
  {
    "reservation_id": 1,
    "box_number": "CAJA999"
  }

Sistema:
  1. Crea nuevo box_reservation_items:
     - status = 'confirmed'
     - scanned_at = now()
     - notes = 'Agregada por operario'
  2. Actualiza inventory:
     - reservation_status = 'confirmed'
     - reserved_for_client_id = {client_id}
     - reservation_id = {reservation_id}
  
Response:
  {
    "status": "added",
    "message": "Caja agregada a la reserva",
    "stats": {
      "total": 16,  // Incrementó
      "confirmed": 2,
      "pending": 14
    }
  }

Caso de Uso: 
  "El operario ve que hay un pallet completo,
   agrega las cajas restantes del pallet aunque
   no estaban en la reserva original"
```

#### Paso 2.5: Completar Reserva
```
API: POST /api/order-preparation/complete-box-reservation
Actor: Operario
Acción:
  1. Confirmar todas las cajas escaneadas
  2. Click "Completar Reserva"
  
Request:
  {
    "reservation_id": 1
  }

Validación:
  - Al menos 1 caja confirmada
  
Sistema:
  1. Genera número de orden: ORD-20251214-0001
  
  2. Crea orden (orders):
     - client_id = {client_id}
     - order_number = ORD-20251214-0001
     - status = 'dispatched'
     - notes = "Creado desde reserva RES-20251214-0001"
     - dispatched_at = now()
  
  3. Para cada caja confirmada:
     a) Crea order_items:
        - order_id = {order_id}
        - inventory_id = {inventory_id}
        - box_number = {box_number}
        - quantity = {quantity}
     
     b) Actualiza inventory:
        - estado = 'Despachado'
        - client_id = {client_id}
        - order_id = {order_id}
     
     c) Crea audit_log:
        - action = 'dispatched'
        - description = "Despachado en orden..."
  
  4. Actualiza box_reservations:
     - status = 'completed'
     - confirmed_by_user_id = {user_id}
     - confirmed_at = now()

Response:
  {
    "status": "completed",
    "message": "Reserva completada. Orden ORD-20251214-0001 creada con 16 cajas",
    "order": {
      "id": 123,
      "order_number": "ORD-20251214-0001",
      "client_name": "Cliente ABC",
      "total_boxes": 16
    }
  }

UI: 
  ✅ Muestra mensaje de éxito
  🎉 Redirige a orden creada
```

## 📊 Estados del Sistema

### Estados de Reserva (box_reservations.status)

| Estado | Descripción | Puede Transicionar a |
|--------|-------------|---------------------|
| `pending` | Reserva creada, esperando confirmación | `in_progress`, `cancelled` |
| `in_progress` | Operario comenzó a confirmar | `completed`, `cancelled` |
| `completed` | Todas las cajas confirmadas, orden creada | - |
| `cancelled` | Reserva cancelada | - |

### Estados de Item (box_reservation_items.status)

| Estado | Descripción | Color Badge |
|--------|-------------|-------------|
| `reserved` | Reservado virtualmente | 🟡 Amarillo |
| `confirmed` | Confirmado físicamente | 🟢 Verde |
| `cancelled` | Cancelado | 🔴 Rojo |

### Estados de Inventario (inventory.reservation_status)

| Estado | Descripción | Disponible para |
|--------|-------------|-----------------|
| `available` | Disponible para reservar | Nueva reserva |
| `reserved` | Reservado virtualmente | Solo confirmación de su reserva |
| `confirmed` | Confirmado físicamente | Despacho inmediato |

## 🔄 Transiciones de Estado

```mermaid
stateDiagram-v2
    [*] --> available: Caja en inventario
    
    available --> reserved: Importar Excel
    reserved --> available: Cancelar reserva
    reserved --> confirmed: Escanear caja
    
    confirmed --> Despachado: Completar reserva
    Despachado --> [*]
    
    note right of reserved
        Estado virtual
        No se movió físicamente
    end note
    
    note right of confirmed
        Escaneada físicamente
        Lista para despacho
    end note
```

## ⚠️ Casos Especiales

### Caso 1: Cancelar Reserva
```
Actor: Usuario Administrativo
Acción: Click "Cancelar Reserva"

Sistema:
  1. Actualiza box_reservations.status = 'cancelled'
  2. Actualiza todos box_reservation_items.status = 'cancelled'
  3. Libera inventario:
     - reservation_status = 'available'
     - reserved_for_client_id = NULL
     - reservation_id = NULL

Resultado: Cajas vuelven a estar disponibles
```

### Caso 2: Eliminar Caja de Reserva
```
Actor: Usuario Administrativo
Acción: Click "Eliminar" en caja específica

Sistema:
  1. Elimina box_reservation_items
  2. Libera esa caja en inventory:
     - reservation_status = 'available'
     - reserved_for_client_id = NULL
     - reservation_id = NULL

Resultado: Caja disponible, otras siguen reservadas
```

### Caso 3: Caja Ya Confirmada
```
Actor: Operario
Acción: Escanear caja que ya fue escaneada

Sistema:
  Response:
    {
      "status": "already_confirmed",
      "message": "Esta caja ya fue confirmada anteriormente"
    }

UI: ℹ️ Muestra mensaje informativo, no error
```

## 📈 Métricas y Reportes

### Progreso de Reserva
```
Fórmula: (cajas_confirmadas / total_cajas) * 100

Ejemplo:
  Total: 15 cajas
  Confirmadas: 10 cajas
  Progreso: 66.67%
  
  UI: Barra de progreso azul hasta 100%
      Barra verde cuando = 100%
```

### Estadísticas Disponibles
```sql
-- Reservas por estado
SELECT status, COUNT(*) 
FROM box_reservations 
GROUP BY status;

-- Cajas más reservadas
SELECT i.n_carton, COUNT(*) as veces_reservada
FROM box_reservation_items bri
JOIN inventory i ON bri.inventory_id = i.id
GROUP BY i.n_carton
ORDER BY veces_reservada DESC;

-- Tiempo promedio de confirmación
SELECT AVG(TIMESTAMPDIFF(SECOND, reserved_at, confirmed_at)) as avg_seconds
FROM box_reservations
WHERE status = 'completed';
```

## 🎯 Puntos Clave

1. **Reserva Virtual**: Las cajas se marcan en BD pero NO se mueven físicamente
2. **Confirmación Física**: El operario DEBE escanear cada caja
3. **Flexibilidad**: Permite agregar cajas extra durante confirmación
4. **Trazabilidad**: Registro completo de quién reservó y quién confirmó
5. **Automatización**: Orden se crea automáticamente al completar
6. **Reversible**: Se puede cancelar antes de confirmar

## 📱 Interfaces de Usuario

### Web (Usuario Admin)
- `/reservations` - Lista de reservas
- `/reservations/create` - Crear nueva
- `/reservations/{id}` - Ver detalle e importar

### Módulo Operario
- `/order-preparation` - Pestaña "Reservas"
- Interfaz de escaneo en tiempo real
- Confirmación visual de cada caja

## 🔐 Permisos Requeridos

| Acción | Permiso |
|--------|---------|
| Ver reservas | `reservations.view` |
| Crear reserva | `reservations.create` |
| Importar cajas | `reservations.import` |
| Cancelar reserva | `reservations.cancel` |
| Confirmar físicamente | `order-preparation.view` |
| Completar reserva | `order-preparation.dispatch` |
