El CRM no tenia CHANGELOG.md. Se crea con el formato del de EFC para que un ticket que cruza los dos productos se lea igual de los dos lados, y se abre con la entrada de T2026-08-046 (fases 5-7). Va en un PR aparte del codigo a proposito: el changelog es el unico archivo garantizado en colision entre tickets, y metido en cada PR de codigo convierte cada merge en una resolucion de conflictos en vez de una revision. La entrada dice tambien lo que NO esta: el lado de EFC del carril todavia no aterriza, las variables de entorno de produccion quedaron sin tocar y el contrato entre repos esta afirmado solo desde el CRM. Un changelog que afirma un entregable completo cuando esta a medias es peor que ninguno. Se versiona ademas el documento Prompt del ticket en docs/planes/, siguiendo la convencion de EFC, para que las decisiones del codigo tengan su porque a la vista sin depender de una carpeta de corrida. Un dato se sustituyo al versionar: un caso de prueba traia un token con forma de llave de pedimento real y aqui va como dummy; el caso prueba que esa FORMA se rechace, asi que el numero concreto no aportaba nada. Refs: T2026-08-046
6.5 KiB
Changelog — CRM Agentes de Carga
Historial de cambios por ticket (más reciente arriba). Cada entrada: fecha, ticket, tipo, repos
afectados, qué se hizo y por qué. El formato es el mismo que el de EFC/backend/CHANGELOG.md, para
que un ticket que cruza los dos productos se lea igual de los dos lados.
Este archivo lo abre la corrida SUNRISE del 2026-08-07: el repo no tenía changelog. Las entradas
llegan en un PR de documentación aparte, nunca dentro del PR de código — el CHANGELOG.md es el
único archivo garantizado en colisión entre tickets, y metido en cada PR convierte cada merge en una
resolución de conflictos.
T2026-08-046 (feature, fases 5-7) — Expediente electrónico del CRM y entrega de documentos a EFC
-
Fecha: 2026-08-07
-
En corto: Cada solicitud de servicio nace ya con su expediente y su folio propio, que el usuario ve en cuanto guarda. Los documentos de un embarque se adjuntan en un solo paso y viajan solos al expediente electrónico; si ese sistema no responde, el documento no se pierde: se queda guardado aquí, la pantalla lo muestra como pendiente de enviar, y se entrega solo cuando el otro lado vuelve. Quien lo necesite puede abrirlo desde el CRM aunque el archivo ya viva del otro lado.
-
Tipo: feature
-
Repos: CRM (backend + frontend). Las fases 1-4, del lado de EFC, son de otra corrida y todavía no están — ver «Lo que falta» al final de la entrada.
-
Branch:
feature/T2026-08-046· PR: (pendiente de abrir a mano) -
Inicio: 2026-08-07T17:40:46 · Fin: 2026-08-10T08:00 (la corrida estuvo tres días en pausa entre medias; el detalle está en
SUNRISE/2026-08-07/Diario-2026-08-07.md) -
Con dos migraciones, generadas y SIN aplicar:
e6f7a8b9c0d1_crm_expedientes.pyyf7a8b9c0d1e2(el outbox del carril).alembic headsdevuelve una sola hoja después de las dos; eldown_revisionse verificó conalembic heads, no se supuso. -
Contexto: el CRM guardaba los documentos de sus embarques en su propio almacén y ahí se quedaban. El expediente electrónico —donde de verdad se consultan— vive en EFC, así que había que volver a subir cada documento a mano del otro lado, o no subirlo. Y el enlace entre un expediente del CRM y un pedimento de EFC no podía colgarse de una columna nueva en la tabla de pedimentos: el expediente del CRM nace antes de que exista pedimento alguno.
-
Qué se hizo:
- El expediente y su folio. Una solicitud de servicio crea su expediente en la misma
transacción del alta: si algo falla, no queda ni la solicitud ni un folio quemado. El consecutivo
lo lleva un contador con bloqueo por
(cliente, empresa, mes)que reinicia cada mes, en una sola sentencia atómica —sin leer-modificar-escribir— para que dos altas simultáneas no puedan sacar el mismo número. La restricción de unicidad del folio lo garantiza aunque el contador fallara. - El carril de entrega hacia EFC. Clon del carril que ya usa Anexo22, con sus tres capas de reintento: el cliente HTTP reintenta lo transitorio y corta en seco ante un error del llamador, la fila pendiente se reintenta con límite de intentos, y un barrido periódico recoge lo que se quedó atrás. Cuatro capas de idempotencia impiden que un reintento duplique un documento del otro lado. La llamada a EFC nunca ocurre dentro de la petición del usuario: se encola y se despacha.
- La subida de un paso y el proxy de descarga. Adjuntar un documento guarda, registra y encola en una sola operación, y responde aunque EFC esté apagado. Para abrirlo, el CRM hace de proxy con streaming: el otro sistema nunca entrega una dirección de descarga reutilizable, y reescribir una dirección ya firmada la invalida.
- La pantalla. La ficha del embarque muestra cada documento con su estado —«Pendiente de enviar», «En expediente», «No se pudo enviar»— y un botón para reintentar el envío cuando algo falló, sin que nadie tenga que entrar a la base.
- El expediente y su folio. Una solicitud de servicio crea su expediente en la misma
transacción del alta: si algo falla, no queda ni la solicitud ni un folio quemado. El consecutivo
lo lleva un contador con bloqueo por
-
Tres defectos preexistentes corregidos de paso, todos en la subida de archivos y todos autorizados por el ticket: un archivo se leía entero en memoria antes de comprobar si excedía el tamaño máximo (un archivo de 2 GB se bufferizaba solo para rechazarlo); no había lista de extensiones permitidas, a diferencia del avatar y del centro de ayuda, que sí la tienen; y firmar una dirección de descarga solo comprobaba el prefijo de la empresa, lo que permitía alcanzar cualquier objeto de esa empresa —facturas, certificados, importaciones— con el permiso más básico del CRM.
-
Un defecto propio, encontrado y corregido antes de mergear: el proxy de descarga comprobaba la respuesta de EFC demasiado tarde, ya dentro del envío del archivo. Para entonces la respuesta del CRM ya había salido como «correcta», así que un documento que EFC no encontraba llegaba al usuario como un archivo vacío en vez de como un error. Ahora la comprobación ocurre antes de empezar a responder. Lo destapó una prueba que el ticket pedía y que la fase original no dejó escrita.
-
Verificación:
pytest tests/ -q→ 215 pasan, 1 se salta, contra las 70 del punto de partida; ningún rojo nuevo. En el frontend, la revisión de tipos y las pruebas unitarias quedan exactamente en los mismos números rojos que ya tenían antes de este trabajo (38 y 2, ambos heredados y ajenos al ticket). Cada verde se vio fallar primero: seis roturas deliberadas, comprobando que la prueba se pusiera roja nombrando lo que faltaba, y restauradas. -
Lo que falta, y hay que saberlo antes de mergear:
- El lado de EFC (fases 1-4) no está. Sin él, el carril entrega a un endpoint que todavía no existe: los documentos se guardan en el CRM y quedan «pendientes de enviar» hasta que aterrice. Eso es degradar limpio, no romper — pero nadie debería mergear esto creyendo que el circuito está cerrado de los dos lados.
- Las variables de entorno de producción no se tocaron. El worker y el proceso periódico de producción no ven la dirección de EFC, así que allá el carril queda apagado hasta que alguien las agregue a mano. Está en la lista de pasos manuales del reporte de la corrida.
- El contrato entre los dos repos está afirmado solo de este lado. El archivo que lo describe vive en el CRM y la suite del CRM lo comprueba; EFC debe afirmar su mitad contra una copia idéntica cuando lleguen sus fases.