Commit Graph
100 Commits
Author SHA1 Message Date
Lizandro GuarnizoandClaude Sonnet 4.6 c1925ef6da fix: cast FECHAFACT to TIMESTAMP for BETWEEN comparison
FACTURA_DIAN.FECHAFACT is DATE type, incompatible with datetime strings.
CAST to TIMESTAMP allows comparison with :fecha_ini/:fecha_fin params.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-28 16:55:17 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 33bd25c6c8 fix: reenviar-venta now fetches all receptions of the factura
Previously used IDRECEPCION to fetch only one reception's services.
Now resolves PREFIJO+NUM_FACTURA from the reception, then fetches all
receptions sharing that factura so the full detallePedido is sent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-28 16:46:38 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 090890fa46 fix: filter ventas by FECHAFACT (billing date) instead of FECHA_RECEPCION
Joins FACTURA_DIAN to get the actual invoice date. Receptions spread
across multiple days now appear together when their factura was billed
on the selected date. Excludes annulled invoices (ANULADA != 'F').

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-28 16:45:18 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 9dd234e124 debug: add /debug-fb/facturas endpoint to search by NUM_FACTURA range
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-28 16:13:02 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 55bb34a1fa chore: remove debug fields from preview response, simplify ventas filter
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-28 16:00:47 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 7ac17e29a9 fix: remove duplicate agrupar_por_factura that was overriding the correct one
The second definition (for RIPS 2.0 transacción grouping) was never called
but silently overrode the CMXC ventas grouper, causing grupos_vta to always
be empty (values were dicts, not lists, so isinstance(v, list) was False).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-28 15:45:56 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 8747ff950e ui: show ventas generation errors as toast in preview
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-28 15:38:47 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 c463c6ecc3 debug: catch generar_factura_venta exceptions in preview, expose in response
Instead of crashing with 500, catches the error and exposes it in
ventas_gen_errors field so it can be diagnosed from the browser.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-28 15:31:23 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 29ab01e729 debug: add /debug-fb/preview-ventas GET endpoint to trace filter logic
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-28 15:29:05 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 0e837e4a2d debug: run actual _SQL_VENTAS query in /debug-fb/cmxc to compare
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-28 15:26:54 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 9e6f1171c6 debug: show SQLite contratos excluir_ventas state in /debug-fb/cmxc
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-28 15:25:16 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 27b15b184c debug: add /debug-fb/cmxc endpoint for direct Firebird CMXC query
Shows IDRECEPCION, PREFIJO, NUM_FACTURA, CODCONTRATO, N_EXAMENES
for all CMXC receptions on a given date.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-28 15:21:32 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 b8bee68d6a debug: expose ventas filter info in preview response
ventas_raw = filas de Firebird antes de filtrar
ventas_grupos_total = grupos por factura antes del filtro
ventas_filtradas = grupos excluidos con motivo (sin_factura / excluido_ventas)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-28 15:10:59 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 c58ecc1757 fix: defensive grouping filter in preview and run ventas endpoints
Replace dict comprehension with explicit loop so that non-list or empty
grupo values are safely skipped, preventing KeyError: 0 on v[0].

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-28 15:05:09 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 3a0964e4ec fix: generar_factura_venta uses PREFIJO from row, not config default
codigoPrefijo in ventas JSON must be the actual Firebird PREFIJO
(e.g. "CMXC"), not the prefijo_tns_default config value which is
intended for RDA/transaccion. Falls back to default_prefijo if row
has no PREFIJO.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-28 09:59:40 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 ae90eaf71c config: increase scheduler ventana from 10 to 60 minutes
Doctors can order exams up to ~45 min after the patient is registered
at reception. With 10 min window the exam sync missed those cases.
60 min ensures late-ordered exams are always captured and pushed to
WhatsApp Lab via upsert.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-28 09:44:26 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 408325192a fix: use FECHA_RECEPCION for exam query in scheduler, not HORAINICIORECEPCION
HORAINICIORECEPCION is a TIME field that can be NULL or outside the
2-minute window even when FECHA_RECEPCION matches, causing patients
to sync without their exams. Using the same FECHA_RECEPCION filter
for both queries ensures consistency.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-28 09:32:42 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 7f2dffc63e fix: group ventas by NUM_FACTURA, not IDRECEPCION
A single CMXC invoice (e.g. CMXC-307) can have multiple receptions.
Previously each reception was sent as a separate ventas, causing TNS
to accept the first and reject the rest with "ya existe" — leaving
only 1/N of the services registered.

