erp-core/docs/05-user-stories/mgn-005/US-MGN-005-003-002-validar-movimiento-stock.md

6.9 KiB

US-MGN-005-003-002: Validar Movimiento de Stock

RF Asociado: RF-MGN-005-003 Módulo: MGN-005 - Inventario Básico Epic: Movimientos de Stock Prioridad: P0 Story Points: 5 Sprint: Sprint 10 Estado: Ready for Development Fecha: 2025-11-24


User Story

Como usuario de inventario, Quiero validar movimientos de stock en estado draft, Para actualizar las cantidades de stock en las ubicaciones origen y destino (quants).


Descripción Detallada

Validar un movimiento cambia su estado de draft → done y ejecuta la lógica de actualización de stock:

  1. Resta cantidad de stock_quants en location_from
  2. Suma cantidad de stock_quants en location_to
  3. Actualiza state=done y fecha de validación
  4. Registra trazabilidad del movimiento

Si no hay stock suficiente en origin, el sistema puede permitir stock negativo (configurable) o rechazar el movimiento.


Criterios de Aceptación

Escenario 1: Validar movimiento con stock suficiente (Camino Feliz)

Dado que tengo movimiento en draft: product=1, from=Zona A (stock=10), to=Zona B, qty=5, Cuando valido el movimiento, Entonces el sistema actualiza: Zona A stock=5, Zona B stock=5, state=done.

Escenario 2: Validar movimiento sin stock (permitir negativo)

Dado que ubicación origen tiene stock=3 y movimiento requiere qty=5, Cuando valido y allow_negative_stock=true, Entonces el sistema actualiza: origen stock=-2, destino stock=5, state=done.

Escenario 3: Error al validar sin stock (no permitir negativo)

Dado que ubicación origen tiene stock=3 y movimiento requiere qty=5, Cuando valido y allow_negative_stock=false, Entonces el sistema retorna error 400 "Stock insuficiente en ubicación origen".

Escenario 4: Error al validar movimiento ya validado

Dado que movimiento está en state=done, Cuando intento validar nuevamente, Entonces el sistema retorna error 400 "Movimiento ya fue validado".

Escenario 5: Error al validar movimiento cancelado

Dado que movimiento está en state=cancelled, Cuando intento validar, Entonces el sistema retorna error 400 "No se puede validar un movimiento cancelado".


Reglas de Negocio

  • RN-1: Solo movimientos en state=draft pueden validarse.
  • RN-2: Validar actualiza stock_quants (resta origen, suma destino).
  • RN-3: Stock negativo permitido según configuración de empresa.
  • RN-4: Movimiento validado no puede modificarse.
  • RN-5: Validación registra fecha y usuario que valida.
  • RN-6: Si producto tiene tracking (lot/serial), se requiere especificar lote.

Tareas Técnicas

Backend

  • Endpoint: POST /api/v1/inventory/stock-moves/:id/validate
  • Service: StockMoveService.validate(moveId)
  • Service: StockMoveService.updateQuants(move)
  • Service: QuantService.updateQuantity(productId, locationId, quantityDelta)
  • Validar movimiento en state=draft
  • Verificar stock disponible
  • Actualizar quants (origen y destino)
  • Actualizar state y fecha
  • Transaction para atomicidad
  • Unit tests (>80% coverage)
  • Integration tests
  • Swagger docs

Frontend

  • Componente: ValidateStockMoveButton.tsx
  • Modal de confirmación con resumen
  • Mostrar stock actual antes/después
  • API client: stockMoveApi.validate(id)
  • Actualizar lista de movimientos tras validar
  • Component tests
  • E2E test: "should validate stock move and update stock"

Database

  • Tabla: inventory.stock_quants (actualización)
  • Índices: idx_stock_quants_product_location
  • Transaction isolation level: READ COMMITTED

Mockups / Wireframes

Modal Validar Movimiento:

┌─────────────────────────────────────────────┐
│ Validar Movimiento de Stock                │
├─────────────────────────────────────────────┤
│ Producto: Laptop HP                        │
│ Cantidad: 5 unidades                       │
│                                             │
│ Ubicación Origen: Zona A                   │
│ Stock Actual: 10 → Nuevo: 5               │
│                                             │
│ Ubicación Destino: Zona B                 │
│ Stock Actual: 3 → Nuevo: 8                │
│                                             │
│ ⚠ Esta acción no puede deshacerse.        │
├─────────────────────────────────────────────┤
│ [Validar]  [Cancelar]                      │
└─────────────────────────────────────────────┘

Casos de Prueba

Funcionales

  1. TC-001: Validar movimiento con stock suficiente
  2. TC-002: Validar movimiento con stock negativo (permitido)
  3. TC-003: Error por stock insuficiente (no permitido)
  4. TC-004: Error por movimiento ya validado
  5. TC-005: Error por movimiento cancelado
  6. TC-006: Transaction rollback en caso de error
  7. TC-007: RLS filtra por empresa

No Funcionales

  1. Performance: < 500ms para validar movimiento
  2. Seguridad: JWT + permiso inventory_validate

Dependencias

  • US bloqueantes: US-MGN-005-003-001 (Crear Movimiento Stock)
  • Módulos requeridos: MGN-001, MGN-002
  • Datos maestros: Stock quants

Notas de Implementación

  • Usar transaction para garantizar atomicidad de actualización de quants
  • Si quant no existe, crear con quantity (INSERT)
  • Si quant existe, actualizar quantity (UPDATE)
  • Considerar bloqueo pesimista (SELECT FOR UPDATE) en quants para evitar condiciones de carrera
  • Frontend: Polling o WebSocket para refresh automático de stock

Estimación Detallada

Tarea Horas
Backend 3
Frontend 2
Testing 2
Code Review 1
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
  • Transaction correctamente implementada
  • RLS aplicado
  • QA validado
  • PO aprobado

Referencias