d85a7196f0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
139 lines
10 KiB
Markdown
139 lines
10 KiB
Markdown
# Conexiones externas (fuentes de datos de otros sistemas)
|
||
|
||
> Leer cuando: se trabaje en traer/consultar datos de sistemas externos (pacientes, empleados de
|
||
> nómina, FoxPro u otra tecnología). No leer si: la tarea no toca datos externos.
|
||
> Contrato técnico de los conectores: [`data/conectores/README.md`](../data/conectores/README.md).
|
||
|
||
Estado (2026-10-29): **conector FoxPro 1.1.0 instalado y funcionando en Exilaser** (ver abajo).
|
||
**Módulo del sistema hecho en dev** (migración 038, `backend/src/modules/integrations`, job
|
||
`integrationSync`), sin commit ni producción.
|
||
|
||
## Arquitectura
|
||
|
||
El sistema **no se conecta directo** a las bases de origen. En cada servidor origen se instala un
|
||
**conector** (API HTTP de solo lectura) y el sistema habla con él por un contrato único (v1).
|
||
Para otra tecnología (SQL Server, Excel, etc.) se desarrolla otro conector con el mismo contrato;
|
||
el sistema no cambia. Ver decisión #2 en `DECISIONES.md`.
|
||
|
||
- Primer caso: Exilaser, Windows Server `192.168.0.253` (SAGA/SistViso en FoxPro), alcanzado por
|
||
la VPN WireGuard. Conector en `C:\api_project\foxpro`, puerto `8455`.
|
||
- Fuentes reales (revisadas por SSH, solo estructura, 2026-10-29):
|
||
|
||
| Fuente | Ruta | Tabla | Registros | Codificación | Campos útiles |
|
||
|---|---|---|---|---|---|
|
||
| Nómina | `C:\Sistema\Nomina\Datos\Exilaser` | `empleado.DBF` (VFP 0x30, sin memo) | 31 | cp1252 | `EMPCED`, `EMPAPE`, `EMPNOM`, `EMPTEL`, `EMPTEL1`, `EMPFECNAC`, `EMPCARGO`, `EMPDEPART`, `EMPINGRESO`, `EMPSALIDA`, `EMPACTIVO` |
|
||
| SAGA clientes | `C:\Sistema\Datos\exilaser` | `clientes.DBF` (VFP 0x30, sin memo, ~20 MB) | 32 985 | **cp850** | `CLICOD`, `CLIRUC`, `CLINOM`, `CLITEL`, `CLIEMAIL`, `CLIDIR`, `CLICIU`, `CLIPERSONA`, `CLITIPRUC`, `CLISEXO`, `INACTIVO`, `CLIESTADO`, `FECHAACT` |
|
||
|
||
- **No exponer** de nómina: `EMPSUELDO`, `EMPBANCO`, `EMPCUENT`, `EMPTIPOCUE`, `EMPNUMIESS`,
|
||
`EMPLET*`, `FIJO1-5`, `EMPCARGAS`, `EMPESTADO` (es estado civil) (van en `denyFields` o se usa lista de campos permitidos).
|
||
- Nómina **no tiene correo**: al crear un usuario desde nómina el correo se escribe a mano.
|
||
- Clientes: el nombre viene en **un solo campo** (`CLINOM`), sin nacimiento; incluye empresas
|
||
(RUC) — para pacientes filtrar personas naturales (`CLIPERSONA`/`CLITIPRUC`). El orden
|
||
apellidos/nombres de `CLINOM` se confirma con una muestra al instalar.
|
||
- `exilaser14`…`exilaser25` son cierres de años anteriores: **no** se exponen.
|
||
- `clientes.DBF` cambia todo el día (SAGA escribe): conviene modo **importar** o caché con
|
||
recarga mínima, para no copiar 20 MB en cada consulta.
|
||
|
||
## Requisitos acordados con el usuario
|
||
|
||
1. **Dos modos por fuente** (lo elige el superadmin): **importar** (copiar a nuestra BD) o
|
||
**consulta en vivo** (leer siempre del origen). En consulta en vivo, al agendar se guarda una
|
||
copia mínima del paciente porque las citas necesitan el registro local.
|
||
2. **Formas de conexión que no comprometan al origen** (superadmin): todo pasa por el conector de
|
||
solo lectura; el sistema no guarda credenciales del origen, solo el token del conector (cifrado
|
||
AES-256-GCM, nunca vuelve al navegador).
|
||
3. **Mapeo en dos pasos** (superadmin): 1) conexión al servidor (URL del conector + token, botón
|
||
Probar); 2) qué fuente/tabla usar y a qué destino (Pacientes, Empleados).
|
||
4. **Importación al configurar o solo consultas**: al terminar la configuración se ofrece
|
||
"Importar ahora" o dejarla solo para consultas.
|
||
5. **Diseño por drivers/conectores** con la misma interfaz (aprobado).
|
||
6. **Empleados de nómina**: se importan a una tabla local de empleados (clave: cédula; los que
|
||
desaparecen del origen quedan inactivos, no se borran). Botón **"Actualizar empleados"** a
|
||
pedido, visible para **admin y superadmin**. Debe funcionar con cualquier tipo de origen.
|
||
7. **Vista previa**: el superadmin ve las columnas y filas reales de la tabla y elige qué
|
||
columnas usar en el sistema.
|
||
8. **Crear usuario desde nómina**: en Organización → Usuarios → Nuevo, opción de elegir un empleado
|
||
de la lista importada; precarga nombre, correo, cargo y departamento si están mapeados, y deja
|
||
el usuario vinculado. No se ofrecen empleados que ya tienen usuario.
|
||
|
||
## Seguridad (resumen)
|
||
|
||
- **Regla (usuario, 2026-10-29): todo lo que se busque o traiga de SAGA es por la API del conector**,
|
||
también las búsquedas que haga Claude a pedido. El SSH al Windows es solo para administrar el
|
||
conector (instalar, actualizar, decidir qué tablas/campos expone), con permiso del usuario. Una
|
||
tabla nueva primero se agrega a `config.json` del conector con los campos mínimos; después se
|
||
consulta por la API.
|
||
|
||
- En el conector: solo `GET`, token (se guarda solo el SHA-256), IPs permitidas en el conector y en
|
||
el firewall de Windows, tablas/campos permitidos y denegados (sueldos, claves), sin rutas ni SQL
|
||
libres, límites de peticiones/concurrencia/página/tiempo, log sin tokens ni valores buscados.
|
||
- FoxPro: se lee una **copia temporal** de DBF+FPT, nunca el original (no bloquea a SAGA).
|
||
- En el sistema: configuración solo superadmin; "Actualizar empleados" admin/superadmin; auditoría
|
||
de pruebas de conexión, importaciones y consultas.
|
||
|
||
## Instalación en Exilaser (2026-10-29)
|
||
|
||
- `C:\api_project\foxpro`, Node 24 del servidor, tarea programada `LinkedCorp-Conector-FoxPro`
|
||
(al arranque, usuario SYSTEM, reinicio si cae), regla de firewall del mismo nombre: TCP 8455 solo
|
||
desde `192.168.222.3` (prod) y `192.168.222.40` (dev).
|
||
- URL desde LinkedCorp: `http://192.168.0.253:8455` (por la VPN). Token: archivo
|
||
`~/.config/linkedcorp/conector-foxpro-exilaser.token` (600) en el equipo de desarrollo; en el
|
||
Windows solo está su SHA-256.
|
||
- Probado desde dev: sin token → 401; nómina 31 empleados (11 campos permitidos); clientes 32 988
|
||
(13 campos); primera carga de clientes ~8 s, luego caché (recarga como mínimo cada 60 s);
|
||
incremental `changedField=FECHAACT` OK; tildes/ñ correctas (cp850).
|
||
- `CLINOM` viene como **APELLIDOS NOMBRES** (ej. "GONZALEZ JIMENEZ RAUL VICENTE"): al importar se
|
||
separa en las 2 primeras palabras = apellidos, resto = nombres (los apellidos compuestos se
|
||
corrigen a mano). Pacientes = `CLIPERSONA = Natural` (en una muestra de 1000: 988 naturales).
|
||
- Mejora a futuro: correr la tarea con una cuenta de dominio de solo lectura en vez de SYSTEM.
|
||
- Actualizar el conector: copiar `src/` a `C:\api_project\foxpro\src`, detener la tarea, matar el
|
||
`node` del conector y volver a iniciar la tarea.
|
||
|
||
## Decisiones del usuario sobre pacientes (2026-10-29)
|
||
|
||
- Con conexión activa **se permite crear pacientes a mano** (quedan como locales).
|
||
- Al vincular por cédula, si los datos difieren **manda SAGA** (el cambio queda en auditoría).
|
||
|
||
## Pendientes
|
||
|
||
- [x] Revisar en el server las carpetas de nómina y clientes (estructura, codificación).
|
||
- [x] Instalar el conector en `C:\api_project\foxpro` y probar desde dev.
|
||
- [x] Módulo del sistema (ver "Cómo quedó en el sistema").
|
||
- [ ] Commit, revisión y producción (migraciones 036–038, conexión y fuentes a configurar allá).
|
||
|
||
## Cómo quedó en el sistema (2026-10-29)
|
||
|
||
- **Configuración → Conexiones externas** (superadmin): conexiones (URL + token cifrado, Probar) y
|
||
fuentes Pacientes/Empleados: conexión → fuente → tabla, vista previa de 20 filas, mapeo de campos,
|
||
filtro (ej. `CLIPERSONA = Natural`), campo de cambios (`FECHAACT`) y modo (pacientes: importar o en
|
||
vivo). Botones "Traer cambios" y "Sincronización completa".
|
||
- **Programación** (job en el backend, cada 5 min revisa): pacientes en modo importar → completa
|
||
**lunes a viernes a las 05:00** (recoge borrados: quedan inactivos) e incremental cada 15 min de
|
||
06:00 a 21:00 (agregados por `_recno` + modificados por `FECHAACT`). La primera vez hace la completa.
|
||
El conector solo copia el DBF cuando el sistema le pide datos (como mínimo cada 60 s).
|
||
- **Organización → Empleados** (admin/superadmin): listado y **"Actualizar empleados"** (a pedido).
|
||
Los que salen de la nómina quedan inactivos. **Nuevo usuario → Desde nómina** precarga nombre,
|
||
cargo y departamento (si coincide por nombre) y vincula el usuario con el empleado.
|
||
- **Médicos (2026-10-29)**: casi todos facturan como **proveedores** de SAGA (`provedor.DBF`, expuesto
|
||
en el conector solo con código, nombre, RUC, teléfono, correo, ciudad, tipo e inactivo). Se cargan
|
||
como empleados con `origin=provider` con `backend/src/scripts/import-provider-employees.js` (lee
|
||
del conector por código de proveedor; sin datos personales en Git). En dev: 9 proveedores + 2 que ya
|
||
eran de nómina (Torres Palacios Nataly, Rodríguez Nava Christian). Códigos usados:
|
||
`137+031 142+033 809 234 040 794 817 565 540 405 676` (`--position=MEDICO`).
|
||
- **Médico nuevo** (desde 2026-10-29): **Organización → Empleados → "Agregar desde proveedores"**
|
||
(admin/superadmin): buscar por nombre, apellido o cédula en la fuente "Proveedores"
|
||
(Configuración → Conexiones externas, en dev: `clientes/PROVEDOR`), elegir, confirmar apellidos,
|
||
nombres y cargo (por defecto MEDICO) y guardar como empleado (`origin=provider`). Marca "Ya es
|
||
empleado" a los existentes. Luego, si entra al sistema: Nuevo usuario → Desde nómina, y Personal de
|
||
la Agenda. Los 11 médicos ya cargados se mantienen. El script queda para cargas masivas.
|
||
- **Protección**: un empleado con usuario en el sistema (p. ej. médico) **no se actualiza ni se
|
||
inactiva** al "Actualizar empleados"; los de origen proveedor tampoco los toca la nómina.
|
||
- **Agenda**: en modo importar se busca entre los importados (también por nombre de origen); en modo
|
||
en vivo el selector agrega los del origen ("Del sistema origen") y al elegir uno se trae solo ese.
|
||
El detalle del paciente muestra su origen.
|
||
- **Nombres de SAGA**: `CLINOM` no tiene orden fijo (a veces nombre primero), así que no se separa:
|
||
se guarda entero como nombre visible (`name_split=0`). Al editar el paciente, recepción separa
|
||
apellidos y nombres; desde ahí la sincronización ya no pisa su nombre (sí cédula/teléfono/correo).
|
||
- Prueba en dev con datos reales: 31 empleados (24 activos), 31 220 pacientes en 24 s; repetir la
|
||
completa sin cambios 1,7 s; 14 cédulas repetidas en SAGA quedan sin cédula en el segundo registro.
|