# US-MGN-007-002-003: Cancelar Sales Order **RF Asociado:** [RF-MGN-007-003](../../02-modelado/requerimientos-funcionales/mgn-007/RF-MGN-007-003-gestión-de-órdenes-de-venta.md) **Módulo:** MGN-007 - Ventas Básico **Epic:** Órdenes de Venta **Prioridad:** P1 **Story Points:** 3 **Sprint:** Sprint 16 **Estado:** Ready for Development **Fecha:** 2025-11-24 --- ## User Story **Como** vendedor o gerente de ventas, **Quiero** cancelar una orden de venta, **Para** anular ventas que no se completarán y liberar recursos reservados. --- ## Descripción Detallada Cancelar una SO significa: - Cambiar estado a cancelled - Registrar fecha de cancelación (date_cancelled) - Registrar motivo de cancelación (cancellation_reason) - Liberar reservas de stock si las hay - Cancelar entregas pendientes asociadas - Notificar a stakeholders - Crear mensaje en chatter con motivo SO canceladas no pueden reactivarse (son inmutables). --- ## Criterios de Aceptación ### Escenario 1: Cancelar SO draft o confirmed (Camino Feliz) **Dado que** SO id=1 está en estado draft, **Cuando** ejecuto action "Cancel" con reason="Cliente canceló pedido", **Entonces** sistema cambia estado a cancelled, registra date_cancelled y reason. ### Escenario 2: Validar que SO no está done **Dado que** SO está en estado done (completamente facturada y entregada), **Cuando** intento cancelar, **Entonces** sistema retorna error 400 "No se puede cancelar orden completada". ### Escenario 3: Validar que SO no tiene entregas validadas **Dado que** SO tiene entregas en estado done, **Cuando** intento cancelar, **Entonces** sistema retorna error 400 "No se puede cancelar orden con entregas validadas". ### Escenario 4: Validar que SO no tiene facturas **Dado que** SO tiene facturas emitidas, **Cuando** intento cancelar, **Entonces** sistema retorna error 400 "No se puede cancelar orden facturada". ### Escenario 5: Cancelar entregas pendientes automáticamente **Dado que** SO tiene 2 entregas en estado draft, **Cuando** cancelo SO, **Entonces** sistema cancela automáticamente las 2 entregas pendientes. ### Escenario 6: Motivo de cancelación obligatorio **Dado que** intento cancelar SO sin proporcionar reason, **Cuando** envío request, **Entonces** sistema retorna error 400 "El motivo de cancelación es obligatorio". --- ## Reglas de Negocio - **RN-1:** Solo SO en draft o confirmed pueden cancelarse. - **RN-2:** SO con entregas validadas (state=done) no pueden cancelarse. - **RN-3:** SO con facturas no pueden cancelarse (deben hacerse notas de crédito). - **RN-4:** Motivo de cancelación es obligatorio. - **RN-5:** Entregas pendientes (draft) se cancelan automáticamente. - **RN-6:** Reservas de stock se liberan automáticamente. - **RN-7:** SO canceladas no pueden reactivarse. - **RN-8:** Permisos: sales_user puede cancelar sus órdenes draft, sales_manager puede cancelar cualquiera. --- ## Tareas Técnicas ### Backend - [ ] Endpoint: `POST /api/v1/sales/orders/:id/cancel` - [ ] Service: `SalesOrderService.cancel(id, cancelDto)` - [ ] DTO: `CancelSalesOrderDto` (reason: string) - [ ] Validar estado (draft o confirmed) - [ ] Validar que no tiene entregas validadas - [ ] Validar que no tiene facturas - [ ] Validar reason no vacío - [ ] Actualizar state=cancelled, date_cancelled=now() - [ ] Cancelar entregas pendientes asociadas - [ ] Liberar reservas de stock (si aplica) - [ ] Crear mensaje en chatter con reason - [ ] Unit tests (>80%) - [ ] Integration tests - [ ] Swagger docs ### Frontend - [ ] Botón: "Cancel" en vista de SO - [ ] Modal: Solicitar motivo de cancelación (textarea) - [ ] Validación: Motivo mínimo 10 caracteres - [ ] Mostrar warnings si hay entregas pendientes - [ ] API client: `salesOrderApi.cancel(id, {reason})` - [ ] Notificación toast de éxito - [ ] Component tests - [ ] E2E test: "should cancel sales order" ### Database - [ ] Columna: `sales.orders.date_cancelled` (timestamp) - [ ] Columna: `sales.orders.cancellation_reason` (text) - [ ] Índice: `idx_orders_date_cancelled` --- ## Mockups / Wireframes **Modal Cancelar SO:** ``` ┌─────────────────────────────────────────────┐ │ Cancelar Orden SO/2024/0001 │ ├─────────────────────────────────────────────┤ │ ⚠ Esta acción no puede deshacerse │ │ │ │ Motivo de cancelación: * │ │ ┌─────────────────────────────────────────┐ │ │ │ Cliente canceló pedido por... │ │ │ │ │ │ │ └─────────────────────────────────────────┘ │ │ │ │ Impactos: │ │ • 2 entregas pendientes serán canceladas │ │ • Reservas de stock serán liberadas │ │ │ │ [Confirmar Cancelación] [Cerrar] │ └─────────────────────────────────────────────┘ ``` --- ## Casos de Prueba ### Funcionales 1. **TC-001:** Cancelar SO draft exitosamente 2. **TC-002:** Cancelar SO confirmed exitosamente 3. **TC-003:** Error al cancelar SO done 4. **TC-004:** Error al cancelar SO con entregas validadas 5. **TC-005:** Error al cancelar SO con facturas 6. **TC-006:** Error si reason está vacío 7. **TC-007:** Entregas pendientes se cancelan automáticamente 8. **TC-008:** date_cancelled y reason se registran correctamente 9. **TC-009:** Mensaje se crea en chatter con reason ### No Funcionales 1. **Performance:** < 500ms para cancelar orden 2. **Seguridad:** JWT + permiso sales_user (own) o sales_manager (all) --- ## Dependencias - **US bloqueantes:** - US-MGN-007-002-002 (Confirmar SO) - **Módulos requeridos:** MGN-007 (Entregas) --- ## Notas de Implementación - Usar transacción para cancelar SO + entregas pendientes atómicamente - Validar permisos: sales_user solo puede cancelar sus propias órdenes draft - Considerar agregar campo `cancelled_by_user_id` para auditoría - Frontend: Deshabilitar botón de cancelación si hay entregas validadas --- ## Estimación Detallada | Tarea | Horas | |-------|-------| | Backend | 1.5 | | Frontend | 1 | | Testing | 1 | | Code Review | 0.5 | | **TOTAL** | **4 horas = 3 SP** | --- ## Definition of Done - [ ] Código implementado según ET - [ ] Tests pasando (>80%) - [ ] Code review aprobado - [ ] Cancelación funciona correctamente - [ ] Validaciones aplicadas - [ ] Entregas pendientes canceladas - [ ] date_cancelled y reason registrados - [ ] Mensaje en chatter creado - [ ] Swagger docs actualizado - [ ] QA validado - [ ] PO aprobado --- ## Referencias - [RF-MGN-007-003](../../02-modelado/requerimientos-funcionales/mgn-007/RF-MGN-007-003-gestión-de-órdenes-de-venta.md) - [ET Backend](../../02-modelado/especificaciones-tecnicas/backend/mgn-007/ET-BACKEND-MGN-007-003-ordenes-venta.md) - [ET Frontend](../../02-modelado/especificaciones-tecnicas/frontend/mgn-007/ET-FRONTEND-MGN-007-003-ordenes-venta.md) - [Traceability](../../02-modelado/trazabilidad/TRACEABILITY-MGN-007.yaml) - [Schema](../../02-modelado/database-design/schemas/sales-schema-ddl.sql)