paperclip-plugin-autopilot-ops 0.1.61 → 0.1.62
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 +1 -1
- package/dist/ui/index.js +1 -1
- package/dist/worker.js +27 -8
- package/package.json +1 -1
package/dist/manifest.js
CHANGED
package/dist/ui/index.js
CHANGED
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.
|
|
39935
|
+
var PLUGIN_VERSION = "0.1.62";
|
|
39936
39936
|
var DB_NAMESPACE_SLUG = "autopilot_ops";
|
|
39937
39937
|
var PAGE_ROUTE = "autopilot";
|
|
39938
39938
|
var TOOL_NAMES = {
|
|
@@ -44708,7 +44708,7 @@ function evaluarRentabilidad(input2) {
|
|
|
44708
44708
|
if (i >= 0) avisos.splice(i, 1);
|
|
44709
44709
|
}
|
|
44710
44710
|
if (valor > 0 && (insumos / valor * 100 > INSUMOS_A_VERIFICAR_PCT || honorarioMax !== null && honorarioMax > valor)) avisos.push("dato_a_verificar");
|
|
44711
|
-
const impacto = impactoPromedio !== null &&
|
|
44711
|
+
const impacto = impactoPromedio !== null && perdidaProfesionales !== null ? Math.min(impactoPromedio, perdidaProfesionales) : impactoPromedio;
|
|
44712
44712
|
const reparto = valor > 0 ? conHonorario.map((h) => {
|
|
44713
44713
|
const m = redondear5(valor - descuento - insumos - indUsado - h.honorario);
|
|
44714
44714
|
return { profesional_id: h.profesional_id, profesional: h.profesional, honorario: h.honorario, margen: m, volumen: h.volumen, por_mes: h.volumen !== null ? porMes(m, h.volumen) : null };
|
|
@@ -44729,9 +44729,12 @@ function evaluarRentabilidad(input2) {
|
|
|
44729
44729
|
}
|
|
44730
44730
|
const honorarioPct = !conHonorario.length ? 0 : segunQuien ? conHonorario.reduce((a, h) => a + h.pct * h.volumen, 0) / totalVol : conHonorario.reduce((m, h) => h.honorario === honorarioMax ? Math.max(m, h.pct) : m, 0);
|
|
44731
44731
|
const indirectosPct = medidoCon === "total" && valor > 0 ? ind.detalle.filter((d) => (input2.indirectos ?? []).some((c) => c.id === d.id && c.reparto === "porcentaje")).reduce((a, d) => a + d.monto, 0) / valor : 0;
|
|
44732
|
-
const
|
|
44733
|
-
const
|
|
44734
|
-
const
|
|
44732
|
+
const peorDebajo = debajoProf.length ? debajoProf.reduce((a, x) => x.h.honorario > a.h.honorario ? x : a).h : null;
|
|
44733
|
+
const [honObj, pctObj] = peorDebajo ? [peorDebajo.honorario, peorDebajo.pct] : [honorarioBase, honorarioPct];
|
|
44734
|
+
const fijos = honObj !== null ? honObj - pctObj * valor + insumos + (indUsado - indirectosPct * valor) : null;
|
|
44735
|
+
const libre = 1 - (umbral + descuentoPct) / 100 - pctObj - indirectosPct;
|
|
44736
|
+
const objetivoCalculado = fijos !== null && libre > 0.05 ? Math.ceil(fijos / libre) : null;
|
|
44737
|
+
const valorObjetivo = objetivoCalculado !== null && objetivoCalculado > valor ? objetivoCalculado : null;
|
|
44735
44738
|
const honorarioObjetivo = valor > 0 ? Math.max(0, Math.floor(valor * (1 - umbral / 100) - descuento - insumos - indUsado)) : null;
|
|
44736
44739
|
const insumosObjetivo = valor > 0 && honorarioBase !== null ? Math.max(0, Math.floor(valor * (1 - umbral / 100) - descuento - honorarioBase - indUsado)) : null;
|
|
44737
44740
|
const e = {
|
|
@@ -44819,6 +44822,8 @@ function oracionRentabilidad(l, e) {
|
|
|
44819
44822
|
const porque = porqueRentabilidad(l, e);
|
|
44820
44823
|
const total = e.medido_con === "total" ? " despu\xE9s de los costos indirectos" : "";
|
|
44821
44824
|
if (e.clase === "perdida") return `${practica} da p\xE9rdida${total}.${porque ? ` ${porque}` : ""}${mensual}`;
|
|
44825
|
+
const prof = e.causa === "honorario_profesional" ? e.causa_profesionales[0] : void 0;
|
|
44826
|
+
if (e.clase === "margen_bajo" && prof && e.valor > 0) return `${practica}: con ${prof.profesional} deja un margen de ${porcentaje(Math.round(prof.margen / e.valor * 1e3) / 10)}${total}, debajo del ${porcentaje(e.umbral)} de la instituci\xF3n.${porque ? ` ${porque}` : ""}${mensual}`;
|
|
44822
44827
|
if (e.clase === "margen_bajo") return `${practica} deja un margen de ${porcentaje(e.margen_pct)}${total}, debajo del ${porcentaje(e.umbral)} de la instituci\xF3n.${porque ? ` ${porque}` : ""}${mensual}`;
|
|
44823
44828
|
return `${practica} deja un margen de ${porcentaje(e.margen_pct)}${total}.`;
|
|
44824
44829
|
}
|
|
@@ -45237,6 +45242,7 @@ ON CONFLICT (company_id) DO UPDATE SET bases = EXCLUDED.bases, practicas = EXCLU
|
|
|
45237
45242
|
return bases;
|
|
45238
45243
|
}
|
|
45239
45244
|
async function guardarMediciones(ctx, companyId, items, quitar = []) {
|
|
45245
|
+
await ctx.db.execute(`DELETE FROM ${t3(ctx, "rentabilidad_medicion")} WHERE company_id = $1 AND medido_el < now() - interval '45 days'`, [companyId]);
|
|
45240
45246
|
for (const referencia of quitar) await ctx.db.execute(`DELETE FROM ${t3(ctx, "rentabilidad_medicion")} WHERE company_id = $1 AND referencia = $2`, [companyId, referencia]);
|
|
45241
45247
|
for (const { lectura: l, evaluacion } of items) {
|
|
45242
45248
|
await ctx.db.execute(
|
|
@@ -45288,7 +45294,7 @@ function decidirApertura(e, ultimo, hoy, piso = 0) {
|
|
|
45288
45294
|
if (antes !== null && antes >= 0 && ahora !== null && ahora < 0) return { abrir: true, motivo: "aceptada cuando dejaba margen, ahora da p\xE9rdida" };
|
|
45289
45295
|
const mismoCalculo = !ultimo.calculo_aceptado || !e.calculo || ultimo.calculo_aceptado === e.calculo;
|
|
45290
45296
|
const [a0, a1] = mismoCalculo ? [antes, ahora] : [ultimo.peor_aceptada ?? null, e.impacto_peor ?? null];
|
|
45291
|
-
if (a0 !== null && a1 !== null && a1 < 0 && a0 - a1 > Math.max(Math.abs(a0) * CRECIMIENTO_QUE_REABRE, piso)) return { abrir: true, motivo: "la p\xE9rdida por mes creci\xF3 m\xE1s de un 20 % desde que la acept\xF3 la direcci\xF3n" };
|
|
45297
|
+
if (a0 !== null && a1 !== null && (a1 < 0 || e.clase === "margen_bajo") && a0 - a1 > Math.max(Math.abs(a0) * CRECIMIENTO_QUE_REABRE, piso)) return { abrir: true, motivo: a1 < 0 ? "la p\xE9rdida por mes creci\xF3 m\xE1s de un 20 % desde que la acept\xF3 la direcci\xF3n" : "lo que deja por mes cay\xF3 m\xE1s de un 20 % desde que la acept\xF3 la direcci\xF3n" };
|
|
45292
45298
|
if (!ultimo.aceptada_hasta && antes === null) return { abrir: false, motivo: "la direcci\xF3n la acept\xF3 as\xED" };
|
|
45293
45299
|
return { abrir: false, motivo: `aceptada por la direcci\xF3n${ultimo.aceptada_hasta ? ` hasta el ${ultimo.aceptada_hasta}` : ""}` };
|
|
45294
45300
|
}
|
|
@@ -45730,6 +45736,17 @@ function pareceNoProfesional(nombre) {
|
|
|
45730
45736
|
const [apellido = "", nombres = ""] = n2.split(",").map((x) => x.trim().toLowerCase());
|
|
45731
45737
|
return /^[^a-záéíóúñü]/i.test(n2) || /\d/.test(n2) || apellido !== "" && apellido === nombres || /\b(admin|administrador|prueba|test|sistema|usuario)\b/i.test(n2);
|
|
45732
45738
|
}
|
|
45739
|
+
function imputarMinutos(lecturas) {
|
|
45740
|
+
const mediana2 = (xs) => {
|
|
45741
|
+
const o = [...xs].sort((a, b) => a - b);
|
|
45742
|
+
return o.length ? o[Math.floor(o.length / 2)] : null;
|
|
45743
|
+
};
|
|
45744
|
+
const conDuracion = lecturas.filter((l) => l.minutos !== null);
|
|
45745
|
+
const general = mediana2(conDuracion.map((l) => l.minutos));
|
|
45746
|
+
const porTipo = /* @__PURE__ */ new Map();
|
|
45747
|
+
for (const l of conDuracion) porTipo.set(l.tipo ?? "", [...porTipo.get(l.tipo ?? "") ?? [], l.minutos]);
|
|
45748
|
+
for (const l of lecturas) if (l.minutos === null) l.minutos = mediana2(porTipo.get(l.tipo ?? "") ?? []) ?? general;
|
|
45749
|
+
}
|
|
45733
45750
|
function resultadoPedido(d, e) {
|
|
45734
45751
|
const accion = str2(d.accion) ?? "pedir_aumento";
|
|
45735
45752
|
const pedido = typeof d.precio_propuesto === "number" ? d.precio_propuesto : null;
|
|
@@ -45737,8 +45754,9 @@ function resultadoPedido(d, e) {
|
|
|
45737
45754
|
if (accion === "revisar_honorario") {
|
|
45738
45755
|
const previo = d.evaluacion && typeof d.evaluacion === "object" ? d.evaluacion : {};
|
|
45739
45756
|
const objetivo = typeof previo.honorario_objetivo === "number" ? previo.honorario_objetivo : null;
|
|
45740
|
-
const
|
|
45741
|
-
const
|
|
45757
|
+
const profs = Array.isArray(previo.causa_profesionales) ? previo.causa_profesionales : [];
|
|
45758
|
+
const honorarios = profs.map((p) => e.reparto.find((r) => r.profesional_id === p.profesional_id)?.honorario ?? null);
|
|
45759
|
+
const ahora = honorarios.length && honorarios.every((h) => h !== null) ? Math.max(...honorarios) : null;
|
|
45742
45760
|
return { accion, pedido: objetivo, ahora, cumple: objetivo !== null && ahora !== null ? ahora <= objetivo + 0.5 : null };
|
|
45743
45761
|
}
|
|
45744
45762
|
return { accion, pedido: null, ahora: null, cumple: e.clase === "rentable" ? true : null };
|
|
@@ -45755,6 +45773,7 @@ async function evaluarRentabilidades(ctx, companyId, lecturas) {
|
|
|
45755
45773
|
const leidas = lecturas.map((x) => leerLecturaRentabilidad(x));
|
|
45756
45774
|
const validas = leidas.flatMap((l) => "error" in l ? [] : [l.lectura]);
|
|
45757
45775
|
for (const l of validas) conInsumosDeOpera(l, insumos);
|
|
45776
|
+
imputarMinutos(validas);
|
|
45758
45777
|
const anteriores = new Map((await listarMediciones(ctx, companyId)).map((m) => [m.referencia, m]));
|
|
45759
45778
|
const completa = validas.length > 0 && validas.length >= anteriores.size * 0.8;
|
|
45760
45779
|
const bases = completa ? await guardarBases(ctx, companyId, validas, opciones.indirectos) : await leerBases(ctx, companyId);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "paperclip-plugin-autopilot-ops",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.62",
|
|
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": [
|