EN
SOP-IT-006 · v2.0
Actualizado 5 Jul 2026

BCBOT — SOP de Verificación de Elegibilidad

Para consultorios con Dentrix · Playbook completo para replicar en cualquier cliente
Producto: Robot autónomo que cada tarde descarga las citas del día siguiente desde Dentrix (que NO tiene API), verifica la elegibilidad del seguro de cada paciente vía Stedi (BC ClearingHouse), genera el PDF de cobertura y manda 2 emails al equipo. 100% sin intervención.
Este SOP es el playbook para replicar BCBOT en cualquier cliente con Dentrix. Seguilo de arriba a abajo para un cliente nuevo.

1. Cómo funciona (resumen del flujo diario)

A las 6:00pm el Task Scheduler lanza el robot, que hace todo solo:

1Abre/loguea Dentrix

Appointment Book + Office Manager. Si ya está abierto, lo usa.

2Daily Huddle Report con fecha = día siguiente

Preview → manda los route slips al Batch Processor.

3Espera la carga del batch

Espera a que la barra termine de cargar todos los route slips (≥90 s).

4Abre el último route slip

Ctrl+End + Enter → espera el render.

5Imprime a PDF

Microsoft Print to PDF → C:\BCBOT\ROUTESLIPS.pdf (espera a que termine de escribirse).

6Lanza el procesamiento Python

Parsea el route slip, cruza con el roster (member ID) y el crosswalk (payer ID de Stedi), consulta elegibilidad, genera PDFs de cobertura (sin logo de Stedi).

7Manda 2 emails a hello@brandacare.com

  • [ESCALACIÓN] — los que NO se pudieron verificar (falta dato, inactivo, payer no soportado, a reintentar).
  • [PDF PARA SUBIR] — los verificados OK, con los PDFs adjuntos para subir a Dentrix.

8Cierra ventanas sueltas

Para dejar limpio el día siguiente.

Regla clave: solo procesa las citas SIN la nota "-BC". Las que ya tienen "-BC" (cualquier variante: - BC, /BC, INS ACTIVE BC) se saltean = ya verificadas. Cuando el equipo resuelve un escalado, le pone "-BC" para que no se reprocese.

2. Requisitos por cliente

3. Instalación (una vez por cliente)

3.1 Software

1Instalar Python 3.x

Marcar "Add to PATH". Anotar la ruta del python.exe.

2Instalar librerías

pip install pdfplumber reportlab pypdf

Agregá --break-system-packages si hace falta.

3Instalar AutoHotkey v2

autohotkey.com

4Explorer → View → File name extensions = ON

Para ver .txt/.ahk reales.

3.2 Carpeta y archivos

  1. Crear C:\BCBOT.
  2. Copiar todos los archivos del sistema (ver §10) a C:\BCBOT.
  3. Ajustar en run_robot.bat y run_daily.bat la ruta al python.exe del cliente.

3.3 Credenciales (archivos de texto, NUNCA en el código)

Crear en C:\BCBOT (Notepad → Guardar como, tipo "Todos los archivos"):

ArchivoContenido
dentrix_user.txtusuario de Dentrix
dentrix_pass.txtcontraseña de Dentrix
stedi_key.txtAPI key de Stedi
smtp_user.txtemail Gmail (ej. hello@brandacare.com)
smtp_pass.txtApp Password de Gmail (16 chars, sin espacios)
Nota de seguridad: el robot lee las credenciales por patrón (dentrix_user*), así que aguanta variaciones chicas de nombre. Aun así, verificá que existan y no estén vacías (si falta dentrix_pass.txt, el login aborta al instante). Riesgo aceptado: la pass de Dentrix queda en texto plano en la máquina.

3.4 Config del provider

En fase0_build_270.py, editar el bloque PROVIDER:

PROVIDER = {
    "organizationName": "NOMBRE LEGAL DEL CONSULTORIO",
    "npi": "NPI_DEL_PROVIDER",
    "taxId": "TIN_SIN_GUION",
}

Y CLINIC en fase0_run.py (nombre corto que aparece en los emails).

4. Datos por cliente (roster + crosswalk de payers)

Esto es lo que hace que el robot verifique a la MAYORÍA, no solo a algunos.

