2 Commits

Author SHA1 Message Date
f9258bad05 test(crm): deja la suite del backend corriendo en CI
CI ejecuta `pytest tests/` sin exclusiones y con `set -e`. En main, cuatro módulos no
coleccionaban, así que pytest se interrumpía y **no corría ni una prueba del backend** —
verificado contra main: "Interrupted: 4 errors during collection". Los tres primeros ya se
arreglaron en esta rama; aquí va el cuarto y las dos fallas que quedaban.

test_efc_entrega_documento.py: recupera sus 13 pruebas. Importaba crm.expedientes y creaba el
Document con expediente_id / efc_sync_state / efc_document_ref, columnas que no existen —eran
del expediente paralelo que 5c4df59 descartó—. El valor de estas pruebas está en
deliver_file_row (ensure-then-upload, corte directo, idempotencia por crm_document_ref), que
trabaja contra la fila del outbox y no necesita esas columnas. Las tres aserciones sobre el
estado del documento se reenfocan a lo que sí es observable: el acuse y el diagnóstico viven en
la fila del outbox, y del documento se comprueba lo único que _marcar_documento_entregado sí
persiste — que suelta su file_key al confirmar, y que NO lo suelta cuando la entrega falla.

test_contrato_efc.py: sus dos pruebas quedan skipped con el motivo completo. Afirman un API
/expedientes/* de nueve endpoints que este repo no implementa, y un DocumentResponse sin
file_key/file_url con columnas efc_*. No son arreglos de una línea: el contrato es la mitad de
un acuerdo que EFC afirma contra una copia idéntica, el frontend usa file_key para descargar, y
las columnas no existen. Se marca PENDIENTE DECISIÓN en vez de dejar CI rojo tapando el resto.

Resultado: 354 pruebas corriendo, 2 skipped, cero fallas.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 14:32:49 -05:00
5c4df590d4 feat(crm): carril hacia EFC montado sobre el expediente existente (crm.cases)
Rebase del lado emisor de T2026-08-046 sobre esta rama. La entrega anterior partia
de feature/crm-cumplimiento-pdf (16-jul), 40 commits atras, y por eso construyo un
expediente PARALELO -- crm.expedientes con su propio generador de folio y su propia
migracion -- que duplicaba el que ya existe aqui. Dos expedientes y dos secuencias
peleando por el mismo namespace EXP no se fusionan; se tira el nuestro.

La estructura del expediente es de esta rama y no se toca: crm.cases es el
expediente, su folio vive en `reference` y el consecutivo lo reserva
crm/common/folios.py con bloqueo de fila. Nuestro aporte es SOLO la conexion:

  - crm.cases gana seis columnas efc_* (espejo de EFC, nunca el handle) y nada mas;
  - crm.efc_sync_outbox y crm.efc_file_outbox, el outbox transaccional, con
    expediente_ref -> crm.cases.id;
  - core/efc_client.py y crm/expediente_gateway/ (outbox, reintentos, barridos),
    clonados del gateway Anexo22 -> EFC que ya corre en produccion;
  - las ocho variables EFC_* en config. EFC_API_URL vacia = carril apagado.

Verificado contra la base real: next_folio(...,'EXP',None,with_direction=False)
devuelve EXP2026-08-001, identico al formato que el contrato con EFC exige, y
storage_token da CRM-{company}-{folio} de 22 caracteres sobre los 25 de
pedimento_app.

Se corrige un error del docstring de storage_token: decia que cabian companies de
7 digitos y son 6 (4+7+1+14 = 26 > 25). Ahora valida y falla ruidosamente en vez de
entregar un token recortado, que apuntaria a la carpeta de otro expediente y
mezclaria documentos en silencio.

El revision id de la migracion tirada (e6f7a8b9c0d1) chocaba con crm_catalog_items
de esta rama: dos migraciones distintas con el mismo id habrian roto alembic al
fusionar. La nueva es c5d6e7f8a9b0, aditiva sobre d4e5f6a7b8c9.

PENDIENTE: falta el pegamento que invocaba el carril desde los flujos de la app
(alta del provisional al mintear el folio, subida de documento -> outbox, rutas en
el router y UI). Por eso test_efc_outbox, test_gateway_rutas y tres casos de
test_contrato_efc todavia no colectan. El carril no esta cableado al router, asi
que la app funciona igual: backend y frontend responden 200.

Ref: T2026-08-046

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 10:35:44 -06:00