Now agrupar_por_factura groups all receptions sharing the same
NUM_FACTURA into one ventas JSON with all their services in
detallePedido. One factura = one send.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-27 17:36:21 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 531fb29122 fix: group terceros by cedula not fecha-as-factura
For terceros, _guardar_envio stores the automation date in the factura
field (not a patient id), so COALESCE(factura, cedula) still collapsed
all terceros into one row. Now GROUP BY uses cedula for tipo=terceros
and factura for transaccion/ventas. Template hides the date in the
factura column for terceros rows.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-26 21:45:14 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 4b70f6f2fa fix: resumen - group terceros by cedula, prioritize success over warning
GROUP BY COALESCE(factura, cedula) fixes terceros (factura=NULL)
collapsing into one row — each paciente now gets its own row.
CASE WHEN in estado_final explicitly prioritizes success > warning > error
instead of relying on alphabetical MAX which returned warning over success.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-26 21:34:45 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 6e9ee32646 fix: group resumen by factura+tipo only, not cedula
Grouping by cedula caused envíos with null/different cedula to split
into separate groups, making success envíos invisible — factura 4989
showed error persistente despite having a success send.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-26 18:09:42 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 ab2ef167f9 feat: add Resumen Diario TNS page as submodule
Groups envios by factura+tipo per day and shows estado_final
(exitoso if any send succeeded, error persistente if all failed).
Supports inline reenvío and JSON detail modal. Added to sidebar
under Historial TNS and as TNS submodule link.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-26 17:59:42 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 3859095f17 fix: contrato 050 tipo_usuario 11 → 12 (particular)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-25 10:33:33 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 f0c4436622 fix: separar routing CMXC (Ventas) vs LHXC (RDA) por prefijo en SQL
- _SQL_PACIENTES y _SQL_RDA: excluyen PREFIJO = 'CMXC'
- _SQL_VENTAS: solo trae PREFIJO = 'CMXC'
- Contrato 050: excluir_ventas=0 para permitir CMXC+050 en Ventas

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-25 08:48:42 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 ebc24bd480 feat: agregar contrato 050 (PARTICULAR COLEGAS) — va a RDA, no a Ventas
Contrato 050 agrupa ~30 laboratorios y clínicas externas (CMXC/LHXC).
Debe enviarse a RDA pero no a Ventas.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-25 08:37:14 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 02b0defef5 fix: ventas CMXC usan NIT_EMPRESA como codTercero en lugar del código de paciente
Las facturas de venta de contratos externos (ej. CMXC) deben ir a nombre
de la empresa referente (NIT sin dígito de verificación), no del paciente.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-24 19:08:02 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 cefc8b664b fix: automation.html usa status string (success/warning/error) no booleano ok
- Fila warning: amarillo, sin botón reenviar
- Tab 'Ya existe' en filtros para ver solo warnings
- Filtros basados en status en lugar de ok boolean
- Toast muestra conteo correcto de 3 estados

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-24 11:02:20 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 6a452cd950 feat: sistema de 3 estados (success/warning/error) para envíos TNS
- _parse_tns_resp retorna 'success'|'warning'|'error' en lugar de bool
- 'ya existe/registrado/autorización' → warning (sin reenvío, no es error real)
- errores reales → error (con reenvío)
- Guarda JSON crudo completo en respuesta_api
- logs.html: badge amarillo para warning, verde para success, rojo para error
- Filtro de historial incluye opción 'warning'
- reenvío en logs.py solo disponible para status='error'
- reenvío en logs.py usa misma lógica _parse_tns_resp y soporta ventas

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-24 10:45:15 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 a37c1bb7d6 fix: _parse_tns_resp distingue status booleano (TNS) de entero HTTP (ASP.NET)
bool(400) era True en Python, haciendo que errores de validación de ASP.NET
(status:400, errors:{campo:[msg]}) se guardaran como success. Ahora:
- status bool → ok directamente
- status int → ok si < 400
- errors dict → mensaje legible "campo: mensaje"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-24 10:34:55 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 2525e053bf fix: agregar codigosucursal al endpoint de ventas en automation
TNS requiere ?codigosucursal= en /v2/facturacion/Ventas/Crear igual que en RdaPaciente/Insertar.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-24 10:21:05 -05:00
Lizandro Guarnizo 6950e5aaed tmp: debug script exploración muestras pendientes Firebird 2026-07-23 12:17:10 -05:00
Lizandro Guarnizo fff34d2003 tmp: debug script para verificar TIPOIDENT en Firebird 2026-07-23 12:09:56 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 59ee62591c chore: bajar intervalo scheduler a 20 segundos
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-23 12:00:09 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 78e9c31d90 fix: usar FECHA_RECEPCION en SQL del scheduler en lugar de filtro Python por HORAINICIORECEPCION
El filtro Python era frágil: si HORAINICIORECEPCION era NULL o tenía formato inesperado, los pacientes no se capturaban. Ahora el filtro de ventana de tiempo va directo en Firebird usando DATEADD sobre FECHA_RECEPCION, que siempre está poblado.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-23 11:38:11 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 cffeae7e94 fix: parallelize WA sync and surface scheduler errors in historial
- whatsapp_sync: send patients concurrently (asyncio.gather + semaphore=10) instead of sequentially — eliminates long waits with many patients
- envios_erp: auto-refresh historial every 60s when scheduler tab is active
- main: wrap scheduler job to catch exceptions and log them to sync_wa_log so failures are visible in historial

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-23 11:34:30 -05:00
Lizandro Guarnizo 5ca97159b4 tmp: debug query paciente 88272630 en Firebird 2026-07-22 23:22:27 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 9bffe4209f fix(automation): parsear respuesta TNS correctamente, tratar 'ya existe' como OK
- _parse_tns_resp() centraliza parsing: lee status/data.success del body JSON
- "ya esta registrado", "ya existe autorización" → ok=True (no bloquea RDA)
- Aplica en los 4 pasos; terceros_fallidos solo acumula errores reales
- Elimina script tmp buscar_paciente.py

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-22 23:12:32 -05:00
Lizandro Guarnizo 988ac672e9 tmp: ver respuesta_api tercero fallido 2026-07-22 23:07:57 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 66d44392ee fix(automation): guardar mensaje_tns en _guardar_envio; eliminar script tmp
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-22 23:01:27 -05:00
Lizandro Guarnizo 36ace04c35 tmp: script buscar paciente en db 2026-07-22 22:52:26 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 9bd247219e fix(automation): skip RDA/preserv si el tercero del paciente falló
Acumula COD_PACIENTE en terceros_fallidos cuando paso1 falla.
En paso2 y paso3, si el paciente está en esa lista se omite el envío
con mensaje claro "Omitido: tercero no creado en TNS".
Evita el error confuso "paciente no existe" en TNS.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-22 22:47:49 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 599391739f feat(logs): filtro por cédula de paciente en historial de envíos
- Agrega columna cedula a tabla envios (migración automática)
- _guardar_envio almacena la cédula en los 4 pasos de automation
- pac_map (COD_PACIENTE→DOCIDENT) para RDA/preserv/ventas
- logs.py busca por cedula LIKE en vez de idrecepcion/contrato
- logs.html etiqueta el input como "Cédula paciente"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-22 22:37:40 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 03655427a5 fix(rips): discapacidad siempre 08, diagnostico default Z017 si vacío
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-22 22:33:59 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 0a234f056c fix: execute_query now handles positional tuple params directly
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 16:26:22 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 329157ca7a fix: use DATEADD(MINUTE, -n, CURRENT_TIMESTAMP) for Firebird interval
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 16:24:09 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 04d2eb5563 fix: remove NUM_FACTURA > 0 filter — sync all receptions by time window
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 16:03:03 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 a880b7fb81 feat: filter exams by time window in SQL (last N minutes), default 10min
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 15:59:11 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 35859e8d75 fix: auto-load libfbclient on macOS from Firebird.framework
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 08:58:26 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 6cbf0732e6 feat: resolve exam prices via TARIFA+EMPRESA JOIN, show company name
- PRECIO now falls back to catalog price (TARIFA) when 0/null
- JOIN EMPRESA + EMPRESA_SUB + TARIFA in exam query
- NOM_EMPRESA propagated to log and historial display

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-18 14:58:10 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 7aa02fe6ac fix: update /debug-fb/recepcion to show all columns and empresa tables
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-18 14:51:07 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 85ae3a0b3e feat: add /debug-fb/tarifas endpoint to explore price tables in Firebird
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-18 14:29:43 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 268451decc fix: render errores_det objects as readable text in historial
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-17 15:39:05 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 33e569c27a fix: historial shows error detail and correct Colombia timestamp
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-17 15:37:00 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 83c8b2aa0b fix: format scheduler times in Colombia UTC-5 server-side
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-17 15:31:40 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 12f5f1388d fix: correct column names in scheduler status query (total, errores)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-17 15:26:34 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 467a24baa4 feat: scheduler live status — endpoint + UI polling every 15s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-17 15:21:32 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 9d79fe932b fix: reduce diagnosticos batch 500→200, add start_from resume param
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-17 15:13:14 -05:00
Lizandro Guarnizo 97f4561283 fix: capture raw PHP response on JSON error in sync-diagnosticos 2026-07-17 10:43:07 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 9a7e4e219b feat: add CIE-10 sync endpoint and migration button in ERP tab
- POST /envios/erp/sync-diagnosticos: reads all 12422 diagnosticos from
  Firebird, sends to WhatsApp in batches of 500 via ingest_diagnosticos.php
