# US-MAE016-005: Cancelar CFDI con motivo ## Metadata | Campo | Valor | |-------|-------| | **ID** | US-MAE016-005 | | **Epica** | EPIC-MAE-016 - Carta Porte CFDI | | **Modulo** | carta-porte | | **Prioridad** | P1 | | **Story Points** | 5 | | **Sprint** | Por asignar | | **Estado** | Backlog | ## Historia de Usuario **Como** contador, **quiero** cancelar un CFDI con complemento Carta Porte indicando el motivo conforme al catalogo del SAT, **para** corregir errores en comprobantes emitidos o documentar operaciones que no se llevaron a cabo, manteniendo un expediente fiscal limpio y auditable. ## Descripcion Detallada La cancelacion de CFDI es un proceso regulado por el SAT que permite invalidar un comprobante fiscal previamente timbrado. A partir de las reformas fiscales, toda cancelacion debe incluir un motivo del catalogo oficial del SAT. El proceso se realiza a traves del PAC y puede requerir la aceptacion del receptor cuando el monto supera cierto umbral. Los motivos de cancelacion son: 01 (Comprobante emitido con errores con relacion), que requiere indicar el UUID del CFDI que sustituye al cancelado; 02 (Comprobante emitido con errores sin relacion), cuando el error no requiere reemision; 03 (No se llevo a cabo la operacion), cuando el viaje no se realizo; y 04 (Operacion nominativa relacionada en factura global). El sistema debe enviar la solicitud de cancelacion al PAC con los datos requeridos (UUID del CFDI a cancelar, motivo y UUID de sustitucion si aplica), registrar la cancelacion en la bitacora de auditoria y actualizar el estado de la carta porte. La cancelacion debe quedar trazada con el usuario que la solicito, la fecha y el motivo detallado. ## Criterios de Aceptacion ### Escenario 1: Cancelacion con motivo 01 (con sustitucion) **Dado** una carta porte en estado TIMBRADA que contiene errores y ya se ha emitido un CFDI de sustitucion con UUID conocido **Cuando** el contador selecciona motivo "01 - Comprobante emitido con errores con relacion" e ingresa el UUID de sustitucion **Entonces** el sistema envia la solicitud al PAC con el UUID a cancelar, motivo '01' y UUID de sustitucion, actualiza el estado a CANCELADA, registra fecha_cancelacion, motivo_cancelacion y uuid_sustitucion en `compliance.cartas_porte`, y registra la operacion en auditoria. ### Escenario 2: Cancelacion con motivo 03 (operacion no realizada) **Dado** una carta porte en estado TIMBRADA para un viaje que no se ejecuto **Cuando** el contador selecciona motivo "03 - No se llevo a cabo la operacion" **Entonces** el sistema envia la solicitud al PAC con motivo '03' sin UUID de sustitucion, actualiza el estado a CANCELADA, registra fecha_cancelacion y motivo_cancelacion, y uuid_sustitucion queda nulo. ### Escenario 3: Motivo 01 sin UUID de sustitucion **Dado** una carta porte en estado TIMBRADA y el contador selecciona motivo "01" **Cuando** el contador no ingresa el UUID de sustitucion y confirma la cancelacion **Entonces** el sistema rechaza la operacion con el mensaje "El motivo 01 requiere indicar el UUID del CFDI de sustitucion" y no envia la solicitud al PAC. ### Escenario 4: Cancelacion rechazada por el PAC **Dado** una carta porte en estado TIMBRADA que se intenta cancelar pero el receptor no acepta la cancelacion (proceso de aceptacion/rechazo del SAT) **Cuando** el PAC retorna un estatus de "Cancelacion en proceso" o "Cancelacion rechazada" **Entonces** el sistema informa al contador el estatus actual de la cancelacion, no cambia el estado de la carta porte y registra el intento en el log de auditoria. ## Tareas Tecnicas - **Database:** Actualizar campos estado, fecha_cancelacion, motivo_cancelacion y uuid_sustitucion en `compliance.cartas_porte` - **Backend:** Crear metodo `CartaPorteService.cancelar(cartaPorteId, motivo, uuidSustitucion?)` que valida motivo y envia al PAC; crear endpoint POST `/api/v1/carta-porte/:id/cancelar` con body `{ motivo: string, uuidSustitucion?: string }`; crear `CancelacionDto` con validacion del motivo (01, 02, 03, 04); registrar en auditoria la cancelacion con usuario y timestamp - **Frontend:** Crear dialogo `CancelarCartaPorteDialog` con selector de motivo (dropdown con los 4 motivos), campo condicional para UUID de sustitucion (visible solo para motivo 01), campo de observaciones adicionales; confirmacion de doble paso ("Esta seguro de cancelar el CFDI {UUID}?"); mostrar estatus de cancelacion despues de enviar - **Tests:** Test unitario de validacion de motivos (01 con UUID, 02-04 sin UUID); test de integracion con PAC en sandbox para cancelacion; test de actualizacion de estado en BD; test de rechazo cuando falta UUID para motivo 01; test de auditoria de cancelacion ## Dependencias - **Depende de:** US-MAE016-003 (Timbrar CFDI - requiere estado TIMBRADA para cancelar) - **Bloquea:** Ningun modulo directamente, pero US-MAE016-006 (Expediente fiscal) muestra la informacion de cancelacion ## Notas Tecnicas - Los motivos de cancelacion del catalogo SAT son: 01 (Comprobante emitido con errores con relacion), 02 (Comprobante emitido con errores sin relacion), 03 (No se llevo a cabo la operacion), 04 (Operacion nominativa relacionada en factura global). - Para el motivo 01, el uuid_sustitucion debe corresponder a un CFDI timbrado valido. El sistema no valida que el UUID exista en la BD local (puede ser un CFDI emitido en otro sistema). - El SAT implemento un esquema de aceptacion/rechazo de cancelacion para CFDI con monto superior a un umbral. El receptor tiene 72 horas para aceptar o rechazar. Si no responde, la cancelacion se acepta por omision. - La cancelacion en el PAC es asincrona en algunos casos. El sistema debe soportar consultar el estatus de cancelacion posteriormente. - Una vez cancelada, la carta porte no puede reactivarse. Si se requiere un nuevo documento, se genera una nueva carta porte para el mismo viaje. - El campo motivo_cancelacion en la BD almacena el texto descriptivo completo, no solo el codigo numerico (ejemplo: "01 - Comprobante emitido con errores con relacion").