Skip to content

Plataforma técnica · Orchestrator

Isapre Service

Remuneraciones Isapre Fonasa

IsapreService cumple dos roles: mantiene el catálogo de instituciones de salud (Fonasa, Banmédica, Cruz Blanca, etc.) y administra los contratos de salud por trabajador, que sí versionan plan UF y vigencia. La distinción es importante: el catálogo es referencia estable; los contratos son donde vive la información que PayrollService consume para calcular el descuento de salud.

A diferencia de AFP (que es un catálogo simple), Isapre requiere contrato porque cada trabajador puede pactar un plan UF distinto y porque ese plan cambia en el tiempo.

  • Directoryorchestrator/src/domain/isapre/
    • IsapreService.ts
    • IsapreRepository.ts
    • types.ts

Tablas: remuneraciones.isapre (catálogo) y remuneraciones.contrato_isapre (contratos de salud). Vista enriquecida: remuneraciones.v_contrato_isapre.

MétodoFirma
findAll(ctx) => Promise<Isapre[]>
findById(ctx, id) => Promise<Isapre | null>
MétodoFirmaUso
findContractsByContrato(ctx, contratoId) => Promise<IsapreContractRow[]>Historial de planes pactados para un contrato laboral.
findContractById(ctx, id) => Promise<IsapreContractRow | null>Detalle individual del contrato de salud.
findContractVigente(ctx, contratoId, year?, month?) => Promise<IsapreContractVigenteRow | null>Plan vigente al periodo. Default: año/mes actual en zona America/Santiago.
listContracts(ctx, limit=50, activeOnly=false) => Promise<IsapreContractRow[]>Listado paginado, clamp [1, 200].
createContract(ctx, data: IsapreContract) => Promise<ServiceResult<IsapreContractRow>>Crea contrato de salud.
updateContract(ctx, id, data: Partial<IsapreContract>) => Promise<ServiceResult<IsapreContractRow>>Update parcial. Falla con Error("No encontrado") si no existe.
deleteContract(ctx, id) => Promise<ServiceResult<boolean>>Borra el contrato de salud. Falla con Error("No encontrado") si 0 filas.
interface Isapre {
id: string;
codigo: string;
nombre: string;
razon_social?: string;
activa?: boolean;
}
interface IsapreContract {
id?: string;
contrato_id: string; // FK a remuneraciones.contratos
isapre_id: string; // FK a remuneraciones.isapre
numero_contrato?: string; // número del contrato Isapre del trabajador
plan_codigo?: string;
plan_nombre?: string;
moneda?: string; // típicamente "UF"
plan_uf: number; // valor pactado
ges_uf?: number; // GES por separado
adicionales_uf?: number;
descuentos_uf?: number;
num_cargas?: number;
vigente_desde: string; // obligatorio
vigente_hasta?: string;
}

findContractVigente es el método más usado por payroll. Resuelve qué plan aplica al periodo del cálculo:

async findContractVigente(ctx, contratoId, year?, month?) {
const { y, m } = currentYearMonthInChile();
const periodStr = `${year ?? y}-${String(month ?? m).padStart(2, "0")}-01`;
return IsapreRepository.findContractVigenteByContrato(pool, contratoId, periodStr);
}
DetalleImplementación
Zona horariaIntl.DateTimeFormat("en-CA", { timeZone: "America/Santiago", ... }). Evita off-by-one cerca de fin de mes en servidores UTC.
Formato del periodoYYYY-MM-01 (primer día del mes).
Comparación en SQLEl repository compara contra vigente_desde <= periodo y (vigente_hasta IS NULL OR vigente_hasta >= periodo).
Sin planSi no hay contrato vigente, devuelve null → payroll asume Fonasa o falla según política.
CampoRegla
contrato_id, isapre_id, vigente_desdeObligatorios — validateRequired.
plan_ufDebe ser >= 0. Number(data.plan_uf) se coacciona; valor inválido → Error("plan_uf inválido").

updateContract valida existencia previa con findContractById.

findContractsByContrato, findContractById y listContracts consultan la vista enriquecida que devuelve campos adicionales sobre la tabla base:

Campo derivadoOrigen
empleado_nombre, empleado_rutJoin con remuneraciones.contratosremuneraciones.empleados.
isapre_nombreJoin con remuneraciones.isapre.
cotizacion_total_ufSuma de plan + ges + adicionales − descuentos.

findContractVigenteByContrato usa un tipo distinto (IsapreContractVigenteRow) que además expone isapre_codigo, empleado_id y la vigencia como rango desde/hasta.

OrigenMensajeCuándo
validateRequired"<campo> es requerido"Falta contrato_id, isapre_id o vigente_desde al crear.
Service"plan_uf inválido"plan_uf no es número o es negativo.
Service"No encontrado"updateContract o deleteContract con id inexistente.
ServiceCómo consume
ContractServicegetEmployeeData hace LEFT JOIN remuneraciones.isapre para incluir isapre_nombre en el PDF.
PayrollServiceLlama a findContractVigente(contratoId, anio, mes) para obtener plan_uf y calcular la diferencia adicional de salud.
PrevisionsServiceAgrupa montos calculados por isapre_id para la planilla Previred.