Saltar al contenido principal

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​

PasoResultado
ConsultoriosCrea Consultorio <n> (recurso tipo consultorio) para cada consultorio nuevo. Los que quedan sin médico solo se reportan
Médicos que coincidenActualiza especialidad, metadata.floor/office/secretary_phone y la ficha de contacto (scheduling_resources.contact_id), y conserva el nombre de la base
Médicos nuevosCrea recurso, contacto y especialidad. No crea horarios: sin ellos el bot no los ofrece
Médicos sobrantesBorrado físico. Si tienen citas (la FK es RESTRICT), solo los desactiva
Rol AsistentePreset de onboarding más contact.write, para que la recepción pueda crear pacientes desde la agenda
AsistentesCuenta 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 (105368690 era 0105368690). 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 único uq_contacts_documento que 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-tenant la 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.