# 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)