- envios_erp.html: new "Migración CIE-10" card with Migrar button and result

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-17 10:27:52 -05:00
Lizandro Guarnizo b65fdf0d9c fix: use uppercase column names for Firebird alias in diagnosticos query 2026-07-17 10:19:04 -05:00
Lizandro Guarnizo e185095e28 fix: use raw RDB$FIELD_NAME key instead of alias for Firebird metadata query 2026-07-17 10:18:10 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 6235b1539c feat: add /debug-fb/diagnosticos endpoint to list CIE-10 from Firebird
Supports ?q=filter and ?limit=N. Returns total count, column names,
and list of {cod, concepto} rows — used to plan DIAGNOSTICO migration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-17 10:11:44 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 6157d2c2f9 fix: show raw PHP response in error message, clean up errores column UI
- sync_paciente: catch JSONDecodeError separately and include HTTP status
  + first 300 chars of raw response so PHP errors are visible in the log
- envios_erp.html: Errores column shows count only (not all inline messages)
  — error detail is already visible in the expandable Ver N row

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-17 09:57:45 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 cd63683869 feat: enrich sync log with exams, diagnosis, EPS and valor per patient
- scheduler.py: after sync_todos(), inject diagnostico, nit_empresa,
  valor_total and examenes_det (cups/nombre/precio) into each detalle entry
