paperclip-plugin-autopilot-ops 0.1.7 → 0.1.8

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.7";
3
+ var PLUGIN_VERSION = "0.1.8";
4
4
  var DB_NAMESPACE_SLUG = "autopilot_ops";
5
5
  var PAGE_ROUTE = "autopilot";
6
6
  var TOOL_NAMES = {
@@ -34,7 +34,7 @@ var manifest = {
34
34
  apiVersion: 1,
35
35
  version: PLUGIN_VERSION,
36
36
  displayName: "Autopilot Care",
37
- description: "Operaci\xF3n aut\xF3noma gobernada para instituciones de salud: workflows determin\xEDsticos por puesto, validaciones, registro de negocio con evidencia, pol\xEDticas (observa / propone / ejecuta / aut\xF3nomo / corte), carga manual del equipo del hospital con comprobaci\xF3n del agente, recupero de turnos liberados desde la lista de espera, tableros de gesti\xF3n publicados por agentes y panel del director.",
37
+ description: "Operaci\xF3n aut\xF3noma gobernada para instituciones de salud: workflows determin\xEDsticos por puesto, validaciones, registro de negocio con evidencia, pol\xEDticas (observa / propone / ejecuta / aut\xF3nomo / corte), carga manual del equipo del hospital con comprobaci\xF3n del agente, recupero de turnos liberados desde la lista de espera, control de cuenta completa antes de facturar, tableros de gesti\xF3n publicados por agentes y panel del director.",
38
38
  author: "Alephoo",
39
39
  categories: ["automation", "ui"],
40
40
  capabilities: [
@@ -84,7 +84,7 @@ var manifest = {
84
84
  {
85
85
  name: TOOL_NAMES.abrirCaso,
86
86
  displayName: "Abrir caso",
87
- description: 'Abre un caso nuevo en un workflow, en su estado inicial. Workflows: `actualizacion_arancel`, `tarea_operativa`, `recupero_turno` (datos: fecha AAAA-MM-DD, hora HH:MM, profesional, especialidad del turno libre; referencia "AAAA-MM-DD HH:MM \xB7 Profesional"). `referencia` identifica el objeto real (convenio, cuenta, turno) y evita duplicados: si ya existe un caso abierto con la misma referencia, se devuelve ese. Pasar `idempotencyKey` para reintentos seguros.',
87
+ description: 'Abre un caso nuevo en un workflow, en su estado inicial. Workflows: `actualizacion_arancel`, `tarea_operativa`, `recupero_turno` (datos: fecha AAAA-MM-DD, hora HH:MM, profesional, especialidad del turno libre; referencia "AAAA-MM-DD HH:MM \xB7 Profesional"), `cuenta_completa` (una prestaci\xF3n pendiente de facturar con faltantes; referencia obligatoria "bono:<n\xFAmero>", datos: bono_id, bono_numero, obra_social, plan, prestacion, fecha_prestacion AAAA-MM-DD, monto_pesos). `referencia` identifica el objeto real (convenio, cuenta, turno) y evita duplicados: si ya existe un caso abierto con la misma referencia, se devuelve ese. Pasar `idempotencyKey` para reintentos seguros.',
88
88
  parametersSchema: {
89
89
  type: "object",
90
90
  properties: {
@@ -101,7 +101,7 @@ var manifest = {
101
101
  {
102
102
  name: TOOL_NAMES.transicionar,
103
103
  displayName: "Transicionar caso",
104
- description: "Aplica una transici\xF3n del workflow al caso (p. ej. `proponer`, `aplicar`, `verificar`). El plugin valida contra la tabla de transiciones, la pol\xEDtica vigente (observa / propone / ejecuta / corte) y las reglas de negocio; si algo falla, el caso no cambia y se devuelve el motivo. Las transiciones humanas (aprobar, rechazar, corregir) no est\xE1n disponibles para agentes. Cuando una persona del hospital carga a mano lo aprobado, el caso queda en `aplicado`: el agente lo comprueba releyendo el sistema y llamando `verificar` con `datos.valor_leido`. En `recupero_turno`: `proponer` con solicitud_id, solicitud_estado, solicitud_especialidad, cola (la lista de espera pendiente de esa especialidad tal como se vio: [{solicitud_id, prioridad, alta}]; el plugin la ordena y exige justificaci\xF3n para no elegir la primera) y fuente; si la instituci\xF3n pide consulta previa (ops_leer_caso lo dice), `ofrecer` con canal y esperar `aceptar`/`no_acepta`; **antes de escribir en el sistema, `autorizar`** (sin esa autorizaci\xF3n no se escribe); despu\xE9s de escribir, `asignar` con accion_id; `verificar` con leido_fecha, leido_hora, leido_profesional y leido_solicitud_id; `sin_candidato` y `descartar` con motivo.",
104
+ description: 'Aplica una transici\xF3n del workflow al caso (p. ej. `proponer`, `aplicar`, `verificar`). El plugin valida contra la tabla de transiciones, la pol\xEDtica vigente (observa / propone / ejecuta / corte) y las reglas de negocio; si algo falla, el caso no cambia y se devuelve el motivo. Las transiciones humanas (aprobar, rechazar, corregir) no est\xE1n disponibles para agentes. Cuando una persona del hospital carga a mano lo aprobado, el caso queda en `aplicado`: el agente lo comprueba releyendo el sistema y llamando `verificar` con `datos.valor_leido`. En `recupero_turno`: `proponer` con solicitud_id, solicitud_estado, solicitud_especialidad, cola (la lista de espera pendiente de esa especialidad tal como se vio: [{solicitud_id, prioridad, alta}]; el plugin la ordena y exige justificaci\xF3n para no elegir la primera) y fuente; si la instituci\xF3n pide consulta previa (ops_leer_caso lo dice), `ofrecer` con canal y esperar `aceptar`/`no_acepta`; **antes de escribir en el sistema, `autorizar`** (sin esa autorizaci\xF3n no se escribe); despu\xE9s de escribir, `asignar` con accion_id; `verificar` con leido_fecha, leido_hora, leido_profesional y leido_solicitud_id; `sin_candidato` y `descartar` con motivo. En `cuenta_completa` el agente solo lee: `observar` con bono_id, bono_estado (no_confirmado, confirmado o prefacturado), faltantes [{regla, detalle, item?}] con reglas del cat\xE1logo (autorizacion_faltante, validacion_faltante, afiliado_faltante, orden_faltante, prestacion_sin_valor, epicrisis_faltante), lectura_id (la lectura registrada con ops_registrar_accion, conector "base") y fuente; `comprobar` con faltantes_leidos (lista vac\xEDa si ya est\xE1 completo), bono_estado_leido y lectura_id; `descartar` con motivo si el bono se elimin\xF3 o anul\xF3.',
105
105
  parametersSchema: {
106
106
  type: "object",
107
107
  properties: {
@@ -123,7 +123,7 @@ var manifest = {
123
123
  properties: {
124
124
  casoId: { type: "string" },
125
125
  tipo: { type: "string", enum: ["lectura", "escritura", "verificacion"] },
126
- conector: { type: "string", enum: ["api", "archivo", "pantalla", "manual"] },
126
+ conector: { type: "string", enum: ["api", "base", "archivo", "pantalla", "manual"], description: "Por d\xF3nde se ley\xF3 o escribi\xF3: api, base (lectura de la base de datos del hospital), archivo, pantalla o manual." },
127
127
  objetivo: { type: "string" },
128
128
  resultado: { type: "string", enum: ["ok", "error", "pendiente"] },
129
129
  evidencia: { type: "object" },
@@ -229,6 +229,14 @@ var manifest = {
229
229
  capability: "api.routes.register",
230
230
  companyResolution: { from: "body", key: "companyId" }
231
231
  },
232
+ {
233
+ routeKey: "no-corresponde",
234
+ method: "POST",
235
+ path: "/casos/:casoId/no-corresponde",
236
+ auth: "board",
237
+ capability: "api.routes.register",
238
+ companyResolution: { from: "body", key: "companyId" }
239
+ },
232
240
  {
233
241
  routeKey: "version",
234
242
  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.7";
11
+ var PLUGIN_VERSION = "0.1.8";
12
12
  var DB_NAMESPACE_SLUG = "autopilot_ops";
13
13
  var PAGE_ROUTE = "autopilot";
14
14
  var TOOL_NAMES = {
@@ -42,7 +42,7 @@ var manifest = {
42
42
  apiVersion: 1,
43
43
  version: PLUGIN_VERSION,
44
44
  displayName: "Autopilot Care",
45
- description: "Operaci\xF3n aut\xF3noma gobernada para instituciones de salud: workflows determin\xEDsticos por puesto, validaciones, registro de negocio con evidencia, pol\xEDticas (observa / propone / ejecuta / aut\xF3nomo / corte), carga manual del equipo del hospital con comprobaci\xF3n del agente, recupero de turnos liberados desde la lista de espera, tableros de gesti\xF3n publicados por agentes y panel del director.",
45
+ description: "Operaci\xF3n aut\xF3noma gobernada para instituciones de salud: workflows determin\xEDsticos por puesto, validaciones, registro de negocio con evidencia, pol\xEDticas (observa / propone / ejecuta / aut\xF3nomo / corte), carga manual del equipo del hospital con comprobaci\xF3n del agente, recupero de turnos liberados desde la lista de espera, control de cuenta completa antes de facturar, tableros de gesti\xF3n publicados por agentes y panel del director.",
46
46
  author: "Alephoo",
47
47
  categories: ["automation", "ui"],
48
48
  capabilities: [
@@ -92,7 +92,7 @@ var manifest = {
92
92
  {
93
93
  name: TOOL_NAMES.abrirCaso,
94
94
  displayName: "Abrir caso",
95
- description: 'Abre un caso nuevo en un workflow, en su estado inicial. Workflows: `actualizacion_arancel`, `tarea_operativa`, `recupero_turno` (datos: fecha AAAA-MM-DD, hora HH:MM, profesional, especialidad del turno libre; referencia "AAAA-MM-DD HH:MM \xB7 Profesional"). `referencia` identifica el objeto real (convenio, cuenta, turno) y evita duplicados: si ya existe un caso abierto con la misma referencia, se devuelve ese. Pasar `idempotencyKey` para reintentos seguros.',
95
+ description: 'Abre un caso nuevo en un workflow, en su estado inicial. Workflows: `actualizacion_arancel`, `tarea_operativa`, `recupero_turno` (datos: fecha AAAA-MM-DD, hora HH:MM, profesional, especialidad del turno libre; referencia "AAAA-MM-DD HH:MM \xB7 Profesional"), `cuenta_completa` (una prestaci\xF3n pendiente de facturar con faltantes; referencia obligatoria "bono:<n\xFAmero>", datos: bono_id, bono_numero, obra_social, plan, prestacion, fecha_prestacion AAAA-MM-DD, monto_pesos). `referencia` identifica el objeto real (convenio, cuenta, turno) y evita duplicados: si ya existe un caso abierto con la misma referencia, se devuelve ese. Pasar `idempotencyKey` para reintentos seguros.',
96
96
  parametersSchema: {
97
97
  type: "object",
98
98
  properties: {
@@ -109,7 +109,7 @@ var manifest = {
109
109
  {
110
110
  name: TOOL_NAMES.transicionar,
111
111
  displayName: "Transicionar caso",
112
- description: "Aplica una transici\xF3n del workflow al caso (p. ej. `proponer`, `aplicar`, `verificar`). El plugin valida contra la tabla de transiciones, la pol\xEDtica vigente (observa / propone / ejecuta / corte) y las reglas de negocio; si algo falla, el caso no cambia y se devuelve el motivo. Las transiciones humanas (aprobar, rechazar, corregir) no est\xE1n disponibles para agentes. Cuando una persona del hospital carga a mano lo aprobado, el caso queda en `aplicado`: el agente lo comprueba releyendo el sistema y llamando `verificar` con `datos.valor_leido`. En `recupero_turno`: `proponer` con solicitud_id, solicitud_estado, solicitud_especialidad, cola (la lista de espera pendiente de esa especialidad tal como se vio: [{solicitud_id, prioridad, alta}]; el plugin la ordena y exige justificaci\xF3n para no elegir la primera) y fuente; si la instituci\xF3n pide consulta previa (ops_leer_caso lo dice), `ofrecer` con canal y esperar `aceptar`/`no_acepta`; **antes de escribir en el sistema, `autorizar`** (sin esa autorizaci\xF3n no se escribe); despu\xE9s de escribir, `asignar` con accion_id; `verificar` con leido_fecha, leido_hora, leido_profesional y leido_solicitud_id; `sin_candidato` y `descartar` con motivo.",
112
+ description: 'Aplica una transici\xF3n del workflow al caso (p. ej. `proponer`, `aplicar`, `verificar`). El plugin valida contra la tabla de transiciones, la pol\xEDtica vigente (observa / propone / ejecuta / corte) y las reglas de negocio; si algo falla, el caso no cambia y se devuelve el motivo. Las transiciones humanas (aprobar, rechazar, corregir) no est\xE1n disponibles para agentes. Cuando una persona del hospital carga a mano lo aprobado, el caso queda en `aplicado`: el agente lo comprueba releyendo el sistema y llamando `verificar` con `datos.valor_leido`. En `recupero_turno`: `proponer` con solicitud_id, solicitud_estado, solicitud_especialidad, cola (la lista de espera pendiente de esa especialidad tal como se vio: [{solicitud_id, prioridad, alta}]; el plugin la ordena y exige justificaci\xF3n para no elegir la primera) y fuente; si la instituci\xF3n pide consulta previa (ops_leer_caso lo dice), `ofrecer` con canal y esperar `aceptar`/`no_acepta`; **antes de escribir en el sistema, `autorizar`** (sin esa autorizaci\xF3n no se escribe); despu\xE9s de escribir, `asignar` con accion_id; `verificar` con leido_fecha, leido_hora, leido_profesional y leido_solicitud_id; `sin_candidato` y `descartar` con motivo. En `cuenta_completa` el agente solo lee: `observar` con bono_id, bono_estado (no_confirmado, confirmado o prefacturado), faltantes [{regla, detalle, item?}] con reglas del cat\xE1logo (autorizacion_faltante, validacion_faltante, afiliado_faltante, orden_faltante, prestacion_sin_valor, epicrisis_faltante), lectura_id (la lectura registrada con ops_registrar_accion, conector "base") y fuente; `comprobar` con faltantes_leidos (lista vac\xEDa si ya est\xE1 completo), bono_estado_leido y lectura_id; `descartar` con motivo si el bono se elimin\xF3 o anul\xF3.',
113
113
  parametersSchema: {
114
114
  type: "object",
115
115
  properties: {
@@ -131,7 +131,7 @@ var manifest = {
131
131
  properties: {
132
132
  casoId: { type: "string" },
133
133
  tipo: { type: "string", enum: ["lectura", "escritura", "verificacion"] },
134
- conector: { type: "string", enum: ["api", "archivo", "pantalla", "manual"] },
134
+ conector: { type: "string", enum: ["api", "base", "archivo", "pantalla", "manual"], description: "Por d\xF3nde se ley\xF3 o escribi\xF3: api, base (lectura de la base de datos del hospital), archivo, pantalla o manual." },
135
135
  objetivo: { type: "string" },
136
136
  resultado: { type: "string", enum: ["ok", "error", "pendiente"] },
137
137
  evidencia: { type: "object" },
@@ -237,6 +237,14 @@ var manifest = {
237
237
  capability: "api.routes.register",
238
238
  companyResolution: { from: "body", key: "companyId" }
239
239
  },
240
+ {
241
+ routeKey: "no-corresponde",
242
+ method: "POST",
243
+ path: "/casos/:casoId/no-corresponde",
244
+ auth: "board",
245
+ capability: "api.routes.register",
246
+ companyResolution: { from: "body", key: "companyId" }
247
+ },
240
248
  {
241
249
  routeKey: "version",
242
250
  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.7";
39935
+ var PLUGIN_VERSION = "0.1.8";
39936
39936
  var DB_NAMESPACE_SLUG = "autopilot_ops";
39937
39937
  var PAGE_ROUTE = "autopilot";
39938
39938
  var TOOL_NAMES = {
@@ -39966,7 +39966,7 @@ var manifest = {
39966
39966
  apiVersion: 1,
39967
39967
  version: PLUGIN_VERSION,
39968
39968
  displayName: "Autopilot Care",
39969
- description: "Operaci\xF3n aut\xF3noma gobernada para instituciones de salud: workflows determin\xEDsticos por puesto, validaciones, registro de negocio con evidencia, pol\xEDticas (observa / propone / ejecuta / aut\xF3nomo / corte), carga manual del equipo del hospital con comprobaci\xF3n del agente, recupero de turnos liberados desde la lista de espera, tableros de gesti\xF3n publicados por agentes y panel del director.",
39969
+ description: "Operaci\xF3n aut\xF3noma gobernada para instituciones de salud: workflows determin\xEDsticos por puesto, validaciones, registro de negocio con evidencia, pol\xEDticas (observa / propone / ejecuta / aut\xF3nomo / corte), carga manual del equipo del hospital con comprobaci\xF3n del agente, recupero de turnos liberados desde la lista de espera, control de cuenta completa antes de facturar, tableros de gesti\xF3n publicados por agentes y panel del director.",
39970
39970
  author: "Alephoo",
39971
39971
  categories: ["automation", "ui"],
39972
39972
  capabilities: [
@@ -40016,7 +40016,7 @@ var manifest = {
40016
40016
  {
40017
40017
  name: TOOL_NAMES.abrirCaso,
40018
40018
  displayName: "Abrir caso",
40019
- description: 'Abre un caso nuevo en un workflow, en su estado inicial. Workflows: `actualizacion_arancel`, `tarea_operativa`, `recupero_turno` (datos: fecha AAAA-MM-DD, hora HH:MM, profesional, especialidad del turno libre; referencia "AAAA-MM-DD HH:MM \xB7 Profesional"). `referencia` identifica el objeto real (convenio, cuenta, turno) y evita duplicados: si ya existe un caso abierto con la misma referencia, se devuelve ese. Pasar `idempotencyKey` para reintentos seguros.',
40019
+ description: 'Abre un caso nuevo en un workflow, en su estado inicial. Workflows: `actualizacion_arancel`, `tarea_operativa`, `recupero_turno` (datos: fecha AAAA-MM-DD, hora HH:MM, profesional, especialidad del turno libre; referencia "AAAA-MM-DD HH:MM \xB7 Profesional"), `cuenta_completa` (una prestaci\xF3n pendiente de facturar con faltantes; referencia obligatoria "bono:<n\xFAmero>", datos: bono_id, bono_numero, obra_social, plan, prestacion, fecha_prestacion AAAA-MM-DD, monto_pesos). `referencia` identifica el objeto real (convenio, cuenta, turno) y evita duplicados: si ya existe un caso abierto con la misma referencia, se devuelve ese. Pasar `idempotencyKey` para reintentos seguros.',
40020
40020
  parametersSchema: {
40021
40021
  type: "object",
40022
40022
  properties: {
@@ -40033,7 +40033,7 @@ var manifest = {
40033
40033
  {
40034
40034
  name: TOOL_NAMES.transicionar,
40035
40035
  displayName: "Transicionar caso",
40036
- description: "Aplica una transici\xF3n del workflow al caso (p. ej. `proponer`, `aplicar`, `verificar`). El plugin valida contra la tabla de transiciones, la pol\xEDtica vigente (observa / propone / ejecuta / corte) y las reglas de negocio; si algo falla, el caso no cambia y se devuelve el motivo. Las transiciones humanas (aprobar, rechazar, corregir) no est\xE1n disponibles para agentes. Cuando una persona del hospital carga a mano lo aprobado, el caso queda en `aplicado`: el agente lo comprueba releyendo el sistema y llamando `verificar` con `datos.valor_leido`. En `recupero_turno`: `proponer` con solicitud_id, solicitud_estado, solicitud_especialidad, cola (la lista de espera pendiente de esa especialidad tal como se vio: [{solicitud_id, prioridad, alta}]; el plugin la ordena y exige justificaci\xF3n para no elegir la primera) y fuente; si la instituci\xF3n pide consulta previa (ops_leer_caso lo dice), `ofrecer` con canal y esperar `aceptar`/`no_acepta`; **antes de escribir en el sistema, `autorizar`** (sin esa autorizaci\xF3n no se escribe); despu\xE9s de escribir, `asignar` con accion_id; `verificar` con leido_fecha, leido_hora, leido_profesional y leido_solicitud_id; `sin_candidato` y `descartar` con motivo.",
40036
+ description: 'Aplica una transici\xF3n del workflow al caso (p. ej. `proponer`, `aplicar`, `verificar`). El plugin valida contra la tabla de transiciones, la pol\xEDtica vigente (observa / propone / ejecuta / corte) y las reglas de negocio; si algo falla, el caso no cambia y se devuelve el motivo. Las transiciones humanas (aprobar, rechazar, corregir) no est\xE1n disponibles para agentes. Cuando una persona del hospital carga a mano lo aprobado, el caso queda en `aplicado`: el agente lo comprueba releyendo el sistema y llamando `verificar` con `datos.valor_leido`. En `recupero_turno`: `proponer` con solicitud_id, solicitud_estado, solicitud_especialidad, cola (la lista de espera pendiente de esa especialidad tal como se vio: [{solicitud_id, prioridad, alta}]; el plugin la ordena y exige justificaci\xF3n para no elegir la primera) y fuente; si la instituci\xF3n pide consulta previa (ops_leer_caso lo dice), `ofrecer` con canal y esperar `aceptar`/`no_acepta`; **antes de escribir en el sistema, `autorizar`** (sin esa autorizaci\xF3n no se escribe); despu\xE9s de escribir, `asignar` con accion_id; `verificar` con leido_fecha, leido_hora, leido_profesional y leido_solicitud_id; `sin_candidato` y `descartar` con motivo. En `cuenta_completa` el agente solo lee: `observar` con bono_id, bono_estado (no_confirmado, confirmado o prefacturado), faltantes [{regla, detalle, item?}] con reglas del cat\xE1logo (autorizacion_faltante, validacion_faltante, afiliado_faltante, orden_faltante, prestacion_sin_valor, epicrisis_faltante), lectura_id (la lectura registrada con ops_registrar_accion, conector "base") y fuente; `comprobar` con faltantes_leidos (lista vac\xEDa si ya est\xE1 completo), bono_estado_leido y lectura_id; `descartar` con motivo si el bono se elimin\xF3 o anul\xF3.',
40037
40037
  parametersSchema: {
40038
40038
  type: "object",
40039
40039
  properties: {
@@ -40055,7 +40055,7 @@ var manifest = {
40055
40055
  properties: {
40056
40056
  casoId: { type: "string" },
40057
40057
  tipo: { type: "string", enum: ["lectura", "escritura", "verificacion"] },
40058
- conector: { type: "string", enum: ["api", "archivo", "pantalla", "manual"] },
40058
+ conector: { type: "string", enum: ["api", "base", "archivo", "pantalla", "manual"], description: "Por d\xF3nde se ley\xF3 o escribi\xF3: api, base (lectura de la base de datos del hospital), archivo, pantalla o manual." },
40059
40059
  objetivo: { type: "string" },
40060
40060
  resultado: { type: "string", enum: ["ok", "error", "pendiente"] },
40061
40061
  evidencia: { type: "object" },
@@ -40161,6 +40161,14 @@ var manifest = {
40161
40161
  capability: "api.routes.register",
40162
40162
  companyResolution: { from: "body", key: "companyId" }
40163
40163
  },
40164
+ {
40165
+ routeKey: "no-corresponde",
40166
+ method: "POST",
40167
+ path: "/casos/:casoId/no-corresponde",
40168
+ auth: "board",
40169
+ capability: "api.routes.register",
40170
+ companyResolution: { from: "body", key: "companyId" }
40171
+ },
40164
40172
  {
40165
40173
  routeKey: "version",
40166
40174
  method: "GET",
@@ -40707,10 +40715,146 @@ var recuperoTurno = {
40707
40715
  }
40708
40716
  ]
40709
40717
  };
40718
+ var REGLAS_CUENTA = {
40719
+ autorizacion_faltante: {
40720
+ nombre: "Falta el n\xFAmero de autorizaci\xF3n",
40721
+ dondeSeCorrige: "Alephoo \u203A Facturaci\xF3n \u203A Preparar Informaci\xF3n \u203A Editar bono: n\xFAmero de autorizaci\xF3n de la prestaci\xF3n (o \xABValidar con broker\xBB)"
40722
+ },
40723
+ validacion_faltante: {
40724
+ nombre: "Falta la validaci\xF3n online del financiador",
40725
+ dondeSeCorrige: "Alephoo \u203A Facturaci\xF3n \u203A Preparar Informaci\xF3n \u203A Editar bono: \xABValidar con broker\xBB en la prestaci\xF3n"
40726
+ },
40727
+ afiliado_faltante: {
40728
+ nombre: "Falta el n\xFAmero de afiliado",
40729
+ dondeSeCorrige: "Alephoo \u203A Facturaci\xF3n \u203A Preparar Informaci\xF3n \u203A Editar bono: n\xFAmero de afiliado (tambi\xE9n actualiza el padr\xF3n del paciente)"
40730
+ },
40731
+ orden_faltante: {
40732
+ nombre: "Faltan los datos de la orden m\xE9dica",
40733
+ dondeSeCorrige: "Alephoo \u203A Facturaci\xF3n \u203A Preparar Informaci\xF3n \u203A Editar bono: m\xE9dico solicitante y fecha de la receta de la prestaci\xF3n"
40734
+ },
40735
+ prestacion_sin_valor: {
40736
+ nombre: "Prestaci\xF3n valorizada en $0",
40737
+ dondeSeCorrige: "Alephoo \u203A Facturaci\xF3n \u203A Configuraci\xF3n de convenios: cargar el valor de la pr\xE1ctica; despu\xE9s Facturaci\xF3n \u203A Actualizar Bonos"
40738
+ },
40739
+ epicrisis_faltante: {
40740
+ nombre: "Internaci\xF3n con egreso y sin epicrisis",
40741
+ dondeSeCorrige: "Alephoo \u203A historia cl\xEDnica del paciente internado \u203A Epicrisis"
40742
+ }
40743
+ };
40744
+ var BONO_POR_FACTURAR = ["no_confirmado", "confirmado", "prefacturado"];
40745
+ var BONO_FACTURADO = ["facturado", "refacturado"];
40746
+ function leerFaltantes(v) {
40747
+ if (!Array.isArray(v)) return null;
40748
+ const out = [];
40749
+ for (const e of v) {
40750
+ if (!e || typeof e !== "object") return null;
40751
+ const r = e;
40752
+ const regla = texto(r.regla);
40753
+ const detalle = texto(r.detalle);
40754
+ if (!regla || !REGLAS_CUENTA[regla] || !detalle) return null;
40755
+ out.push({ regla, detalle, item: refExterna(r.item) });
40756
+ }
40757
+ return out;
40758
+ }
40759
+ function validarFaltantes(campo, v, alMenosUno) {
40760
+ const lista = leerFaltantes(v);
40761
+ if (!lista) {
40762
+ return falla("faltantes_validos", `${campo} tiene que ser una lista [{regla, detalle, item?}] con reglas del cat\xE1logo: ${Object.keys(REGLAS_CUENTA).join(", ")}`);
40763
+ }
40764
+ if (alMenosUno && lista.length === 0) return falla("faltantes_validos", `${campo} est\xE1 vac\xEDo: una cuenta sin faltantes no se abre`);
40765
+ return ok("faltantes_validos", lista.length === 0 ? "sin faltantes" : lista.length === 1 ? "1 faltante" : `${lista.length} faltantes`);
40766
+ }
40767
+ function estadoBono(v) {
40768
+ const s = texto(v);
40769
+ return s ? s.toLowerCase().replace(/[\s-]+/g, "_") : null;
40770
+ }
40771
+ var cuentaCompleta = {
40772
+ clave: "cuenta_completa",
40773
+ nombre: "Cuenta completa antes de facturar",
40774
+ puesto: "Admisi\xF3n y cuenta",
40775
+ descripcion: "Lee en el sistema del hospital cada prestaci\xF3n pendiente de facturar y marca lo que le falta para facturarse sin d\xE9bito (autorizaci\xF3n, validaci\xF3n, afiliado, orden, valor, epicrisis). El equipo lo completa y el puesto lo comprueba volviendo a leer. El puesto no escribe en el sistema.",
40776
+ inicial: "detectado",
40777
+ estados: ["detectado", "para_completar", "completado", "con_faltantes", "completa", "facturado_incompleto", "no_corresponde", "descartado"],
40778
+ finalesOk: ["completa"],
40779
+ finalesNoOk: ["facturado_incompleto", "no_corresponde", "descartado"],
40780
+ minutosAbsorbidos: 10,
40781
+ transiciones: [
40782
+ {
40783
+ via: "observar",
40784
+ de: ["detectado"],
40785
+ a: "para_completar",
40786
+ actor: ["agente", "humano"],
40787
+ nivelRequerido: "observa",
40788
+ descripcion: "Informar lo que le falta a la prestaci\xF3n (bono) para facturarse, con la lectura registrada que lo muestra. Solo faltantes del cat\xE1logo; el bono tiene que estar todav\xEDa sin facturar.",
40789
+ validar: (caso, datos) => {
40790
+ const l = { ...caso.datos, ...datos };
40791
+ const estado = estadoBono(datos.bono_estado);
40792
+ return [
40793
+ refExterna(l.bono_id) ? ok("bono_presente") : falla("bono_presente", "observar requiere bono_id: el n\xFAmero de bono en el sistema del hospital"),
40794
+ estado && BONO_POR_FACTURAR.includes(estado) ? ok("bono_sin_facturar", estado) : falla("bono_sin_facturar", `el bono tiene que estar sin facturar (${BONO_POR_FACTURAR.join(", ")}); est\xE1: ${texto(datos.bono_estado) ?? "sin informar"}`),
40795
+ validarFaltantes("faltantes", datos.faltantes, true),
40796
+ texto(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "observar requiere lectura_id: la lectura de la base registrada con ops_registrar_accion"),
40797
+ texto(datos.fuente) ? ok("fuente_presente") : falla("fuente_presente", "fuente (base y consulta de donde salen los faltantes) es obligatoria")
40798
+ ];
40799
+ }
40800
+ },
40801
+ {
40802
+ via: "completar",
40803
+ de: ["para_completar", "con_faltantes"],
40804
+ a: "completado",
40805
+ actor: ["humano"],
40806
+ cargaManual: true,
40807
+ descripcion: "Una persona del hospital complet\xF3 en el sistema lo que faltaba. El puesto lo comprueba volviendo a leer.",
40808
+ validar: (_caso, datos) => [
40809
+ texto(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "completar requiere accion_id de la carga registrada")
40810
+ ]
40811
+ },
40812
+ {
40813
+ // Lo decide el plugin con lo que se volvió a leer: sin faltantes, completa; facturada con faltantes, sale con riesgo de débito.
40814
+ via: "comprobar",
40815
+ de: ["para_completar", "completado", "con_faltantes"],
40816
+ a: (caso, datos) => {
40817
+ const faltan = leerFaltantes(datos.faltantes_leidos) ?? [];
40818
+ if (faltan.length === 0) return "completa";
40819
+ if (BONO_FACTURADO.includes(estadoBono(datos.bono_estado_leido) ?? "")) return "facturado_incompleto";
40820
+ return caso.estado === "completado" ? "con_faltantes" : caso.estado;
40821
+ },
40822
+ actor: ["agente", "humano", "sistema"],
40823
+ nivelRequerido: "observa",
40824
+ descripcion: "Volver a leer el bono en el sistema e informar lo que todav\xEDa falta (lista vac\xEDa si est\xE1 completo) y su estado. El plugin decide: completa, sigue para completar, con faltantes o facturada incompleta.",
40825
+ validar: (_caso, datos) => {
40826
+ const estado = estadoBono(datos.bono_estado_leido);
40827
+ return [
40828
+ validarFaltantes("faltantes_leidos", datos.faltantes_leidos, false),
40829
+ estado && [...BONO_POR_FACTURAR, ...BONO_FACTURADO].includes(estado) ? ok("estado_leido", estado) : falla("estado_leido", `bono_estado_leido tiene que ser uno de: ${[...BONO_POR_FACTURAR, ...BONO_FACTURADO].join(", ")} (si el bono se elimin\xF3 o se anul\xF3, descartar)`),
40830
+ texto(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "comprobar requiere lectura_id: la lectura de la base registrada con ops_registrar_accion")
40831
+ ];
40832
+ }
40833
+ },
40834
+ {
40835
+ via: "no_corresponde",
40836
+ de: ["para_completar", "completado", "con_faltantes"],
40837
+ a: "no_corresponde",
40838
+ actor: ["humano"],
40839
+ descripcion: "El equipo indica que lo marcado no hace falta para esta prestaci\xF3n (por ejemplo, el financiador no pide autorizaci\xF3n). Queda registrado con el motivo.",
40840
+ validar: (_caso, datos) => [texto(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "no_corresponde requiere motivo")]
40841
+ },
40842
+ {
40843
+ via: "descartar",
40844
+ de: ["detectado", "para_completar", "completado", "con_faltantes"],
40845
+ a: "descartado",
40846
+ actor: ["agente", "humano"],
40847
+ nivelRequerido: "observa",
40848
+ descripcion: "El bono se elimin\xF3, se anul\xF3 o qued\xF3 como no cobrable: ya no hay nada que completar.",
40849
+ validar: (_caso, datos) => [texto(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "descartar requiere motivo")]
40850
+ }
40851
+ ]
40852
+ };
40710
40853
  var WORKFLOWS = {
40711
40854
  [actualizacionArancel.clave]: actualizacionArancel,
40712
40855
  [tareaOperativa.clave]: tareaOperativa,
40713
- [recuperoTurno.clave]: recuperoTurno
40856
+ [recuperoTurno.clave]: recuperoTurno,
40857
+ [cuentaCompleta.clave]: cuentaCompleta
40714
40858
  };
40715
40859
  function getWorkflow(clave) {
40716
40860
  return WORKFLOWS[clave] ?? null;
@@ -41030,6 +41174,11 @@ async function abrirCaso(ctx, input2) {
41030
41174
  if (prev[0]) return { caso: mapCaso(prev[0]), creado: false };
41031
41175
  }
41032
41176
  const referencia = str(input2.referencia);
41177
+ if (wf.clave === "cuenta_completa") {
41178
+ const bono = refExterna(input2.datos?.bono_id);
41179
+ if (!referencia || !/^bono:\S+$/.test(referencia)) throw new OpsError("referencia_requerida", "en cuenta_completa la referencia es obligatoria: bono:<n\xFAmero de bono>");
41180
+ if (bono && referencia !== `bono:${bono}`) throw new OpsError("referencia_requerida", `la referencia ${referencia} no coincide con el bono_id ${bono}`);
41181
+ }
41033
41182
  if (referencia) {
41034
41183
  const abiertos = await ctx.db.query(
41035
41184
  `SELECT ${CASO_COLS} FROM ${t(ctx, "caso")} WHERE company_id = $1 AND workflow = $2 AND referencia = $3 AND cerrado_at IS NULL ORDER BY created_at DESC LIMIT 1`,
@@ -41124,6 +41273,35 @@ async function transicionar(ctx, input2) {
41124
41273
  throw new OpsError("validacion", `accion_registrada: ${problema}`, { validaciones: [{ regla: "accion_registrada", ok: false, detalle: problema }], estado: caso.estado });
41125
41274
  }
41126
41275
  }
41276
+ const lecturaId = str(datos.lectura_id);
41277
+ if (lecturaId) {
41278
+ const rows = await ctx.db.query(
41279
+ `SELECT id, caso_id, tipo, resultado, created_at FROM ${t(ctx, "accion")} WHERE company_id = $1 AND id = $2 LIMIT 1`,
41280
+ [input2.companyId, lecturaId]
41281
+ );
41282
+ const lectura = rows[0];
41283
+ let vieja = false;
41284
+ if (lectura && resultado.via === "comprobar") {
41285
+ const ultima = await ctx.db.query(
41286
+ `SELECT max(created_at) AS ultima FROM ${t(ctx, "transicion")} WHERE company_id = $1 AND caso_id = $2`,
41287
+ [input2.companyId, caso.id]
41288
+ );
41289
+ const desde = ultima[0]?.ultima ? Date.parse(iso(ultima[0].ultima)) : NaN;
41290
+ vieja = Number.isFinite(desde) && Date.parse(iso(lectura.created_at)) <= desde;
41291
+ }
41292
+ const problema = !lectura ? `lectura_id ${lecturaId} no existe en esta instituci\xF3n` : String(lectura.caso_id) !== caso.id ? `la lectura ${lecturaId} pertenece a otro caso` : !["lectura", "verificacion"].includes(String(lectura.tipo)) ? `la acci\xF3n ${lecturaId} es de tipo ${String(lectura.tipo)}; hace falta una lectura o verificaci\xF3n` : String(lectura.resultado) !== "ok" ? `la lectura ${lecturaId} termin\xF3 con resultado ${String(lectura.resultado)}` : vieja ? `la lectura ${lecturaId} es anterior al \xFAltimo cambio del caso: volver a leer el bono y registrar esa lectura` : null;
41293
+ if (problema) {
41294
+ throw new OpsError("validacion", `lectura_registrada: ${problema}`, { validaciones: [{ regla: "lectura_registrada", ok: false, detalle: problema }], estado: caso.estado });
41295
+ }
41296
+ }
41297
+ if (caso.workflow === "cuenta_completa" && resultado.via === "observar") {
41298
+ datos.faltantes = leerFaltantes(datos.faltantes) ?? [];
41299
+ datos.faltantes_iniciales = datos.faltantes;
41300
+ }
41301
+ if (caso.workflow === "cuenta_completa" && resultado.via === "comprobar") {
41302
+ datos.faltantes = leerFaltantes(datos.faltantes_leidos) ?? [];
41303
+ delete datos.faltantes_leidos;
41304
+ }
41127
41305
  if (caso.workflow === "recupero_turno" && resultado.via === "no_acepta") {
41128
41306
  const previas = Array.isArray(caso.datos.declinaron) ? caso.datos.declinaron.map((v) => refExterna(v)).filter((v) => v !== null) : [];
41129
41307
  const esta = refExterna(caso.datos.solicitud_id);
@@ -41179,7 +41357,7 @@ async function transicionar(ctx, input2) {
41179
41357
  };
41180
41358
  }
41181
41359
  var TIPOS_ACCION = ["lectura", "escritura", "verificacion"];
41182
- var CONECTORES = ["api", "archivo", "pantalla", "manual"];
41360
+ var CONECTORES = ["api", "base", "archivo", "pantalla", "manual"];
41183
41361
  var RESULTADOS_ACCION = ["ok", "error", "pendiente"];
41184
41362
  async function registrarAccion(ctx, input2) {
41185
41363
  const caso = await leerCaso(ctx, input2.companyId, input2.casoId);
@@ -41189,6 +41367,9 @@ async function registrarAccion(ctx, input2) {
41189
41367
  if (!RESULTADOS_ACCION.includes(input2.resultado)) throw new OpsError("resultado_invalido", `resultado debe ser: ${RESULTADOS_ACCION.join(", ")}`);
41190
41368
  const objetivo = str(input2.objetivo);
41191
41369
  if (!objetivo) throw new OpsError("objetivo_requerido", "objetivo es obligatorio (qu\xE9 pantalla, endpoint o archivo se toc\xF3)");
41370
+ if (caso.workflow === "cuenta_completa" && input2.tipo === "escritura" && input2.actor.tipo === "agente") {
41371
+ throw new OpsError("politica", "en cuenta_completa el puesto solo lee: no registra escrituras sobre el sistema del hospital; lo que falta lo completa el equipo");
41372
+ }
41192
41373
  if (input2.tipo === "escritura" && input2.actor.tipo === "agente") {
41193
41374
  const modo = await obtenerModo(ctx, input2.companyId, caso.workflow);
41194
41375
  if (!modoHabilita(modo, "ejecuta")) throw new OpsError("politica", `la pol\xEDtica vigente de ${caso.workflow} es "${modo}": un agente no puede registrar escrituras sobre el sistema del hospital`);
@@ -41275,6 +41456,7 @@ async function registrarCargaManual(ctx, input2) {
41275
41456
  ...valorCargado !== null ? { valor_cargado: valorCargado } : {},
41276
41457
  ...caso.datos.valor_nuevo !== void 0 ? { valor_aprobado: caso.datos.valor_nuevo } : {},
41277
41458
  ...caso.datos.vigencia_desde !== void 0 ? { vigencia_desde: caso.datos.vigencia_desde } : {},
41459
+ ...caso.workflow === "cuenta_completa" ? { faltantes_que_completo: caso.datos.faltantes ?? [] } : {},
41278
41460
  ...comentario ? { nota: comentario } : {}
41279
41461
  },
41280
41462
  detalle: comentario,
@@ -41932,8 +42114,13 @@ async function manejarApi(ctx, input2) {
41932
42114
  return respuesta(200, await registrarCargaManual(ctx, { companyId, casoId: input2.params.casoId ?? "", valorCargado: body.valorCargado, comentario: str2(body.comentario), persona: decididoPor, idempotencyKey: str2(body.idempotencyKey), actor }));
41933
42115
  case "respuesta-paciente":
41934
42116
  return respuesta(200, await registrarRespuestaPaciente(ctx, { companyId, casoId: input2.params.casoId ?? "", acepto: body.acepto === true, comentario: str2(body.comentario), persona: decididoPor, idempotencyKey: str2(body.idempotencyKey), actor }));
42117
+ case "no-corresponde": {
42118
+ if (actor.tipo !== "humano") return respuesta(403, { error: "actor_no_permitido", motivo: "no_corresponde lo decide una persona del hospital" });
42119
+ if (!str2(body.motivo)) return respuesta(422, { error: "validacion", motivo: "motivo_presente: no_corresponde requiere motivo" });
42120
+ return respuesta(200, await transicionar(ctx, { companyId, casoId: input2.params.casoId ?? "", via: "no_corresponde", motivo: motivoConPersona(str2(body.motivo)), datos: conPersona(obj(body.datos)), idempotencyKey: str2(body.idempotencyKey), actor }));
42121
+ }
41935
42122
  case "version":
41936
- return respuesta(200, { version: manifest_default.version, capacidades: ["carga-manual", "recupero-turnos", "ofrecer-primero"], workflows: listarWorkflows().map((w) => w.clave) });
42123
+ return respuesta(200, { version: manifest_default.version, capacidades: ["carga-manual", "recupero-turnos", "ofrecer-primero", "cuenta-completa"], workflows: listarWorkflows().map((w) => w.clave) });
41937
42124
  case "politicas":
41938
42125
  return respuesta(200, { politicas: await listarPoliticas(ctx, companyId) });
41939
42126
  case "serie":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paperclip-plugin-autopilot-ops",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
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": [