erp-transportistas-v2/docs/02-definicion-modulos/MAI-003-ordenes-transporte/historias-usuario/US-MAI003-007.md
Adrian Flores Cortes ec43d9c6cd docs: Add Phase 3 secondary modules specifications (P1/P2/P3)
Modules documented:
- MAI-003 (OT): README, REQUERIMIENTOS, RESUMEN-EPICA, 10 US
- MAI-006 (Tracking): README, REQUERIMIENTOS, RESUMEN-EPICA
- MAI-008 (Incidencias): 3 US (18 SP)
- MAI-011 (Flota): README, REQUERIMIENTOS, RESUMEN-EPICA
- MAI-012 (Combustible): 3 US (18 SP)
- MAI-013 (Mantenimiento): 3 US (18 SP)
- MAI-014 (Carriers): 3 US (18 SP)
- MAI-015 (Portal): 3 US (18 SP)
- MAE-016 (Carta Porte): 10 US
- MAE-017 (HOS): 3 US (16 SP)
- MAE-018 (Reportes): 3 US (18 SP)

Phase 2+3 complete: 13 modules, 50+ User Stories

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 02:24:35 -06:00

4.9 KiB

US-MAI003-007: Cancelar OT

Metadata

Campo Valor
ID US-MAI003-007
Epica EPIC-MAI-003 - Ordenes de Transporte
Modulo ordenes-transporte
Prioridad P1
Story Points 3
Sprint Por asignar
Estado Backlog

Historia de Usuario

Como despachador o coordinador de una empresa transportista, quiero cancelar una orden de transporte que ya no sera ejecutada, para liberar los recursos asociados y mantener actualizado el estado de las operaciones con un registro claro del motivo de cancelacion.

Descripcion Detallada

La cancelacion de una OT es una operacion necesaria cuando el cliente retira la solicitud, se duplica una orden, o se presentan circunstancias que impiden la ejecucion del servicio. El sistema debe permitir cancelar OTs en estados previos a la ejecucion (BORRADOR, CONFIRMADA y ASIGNADA), pero no una vez que el viaje esta en proceso o completado.

Al cancelar, el sistema debe registrar el motivo de cancelacion y marcar la OT con estado CANCELADA y deleted_at como fecha de cancelacion logica. Si la OT estaba agrupada en un embarque, debe removerse automaticamente y recalcular los totales del embarque. Si estaba asignada a un viaje, se debe evaluar si el viaje puede continuar sin esa OT.

La cancelacion es una operacion irreversible: una OT cancelada no puede volver a un estado activo. Si se necesita reactivar, se debe crear una nueva OT.

Criterios de Aceptacion

Escenario 1: Cancelar OT en estado BORRADOR

Dado que existe una OT en estado BORRADOR, Cuando el despachador solicita la cancelacion con motivo "Solicitud retirada por el cliente", Entonces el sistema cambia el estado a CANCELADA, registra deleted_at con la fecha actual, registra updated_by_id con el usuario que cancela, y la OT deja de aparecer en listados activos.

Escenario 2: Cancelar OT CONFIRMADA que pertenece a un embarque

Dado que una OT en estado CONFIRMADA esta agrupada en un embarque con 3 OTs, Cuando el coordinador cancela la OT con motivo "Carga no disponible en origen", Entonces el sistema cambia la OT a CANCELADA, la remueve del embarque (limpia embarque_id), recalcula los totales del embarque (total_ots = 2, peso y volumen actualizados).

Escenario 3: Rechazo de cancelacion en estado EN_PROCESO

Dado que una OT se encuentra en estado EN_PROCESO (viaje en curso), Cuando el usuario intenta cancelar la OT, Entonces el sistema rechaza la operacion con error 422 y mensaje "No se puede cancelar una orden de transporte en estado EN_PROCESO. Registre una incidencia en su lugar."

Escenario 4: Motivo de cancelacion obligatorio

Dado que el usuario solicita cancelar una OT en estado valido, Cuando no proporciona un motivo de cancelacion, Entonces el sistema rechaza la operacion indicando que el motivo de cancelacion es obligatorio.

Tareas Tecnicas

  • Database: Utilizar campo estado para marcar como CANCELADA y deleted_at para soft delete. El campo deleted_at (TIMESTAMPTZ) sirve como fecha de cancelacion logica.
  • Backend: Agregar metodo cancelar(id, motivo, userId) en OrdenTransporteService con validacion de estado: solo permitir cancelacion desde BORRADOR, CONFIRMADA o ASIGNADA. Si la OT tiene embarque_id, invocar EmbarqueService.removeOt() para limpiar la referencia y recalcular totales. Configurar endpoint PATCH /api/v1/ordenes-transporte/:id/cancelar. Crear CancelarOrdenTransporteDto con campo obligatorio motivo.
  • Frontend: Agregar boton "Cancelar OT" visible solo en estados BORRADOR, CONFIRMADA y ASIGNADA. Al presionar, mostrar dialogo de confirmacion con campo obligatorio de motivo. Tras cancelacion exitosa, redirigir al listado con mensaje de confirmacion.
  • Tests: Tests unitarios de validacion de estados permitidos para cancelacion. Tests de integracion del flujo con embarque (remocion y recalculo). Tests de motivo obligatorio. Tests de rechazo en estados no cancelables.

Dependencias

  • Depende de: US-MAI003-001 (la OT debe existir), US-MAI003-004 (logica de remocion de embarque)
  • Bloquea: Ninguno directamente (flujo terminal)

Notas Tecnicas

  • Endpoint: PATCH /api/v1/ordenes-transporte/:id/cancelar
  • Body: { "motivo": "string (requerido)" }
  • Estados cancelables: BORRADOR, CONFIRMADA, ASIGNADA
  • Estados no cancelables: EN_PROCESO, COMPLETADA, FACTURADA, CANCELADA
  • Soft delete: deleted_at = NOW() marca la cancelacion logica. Los listados por defecto filtran WHERE deleted_at IS NULL
  • Efecto cascada: Si la OT pertenece a un embarque, el servicio debe: 1) limpiar embarque_id de la OT, 2) recalcular totales del embarque, 3) si el embarque queda sin OTs, evaluar si se cierra automaticamente
  • Irreversibilidad: No existe endpoint para reactivar una OT cancelada. El motivo de cancelacion se almacena en la columna instrucciones_especiales o en una tabla de auditoria dedicada

US-MAI003-007 - ERP Transportistas v1.0.0