erp-core/docs/05-user-stories/mgn-005/US-MGN-005-002-001-gestionar-almacenes-ubicaciones.md

8.5 KiB

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

RF Asociado: RF-MGN-005-002 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