Alta de médicos y asistentes desde Excel
Un hospital suele entregar dos hojas: la nómina de médicos (cédula, especialidad, piso, consultorio,
correo y teléfono) y las cuentas de sus asistentes. El primer caso fue Manta Hospital Center, con
backend/scripts/setup-mhc-tenant.ts.
cd backend
npm run setup:mhc -- --doctors "<nómina>.xlsx" --assistants "<asistentes>.xlsx" # dry-run
npm run setup:mhc -- --doctors ... --assistants ... --apply
npm run setup:mhc -- ... --env-file <archivo .env del entorno> # otro entorno
npm run setup:mhc -- ... --move-from-other-tenant [email protected] # cuenta creada en otro tenant por error
Los Excel no se versionan, porque traen cédulas y teléfonos reales: se pasan por argumento. Tampoco se copian a la documentación.
Qué hace
| Paso | Resultado |
|---|---|
| Consultorios | Crea Consultorio <n> (recurso tipo consultorio) para cada consultorio nuevo. Los que quedan sin médico solo se reportan |
| Médicos que coinciden | Actualiza especialidad, metadata.floor/office/secretary_phone y la ficha de contacto (scheduling_resources.contact_id), y conserva el nombre de la base |
| Médicos nuevos | Crea recurso, contacto y especialidad. No crea horarios: sin ellos el bot no los ofrece |
| Médicos sobrantes | Borrado físico. Si tienen citas (la FK es RESTRICT), solo los desactiva |
Rol Asistente | Preset de onboarding más contact.write, para que la recepción pueda crear pacientes desde la agenda |
| Asistentes | Cuenta con invited_flow (ver Alta de usuarios), una sola membership y user_metadata.default_floor |
La normalización y el emparejamiento son funciones puras, con tests, en
backend/src/onboarding/roster/doctor-roster.ts. Sirven para cualquier cliente con una hoja
parecida.
Trampas de los datos
- Cédula sin el 0: Excel guarda la cédula como número y se come el cero (
105368690era0105368690). El script lo repone. Una cédula que no pasa el verificador módulo 10 no se guarda, porque suele ser un teléfono pegado en la columna equivocada y ocuparía el índice únicouq_contacts_documentoque después necesita el paciente real. Se reporta. - Nombres distintos: el directorio trae el nombre completo y el cliente la forma corta, con erratas («Lissete» / «Lisette», «Maria F.» / «Maria Fernanda»). El emparejamiento tolera diferencias por largo de palabra, pero exige dos palabras idénticas. Eso evita casar a hermanos que comparten los dos apellidos. Si una fila tiene dos candidatos, no se adivina: queda como ambigua en el informe.
- Especialidades con erratas: «Neumólogo», «Anesteciología», «Urólogía». Hay alias hacia el catálogo. Lo que de verdad no existe (por ejemplo «Cosmeatría») se crea como especialidad nueva, a 30 minutos.
- Asistente ya creada en otro tenant: el script no la toca y lo reporta. Si fue un error y la
cuenta tiene una sola membership,
--move-from-other-tenantla muda.
Pisos
El piso de cada médico va en metadata.floor y alimenta el filtro Piso del calendario y del
listado de citas (frontend/src/sections/scheduling/resource-floor.ts). El filtro no es un permiso:
las asistentes tienen view_all, y el piso solo ordena lo que ya ven. Se descartaron los workspaces
por piso por estas razones:
- Ningún código asigna
scheduling_resources.workspace_id. - Los guards de escritura (
appointment-write.guard.ts) no tienen rama de workspace. - La agenda esconde a los colegas cuando solo hay
view_own. - Los chats de pacientes que aún no tienen cita quedarían invisibles para todas.
- El bot no se divide por workspace: sus herramientas trabajan por tenant.