# US-MGN-005-002-001: Gestionar Almacenes y Ubicaciones

**RF Asociado:** [RF-MGN-005-002](../../02-modelado/requerimientos-funcionales/mgn-005/RF-MGN-005-002-gestión-de-almacenes-y-ubicaciones.md)
**Módulo:** MGN-005 - Inventario Básico
**Epic:** Almacenes y Ubicaciones
**Prioridad:** P0
**Story Points:** 5
**Sprint:** Sprint 9
**Estado:** Ready for Development
**Fecha:** 2025-11-24

---

## User Story

**Como** usuario de inventario,
**Quiero** crear almacenes con ubicaciones jerárquicas (zona → pasillo → anaquel),
**Para** organizar el stock físicamente y facilitar la gestión de inventario.

---

## Descripción Detallada

Los almacenes representan instalaciones físicas donde se almacenan productos. Cada almacén puede tener ubicaciones jerárquicas organizadas en niveles:
- **Almacén:** Edificio o instalación principal
- **Zona:** Área dentro del almacén (ej: Zona A, Zona B)
- **Pasillo:** Pasillo dentro de una zona (ej: Pasillo 1, Pasillo 2)
- **Anaquel:** Estante específico (ej: Anaquel A1, A2)

Las ubicaciones usan parent_id para crear jerarquía. El stock se registra a nivel de ubicación más específica (quant por ubicación).

---

## Criterios de Aceptación

### Escenario 1: Crear almacén principal (Camino Feliz)
**Dado que** soy usuario con permiso inventory_user,
**Cuando** creo un almacén con name="Almacén Central", code="WH-01", address="Calle 123",
**Entonces** el sistema crea el almacén exitosamente y genera ubicaciones por defecto (Stock, Input, Output).

### Escenario 2: Crear ubicaciones jerárquicas
**Dado que** tengo un almacén "WH-01",
**Cuando** creo ubicación "Zona A" (parent=WH-01), luego "Pasillo 1" (parent=Zona A), luego "Anaquel A1" (parent=Pasillo 1),
**Entonces** el sistema crea jerarquía de 3 niveles correctamente.

### Escenario 3: Visualizar árbol de ubicaciones
**Dado que** un almacén tiene ubicaciones jerárquicas,
**Cuando** consulto el almacén,
**Entonces** el sistema retorna estructura de árbol con todas las ubicaciones anidadas.

### Escenario 4: Validar código único de almacén
**Dado que** ya existe almacén con code="WH-01",
**Cuando** intento crear otro con el mismo código,
**Entonces** el sistema retorna error 400 "El código WH-01 ya está en uso".

### Escenario 5: Validar ubicación pertenece a almacén
**Dado que** intento crear ubicación con parent_id de otro almacén,
**Cuando** envío el request,
**Entonces** el sistema retorna error 400 "La ubicación padre no pertenece al mismo almacén".

---

## Reglas de Negocio

- **RN-1:** Código de almacén es único por empresa.
- **RN-2:** Ubicaciones usan parent_id para jerarquía.
- **RN-3:** Todo almacén tiene ubicaciones por defecto: Stock, Input (recepción), Output (envío).
- **RN-4:** Stock se registra por ubicación específica (stock_quants.location_id).
- **RN-5:** Ubicaciones pueden tener tipo: view (virtual), internal (física), supplier, customer, transit.
- **RN-6:** RLS filtra almacenes por empresa.

---

## Tareas Técnicas

### Backend
- [ ] Endpoint: POST /api/v1/inventory/warehouses
- [ ] Endpoint: GET /api/v1/inventory/warehouses
- [ ] Endpoint: GET /api/v1/inventory/warehouses/:id
- [ ] Endpoint: POST /api/v1/inventory/warehouses/:id/locations
- [ ] Endpoint: GET /api/v1/inventory/locations (tree view)
- [ ] Service: WarehouseService.create(createWarehouseDto)
- [ ] Service: WarehouseService.createDefaultLocations(warehouseId)
- [ ] Service: LocationService.create(createLocationDto)
- [ ] Service: LocationService.getTree(warehouseId)
- [ ] DTO: CreateWarehouseDto, CreateLocationDto
- [ ] Validar código único
- [ ] Validar jerarquía de ubicaciones
- [ ] Unit tests (>80% coverage)
- [ ] Integration tests
- [ ] Swagger docs

