paperclip-plugin-autopilot-ops 0.1.37 → 0.1.38

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.37";
3
+ var PLUGIN_VERSION = "0.1.38";
4
4
  var DB_NAMESPACE_SLUG = "autopilot_ops";
5
5
  var PAGE_ROUTE = "autopilot";
6
6
  var TOOL_NAMES = {
@@ -458,6 +458,14 @@ var manifest = {
458
458
  capability: "api.routes.register",
459
459
  companyResolution: { from: "body", key: "companyId" }
460
460
  },
461
+ {
462
+ routeKey: "respuesta-equipo",
463
+ method: "POST",
464
+ path: "/casos/:casoId/respuesta-equipo",
465
+ auth: "board",
466
+ capability: "api.routes.register",
467
+ companyResolution: { from: "body", key: "companyId" }
468
+ },
461
469
  {
462
470
  routeKey: "envio-nota",
463
471
  method: "POST",
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.37";
11
+ var PLUGIN_VERSION = "0.1.38";
12
12
  var DB_NAMESPACE_SLUG = "autopilot_ops";
13
13
  var PAGE_ROUTE = "autopilot";
14
14
  var TOOL_NAMES = {
@@ -466,6 +466,14 @@ var manifest = {
466
466
  capability: "api.routes.register",
467
467
  companyResolution: { from: "body", key: "companyId" }
468
468
  },
469
+ {
470
+ routeKey: "respuesta-equipo",
471
+ method: "POST",
472
+ path: "/casos/:casoId/respuesta-equipo",
473
+ auth: "board",
474
+ capability: "api.routes.register",
475
+ companyResolution: { from: "body", key: "companyId" }
476
+ },
469
477
  {
470
478
  routeKey: "envio-nota",
471
479
  method: "POST",
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.37";
39935
+ var PLUGIN_VERSION = "0.1.38";
39936
39936
  var DB_NAMESPACE_SLUG = "autopilot_ops";
39937
39937
  var PAGE_ROUTE = "autopilot";
39938
39938
  var TOOL_NAMES = {
@@ -40390,6 +40390,14 @@ var manifest = {
40390
40390
  capability: "api.routes.register",
40391
40391
  companyResolution: { from: "body", key: "companyId" }
40392
40392
  },
40393
+ {
40394
+ routeKey: "respuesta-equipo",
40395
+ method: "POST",
40396
+ path: "/casos/:casoId/respuesta-equipo",
40397
+ auth: "board",
40398
+ capability: "api.routes.register",
40399
+ companyResolution: { from: "body", key: "companyId" }
40400
+ },
40393
40401
  {
40394
40402
  routeKey: "envio-nota",
40395
40403
  method: "POST",
@@ -42797,7 +42805,8 @@ var circularAranceles = {
42797
42805
  }
42798
42806
  ]
42799
42807
  };
42800
- var RESPUESTAS_AJUSTE = ["aprobado", "aprobado_otro", "rechazado"];
42808
+ var RESPUESTAS_AJUSTE = ["aprobado", "aprobado_otro", "rechazado", "insistir", "contraoferta"];
42809
+ var RESPUESTAS_DEL_FINANCIADOR = ["aprobado", "otro", "rechazado"];
42801
42810
  var CANALES_NOTA = ["correo", "portal_del_financiador", "nota", "otro"];
42802
42811
  function calcularAjuste(caso, datos, contexto) {
42803
42812
  const formula = contexto.formulaAjuste ?? FORMULA_POR_DEFECTO;
@@ -42831,7 +42840,7 @@ var ajusteConvenio = {
42831
42840
  puesto: "Convenios y facturaci\xF3n",
42832
42841
  descripcion: "Calcula el aumento de un convenio con los \xEDndices publicados (IPC de INDEC) y la f\xF3rmula de la instituci\xF3n, arma los valores nuevos de cada pr\xE1ctica y la nota al financiador; la direcci\xF3n revisa y aprueba, se registra la respuesta del financiador, se carga con el archivo que genera el plugin y el puesto comprueba releyendo cada valor.",
42833
42842
  inicial: "abierto",
42834
- estados: ["abierto", "calculado", "pendiente_aprobacion", "por_enviar", "enviado", "acordado", "aplicado", "verificado", "con_diferencias", "rechazado", "rechazado_financiador", "cancelado"],
42843
+ estados: ["abierto", "calculado", "pendiente_aprobacion", "por_enviar", "enviado", "respuesta_recibida", "acordado", "aplicado", "verificado", "con_diferencias", "rechazado", "rechazado_financiador", "cancelado"],
42835
42844
  finalesOk: ["verificado"],
42836
42845
  finalesNoOk: ["rechazado", "rechazado_financiador", "cancelado"],
42837
42846
  minutosAbsorbidos: 40,
@@ -42932,15 +42941,39 @@ var ajusteConvenio = {
42932
42941
  ]
42933
42942
  },
42934
42943
  {
42935
- via: "responder",
42944
+ via: "informar_respuesta",
42936
42945
  de: ["enviado"],
42937
- a: (_caso, datos) => datos.respuesta === "rechazado" ? "rechazado_financiador" : "acordado",
42946
+ // Si aceptó lo propuesto no hay nada que decidir: queda el archivo. Otro porcentaje o un rechazo los decide la dirección.
42947
+ a: (_caso, datos) => datos.respuesta === "aprobado" ? "acordado" : "respuesta_recibida",
42938
42948
  actor: ["humano"],
42939
- descripcion: "Registrar la respuesta del financiador: aprobado, aprobado con otro porcentaje (porcentaje) o rechazado (motivo).",
42949
+ descripcion: "El equipo registra lo que contest\xF3 el financiador: acept\xF3 lo propuesto, pidi\xF3 otro porcentaje (porcentaje) o no lo acept\xF3 (motivo).",
42950
+ validar: (_caso, datos) => {
42951
+ const r = datos.respuesta;
42952
+ if (!RESPUESTAS_DEL_FINANCIADOR.includes(r)) return [falla("respuesta_valida", `respuesta: ${RESPUESTAS_DEL_FINANCIADOR.join(", ")}`)];
42953
+ if (r === "otro") return [ok("respuesta_valida"), validarPorcentajeHumano(datos.porcentaje, "porcentaje_valido")];
42954
+ if (r === "rechazado") return [ok("respuesta_valida"), texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "anotar qu\xE9 respondi\xF3 el financiador")];
42955
+ return [ok("respuesta_valida")];
42956
+ }
42957
+ },
42958
+ {
42959
+ via: "reenviar",
42960
+ de: ["enviado"],
42961
+ a: "enviado",
42962
+ actor: ["humano", "agente"],
42963
+ nivelRequerido: "ejecuta",
42964
+ descripcion: "Registrar que se volvi\xF3 a mandar la nota (el financiador no respondi\xF3 en el plazo).",
42965
+ validar: (_caso, datos) => [texto4(datos.destinatario) ? ok("destinatario_presente") : falla("destinatario_presente", "destinatario (a qui\xE9n se reenvi\xF3) es obligatorio")]
42966
+ },
42967
+ {
42968
+ via: "responder",
42969
+ de: ["enviado", "respuesta_recibida"],
42970
+ a: (_caso, datos) => datos.respuesta === "rechazado" ? "rechazado_financiador" : datos.respuesta === "insistir" || datos.respuesta === "contraoferta" ? "por_enviar" : "acordado",
42971
+ actor: ["humano"],
42972
+ descripcion: "La direcci\xF3n decide sobre la respuesta del financiador: aceptar lo propuesto, aceptar otro porcentaje (porcentaje), contraofertar (porcentaje: vuelve a salir una nota), insistir (se reenv\xEDa la nota) o darlo por rechazado (motivo).",
42940
42973
  validar: (_caso, datos) => {
42941
42974
  const r = datos.respuesta;
42942
42975
  if (!RESPUESTAS_AJUSTE.includes(r)) return [falla("respuesta_valida", `respuesta: ${RESPUESTAS_AJUSTE.join(", ")}`)];
42943
- if (r === "aprobado_otro") return [ok("respuesta_valida"), validarPorcentajeHumano(datos.porcentaje, "porcentaje_valido")];
42976
+ if (r === "aprobado_otro" || r === "contraoferta") return [ok("respuesta_valida"), validarPorcentajeHumano(datos.porcentaje, "porcentaje_valido")];
42944
42977
  if (r === "rechazado") return [ok("respuesta_valida"), texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "anotar qu\xE9 respondi\xF3 el financiador")];
42945
42978
  return [ok("respuesta_valida")];
42946
42979
  }
@@ -42991,7 +43024,7 @@ var ajusteConvenio = {
42991
43024
  },
42992
43025
  {
42993
43026
  via: "cancelar",
42994
- de: ["abierto", "calculado", "pendiente_aprobacion", "por_enviar", "enviado", "acordado", "con_diferencias"],
43027
+ de: ["abierto", "calculado", "pendiente_aprobacion", "por_enviar", "enviado", "respuesta_recibida", "acordado", "con_diferencias"],
42995
43028
  a: "cancelado",
42996
43029
  actor: ["humano", "agente"],
42997
43030
  nivelRequerido: "observa",
@@ -45431,20 +45464,25 @@ async function transicionar(ctx, input2) {
45431
45464
  datos.excluir = excluir;
45432
45465
  recalcular(pedido ?? porcentajeAntes, excluir);
45433
45466
  } else if (resultado.via !== "calcular") delete datos.excluir;
45434
- if (resultado.via === "responder" && datos.respuesta === "aprobado_otro" && pedido !== null) {
45435
- datos.porcentaje_acordado = pedido;
45467
+ if (resultado.via === "informar_respuesta") {
45468
+ datos.respuesta_financiador = { respuesta: datos.respuesta, porcentaje: pedido, detalle: str2(datos.motivo) ?? str2(datos.detalle) };
45469
+ if (datos.respuesta === "aprobado") datos.porcentaje_acordado = porcentajeAntes;
45470
+ }
45471
+ if (resultado.via === "responder" && (datos.respuesta === "aprobado_otro" || datos.respuesta === "contraoferta") && pedido !== null) {
45472
+ if (datos.respuesta === "aprobado_otro") datos.porcentaje_acordado = pedido;
45436
45473
  recalcular(pedido, caso.datos.excluir);
45437
45474
  }
45438
45475
  if (resultado.via === "responder" && datos.respuesta === "aprobado") datos.porcentaje_acordado = porcentajeAntes;
45439
45476
  if (resultado.a === "por_enviar") {
45440
45477
  const op = await obtenerOpciones(ctx, input2.companyId, caso.workflow);
45441
- const r = caso.datos.resumen;
45478
+ const porcentajeNota = typeof datos.porcentaje === "number" ? datos.porcentaje : porcentajeAntes;
45479
+ const r = datos.resumen ?? caso.datos.resumen;
45442
45480
  datos.nota = armarNota(op.nota, {
45443
45481
  institucion: str2(op.institucion) ?? str2(caso.datos.institucion) ?? "",
45444
45482
  financiador: str2(caso.datos.financiador) ?? "",
45445
45483
  convenio: str2(caso.datos.convenio) ?? "",
45446
- porcentaje: porcentajeAntes,
45447
- indices: textoIndices(caso.datos.detalle ?? { fijo: porcentajeAntes }, str2(caso.datos.ultimo_ajuste), str2(caso.datos.periodo_hasta)),
45484
+ porcentaje: porcentajeNota,
45485
+ indices: textoIndices(caso.datos.detalle ?? { fijo: porcentajeNota }, str2(caso.datos.ultimo_ajuste), str2(caso.datos.periodo_hasta)),
45448
45486
  vigencia: str2(caso.datos.vigencia_desde) ?? "",
45449
45487
  firma: str2(op.firma) ?? "",
45450
45488
  practicas: r?.practicas ?? 0
@@ -46348,6 +46386,20 @@ async function registrarEnvioLiquidacion(ctx, input2) {
46348
46386
  });
46349
46387
  return transicionar(ctx, { companyId: input2.companyId, casoId: caso.id, via: "enviar", datos: { aviso_id: accion.id, canal, ...destinatario ? { destinatario } : {}, ...persona ? { registrado_por: persona } : {} }, actor: input2.actor });
46350
46388
  }
46389
+ async function registrarRespuestaEquipo(ctx, input2) {
46390
+ const caso = await leerCaso(ctx, input2.companyId, input2.casoId);
46391
+ if (!caso) throw new OpsError("caso_inexistente", `no existe el caso ${input2.casoId} en esta instituci\xF3n`);
46392
+ if (caso.workflow !== "ajuste_convenio") throw new OpsError("workflow_invalido", "solo los ajustes de convenio esperan una respuesta del financiador");
46393
+ if (input2.actor.tipo !== "humano") throw new OpsError("actor_no_permitido", "la respuesta la registra una persona");
46394
+ const persona = str2(input2.persona);
46395
+ if (input2.reenvio) {
46396
+ const canal = typeof input2.reenvio.canal === "string" && CANALES_NOTA.includes(input2.reenvio.canal) ? input2.reenvio.canal : "otro";
46397
+ const accion = await registrarAccion(ctx, { companyId: input2.companyId, casoId: caso.id, tipo: "aviso", conector: canal === "correo" ? "mail" : "manual", objetivo: `Nota de ajuste reenviada a ${str2(caso.datos.financiador) ?? "el financiador"}`, resultado: "ok", evidencia: { canal, destinatario: input2.reenvio.destinatario, ...persona ? { registrado_por: persona } : {} }, actor: input2.actor });
46398
+ return transicionar(ctx, { companyId: input2.companyId, casoId: caso.id, via: "reenviar", datos: { aviso_id: accion.id, canal, destinatario: input2.reenvio.destinatario, ...persona ? { registrado_por: persona } : {} }, actor: input2.actor });
46399
+ }
46400
+ const n = typeof input2.porcentaje === "number" ? input2.porcentaje : typeof input2.porcentaje === "string" && input2.porcentaje.trim() ? Number(input2.porcentaje) : void 0;
46401
+ return transicionar(ctx, { companyId: input2.companyId, casoId: caso.id, via: "informar_respuesta", motivo: str2(input2.detalle), datos: { respuesta: input2.respuesta, ...n !== void 0 ? { porcentaje: n } : {}, ...str2(input2.detalle) ? { motivo: str2(input2.detalle) } : {}, ...persona ? { registrado_por: persona } : {} }, actor: input2.actor });
46402
+ }
46351
46403
  async function registrarEnvioNota(ctx, input2) {
46352
46404
  const caso = await leerCaso(ctx, input2.companyId, input2.casoId);
46353
46405
  if (!caso) throw new OpsError("caso_inexistente", `no existe el caso ${input2.casoId} en esta instituci\xF3n`);
@@ -47403,6 +47455,11 @@ async function manejarApi(ctx, input2) {
47403
47455
  const datosA = { ...body.porcentaje !== void 0 ? { porcentaje: body.porcentaje } : {}, ...Array.isArray(body.excluir) ? { excluir: body.excluir } : {} };
47404
47456
  return respuesta(200, await transicionar(ctx, { companyId, casoId: input2.params.casoId ?? "", via: "ajustar", motivo: motivoConPersona(str3(body.motivo)), datos: conPersona({ ...datosA, ...str3(body.motivo) ? { motivo: str3(body.motivo) } : {} }), idempotencyKey: str3(body.idempotencyKey), actor }));
47405
47457
  }
47458
+ case "respuesta-equipo": {
47459
+ if (actor.tipo !== "humano") return respuesta(403, { error: "actor_no_permitido", motivo: "la respuesta la registra una persona" });
47460
+ const reenvio = body.reenvio && typeof body.reenvio === "object" ? body.reenvio : null;
47461
+ return respuesta(200, await registrarRespuestaEquipo(ctx, { companyId, casoId: input2.params.casoId ?? "", respuesta: body.respuesta, porcentaje: body.porcentaje, detalle: str3(body.detalle), reenvio: reenvio ? { canal: reenvio.canal, destinatario: str3(reenvio.destinatario) } : null, persona: decididoPor, actor }));
47462
+ }
47406
47463
  case "envio-nota": {
47407
47464
  if (actor.tipo !== "humano") return respuesta(403, { error: "actor_no_permitido", motivo: "el env\xEDo lo registra una persona" });
47408
47465
  return respuesta(200, await registrarEnvioNota(ctx, { companyId, casoId: input2.params.casoId ?? "", canal: body.canal, destinatario: str3(body.destinatario), persona: decididoPor, actor }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paperclip-plugin-autopilot-ops",
3
- "version": "0.1.37",
3
+ "version": "0.1.38",
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": [