paperclip-plugin-autopilot-ops 0.1.63 → 0.1.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/manifest.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/manifest.ts
2
2
  var PLUGIN_ID = "alephoo.autopilot-ops";
3
- var PLUGIN_VERSION = "0.1.63";
3
+ var PLUGIN_VERSION = "0.1.65";
4
4
  var DB_NAMESPACE_SLUG = "autopilot_ops";
5
5
  var PAGE_ROUTE = "autopilot";
6
6
  var TOOL_NAMES = {
package/dist/ui/index.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
 
9
9
  // src/manifest.ts
10
10
  var PLUGIN_ID = "alephoo.autopilot-ops";
11
- var PLUGIN_VERSION = "0.1.63";
11
+ var PLUGIN_VERSION = "0.1.65";
12
12
  var DB_NAMESPACE_SLUG = "autopilot_ops";
13
13
  var PAGE_ROUTE = "autopilot";
14
14
  var TOOL_NAMES = {
package/dist/worker.js CHANGED
@@ -39932,7 +39932,7 @@ function startWorkerRpcHost(options) {
39932
39932
 
39933
39933
  // src/manifest.ts
39934
39934
  var PLUGIN_ID = "alephoo.autopilot-ops";
39935
- var PLUGIN_VERSION = "0.1.63";
39935
+ var PLUGIN_VERSION = "0.1.65";
39936
39936
  var DB_NAMESPACE_SLUG = "autopilot_ops";
39937
39937
  var PAGE_ROUTE = "autopilot";
39938
39938
  var TOOL_NAMES = {
@@ -44720,7 +44720,7 @@ function evaluarRentabilidad(input2) {
44720
44720
  if ((clase2 === "perdida" || clase2 === "margen_bajo") && honorarioBase !== null) {
44721
44721
  const sinInsumos = valor - descuento - honorarioBase - indUsado;
44722
44722
  const llegan = reparto.filter((r) => r.margen >= minimo);
44723
- const noLlegan = reparto.filter((r) => r.margen < minimo);
44723
+ const noLlegan = reparto.filter((r) => r.margen < minimo).sort((a, b) => a.margen - b.margen);
44724
44724
  if (llegan.length > 0 && noLlegan.length > 0) {
44725
44725
  causa = "honorario_profesional";
44726
44726
  causaProfesionales = noLlegan.map((r) => ({ profesional_id: r.profesional_id, profesional: r.profesional, honorario: r.honorario, margen: r.margen }));
@@ -44771,7 +44771,7 @@ function evaluarRentabilidad(input2) {
44771
44771
  insumos_objetivo: causa === "insumos" ? insumosObjetivo : null,
44772
44772
  descuento,
44773
44773
  descuento_pct: descuentoPct,
44774
- no_es_practica: noEsPractica(l),
44774
+ no_es_practica: !input2.esPractica && noEsPractica(l),
44775
44775
  perdida_menor: impacto !== null && impacto < 0 && Math.abs(impacto) < perdidaMenor,
44776
44776
  porque: null,
44777
44777
  faltas,
@@ -45215,7 +45215,8 @@ function opcionesRentabilidad(op) {
45215
45215
  sinInsumos: Array.isArray(op.practicas_sin_insumos) ? op.practicas_sin_insumos.map(String).slice(0, 5e3) : [],
45216
45216
  descuento: porcentajeDescuento(op.descuento_cobro) ?? 0,
45217
45217
  descuentoPorFinanciador: leerDescuentos(op.descuentos_financiador),
45218
- rutina: op.rutina_liquidacion === "mensual" ? "mensual" : "nueva"
45218
+ rutina: op.rutina_liquidacion === "mensual" ? "mensual" : "nueva",
45219
+ sonPracticas: Array.isArray(op.son_practicas) ? op.son_practicas.map(String).slice(0, 5e3) : []
45219
45220
  };
45220
45221
  }
45221
45222
  async function leerBases(ctx, companyId) {
@@ -45225,7 +45226,7 @@ async function leerBases(ctx, companyId) {
45225
45226
  async function recalcularBases(ctx, companyId, costos) {
45226
45227
  const ms = await listarMediciones(ctx, companyId);
45227
45228
  if (!ms.length) return null;
45228
- const lecturas = ms.map((m) => ({ minutos: m.minutos, tipo: m.tipo, volumen: m.evaluacion.volumen ?? 0, dias: m.evaluacion.dias ?? 90, componentes: m.componentes }));
45229
+ const lecturas = ms.filter((m) => !m.evaluacion.no_es_practica).map((m) => ({ minutos: m.minutos, tipo: m.tipo, volumen: m.evaluacion.volumen ?? 0, dias: m.evaluacion.dias ?? 90, componentes: m.componentes }));
45229
45230
  const bases = basesIndirectos(lecturas, costos);
45230
45231
  await ctx.db.execute(
45231
45232
  `INSERT INTO ${t3(ctx, "rentabilidad_base")} (company_id, bases, practicas, calculada_el) VALUES ($1, $2::jsonb, $3, now())
@@ -45482,21 +45483,27 @@ function evaluarCostoInternacion(input2) {
45482
45483
  const costo = redondear7(honorarios + insumos + cama + quirofano);
45483
45484
  const calculable = faltas.length === 0 && facturado > 0;
45484
45485
  const margen = calculable ? redondear7(facturado - costo) : null;
45485
- const margen_pct = margen !== null ? Math.round(margen / facturado * 1e3) / 10 : null;
45486
+ let margen_pct = margen !== null ? Math.round(margen / facturado * 1e3) / 10 : null;
45487
+ if (margen_pct !== null && margen_pct < -RESULTADO_DUDOSO_PCT) {
45488
+ faltas.push("facturado_dudoso");
45489
+ margen_pct = null;
45490
+ }
45486
45491
  let clase2;
45487
45492
  if (margen === null || margen_pct === null) clase2 = "datos_incompletos";
45488
45493
  else if (margen < 0) clase2 = "perdida";
45489
45494
  else if (margen_pct < umbral) clase2 = "margen_bajo";
45490
45495
  else clase2 = "rentable";
45491
- return { clase: clase2, facturado, honorarios, insumos, cama, quirofano, costo, margen, margen_pct, umbral, dias: total, dias_por_servicio, minutos_quirofano: minutos, faltas, avisos, insumos_sin_costo: sinCosto, prestaciones_sin_regla: sinRegla };
45496
+ return { clase: clase2, facturado, honorarios, insumos, cama, quirofano, costo, margen: margen_pct === null ? null : margen, margen_pct, umbral, dias: total, dias_por_servicio, minutos_quirofano: minutos, faltas, avisos, insumos_sin_costo: sinCosto, prestaciones_sin_regla: sinRegla };
45492
45497
  }
45493
45498
  var NOMBRE_FALTA2 = {
45494
45499
  sin_facturar: "no tiene nada facturado",
45495
45500
  insumo_sin_costo: "hay insumos sin costo de compra en el HIS",
45496
45501
  sin_costo_cama: "falta el costo del d\xEDa cama",
45497
45502
  sin_costo_quirofano: "falta el costo de la hora de quir\xF3fano",
45498
- cirugia_sin_duracion: "hay cirug\xEDas sin la duraci\xF3n en el parte quir\xFArgico"
45503
+ cirugia_sin_duracion: "hay cirug\xEDas sin la duraci\xF3n en el parte quir\xFArgico",
45504
+ facturado_dudoso: "lo que cost\xF3 es m\xE1s de cuatro veces lo facturado: hay que verificar la facturaci\xF3n o los d\xEDas"
45499
45505
  };
45506
+ var RESULTADO_DUDOSO_PCT = 300;
45500
45507
  var porcentaje2 = (n2) => `${n2.toLocaleString("es-AR", { maximumFractionDigits: 1 })} %`;
45501
45508
  var enumerar = (xs) => xs.length > 1 ? `${xs.slice(0, -1).join(", ")} y ${xs[xs.length - 1]}` : xs[0] ?? "";
45502
45509
  function oracionCostoInternacion(l, e) {
@@ -45770,7 +45777,7 @@ function resultadoPedido(d, e) {
45770
45777
  return { accion, pedido: null, ahora: null, cumple: e.clase === "rentable" ? true : null };
45771
45778
  }
45772
45779
  function evaluarConOpciones(l, hoy, op, bases) {
45773
- return evaluarRentabilidad({ lectura: l, hoy, umbral: op.umbral, mesesPrecio: op.mesesPrecio, indirectos: op.indirectos, bases, medirCon: op.medirCon, perdidaMenor: op.perdidaMenor, sinInsumos: op.sinInsumos.includes(normalizarCodigo(l.codigo) ?? ""), descuento: descuentoDe(op, l.financiador), rutina: op.rutina });
45780
+ return evaluarRentabilidad({ lectura: l, hoy, umbral: op.umbral, mesesPrecio: op.mesesPrecio, indirectos: op.indirectos, bases, medirCon: op.medirCon, perdidaMenor: op.perdidaMenor, sinInsumos: op.sinInsumos.includes(normalizarCodigo(l.codigo) ?? ""), descuento: descuentoDe(op, l.financiador), rutina: op.rutina, esPractica: op.sonPracticas.includes(normalizarCodigo(l.codigo) ?? "") });
45774
45781
  }
45775
45782
  async function evaluarRentabilidades(ctx, companyId, lecturas) {
45776
45783
  if (!Array.isArray(lecturas)) throw new OpsError("validacion", "lecturas: tiene que ser una lista");
@@ -45784,11 +45791,11 @@ async function evaluarRentabilidades(ctx, companyId, lecturas) {
45784
45791
  imputarMinutos(validas);
45785
45792
  const anteriores = new Map((await listarMediciones(ctx, companyId)).map((m) => [m.referencia, m]));
45786
45793
  const completa = validas.length > 0 && validas.length >= anteriores.size * 0.8;
45787
- const bases = completa ? await guardarBases(ctx, companyId, validas, opciones.indirectos) : await leerBases(ctx, companyId);
45794
+ const practicas = validas.filter((l) => opciones.sonPracticas.includes(normalizarCodigo(l.codigo) ?? "") || !noEsPractica(l));
45795
+ const bases = completa ? await guardarBases(ctx, companyId, practicas, opciones.indirectos) : await leerBases(ctx, companyId);
45788
45796
  const pedidos = await ultimosPedidos(ctx, companyId);
45789
45797
  const medidas = [];
45790
45798
  const resultados = [];
45791
- const noSonPracticas = [];
45792
45799
  for (const [indice, l] of leidas.entries()) {
45793
45800
  if ("error" in l) {
45794
45801
  resultados.push({ indice, error: l.error });
@@ -45797,8 +45804,7 @@ async function evaluarRentabilidades(ctx, companyId, lecturas) {
45797
45804
  const evaluacion = evaluarConOpciones(l.lectura, hoy, opciones, bases);
45798
45805
  const referencia = `rentabilidad:${l.lectura.prestacion_id}:${l.lectura.financiador_id}`;
45799
45806
  const previa = anteriores.get(referencia);
45800
- if (evaluacion.no_es_practica) noSonPracticas.push(referencia);
45801
- else await registrarCambiosHis(ctx, {
45807
+ if (!evaluacion.no_es_practica) await registrarCambiosHis(ctx, {
45802
45808
  companyId,
45803
45809
  referencia,
45804
45810
  codigo: l.lectura.codigo,
@@ -45806,11 +45812,11 @@ async function evaluarRentabilidades(ctx, companyId, lecturas) {
45806
45812
  antes: previa ? { valor: previa.evaluacion.valor, honorarios: (previa.evaluacion.honorarios ?? []).map((h) => ({ profesional_id: h.profesional_id, profesional: h.profesional, honorario: h.honorario })) } : null,
45807
45813
  despues: { valor: evaluacion.valor, honorarios: evaluacion.honorarios.map((h) => ({ profesional_id: h.profesional_id, profesional: h.profesional, honorario: h.honorario })) }
45808
45814
  });
45809
- if (!evaluacion.no_es_practica) medidas.push({ lectura: l.lectura, evaluacion });
45815
+ medidas.push({ lectura: l.lectura, evaluacion });
45810
45816
  const apertura = decidirApertura(evaluacion, pedidos.get(referencia) ?? null, hoy, opciones.perdidaMenor);
45811
45817
  resultados.push({ clave: `${l.lectura.prestacion_id}:${l.lectura.financiador_id}`, referencia, codigo: l.lectura.codigo, practica: l.lectura.nombre, financiador: l.lectura.financiador, evaluacion, oracion: oracionRentabilidad(l.lectura, evaluacion), abrir: apertura.abrir, motivo_abrir: apertura.motivo });
45812
45818
  }
45813
- await guardarMediciones(ctx, companyId, medidas, noSonPracticas);
45819
+ await guardarMediciones(ctx, companyId, medidas);
45814
45820
  return { resultados, opciones };
45815
45821
  }
45816
45822
  function enteroEntre2(v, min, max) {
@@ -45922,6 +45928,10 @@ async function cambiarPolitica(ctx, input2) {
45922
45928
  }
45923
45929
  if (opciones.rutina_liquidacion !== void 0 && opciones.rutina_liquidacion !== "nueva" && opciones.rutina_liquidacion !== "mensual") throw new OpsError("validacion", "rutina_liquidacion: tiene que ser \xABnueva\xBB o \xABmensual\xBB");
45924
45930
  if (opciones.descuentos_financiador !== void 0) opciones.descuentos_financiador = leerDescuentos(opciones.descuentos_financiador);
45931
+ if (opciones.son_practicas !== void 0) {
45932
+ if (!Array.isArray(opciones.son_practicas)) throw new OpsError("validacion", "son_practicas: tiene que ser una lista de c\xF3digos");
45933
+ opciones.son_practicas = [...new Set(opciones.son_practicas.map((c) => normalizarCodigo(String(c ?? ""))).filter((c) => Boolean(c)))].slice(0, 5e3);
45934
+ }
45925
45935
  if (opciones.practicas_sin_insumos !== void 0) {
45926
45936
  if (!Array.isArray(opciones.practicas_sin_insumos)) throw new OpsError("validacion", "practicas_sin_insumos: tiene que ser una lista de c\xF3digos");
45927
45937
  opciones.practicas_sin_insumos = [...new Set(opciones.practicas_sin_insumos.map((c) => normalizarCodigo(String(c ?? ""))).filter((c) => Boolean(c)))].slice(0, 5e3);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paperclip-plugin-autopilot-ops",
3
- "version": "0.1.63",
3
+ "version": "0.1.65",
4
4
  "type": "module",
5
5
  "description": "Autopilot Care · operación autónoma gobernada para instituciones de salud: workflows determinísticos, validaciones, registro de negocio, políticas (observa/propone/ejecuta/corte) y tablero del director, como plugin de Paperclip.",
6
6
  "files": [