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

6.2 KiB

US-MGN-005-003-003: Cancelar Movimiento de Stock

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


User Story

Como usuario de inventario, Quiero cancelar movimientos de stock en estado draft o done, Para revertir movimientos erróneos y mantener la integridad del stock.


Descripción Detallada

Cancelar un movimiento cambia su estado a cancelled. El comportamiento depende del estado actual:

  • draft: Solo cambia estado a cancelled (no hay reversión de stock)
  • done: Revierte el stock (suma a origen, resta a destino) y cambia estado

Los movimientos cancelados no pueden volver a validarse ni editarse.


Criterios de Aceptación

Escenario 1: Cancelar movimiento draft (Camino Feliz)

Dado que tengo movimiento en state=draft, Cuando cancelo el movimiento, Entonces el sistema cambia state=cancelled sin afectar stock.

Escenario 2: Cancelar movimiento done (revertir stock)

Dado que tengo movimiento done: product=1, from=Zona A (stock=5), to=Zona B (stock=8), qty=5, Cuando cancelo el movimiento, Entonces el sistema revierte: Zona A stock=10, Zona B stock=3, state=cancelled.

Escenario 3: Error al cancelar movimiento ya cancelado

Dado que movimiento está en state=cancelled, Cuando intento cancelar nuevamente, Entonces el sistema retorna error 400 "Movimiento ya fue cancelado".

Escenario 4: Registrar motivo de cancelación

Dado que cancelo movimiento con reason="Error en cantidad", Cuando envío el request, Entonces el sistema guarda el motivo y fecha de cancelación.


Reglas de Negocio

  • RN-1: Movimientos draft y done pueden cancelarse.
  • RN-2: Movimientos cancelled no pueden cancelarse nuevamente.
  • RN-3: Cancelar movimiento done revierte stock (operación inversa).
  • RN-4: Cancelar movimiento draft no afecta stock.
  • RN-5: Cancelación registra fecha, usuario y motivo.
  • RN-6: Movimientos cancelados no pueden reactivarse.

Tareas Técnicas

Backend

  • Endpoint: POST /api/v1/inventory/stock-moves/:id/cancel
  • Service: StockMoveService.cancel(moveId, reason)
  • Service: StockMoveService.reverseQuants(move)
  • Validar movimiento no está cancelado
  • Si done: revertir quants (suma origen, resta destino)
  • Si draft: solo cambiar estado
  • Registrar fecha, usuario, motivo
  • Transaction para atomicidad
  • Unit tests (>80% coverage)
  • Integration tests
  • Swagger docs

Frontend

  • Componente: CancelStockMoveButton.tsx
  • Modal de confirmación con campo motivo
  • Mostrar impacto en stock (si done)
  • API client: stockMoveApi.cancel(id, reason)
  • Component tests
  • E2E test: "should cancel stock move"

Database

  • Tabla: inventory.stock_moves (campos: cancelled_date, cancelled_by, cancel_reason)
  • Transaction isolation level: READ COMMITTED

Mockups / Wireframes

Modal Cancelar Movimiento:

┌─────────────────────────────────────────────┐
│ Cancelar Movimiento de Stock               │
├─────────────────────────────────────────────┤
│ Movimiento: #SM-00123                      │
│ Estado Actual: Done                        │
│                                             │
│ ⚠ Cancelar revertirá los cambios de stock:│
│ Zona A: 5 → 10 (+5)                       │
│ Zona B: 8 → 3 (-5)                        │
│                                             │
│ Motivo de Cancelación: *                   │
│ [TextArea: Error en cantidad registrada]  │
│                                             │
│ ⚠ Esta acción no puede deshacerse.        │
├─────────────────────────────────────────────┤
│ [Cancelar Movimiento]  [Volver]           │
└─────────────────────────────────────────────┘

Casos de Prueba

Funcionales

  1. TC-001: Cancelar movimiento draft exitosamente
  2. TC-002: Cancelar movimiento done y revertir stock
  3. TC-003: Error por movimiento ya cancelado
  4. TC-004: Registrar motivo de cancelación
  5. TC-005: Transaction rollback en caso de error
  6. TC-006: RLS filtra por empresa

No Funcionales

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

Dependencias

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

Notas de Implementación

  • Usar transaction para garantizar atomicidad
  • Reversión = operación inversa de validación
  • Considerar agregar audit trail de cancelaciones
  • Frontend: Deshabilitar botón cancelar si ya está cancelado

Estimación Detallada

Tarea Horas
Backend 2
Frontend 1.5
Testing 1
Code Review 0.5
TOTAL 5 horas = 3 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