# US-MGN-005-004-002: Reservar Stock para Pedidos

**RF Asociado:** [RF-MGN-005-003](../../02-modelado/requerimientos-funcionales/mgn-005/RF-MGN-005-003-movimientos-de-stock.md)
**Módulo:** MGN-005 - Inventario Básico
**Epic:** Stock Quants
**Prioridad:** P1
**Story Points:** 4
**Sprint:** Sprint 10
**Estado:** Ready for Development
**Fecha:** 2025-11-24

---

## User Story

**Como** sistema de ventas,
**Quiero** reservar stock en ubicaciones para pedidos confirmados,
**Para** garantizar disponibilidad y evitar sobreventa.

---

## Descripción Detallada

La reserva de stock incrementa reserved_quantity en stock_quants sin mover físicamente el producto. Esto asegura que el stock esté comprometido para un pedido específico.

Cuando se valida una entrega, la reserva se libera y el stock se mueve físicamente (quantity se decrementa).

---

## Criterios de Aceptación

### Escenario 1: Reservar stock disponible (Camino Feliz)
**Dado que** ubicación Zona A tiene product=1, quantity=10, reserved=0,
**Cuando** reservo 5 unidades,
**Entonces** el sistema actualiza reserved_quantity=5, available=5.

### Escenario 2: Error al reservar más del disponible
**Dado que** ubicación tiene quantity=10, reserved=3 (available=7),
**Cuando** intento reservar 8 unidades,
**Entonces** el sistema retorna error 400 "Stock disponible insuficiente (disponible: 7, solicitado: 8)".

### Escenario 3: Liberar reserva
**Dado que** ubicación tiene quantity=10, reserved=5,
**Cuando** libero 5 unidades de reserva,
**Entonces** el sistema actualiza reserved_quantity=0, available=10.

### Escenario 4: Reservar en múltiples ubicaciones
**Dado que** necesito reservar 15 unidades de product=1,
**Cuando** hay 10 en Zona A y 8 en Zona B,
**Entonces** el sistema reserva 10 de Zona A y 5 de Zona B.

---

## Reglas de Negocio

- **RN-1:** reserved_quantity no puede exceder quantity.
- **RN-2:** available_quantity = quantity - reserved_quantity.
- **RN-3:** Reservas se vinculan a pedidos de venta (sale_order_line_id).
- **RN-4:** Liberar reserva restaura available_quantity.
- **RN-5:** Reservas pueden distribuirse en múltiples ubicaciones.

---

## Tareas Técnicas

### Backend
- [ ] Endpoint: POST /api/v1/inventory/stock-quants/reserve
- [ ] Endpoint: POST /api/v1/inventory/stock-quants/unreserve
- [ ] Service: QuantService.reserve(productId, quantity, orderId)
- [ ] Service: QuantService.unreserve(productId, quantity, orderId)
- [ ] Service: QuantService.findAvailableLocations(productId, quantity)
- [ ] DTO: ReserveStockDto (product_id, quantity, order_id)
- [ ] Validar stock disponible
- [ ] Actualizar reserved_quantity
- [ ] Manejar reservas en múltiples ubicaciones
- [ ] Transaction para atomicidad
- [ ] Unit tests
- [ ] Integration tests
- [ ] Swagger docs

### Frontend
- [ ] Componente: ReserveStockButton.tsx
- [ ] Modal de confirmación
- [ ] API client: quantApi.reserve(data)
- [ ] Component tests
- [ ] E2E test: "should reserve stock"

### Database
- [ ] Tabla: inventory.stock_reservations (opcional - tracking de reservas)
- [ ] Transaction isolation level: READ COMMITTED
- [ ] Lock: SELECT FOR UPDATE en quants

---

## Mockups / Wireframes

**Modal Reservar Stock:**
```
┌─────────────────────────────────────────────┐
│ Reservar Stock                             │
├─────────────────────────────────────────────┤
│ Pedido: SO-00123                           │
│ Producto: Laptop HP                        │
│ Cantidad a Reservar: 15 unidades           │
│                                             │
│ Distribución Propuesta:                    │
│ ┌───────────────────────────────────────┐  │
│ │Ubicación │Disponible│Reservar        │  │
│ ├──────────┼──────────┼────────────────┤  │
│ │Zona A-P1 │    10    │  10  [✓]       │  │
│ │Zona B-P2 │     8    │   5  [✓]       │  │
│ └───────────────────────────────────────┘  │
│                                             │
│ Total Reservado: 15 / 15 ✓                 │
├─────────────────────────────────────────────┤
│ [Confirmar Reserva]  [Cancelar]           │
└─────────────────────────────────────────────┘
```

---

## Casos de Prueba

### Funcionales
1. **TC-001:** Reservar stock disponible exitosamente
2. **TC-002:** Error por stock insuficiente
3. **TC-003:** Liberar reserva exitosamente
4. **TC-004:** Reservar en múltiples ubicaciones
5. **TC-005:** Transaction rollback en caso de error
6. **TC-006:** RLS filtra por empresa

### No Funcionales
1. **Performance:** < 400ms para reservar stock
2. **Seguridad:** JWT + permiso inventory_user

---

## Dependencias

- **US bloqueantes:** US-MGN-005-004-001 (Visualizar Quants)
- **Módulos requeridos:** MGN-007 (Ventas - opcional)
- **Datos maestros:** Ninguno

---

## Notas de Implementación

- Usar SELECT FOR UPDATE para evitar condiciones de carrera
- Algoritmo de selección de ubicaciones: FIFO (primeras ubicaciones con stock)
- Considerar tabla stock_reservations para trazabilidad detallada
- Frontend: Mostrar preview de distribución antes de confirmar

---

## Estimación Detallada

| Tarea | Horas |
|-------|-------|
| Backend | 2.5 |
| Frontend | 2 |
| Testing | 1.5 |
| Code Review | 0.5 |
| **TOTAL** | **6.5 horas = 4 SP** |

---

## Definition of Done

- [ ] Código implementado según ET
- [ ] Tests pasando (>80%)
- [ ] Code review aprobado
- [ ] Documentación actualizada
- [ ] Swagger docs completo
- [ ] Transaction correctamente implementada
- [ ] RLS aplicado
- [ ] QA validado
- [ ] PO aprobado

---

## Referencias

- [RF-MGN-005-003](../../02-modelado/requerimientos-funcionales/mgn-005/RF-MGN-005-003-movimientos-de-stock.md)
- [ET Backend](../../02-modelado/especificaciones-tecnicas/backend/mgn-005/ET-BACKEND-MGN-005-003-movimientos-de-stock.md)
- [ET Frontend](../../02-modelado/especificaciones-tecnicas/frontend/mgn-005/ET-FRONTEND-MGN-005-003-movimientos-de-stock.md)
- [Traceability](../../02-modelado/trazabilidad/TRACEABILITY-MGN-005.yaml)
- [Schema](../../02-modelado/database-design/schemas/inventory-schema-ddl.sql)