- whatsapp_sync.py: guardar_sync_log stores full enriched fields in detalle_json
- envios_erp.html: expanded row shows per-patient card with Dx, EPS, valor
  and a CUPS/examen/precio table — scrollable, max-h-96

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-17 09:52:08 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 e044f21e3e feat: store and display per-patient sync detail in historial
- Add detalle_json column to sync_wa_log via migration
- guardar_sync_log() now stores doc, nombre, action, examenes count per patient
- Historial table shows "Ver N" button that expands a row with patient list,
  action badge (Nuevo/Actualizado/Omitido) and exam count per patient

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-17 09:33:46 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 29b6aa4016 fix: pass user_id=None in scheduler sync log to avoid FK constraint
sync_wa_log.user_id has a FK to users; passing 0 fails since no user
with id=0 exists. Scheduler runs without a user context, so use NULL.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-17 09:25:17 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 863e012c12 fix: handle Firebird Decimal and datetime types in JSON serialization
- PRECIO and VALORTOTAL are Decimal from fdb driver; convert via _safe_num()
- HORAINICIORECEPCION is a datetime object; use _fmt_hora_str() for HH:MM:SS
- _parse_hora() now handles datetime objects directly (no str() roundtrip)
- Same fixes applied to pacientes.py exam builder
- sync-now endpoint catches exceptions and returns traceback as JSON

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-17 09:10:41 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 fc18acc761 fix: use CAST(FECHA_RECEPCION AS DATE) for Firebird timestamp comparison
FECHA_RECEPCION is a TIMESTAMP field, so comparing directly with
CURRENT_DATE (DATE) always returns 0 rows in Firebird. Cast to DATE first.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-16 21:45:25 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 37c4124559 debug: add /debug-fb/recepcion diagnostic endpoint
Shows recent recepciones without filters, CURRENT_DATE from Firebird,
and counts with/without NUM_FACTURA filter to diagnose zero-result sync.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-16 21:43:40 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 dc18d128fb feat(envios/erp): add manual sync trigger endpoint and test UI
- POST /envios/erp/sync-now?ventana_min=N calls sync_recientes with configurable window
- sync_recientes() now returns a result dict (ok, total, created, updated, skipped, errores, detalle)
- ERP tab shows a "Prueba manual" card with ventana selector (2m / 30m / 2h / hoy) and result breakdown

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-16 21:40:54 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 8e27225326 feat: módulos de envío TNS/ERP Lab + sync de médico, empresa y valor total
- Hub /envios/tns con 5 sub-tabs (Terceros, Transacción RIPS, Facturas Venta, Prueba RDA, Automatización) via iframe lazy
- Hub /envios/erp con sub-tabs Pacientes y Sync Automático (historial scheduler)
- Modo embed (?embed=1) en base.html para cargar páginas sin sidebar/header dentro de iframes
- Sidebar simplificado: 6 ítems individuales reemplazados por módulos TNS y ERP Lab
- Scheduler y endpoint /pacientes/examenes ahora incluyen médico ordenante (DOCIDMEDICO), empresa/EPS (NIT_EMPRESA) y valor total (VALORTOTAL) desde Firebird

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-16 21:13:48 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 31c0b71c90 fix(automation): quitar filtro por convenio del panel de control
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 15:26:55 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 c584097426 fix(automation): excluir ventas con NUM_FACTURA=0 (numero 00000)
No enviar facturas cuyo número sea 0 — quedarían como "00000" en TNS.
Filtro aplicado en preview, run y reenviar-venta.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 15:22:46 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 6dee8fba82 feat(automation): resultados con filtro Errores/Enviados/Todos y filas descriptivas
- Lista unificada reemplaza los dos paneles separados (failures/successes)
- Tabs de filtro: Errores (default si hay), Enviados, Todos — con contadores
- Filas de error: borde rojo, badge del paso, factura+paciente, mensaje inline, botón Reenviar
- Reenvío actualiza la fila en tiempo real: rojo → verde sin recarga
- btn-run solo se habilita si los pasos activos tienen datos reales

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 15:12:13 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 fe31af2f9a feat(automation): paso chips, results failure-first con reenvío por item
- 4 chips toggleables (Terceros/RDA/Pre-servicios/Ventas) que controlan
  qué pasos se ejecutan en vista previa y en el envío masivo
