paperclip-plugin-autopilot-ops 0.1.46 → 0.1.48

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.46";
3
+ var PLUGIN_VERSION = "0.1.48";
4
4
  var DB_NAMESPACE_SLUG = "autopilot_ops";
5
5
  var PAGE_ROUTE = "autopilot";
6
6
  var TOOL_NAMES = {
@@ -345,6 +345,14 @@ var manifest = {
345
345
  capability: "api.routes.register",
346
346
  companyResolution: { from: "body", key: "companyId" }
347
347
  },
348
+ {
349
+ routeKey: "suspender-agenda",
350
+ method: "POST",
351
+ path: "/casos/:casoId/suspender-agenda",
352
+ auth: "board",
353
+ capability: "api.routes.register",
354
+ companyResolution: { from: "body", key: "companyId" }
355
+ },
348
356
  {
349
357
  routeKey: "version",
350
358
  method: "GET",
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.46";
11
+ var PLUGIN_VERSION = "0.1.48";
12
12
  var DB_NAMESPACE_SLUG = "autopilot_ops";
13
13
  var PAGE_ROUTE = "autopilot";
14
14
  var TOOL_NAMES = {
@@ -353,6 +353,14 @@ var manifest = {
353
353
  capability: "api.routes.register",
354
354
  companyResolution: { from: "body", key: "companyId" }
355
355
  },
356
+ {
357
+ routeKey: "suspender-agenda",
358
+ method: "POST",
359
+ path: "/casos/:casoId/suspender-agenda",
360
+ auth: "board",
361
+ capability: "api.routes.register",
362
+ companyResolution: { from: "body", key: "companyId" }
363
+ },
356
364
  {
357
365
  routeKey: "version",
358
366
  method: "GET",
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.46";
39935
+ var PLUGIN_VERSION = "0.1.48";
39936
39936
  var DB_NAMESPACE_SLUG = "autopilot_ops";
39937
39937
  var PAGE_ROUTE = "autopilot";
39938
39938
  var TOOL_NAMES = {
@@ -40277,6 +40277,14 @@ var manifest = {
40277
40277
  capability: "api.routes.register",
40278
40278
  companyResolution: { from: "body", key: "companyId" }
40279
40279
  },
40280
+ {
40281
+ routeKey: "suspender-agenda",
40282
+ method: "POST",
40283
+ path: "/casos/:casoId/suspender-agenda",
40284
+ auth: "board",
40285
+ capability: "api.routes.register",
40286
+ companyResolution: { from: "body", key: "companyId" }
40287
+ },
40280
40288
  {
40281
40289
  routeKey: "version",
40282
40290
  method: "GET",
@@ -42494,15 +42502,16 @@ function observacionDe(r) {
42494
42502
  if (r.situacion !== "habilitado") return "inhabilitada";
42495
42503
  return null;
42496
42504
  }
42505
+ var GRAVES_MATRICULA = ["inhabilitada", "sancion", "otra_persona"];
42497
42506
  var credencialProfesional = {
42498
42507
  clave: "credencial_profesional",
42499
- nombre: "Credenciales del profesional",
42508
+ nombre: "Control de matr\xEDculas",
42500
42509
  puesto: "Personal y profesionales",
42501
- descripcion: "Lee en el HIS la matr\xEDcula de cada profesional con agenda y la verifica contra el registro nacional de profesionales de la salud (REFEPS). Si no figura, est\xE1 a nombre de otra persona, est\xE1 inhabilitada o falta cargarla, avisa al equipo con d\xF3nde se corrige. El puesto no escribe en el sistema.",
42510
+ descripcion: "Lee en el HIS la matr\xEDcula de cada profesional con agenda y la verifica contra el registro nacional de profesionales de la salud (REFEPS). Si no figura, est\xE1 a nombre de otra persona, est\xE1 inhabilitada o falta cargarla, avisa al equipo con d\xF3nde se corrige. El agente no escribe en el sistema.",
42502
42511
  inicial: "detectado",
42503
- estados: ["detectado", "vigente", "observada", "corregida", "no_corresponde", "descartado"],
42512
+ estados: ["detectado", "vigente", "observada", "corregida", "no_corresponde", "agenda_suspendida", "descartado"],
42504
42513
  finalesOk: ["vigente"],
42505
- finalesNoOk: ["no_corresponde", "descartado"],
42514
+ finalesNoOk: ["no_corresponde", "agenda_suspendida", "descartado"],
42506
42515
  minutosAbsorbidos: 5,
42507
42516
  transiciones: [
42508
42517
  {
@@ -42534,7 +42543,7 @@ var credencialProfesional = {
42534
42543
  a: "corregida",
42535
42544
  actor: ["humano"],
42536
42545
  cargaManual: true,
42537
- descripcion: "Una persona de la instituci\xF3n corrigi\xF3 la ficha del profesional en el HIS. El puesto vuelve a verificar.",
42546
+ descripcion: "Una persona de la instituci\xF3n corrigi\xF3 la ficha del profesional en el HIS. El agente vuelve a consultar el registro.",
42538
42547
  validar: (_caso, datos) => [
42539
42548
  texto4(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "corregir requiere accion_id de la carga registrada")
42540
42549
  ]
@@ -42547,6 +42556,17 @@ var credencialProfesional = {
42547
42556
  descripcion: "El equipo indica que la observaci\xF3n no aplica (por ejemplo, personal no matriculado o matr\xEDcula provincial confirmada con el colegio). Queda registrado con el motivo.",
42548
42557
  validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "no_corresponde requiere motivo")]
42549
42558
  },
42559
+ {
42560
+ via: "suspender_agenda",
42561
+ de: ["observada"],
42562
+ a: "agenda_suspendida",
42563
+ actor: ["humano"],
42564
+ descripcion: "La matr\xEDcula est\xE1 de verdad inhabilitada, con sanci\xF3n o a nombre de otra persona: la instituci\xF3n suspendi\xF3 la agenda del profesional hasta que lo regularice. Queda registrado qui\xE9n lo decidi\xF3 y por qu\xE9.",
42565
+ validar: (caso, datos) => [
42566
+ GRAVES_MATRICULA.includes(texto4(caso.datos.observacion) ?? "") ? ok("observacion_grave") : falla("observacion_grave", "suspender la agenda es para una matr\xEDcula inhabilitada, con sanci\xF3n o a nombre de otra persona"),
42567
+ texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "suspender_agenda requiere motivo")
42568
+ ]
42569
+ },
42550
42570
  {
42551
42571
  via: "descartar",
42552
42572
  de: ["detectado", "observada", "corregida"],
@@ -45799,6 +45819,12 @@ async function transicionar(ctx, input2) {
45799
45819
  datos.observacion = observacionDe(r);
45800
45820
  datos.verificada_el = contexto.hoy ?? null;
45801
45821
  }
45822
+ const ag = datos.agenda && typeof datos.agenda === "object" ? datos.agenda : null;
45823
+ if (ag) {
45824
+ const proximo = typeof ag.proximo_turno === "string" && /^\d{4}-\d{2}-\d{2}( \d{2}:\d{2})?$/.test(ag.proximo_turno) ? ag.proximo_turno : null;
45825
+ const n = Number(ag.turnos_7_dias);
45826
+ datos.agenda = { proximo_turno: proximo, turnos_7_dias: Number.isInteger(n) && n >= 0 && n < 1e4 ? n : 0, leida_el: contexto.hoy ?? null };
45827
+ } else delete datos.agenda;
45802
45828
  }
45803
45829
  if (caso.workflow === "facturacion_pendiente" && resultado.via === "observar") {
45804
45830
  const fecha5 = String(datos.fecha_prestacion ?? caso.datos.fecha_prestacion ?? "");
@@ -46322,8 +46348,9 @@ async function tablero(ctx, companyId, diasInput) {
46322
46348
  p2
46323
46349
  );
46324
46350
  const totalRows = await ctx.db.query(
46325
- `SELECT coalesce(sum(minutos_absorbidos), 0)::int AS minutos FROM ${t3(ctx, "caso")} WHERE company_id = $1 AND NOT (estado = ANY($2::text[]))`,
46326
- [companyId, [...finalesSinTrabajo()]]
46351
+ // Los estados van escritos en la consulta (salen del código, no del usuario): el host no pasa listas como parámetro.
46352
+ `SELECT coalesce(sum(minutos_absorbidos), 0)::int AS minutos FROM ${t3(ctx, "caso")} WHERE company_id = $1${[...finalesSinTrabajo()].filter((e) => /^[a-z_]+$/.test(e)).map((e) => ` AND estado <> '${e}'`).join("")}`,
46353
+ p1
46327
46354
  );
46328
46355
  const accionesRows = await ctx.db.query(
46329
46356
  `SELECT tipo, count(*)::int AS cantidad FROM ${t3(ctx, "accion")} WHERE company_id = $1 AND created_at >= now() - ($2::int * interval '1 day') GROUP BY tipo`,
@@ -46580,7 +46607,8 @@ var ROLES = {
46580
46607
  facturacion: "Facturaci\xF3n",
46581
46608
  internacion: "Internaci\xF3n",
46582
46609
  honorarios: "Honorarios",
46583
- personal: "Administraci\xF3n de personal"
46610
+ personal: "Administraci\xF3n de personal",
46611
+ direccion_medica: "Direcci\xF3n m\xE9dica"
46584
46612
  };
46585
46613
  var ESPERAN_PERSONA = {
46586
46614
  cuenta_completa: ["para_completar", "con_faltantes"],
@@ -46680,11 +46708,12 @@ function pendientesDe(caso, hoy) {
46680
46708
  const nombre = texto8(d.profesional) ?? (id3 ? `Profesional ${id3}` : "Profesional");
46681
46709
  const obs = texto8(d.observacion);
46682
46710
  const que = `${nombre}: ${(obs && OBSERVACIONES_MATRICULA[obs]) ?? "la matr\xEDcula tiene una observaci\xF3n del registro nacional"}`;
46683
- return [{ ...base, que, responsable: id3 ? { clave: `profesional:${id3}`, nombre, reserva: "rol:personal" } : rol("personal") }];
46711
+ const grave = obs === "inhabilitada" || obs === "sancion" || obs === "otra_persona";
46712
+ return [{ ...base, que, responsable: rol("personal") }, ...grave ? [{ ...base, que, responsable: rol("direccion_medica") }] : []];
46684
46713
  }
46685
46714
  return [];
46686
46715
  }
46687
- var CLAVE_RE = /^(profesional:[A-Za-z0-9_-]{1,40}|financiador:\d{1,12}|rol:(admision|aranceles|facturacion|internacion|personal|honorarios))$/;
46716
+ var CLAVE_RE = /^(profesional:[A-Za-z0-9_-]{1,40}|financiador:\d{1,12}|rol:(admision|aranceles|facturacion|internacion|personal|honorarios|direccion_medica))$/;
46688
46717
  var MAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
46689
46718
  var COLS_CONTACTO = "id, clave, nombre, mail, whatsapp, activo, updated_at";
46690
46719
  function mapContacto(r) {
@@ -47671,6 +47700,11 @@ async function manejarApi(ctx, input2) {
47671
47700
  return respuesta(200, await registrarCargaManual(ctx, { companyId, casoId: input2.params.casoId ?? "", valorCargado: body.valorCargado, archivoHash: str3(body.archivoHash), canal: str3(body.canal), destinatario: str3(body.destinatario), comentario: str3(body.comentario), persona: decididoPor, idempotencyKey: str3(body.idempotencyKey), actor }));
47672
47701
  case "respuesta-paciente":
47673
47702
  return respuesta(200, await registrarRespuestaPaciente(ctx, { companyId, casoId: input2.params.casoId ?? "", acepto: body.acepto === true, comentario: str3(body.comentario), persona: decididoPor, idempotencyKey: str3(body.idempotencyKey), actor }));
47703
+ case "suspender-agenda": {
47704
+ if (actor.tipo !== "humano") return respuesta(403, { error: "actor_no_permitido", motivo: "suspender la agenda lo decide una persona de la instituci\xF3n" });
47705
+ if (!str3(body.motivo)) return respuesta(422, { error: "validacion", motivo: "motivo_presente: suspender_agenda requiere motivo" });
47706
+ return respuesta(200, await transicionar(ctx, { companyId, casoId: input2.params.casoId ?? "", via: "suspender_agenda", motivo: motivoConPersona(str3(body.motivo)), datos: conPersona(obj(body.datos)), idempotencyKey: str3(body.idempotencyKey), actor }));
47707
+ }
47674
47708
  case "no-corresponde": {
47675
47709
  if (actor.tipo !== "humano") return respuesta(403, { error: "actor_no_permitido", motivo: "no_corresponde lo decide una persona de la instituci\xF3n" });
47676
47710
  if (!str3(body.motivo)) return respuesta(422, { error: "validacion", motivo: "motivo_presente: no_corresponde requiere motivo" });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paperclip-plugin-autopilot-ops",
3
- "version": "0.1.46",
3
+ "version": "0.1.48",
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": [