### Frontend
- [ ] Componente: CreateWarehouseForm.tsx
- [ ] Componente: WarehouseCard.tsx
- [ ] Componente: LocationTree.tsx (árbol jerárquico)
- [ ] Componente: CreateLocationModal.tsx
- [ ] Página: WarehousesPage.tsx (/inventory/warehouses)
- [ ] Página: WarehouseDetailsPage.tsx (/inventory/warehouses/:id)
- [ ] API client: warehouseApi.create(data), locationApi.create(data)
- [ ] State management: useWarehouseStore
- [ ] Component tests
- [ ] E2E test: "should create warehouse and locations"

### Database
- [ ] Tabla: inventory.warehouses
- [ ] Tabla: inventory.locations
- [ ] Índices: idx_warehouses_company_id, idx_warehouses_code
- [ ] Índices: idx_locations_warehouse_id, idx_locations_parent_id
- [ ] Constraint: uq_warehouses_code_company
- [ ] RLS policy: company_isolation_warehouses, company_isolation_locations

---

## Mockups / Wireframes

**Formulario Crear Almacén:**
```
┌─────────────────────────────────────────────┐
│ Crear Almacén                              │
├─────────────────────────────────────────────┤
│ Código: [Input: WH-01] *                   │
│ Nombre: [Input: Almacén Central] *        │
│ Dirección: [TextArea]                      │
│                                             │
│ [✓] Crear ubicaciones por defecto          │
│     (Stock, Input, Output)                  │
├─────────────────────────────────────────────┤
│ [Guardar]  [Cancelar]                      │
└─────────────────────────────────────────────┘
```

**Árbol de Ubicaciones:**
```
┌─────────────────────────────────────────────┐
│ Almacén Central (WH-01)                    │
├─────────────────────────────────────────────┤
│ ▼ Stock                                    │
│   ▼ Zona A                                 │
│     ▼ Pasillo 1                            │
│       ▶ Anaquel A1                         │
│       ▶ Anaquel A2                         │
│     ▶ Pasillo 2                            │
│   ▶ Zona B                                 │
│ ▶ Input (Recepción)                        │
│ ▶ Output (Envío)                           │
│                                             │
│ [+ Nueva Ubicación]                        │
└─────────────────────────────────────────────┘
```

---

## Casos de Prueba

### Funcionales
1. **TC-001:** Crear almacén con ubicaciones por defecto
2. **TC-002:** Crear ubicaciones jerárquicas (3 niveles)
3. **TC-003:** Visualizar árbol de ubicaciones
4. **TC-004:** Error por código de almacén duplicado
5. **TC-005:** Error por ubicación padre de otro almacén
6. **TC-006:** RLS filtra por empresa

### No Funcionales
1. **Performance:** < 400ms para crear almacén
2. **Seguridad:** JWT + permiso inventory_user

---

## Dependencias

- **US bloqueantes:** US-MGN-002-001-001 (Gestión de Empresas)
- **Módulos requeridos:** MGN-001, MGN-002
- **Datos maestros:** Ninguno

---

## Notas de Implementación

- Usar patrón de árbol con parent_id (closure table opcional para queries más eficientes)
- Frontend: Usar react-complex-tree o similar para árbol de ubicaciones
- Considerar profundidad máxima de jerarquía (ej: 5 niveles)
- Ubicaciones por defecto: Stock (internal), Input (supplier location), Output (customer location)

---

## Estimación Detallada

| Tarea | Horas |
|-------|-------|
| Backend | 2.5 |
| Frontend | 3 |
| Testing | 2 |
| Code Review | 0.5 |
| **TOTAL** | **8 horas = 5 SP** |

---

## Definition of Done

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

---

## Referencias

- [RF-MGN-005-002](../../02-modelado/requerimientos-funcionales/mgn-005/RF-MGN-005-002-gestión-de-almacenes-y-ubicaciones.md)
- [ET Backend](../../02-modelado/especificaciones-tecnicas/backend/mgn-005/ET-BACKEND-MGN-005-002-gestión-de-almacenes-y-ubicaciones.md)
- [ET Frontend](../../02-modelado/especificaciones-tecnicas/frontend/mgn-005/ET-FRONTEND-MGN-005-002-gestión-de-almacenes-y-ubicaciones.md)
- [Traceability](../../02-modelado/trazabilidad/TRACEABILITY-MGN-005.yaml)
- [Schema](../../02-modelado/database-design/schemas/inventory-schema-ddl.sql)