- Backend: parámetro `pasos` en run_automation para saltarse pasos no
  seleccionados; agrega `idrecepcion`/`codigo` a cada detalle item
- Nuevos endpoints POST /automation/reenviar-tercero, /reenviar-rda y
  /reenviar-venta para reenvío individual con SQL BY_ID para cada tipo
- Panel de resultados rediseñado: barra de resumen por paso, sección
  de fallos expandida con botón "Reenviar" por item (actualiza row in-
  place), sección de exitosos colapsada por defecto

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 15:03:49 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 f8c76f7ce2 fix: ensure_defaults no sobreescribe toggles de contratos al reiniciar
Los campos excluir/sin_contrato/excluir_ventas solo se aplican en INSERT
(contratos nuevos del seed). En contratos existentes solo se actualizan
los datos descriptivos (nit, tipo_usuario, descripcion) para preservar
la configuracion que el usuario haya definido desde la UI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 14:38:09 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 73062af8bc feat: paso 4 ventas en automation + fixes varios
- Automation: agrega Paso 4 (Ventas/Crear) con fetch _SQL_VENTAS,
  filtro por excluded_ventas_set, loop de envío y log de actividad
- Automation: _guardar_envio ahora almacena idrecepcion y contrato
  para que /ventas reconozca registros enviados por automation