4.1 Roster (member IDs) — reporte "Insurance Carrier List"

En Dentrix → Office Manager → Reports → Reference → Insurance Carrier List:

Parsear a cache:

python fase0_parse_roster.py roster_full.pdf roster_cache.json

Genera roster_cache.json (Chart# → member ID + payer ID + carrier). Refrescalo cada 1–3 meses o cuando entren muchos pacientes nuevos (los nuevos no aparecen hasta re-generar el roster).

Nota crítica: el "Insurance Carrier List" completo (todos los carriers) es la diferencia entre verificar pocos o muchos. Un roster filtrado deja fuera carriers enteros (ej. Delta Dental, Cigna) y esos pacientes salen "falta member_id".

4.2 Crosswalk de payers (nombre de carrier → payer ID de Stedi)

El payer ID del roster de Dentrix es basura ("SOURCE") en ~2/3 de los casos, así que el payer ID real se resuelve por el nombre del carrier:

Prioridad de resolución del payer (ya implementada en fase0_build_270.py):

  1. Payer REAL del roster del paciente (si es válido, no "SOURCE") — manda.
  2. Crosswalk revisado por nombre (exacto o sin espacios: "Met life" = "MetLife").
  3. Match contra payer_map.csv maestro (subset de tokens, seguro).
  4. Crosswalk manual local.

4.3 Payers NO soportados por Stedi

En carrier_map.py, mantener la lista de carriers/payers que Stedi no soporta (ej. Solstice / 76578). Esos se escalan directo sin consultar (se verifican en el portal propio del payer). Agregá los que el cliente use y Stedi rechace.

4.4 Self-pay / Medicaid

Se detectan por nombre de carrier y se listan aparte (no se escalan como "falta dato") — no tienen seguro que verificar.

5. Convención de la nota "-BC"

El equipo marca las citas ya verificadas con "BC" suelto en la nota (cualquier variante: -BC, - BC, /BC, INS ACTIVE BC). El robot saltea esas y solo procesa las SIN marca. Entrenar al front-desk en esta convención es parte del onboarding.

Detección robusta: el robot detecta la marca tanto en la nota de la cita (NOTES:) como en las notas del paciente (Patient Notes:), y aunque quede en una segunda línea. No confunde BCBS ni IDs tipo BC123 — solo cuenta "BC" como palabra suelta.

6. Automatización

6.1 Auto-login de Windows (recomendado, para caídas)

Si la máquina se reinicia sola, Windows debe quedar logueado para que el robot pueda manejar ventanas. Configurar auto-login (netplwiz → destildar "Users must enter a user name and password", o AutoAdminLogon en el registro).

Tradeoff: la máquina arranca sin pedir password de Windows.

6.2 Tarea programada a las 6pm

En cmd (como admin):

schtasks /Create /TN "BCBOT Diario" /TR "C:\BCBOT\run_daily.bat" /SC DAILY /ST 18:00 /F

run_daily.bat lanza el robot en modo AUTO (sin carteles) que corre todo y cierra. La tarea es permanente: sobrevive reinicios y corre cada día sola.

Requisito: la sesión de Windows debe estar iniciada (no en pantalla de login) a las 6pm. Con auto-login + máquina prendida, cubierto. Si la máquina está APAGADA a las 6pm, ese día se saltea — opcionalmente, en Task Scheduler → la tarea → Settings → tildar "Run task as soon as possible after a scheduled start is missed" para que recupere al prender.

7. Los 2 emails (salida diaria)

[ESCALACIÓN] {CLINIC} — {fecha}

Pacientes a resolver a mano, agrupados por motivo (no se pudo verificar / inactivo / payer no soportado / reintentar). El equipo los verifica manual y les pone "-BC".

[PDF PARA SUBIR {CLINIC} {fecha}]

Verificados OK, con los PDFs de cobertura adjuntos (logo de Stedi tapado) para subir al archivo del paciente en Dentrix.

Cliente-facing: en el texto al cliente nunca se menciona "Stedi": se usa "BC ClearingHouse".

Si el SMTP falla, los emails quedan en C:\BCBOT\out\ (email_1_escalacion.txt, email_2_pdfs_para_subir.txt) y los PDFs en out/ para mandarlos a mano.

8. Alertas

9. Mantenimiento y troubleshooting

Rutina:
  • Refrescar el roster cada 1–3 meses (§4.1)
  • Agregar al crosswalk los carriers nuevos que aparezcan escalados por "falta payer_id"
  • Agregar a la lista de no-soportados los payers que Stedi rechace consistentemente
SíntomaCausa / Fix
Login falla al instanteFalta dentrix_pass.txt (o vacío). Recrearlo.
No abre DentrixEl login se llama distinto ("Appointments, Open" vs "Office Manager, Open"): el robot acepta ambos. Verificar credenciales y ruta de Office.exe.
ROUTESLIPS.pdf en 0 KBImprimió antes de renderizar, o el archivo estaba abierto en Edge (bloqueado). El robot espera a que el PDF termine de escribirse. Cerrar Edge.
Guarda route slip viejoEl batch estaba cargando aún. El robot espera ≥90 s tras Preview.
Emojis rompen el logResuelto (prints en ASCII + PYTHONIOENCODING=utf-8).
Payer cambia entre corridasResuelto: el payer del roster manda sobre la adivinanza por nombre.
"falta member_id"Paciente no está en el roster (nuevo) → refrescar roster, o cargar el seguro en Dentrix. El route slip NO imprime el member ID.
"DESCONOCIDO"El payer respondió pero no determinó cobertura (a veces payer ID de otro estado, ej. BCBS). Revisar a mano.
"payer no soportado"Stedi no soporta ese payer (ej. Solstice). Verificar en el portal del payer.
HTTP 401 StediLa API key necesita prefijo Key (ya contemplado). Regenerar key si sigue.
SMTP 535Regenerar el App Password de Gmail (16 chars, sin espacios).

10. Inventario de archivos (C:\BCBOT)

Robot / automatización

ArchivoFunción
robot.ahkRobot AutoHotkey (login + descarga + orquestación). TEST_DATE="" = día siguiente.
run_daily.batLanza el robot en modo AUTO (lo dispara el Task Scheduler).
run_robot.batCorre solo el procesamiento Python sobre ROUTESLIPS.pdf.
alert_login.py / alert_login.batEmail de alerta si no puede abrir Dentrix.

Pipeline Python

ArchivoFunción
fase0_run.pyOrquestador (parsea, verifica, arma emails). CLINIC acá.
fase0_parse_route_slip.py / fase0_parse_schedule.pyParser de route slips.
fase0_parse_roster.pyParser del "Insurance Carrier List" → roster_cache.json.
fase0_build_270.pyJoin route slip + roster + crosswalk → request 270 (config PROVIDER acá).
carrier_map.pyCrosswalk carrier → payer ID (roster + maestro), self-pay, no-soportados.
stedi_client.pyLlamadas a Stedi (elegibilidad + PDF de cobertura).
pdf_postprocess.pyTapa el logo de Stedi.
fase0_pdf.pyPDF de respaldo si el de Stedi falla.
fase0_email.pyArma y manda los 2 emails.

Datos

ArchivoFunción
roster_cache.jsonRoster parseado (Chart# → member ID + payer ID).
payer_map.csvLista maestra carrier → payer ID de Stedi.
carrier_to_payer_REVIEW.csvCrosswalk revisado del cliente.

Credenciales (§3.3) — 5 archivos .txt.
SalidaC:\BCBOT\out\ (logs, emails en .txt, PDFs de cobertura).

11. Checklist de onboarding de un cliente nuevo

#Paso
1Acceso remoto a la máquina con Dentrix
2Python + AutoHotkey v2 instalados; ruta de python.exe en los .bat
3C:\BCBOT con todos los archivos (§10)
45 archivos de credenciales creados
5PROVIDER (NPI/TIN/nombre) y CLINIC configurados
6Roster generado (Insurance Carrier List, ALL) → roster_cache.json
7Crosswalk de payers revisado (carrier_to_payer_REVIEW.csv)
8Lista de payers no-soportados del cliente
9Front-desk entrenado en la convención "-BC"
10Auto-login de Windows configurado
11Tarea de las 6pm programada (schtasks)
12Corrida de prueba OK (llegan los 2 emails, PDFs con peso real)