Propósito
Importar masivamente un fee schedule (UCR u otro tipo) a Open Dental para un cliente activo, usando el script
create_fee_schedule.py. Este SOP garantiza que no se sobreescriban precios existentes
y que los errores se detecten antes del write.
Requisitos: Cliente con OD API habilitada · CSV o PDF con los fees · Acceso al repo + venv activado.
Flujo visual
tiene OD API] --> B[2. Listar fee schedules
existentes] B --> C{Schedule
existe?} C -->|No| D[Crear manual
en OD UI] C -->|Sí| E[3. Anotar
FeeSchedNum] D --> E E --> F[4. Preparar CSV
desde PDF o manual] F --> G[5. DRY-RUN
no toca nada] G --> H{Output
OK?} H -->|Typos /
precios raros| F H -->|Códigos faltantes
en OD| I[Activar códigos
en OD Definitions] I --> G H -->|Todo OK| J[6. Import real
--confirm] J --> K[7. Verificar
en OD UI] K --> L[8. Opcional:
Asignar como UCR] style A fill:#4B6AF7,color:#fff,stroke:#415EDB style G fill:#F1CCB1,color:#1a1a2e,stroke:#c9690a style J fill:#2d8659,color:#fff,stroke:#2d8659 style L fill:#415EDB,color:#fff,stroke:#415EDB
Pre-checks
| Check | Cómo verificar |
|---|---|
| Cliente existe | ls clients/<client-id>.json |
| OD API habilitada | En el JSON: "has_od_api": true + customer_key presente |
| venv activado | source .venv/bin/activate (prompt empieza con (.venv)) |
| CSV listo | Columnas obligatorias: ProcCode, Amount |
Pasos detallados
1Verificar cliente y listar fee schedules existentes
Confirma que el cliente está bien configurado y muestra qué fee schedules ya tiene Open Dental.
python create_fee_schedule.py <client-id> --list
FeeSchedNum Type Hidden Description ------------- -------------- ------- ---------------------------------------- 53 Normal Office Fees 57 Normal Delta Dental PPO 66 Normal Office Fee 2026 ← el nuevo
2Crear el fee schedule (si no existe)
Política BrandaCare: el fee schedule se crea manualmente en OD UI (no por API) para evitar duplicados accidentales.
En Open Dental:
- Setup → Fee Schedules → Add
- Description: nombre claro (ej. "Office Fee 2026")
- Type: Normal (UCR) o Insurance (PPO)
- Save → ANOTAR EL FeeSchedNum
python create_fee_schedule.py <client-id> --create "Office Fee 2026" — confirmá antes con el cliente para evitar nombres duplicados.
3Preparar el CSV
Opción A — desde PDF (lo más común con clientes nuevos):
python parse_pdf_fee_schedule.py "Dr Smith Fees 2026.pdf" clients/smith_fees_2026.csv
El parser detecta líneas D#### Description $Amount y marca posibles typos automáticamente (precios >$5000 o <$10).
Opción B — CSV manual:
ProcCode,Amount,Description D0120,150.00,Periodic oral evaluation D0150,200.00,Comprehensive oral evaluation ...
4Dry-run (CRÍTICO — no toca nada)
python create_fee_schedule.py <client-id> \
--csv clients/smith_fees_2026.csv \
--to <FeeSchedNum> \
--dry-run
Revisar el output con cuidado:
- OK
[dry] D0120 = $150.00— línea va a importar - SKIP
⚠ código X no encontrado en OD— código ADA no activo en este cliente - TYPO Cualquier precio >$5000 que no sea cirugía/protésica grande
Al final ves:
✅ 516 fees simulados, 17 saltados 📄 Lista guardada en: clients/smith_fees_2026_SKIPPED.csv
5Import real — --confirm
- El fee schedule está vacío en OD (si tiene fees, se duplican).
- Los typos del parse están corregidos.
- El FeeSchedNum coincide con el del paso 1.
python create_fee_schedule.py <client-id> \
--csv clients/smith_fees_2026.csv \
--to <FeeSchedNum> \
--confirm
Progreso cada 50 fees. Tarda ~6 min por 500 fees.
6Verificar en OD
- OD UI → Setup → Fee Schedules → tu schedule → debe tener ≈ N fees creados
- Spot check: buscar 3-4 códigos al azar y confirmar el precio
- Revisar
<csv>_SKIPPED.csvy mandar al cliente para activar los códigos faltantes (opcional)
7Opcional — Asignar como UCR del provider
Esto hace que los nuevos procedures usen este fee schedule como precio default. No afecta procedures existentes.
python create_fee_schedule.py <client-id> \
--assign-ucr <FeeSchedNum> \
--to-provider <ProvNum> \
--confirm
Troubleshooting
| Error | Causa | Fix |
|---|---|---|
cliente no encontrado | Typo en client_id | ls clients/ y copiar el nombre exacto |
código X no encontrado en OD | Código ADA no activo en cliente | OD → Setup → Definitions → Procedure Codes → activar |
este cliente no tiene OD API | Falta customer_key en JSON | Pedirla al cliente (Google Secret Manager si interna) |
| Precios duplicados post-import | FeeSched destino no estaba vacío | Borrar manual en OD y re-importar |
ReadTimeout intermitente | OD API lenta | Re-correr — el script reintenta automático |
Reglas de seguridad
- DEFAULT Todos los comandos son read-only por default.
- --dry-run Siempre primero. Sin excepción.
- --confirm Required para cualquier write. Doble-check el client_id y FeeSchedNum antes.
- CSV Validar warnings del parser PDF antes del import.
Comandos copy-paste
# 1. Listar python create_fee_schedule.py <client-id> --list # 2. Parsear PDF (si aplica) python parse_pdf_fee_schedule.py "fee_schedule.pdf" output.csv # 3. Dry-run python create_fee_schedule.py <client-id> --csv path/to.csv --to <num> --dry-run # 4. Import real python create_fee_schedule.py <client-id> --csv path/to.csv --to <num> --confirm # 5. Asignar como UCR (opcional) python create_fee_schedule.py <client-id> --assign-ucr <num> --to-provider <prov> --confirm
Histórico de imports
| Fecha | Cliente | FeeSched | Resultado |
|---|---|---|---|
| 2026-06-11 | Casas Family Dentistry | 66 — Office Fee 2026 | 516 fees creados, 17 skipped |