- Contratos: corrige NameError en toggle_excluir (faltaba request: Request)
- Ventas: agrega check if not q en send_one y send para evitar TypeError
- Ventas HTML: agrega columna Contrato en la tabla de facturas
- json_generator: normaliza etnia >2 chars a '99' (ej: 999 → 99)
- json_generator: agrega campo ciudadExp usando el mismo cod_ciudad

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 14:29:39 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 21eb99d18d fix: agregar tipo ventas al historial de logs
Badge verde para ventas, opción en filtro de tipo.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 11:57:14 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 f103d536c7 feat: excluir_ventas independiente por contrato
- Nueva columna excluir_ventas en tabla contratos (migración automática)
- load_excluded_ventas_set() para filtrar en /ventas
- Toggle independiente en /contratos para RDA y Ventas por separado
- Modal edición con checkbox excluir_ventas
- 040 marcado excluir_rda=1, excluir_ventas=0 en seed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 11:56:28 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 af71968c7f fix: TRIM en CODCONTRATO de queries ventas 040
Firebird rellena campos CHAR con espacios, causando que '040' != '040   '.
TRIM(e.CODCONTRATO) = '040' soluciona el filtro.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 11:37:08 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 6fdca61636 fix: ampliar CHECK constraint para soportar tipo ventas
Las tablas queries y envios tenían CHECK constraints que solo permitían
terceros/transaccion. Se agrega ventas al constraint vía migración automática
en _migrate para bases de datos existentes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 11:31:05 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 6b84ecfd90 feat: módulo de facturas venta (Ventas/Crear) para contrato 040
- generar_factura_venta en json_generator.py con mapeo completo del JSON
- Queries default tipo 'ventas' (por fecha y por número) filtradas a contrato 040
- Ruta /ventas con preview, send-one y send masivo
- Template ventas.html con tabla, resumen y modal JSON
- Link en navegación lateral

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 11:16:42 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 6fb18a7af6 revert: especialidad siempre usa el default de config
Revertir el uso de COD_ESPECIALIDAD desde la BD; la especialidad
siempre debe venir del valor configurado (especialidad_default).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 10:23:33 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 3e85e0a3f6 fix: corregir claves de config en preview_automation
preview_automation usaba _defecto en vez de _default, causando que
profesional y especialidad salieran null en la vista previa del automation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 10:20:53 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 3313337672 fix: usar COD_ESPECIALIDAD de la BD en detallePedido
La especialidad ahora toma el valor del campo COD_ESPECIALIDAD de la tabla
MEDICO (ya presente en todos los SELECTs), con fallback al default de config.
El profesional sigue viniendo de configuración en todos los flujos.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 10:19:42 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 daa50a70cf Add pre-servicios support in /transaccion + letter search fix
- Add 'RDA Pre-servicios por fecha' and 'RDA Pre-servicios por número'
  default queries joining PRESSERV_DIAN (ID_PS, PS_PREFIJO, PS_NUMERO)
- Refactor _query_rows: only pass params the query actually uses;
  prefix filter works for both PREFIJO and PS_PREFIJO columns
- Add _is_preserv(), _agrupar(), _build_rda() helpers that detect
  pre-servicio rows and produce correct prefijo/numero overrides
- All 4 send endpoints (preview, send-one, send, send-direct) now
  group by ID_PS for pre-servicio queries and pass correct RDA fields
- RCXC prefix still maps to '00' in the RDA codigoPrefijo

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 10:14:13 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 987959a975 Double json_enviado storage limit from 5000 to 10000 chars
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 10:03:32 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 cb3b327938 Add reenviar button in /logs for failed envios
POST /logs/reenviar/{id} re-sends stored JSON to TNS and updates
status to 'success' in-place if it succeeds. Button appears only
on error rows with saved JSON; updates row color and badge without reload.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 09:24:22 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 3d848fbf2d Propagate sin_contrato_set to transaccion and test-rda routes
All generar_rda_paciente calls in transaccion.py (4) and test_rda.py (2)
now pass sin_contrato_set so contract 040 sends numeroContrato: null
consistently across all send paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 09:22:00 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 c18da17317 Fix pre-servicios preview: clear store once, clean row HTML structure
- Move _rdaJsonStore={} reset to before both sections so ps-json-* keys
  are not wiped when pacientes section renders
- Replace divide-y wrapper divs with explicit border-b on each row,
  eliminating duplicate/misplaced dividers in the pre-servicios list

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 09:18:58 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 c4c6a2cd35 Send codigoPrefijo as '00' for RCXC pre-servicios
RCXC is an internal Firebird prefix not recognized by TNS; map it to '00'
in the RDA JSON. SC prefix remains unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 09:13:35 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 2a7553267b Fix tipoDocumento PE/PT: map to single char 'E' for TNS API compatibility
TNS API (C#) expects System.Char for tipoDocumento; "PE" and "PT" caused
400 validation errors. Mapped both to "E" (Cédula Extranjería).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 08:31:33 -05:00
Lizandro Guarnizo 2794e9f9dd fix: verificar rows_ps en condicion de datos vacios para no saltar paso 3 2026-07-10 21:39:11 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 316205466f fix: tipo 'preserv' invalido en CHECK constraint de envios
- Paso 3 usaba tipo='preserv' que no esta en CHECK(tipo IN ('terceros','transaccion'))
- Cambia a 'transaccion' (factura RCXC-XXXXX distingue el registro)
- _guardar_envio con try/except para que error de DB no detenga el loop de envios

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-10 21:37:42 -05:00
Lizandro Guarnizo a47e0a843a fix: mismo patron store+textContent para JSON de pre-servicios 2026-07-10 21:35:45 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 e6860a6957 fix: JSON preview recepciones via store (evita innerHTML injection)
feat: paso 1 registra terceros EPS de pre-servicios junto a particulares

- _rdaJsonStore guarda JSON por key, toggleRdaJson usa textContent
- escHtml() para caracteres especiales en diagnostico
- _SQL_PACIENTES_EPS obtiene pacientes de PRESSERV_DIAN
- rows_pac_todos fusiona particulares + EPS deduplicando por CODIGO

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-10 21:33:00 -05:00
Lizandro Guarnizo ef02303dde feat: mostrar JSON de recepciones paso 2 en preview (expandible) 2026-07-10 21:25:22 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 9f2bd5164e feat: opcion 'sin contrato' para enviar numeroContrato null en TNS
- Agrega columna sin_contrato en tabla contratos (migration automatica)
- Contrato 040 marcado excluir=0, sin_contrato=1 en seed
- load_sin_contrato_set() retorna contratos que deben ir con null
- generar_rda_paciente acepta sin_contrato_set y fuerza numeroContrato=null
- Automation paso 2 y 3 pasan sin_contrato_set al generador
- Pagina contratos: columna y toggle "Sin contrato", checkbox en modal editar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-10 21:22:09 -05:00
Lizandro Guarnizo eeabb6268e debug: mostrar CODCONTRATO y si esta excluido en debug-cmxc 2026-07-10 21:12:05 -05:00
Lizandro Guarnizo 8d9d2ae89c debug: mostrar envios recientes y total en debug-cmxc 2026-07-10 21:08:13 -05:00