paperclip-plugin-autopilot-ops 0.1.26 → 0.1.28

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/worker.js CHANGED
@@ -3627,15 +3627,15 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def2) =
3627
3627
  const syms = normalized.symbolKeys;
3628
3628
  const doc = new Doc(["payload", "ctx"], { shape, inst, memo: memo2, syms });
3629
3629
  const parseStr = (k) => `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
3630
- const prefixStr = (id, k) => `
3631
- let ${id}_ab = false;
3632
- for (let i = 0; i < ${id}.issues.length; i++) {
3633
- const iss = ${id}.issues[i];
3630
+ const prefixStr = (id2, k) => `
3631
+ let ${id2}_ab = false;
3632
+ for (let i = 0; i < ${id2}.issues.length; i++) {
3633
+ const iss = ${id2}.issues[i];
3634
3634
  iss.path = iss.path ? [${k}, ...iss.path] : [${k}];
3635
3635
  payload.issues.push(iss);
3636
- if (iss.continue !== true) ${id}_ab = true;
3636
+ if (iss.continue !== true) ${id2}_ab = true;
3637
3637
  }
3638
- if (${id}_ab && ctx && ctx.abortEarly) {
3638
+ if (${id2}_ab && ctx && ctx.abortEarly) {
3639
3639
  payload.value = newResult;
3640
3640
  return payload;
3641
3641
  }`;
@@ -3649,34 +3649,34 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def2) =
3649
3649
  for (const key of normalized.allKeys) {
3650
3650
  if (key === "__proto__")
3651
3651
  continue;
3652
- const id = ids[key];
3652
+ const id2 = ids[key];
3653
3653
  const k = typeof key === "symbol" ? `syms[${syms.indexOf(key)}]` : esc(key);
3654
3654
  const isPresent = `${k} in input`;
3655
3655
  const schema = shape[key];
3656
3656
  const optin = schema?._zod?.optin;
3657
3657
  const isOptionalIn = optin !== void 0;
3658
3658
  const isOptionalOut = schema?._zod?.optout === "optional";
3659
- doc.write(`const ${id} = ${parseStr(k)};`);
3659
+ doc.write(`const ${id2} = ${parseStr(k)};`);
3660
3660
  if (isOptionalIn && isOptionalOut) {
3661
- const assign = optin === "optional" ? `${id}_present` : `${id}.value !== undefined || ${id}_present`;
3661
+ const assign = optin === "optional" ? `${id2}_present` : `${id2}.value !== undefined || ${id2}_present`;
3662
3662
  doc.write(`
3663
- const ${id}_present = ${isPresent};
3664
- if (!${id}.issues.length || ${id}_present) {
3665
- if (${id}.issues.length) {${prefixStr(id, k)}
3663
+ const ${id2}_present = ${isPresent};
3664
+ if (!${id2}.issues.length || ${id2}_present) {
3665
+ if (${id2}.issues.length) {${prefixStr(id2, k)}
3666
3666
  }
3667
3667
 
3668
3668
  if (${assign}) {
3669
- newResult[${k}] = ${id}.value;
3669
+ newResult[${k}] = ${id2}.value;
3670
3670
  }
3671
3671
  }
3672
3672
 
3673
3673
  `);
3674
3674
  } else if (!isOptionalIn) {
3675
3675
  doc.write(`
3676
- const ${id}_present = ${isPresent};
3677
- if (${id}.issues.length) {${prefixStr(id, k)}
3676
+ const ${id2}_present = ${isPresent};
3677
+ if (${id2}.issues.length) {${prefixStr(id2, k)}
3678
3678
  }
3679
- if (!${id}_present && !${id}.issues.length) {
3679
+ if (!${id2}_present && !${id2}.issues.length) {
3680
3680
  payload.issues.push({
3681
3681
  code: "invalid_type",
3682
3682
  expected: "nonoptional",
@@ -3689,22 +3689,22 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def2) =
3689
3689
  }
3690
3690
  }
3691
3691
 
3692
- if (${id}_present) {
3693
- newResult[${k}] = ${id}.value;
3692
+ if (${id2}_present) {
3693
+ newResult[${k}] = ${id2}.value;
3694
3694
  }
3695
3695
 
3696
3696
  `);
3697
3697
  } else {
3698
3698
  doc.write(`
3699
- if (${id}.issues.length) {${prefixStr(id, k)}
3699
+ if (${id2}.issues.length) {${prefixStr(id2, k)}
3700
3700
  }
3701
3701
  `);
3702
3702
  if (optin === "defaulted") {
3703
- doc.write(`newResult[${k}] = ${id}.value;`);
3703
+ doc.write(`newResult[${k}] = ${id2}.value;`);
3704
3704
  } else {
3705
3705
  doc.write(`
3706
- if (${id}.value !== undefined || ${isPresent}) {
3707
- newResult[${k}] = ${id}.value;
3706
+ if (${id2}.value !== undefined || ${isPresent}) {
3707
+ newResult[${k}] = ${id2}.value;
3708
3708
  }
3709
3709
  `);
3710
3710
  }
@@ -15732,26 +15732,26 @@ function extractDefs(ctx, schema) {
15732
15732
  return;
15733
15733
  const idToSchema = /* @__PURE__ */ new Map();
15734
15734
  for (const entry of ctx.seen.entries()) {
15735
- const id = ctx.metadataRegistry.get(entry[0])?.id;
15736
- if (id) {
15737
- const existing = idToSchema.get(id);
15735
+ const id2 = ctx.metadataRegistry.get(entry[0])?.id;
15736
+ if (id2) {
15737
+ const existing = idToSchema.get(id2);
15738
15738
  if (existing && existing !== entry[0]) {
15739
- throw new Error(`Duplicate schema id "${id}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);
15739
+ throw new Error(`Duplicate schema id "${id2}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);
15740
15740
  }
15741
- idToSchema.set(id, entry[0]);
15741
+ idToSchema.set(id2, entry[0]);
15742
15742
  }
15743
15743
  }
15744
15744
  const makeURI = (entry) => {
15745
15745
  const defsSegment = ctx.target === "draft-2020-12" ? "$defs" : "definitions";
15746
15746
  if (ctx.external) {
15747
15747
  const externalId = ctx.external.registry.get(entry[0])?.id;
15748
- const uriGenerator = ctx.external.uri ?? ((id2) => id2);
15748
+ const uriGenerator = ctx.external.uri ?? ((id3) => id3);
15749
15749
  if (externalId) {
15750
15750
  return { ref: uriGenerator(externalId) };
15751
15751
  }
15752
- const id = entry[1].defId ?? entry[1].schema.id ?? `schema${ctx.counter++}`;
15753
- entry[1].defId = id;
15754
- return { defId: id, ref: `${uriGenerator("__shared")}#/${defsSegment}/${encodeJSONPointerSegment(id)}` };
15752
+ const id2 = entry[1].defId ?? entry[1].schema.id ?? `schema${ctx.counter++}`;
15753
+ entry[1].defId = id2;
15754
+ return { defId: id2, ref: `${uriGenerator("__shared")}#/${defsSegment}/${encodeJSONPointerSegment(id2)}` };
15755
15755
  }
15756
15756
  const uriPrefix = `#`;
15757
15757
  const defUriPrefix = `${uriPrefix}/${defsSegment}/`;
@@ -15799,8 +15799,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15799
15799
  continue;
15800
15800
  }
15801
15801
  }
15802
- const id = ctx.metadataRegistry.get(entry[0])?.id;
15803
- if (id) {
15802
+ const id2 = ctx.metadataRegistry.get(entry[0])?.id;
15803
+ if (id2) {
15804
15804
  extractToDef(entry);
15805
15805
  continue;
15806
15806
  }
@@ -16033,10 +16033,10 @@ function finalize(ctx, schema) {
16033
16033
  } else {
16034
16034
  }
16035
16035
  if (ctx.external?.uri) {
16036
- const id = ctx.external.registry.get(schema)?.id;
16037
- if (!id)
16036
+ const id2 = ctx.external.registry.get(schema)?.id;
16037
+ if (!id2)
16038
16038
  throw new Error("Schema is missing an `id` property");
16039
- result.$id = ctx.external.uri(id);
16039
+ result.$id = ctx.external.uri(id2);
16040
16040
  }
16041
16041
  assignProps(result, root.defId ? root.schema : root.def ?? root.schema);
16042
16042
  const rootMetaId = ctx.metadataRegistry.get(schema)?.id;
@@ -16642,7 +16642,7 @@ function stringifyKeyNames(bySchema, json2, visited) {
16642
16642
  const values = json2.enum ?? (json2.const !== void 0 ? [json2.const] : void 0);
16643
16643
  if (!numericType && !values?.some((v) => typeof v === "number"))
16644
16644
  return json2;
16645
- const { minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, format, id, ...rest } = json2;
16645
+ const { minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, format, id: id2, ...rest } = json2;
16646
16646
  if (rest.enum)
16647
16647
  rest.enum = rest.enum.map((v) => typeof v === "number" ? String(v) : v);
16648
16648
  else if (typeof rest.const === "number")
@@ -29760,7 +29760,7 @@ var createAskUserQuestionsPayloadSchema = askUserQuestionsPayloadSchema.superRef
29760
29760
  return;
29761
29761
  const shown = new Set(value.questionSet.questions.map((question) => question.id));
29762
29762
  const stored = new Set(value.questions.map((question) => question.id));
29763
- if (shown.size !== stored.size || [...shown].some((id) => !stored.has(id))) {
29763
+ if (shown.size !== stored.size || [...shown].some((id2) => !stored.has(id2))) {
29764
29764
  ctx.addIssue({
29765
29765
  code: external_exports.ZodIssueCode.custom,
29766
29766
  path: ["questionSet", "questions"],
@@ -31268,7 +31268,7 @@ var pluginManifestV1Schema = external_exports.object({
31268
31268
  if (manifest2.ui) {
31269
31269
  if (manifest2.ui.slots) {
31270
31270
  const slotIds = manifest2.ui.slots.map((s) => s.id);
31271
- const duplicates = slotIds.filter((id, i) => slotIds.indexOf(id) !== i);
31271
+ const duplicates = slotIds.filter((id2, i) => slotIds.indexOf(id2) !== i);
31272
31272
  if (duplicates.length > 0) {
31273
31273
  ctx.addIssue({
31274
31274
  code: external_exports.ZodIssueCode.custom,
@@ -31284,7 +31284,7 @@ var pluginManifestV1Schema = external_exports.object({
31284
31284
  ];
31285
31285
  if (allLaunchers.length > 0) {
31286
31286
  const launcherIds = allLaunchers.map((launcher) => launcher.id);
31287
- const duplicates = launcherIds.filter((id, i) => launcherIds.indexOf(id) !== i);
31287
+ const duplicates = launcherIds.filter((id2, i) => launcherIds.indexOf(id2) !== i);
31288
31288
  if (duplicates.length > 0) {
31289
31289
  ctx.addIssue({
31290
31290
  code: external_exports.ZodIssueCode.custom,
@@ -38221,28 +38221,28 @@ var DUPLEX_CHANNEL_DATA_NOTIFICATION = "duplexChannel.data";
38221
38221
  var DUPLEX_CHANNEL_EXIT_NOTIFICATION = "duplexChannel.exit";
38222
38222
  var _nextId = 1;
38223
38223
  var MAX_SAFE_RPC_ID = Number.MAX_SAFE_INTEGER - 1;
38224
- function createRequest(method, params, id) {
38224
+ function createRequest(method, params, id2) {
38225
38225
  if (_nextId >= MAX_SAFE_RPC_ID) {
38226
38226
  _nextId = 1;
38227
38227
  }
38228
38228
  return {
38229
38229
  jsonrpc: JSONRPC_VERSION,
38230
- id: id ?? _nextId++,
38230
+ id: id2 ?? _nextId++,
38231
38231
  method,
38232
38232
  params
38233
38233
  };
38234
38234
  }
38235
- function createSuccessResponse(id, result) {
38235
+ function createSuccessResponse(id2, result) {
38236
38236
  return {
38237
38237
  jsonrpc: JSONRPC_VERSION,
38238
- id,
38238
+ id: id2,
38239
38239
  result
38240
38240
  };
38241
38241
  }
38242
- function createErrorResponse(id, code, message2, data) {
38242
+ function createErrorResponse(id2, code, message2, data) {
38243
38243
  const response = {
38244
38244
  jsonrpc: JSONRPC_VERSION,
38245
- id,
38245
+ id: id2,
38246
38246
  error: data !== void 0 ? { code, message: message2, data } : { code, message: message2 }
38247
38247
  };
38248
38248
  return response;
@@ -38401,7 +38401,7 @@ function startWorkerRpcHost(options) {
38401
38401
  if (nextOutboundId >= MAX_OUTBOUND_ID) {
38402
38402
  nextOutboundId = 1;
38403
38403
  }
38404
- const id = nextOutboundId++;
38404
+ const id2 = nextOutboundId++;
38405
38405
  const timeout = timeoutMs ?? rpcTimeoutMs;
38406
38406
  let settled = false;
38407
38407
  const settle2 = (fn, value) => {
@@ -38409,7 +38409,7 @@ function startWorkerRpcHost(options) {
38409
38409
  return;
38410
38410
  settled = true;
38411
38411
  clearTimeout(timer);
38412
- pendingRequests.delete(id);
38412
+ pendingRequests.delete(id2);
38413
38413
  fn(value);
38414
38414
  };
38415
38415
  const timer = setTimeout(() => {
@@ -38418,7 +38418,7 @@ function startWorkerRpcHost(options) {
38418
38418
  message: `Worker\u2192host call "${method}" timed out after ${timeout}ms`
38419
38419
  }));
38420
38420
  }, timeout);
38421
- pendingRequests.set(id, {
38421
+ pendingRequests.set(id2, {
38422
38422
  resolve: (response) => {
38423
38423
  if (isJsonRpcSuccessResponse(response)) {
38424
38424
  settle2(resolve, response.result);
@@ -38433,7 +38433,7 @@ function startWorkerRpcHost(options) {
38433
38433
  try {
38434
38434
  const activeInvocation = invocationContextStorage.getStore();
38435
38435
  const request = {
38436
- ...createRequest(method, params, id),
38436
+ ...createRequest(method, params, id2),
38437
38437
  ...activeInvocation ? { paperclipInvocationId: activeInvocation.id } : {}
38438
38438
  };
38439
38439
  sendMessage(request);
@@ -39329,15 +39329,15 @@ function startWorkerRpcHost(options) {
39329
39329
  }
39330
39330
  const ctx = buildContext();
39331
39331
  async function handleHostRequest(request) {
39332
- const { id, method, params } = request;
39332
+ const { id: id2, method, params } = request;
39333
39333
  try {
39334
39334
  const invoke = () => dispatchMethod(method, params);
39335
39335
  const result = request.paperclipInvocation ? await invocationContextStorage.run(request.paperclipInvocation, invoke) : await invoke();
39336
- sendMessage(createSuccessResponse(id, result ?? null));
39336
+ sendMessage(createSuccessResponse(id2, result ?? null));
39337
39337
  } catch (err) {
39338
39338
  const errorMessage = err instanceof Error ? err.message : String(err);
39339
39339
  const errorCode = typeof err?.code === "number" ? err.code : PLUGIN_RPC_ERROR_CODES.WORKER_ERROR;
39340
- sendMessage(createErrorResponse(id, errorCode, errorMessage, method === "environmentAcquireLease" || method === "environmentDestroyLease" ? environmentCreationCleanupErrorData(err) : void 0));
39340
+ sendMessage(createErrorResponse(id2, errorCode, errorMessage, method === "environmentAcquireLease" || method === "environmentDestroyLease" ? environmentCreationCleanupErrorData(err) : void 0));
39341
39341
  }
39342
39342
  }
39343
39343
  async function dispatchMethod(method, params) {
@@ -39819,14 +39819,14 @@ function startWorkerRpcHost(options) {
39819
39819
  return true;
39820
39820
  }
39821
39821
  function handleHostResponse(response) {
39822
- const id = response.id;
39823
- if (id === null || id === void 0)
39822
+ const id2 = response.id;
39823
+ if (id2 === null || id2 === void 0)
39824
39824
  return;
39825
- const pending = pendingRequests.get(id);
39825
+ const pending = pendingRequests.get(id2);
39826
39826
  if (!pending)
39827
39827
  return;
39828
39828
  clearTimeout(pending.timer);
39829
- pendingRequests.delete(id);
39829
+ pendingRequests.delete(id2);
39830
39830
  pending.resolve(response);
39831
39831
  }
39832
39832
  function handleLine(line) {
@@ -39881,9 +39881,9 @@ function startWorkerRpcHost(options) {
39881
39881
  readline.close();
39882
39882
  readline = null;
39883
39883
  }
39884
- for (const [id, pending] of pendingRequests) {
39884
+ for (const [id2, pending] of pendingRequests) {
39885
39885
  clearTimeout(pending.timer);
39886
- pending.resolve(createErrorResponse(id, PLUGIN_RPC_ERROR_CODES.WORKER_UNAVAILABLE, "Worker RPC host is shutting down"));
39886
+ pending.resolve(createErrorResponse(id2, PLUGIN_RPC_ERROR_CODES.WORKER_UNAVAILABLE, "Worker RPC host is shutting down"));
39887
39887
  }
39888
39888
  pendingRequests.clear();
39889
39889
  sessionEventCallbacks.clear();
@@ -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.26";
39935
+ var PLUGIN_VERSION = "0.1.28";
39936
39936
  var DB_NAMESPACE_SLUG = "autopilot_ops";
39937
39937
  var PAGE_ROUTE = "autopilot";
39938
39938
  var TOOL_NAMES = {
@@ -40045,7 +40045,7 @@ var manifest = {
40045
40045
  {
40046
40046
  name: TOOL_NAMES.abrirCaso,
40047
40047
  displayName: "Abrir caso",
40048
- description: 'Abre un caso nuevo en un workflow, en su estado inicial. Workflows: `internacion_al_dia` (una internaci\xF3n abierta; referencia obligatoria `internacion:<id>`; datos: internacion_id), `cobranza_financiador` (un caso abierto por financiador; referencia obligatoria `cobranza:<obra_social_id>`; datos: obra_social (nombre como en el HIS), obra_social_id, institucion (nombre de la instituci\xF3n para el reclamo)), `circular_aranceles` (una circular de aranceles entera; referencia obligatoria `circular:<obra social>:<hash corto del archivo>`; datos: obra_social, convenio (nombre en el HIS), archivo {nombre, hash, paginas}, vigencia_desde AAAA-MM-DD, porcentaje_declarado y filas_declaradas si la circular los dice), `demanda_pendiente` (referencia obligatoria `orden:<id>`, `solicitud:<id>` o `control:<persona_id>:<regla_id>`; datos: regla_id obligatorio y la regla tiene que estar activa, persona_id, tipo de origen, estudio o especialidad o prestacion, fecha_origen AAAA-MM-DD, dias; el plugin fija regla_version, canal, intentos, vence_el; nunca nombre, documento ni tel\xE9fono del paciente),`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, internacion_id opcional; en faltantes, `responsable` {tipo profesional, id, nombre} opcional para que el plugin avise a quien resuelve), `facturacion_pendiente` (una prestaci\xF3n sin facturar; misma referencia `bono:<n\xFAmero>` y mismos datos; el plugin calcula plazo_dias, vence_el y plazo_confirmado con los plazos por obra social de la instituci\xF3n), `credencial_profesional` (un profesional con agenda; referencia obligatoria `profesional:<id>`; datos: profesional_id, profesional (apellido y nombre, es personal de la instituci\xF3n), matricula_nacional, matricula_provincial, codigo_provincia, especialidades). `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.',
40048
+ description: 'Abre un caso nuevo en un workflow, en su estado inicial. Workflows: `internacion_al_dia` (una internaci\xF3n abierta; referencia obligatoria `internacion:<id>`; datos: internacion_id), `honorario_en_cero` (referencia `honorarios:<profesional_id>`; datos: profesional_id, profesional), `debito_profesional` (referencia `debito:<profesional_id>:<nota_credito_id>`; datos: profesional_id, profesional, nota_credito_id, obra_social), `liquidacion_profesional` (referencia `liquidacion:<profesional_id>:<AAAA-MM-DD>`; datos: profesional_id, profesional, liquidado_el, institucion, mail_his), `cobranza_financiador` (un caso abierto por financiador; referencia obligatoria `cobranza:<obra_social_id>`; datos: obra_social (nombre como en el HIS), obra_social_id, institucion (nombre de la instituci\xF3n para el reclamo)), `circular_aranceles` (una circular de aranceles entera; referencia obligatoria `circular:<obra social>:<hash corto del archivo>`; datos: obra_social, convenio (nombre en el HIS), archivo {nombre, hash, paginas}, vigencia_desde AAAA-MM-DD, porcentaje_declarado y filas_declaradas si la circular los dice), `demanda_pendiente` (referencia obligatoria `orden:<id>`, `solicitud:<id>` o `control:<persona_id>:<regla_id>`; datos: regla_id obligatorio y la regla tiene que estar activa, persona_id, tipo de origen, estudio o especialidad o prestacion, fecha_origen AAAA-MM-DD, dias; el plugin fija regla_version, canal, intentos, vence_el; nunca nombre, documento ni tel\xE9fono del paciente),`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, internacion_id opcional; en faltantes, `responsable` {tipo profesional, id, nombre} opcional para que el plugin avise a quien resuelve), `facturacion_pendiente` (una prestaci\xF3n sin facturar; misma referencia `bono:<n\xFAmero>` y mismos datos; el plugin calcula plazo_dias, vence_el y plazo_confirmado con los plazos por obra social de la instituci\xF3n), `credencial_profesional` (un profesional con agenda; referencia obligatoria `profesional:<id>`; datos: profesional_id, profesional (apellido y nombre, es personal de la instituci\xF3n), matricula_nacional, matricula_provincial, codigo_provincia, especialidades). `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.',
40049
40049
  parametersSchema: {
40050
40050
  type: "object",
40051
40051
  properties: {
@@ -40062,7 +40062,7 @@ var manifest = {
40062
40062
  {
40063
40063
  name: TOOL_NAMES.transicionar,
40064
40064
  displayName: "Transicionar caso",
40065
- 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 de la instituci\xF3n 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. En `facturacion_pendiente` (solo lee): `observar` con bono_id, bono_estado, fecha_prestacion, obra_social, lectura_id (conector "base") y fuente; `comprobar` con bono_estado_leido y lectura_id (facturado/refacturado \u2192 facturada; prefacturado \u2192 en prefactura; si no, sigue por presentar); `descartar` con motivo. En `cobranza_financiador`, `circular_aranceles` e `internacion_al_dia` los datos de cada v\xEDa est\xE1n en la skill del puesto (cobranzas, aranceles, internaciones): el agente informa lo que ley\xF3 del HIS o del documento tal cual y el plugin decide qu\xE9 se reclama o se carga. En `demanda_pendiente`: `contactar` (nivel ejecuta; datos: canal igual al de la regla y accion_id de la escritura registrada; el plugin controla regla activa, intentos, espera entre intentos y horario), `responder` (respuesta: acepta|rechaza|no_contesta), `comprobar` (lectura_id de la relectura del HIS, turno_id y turno_estado del turno encontrado), `cerrar` (motivo; solo con los intentos agotados o el plazo vencido), `descartar` (motivo). `credencial_profesional` (solo lee): `verificar` con profesional_id, matricula y tipo_matricula (nacional|provincial) si hay matr\xEDcula, resultado = el objeto que devuelve verificar-matriculas.mjs tal cual ({sin_matricula, encontrada, coincide_nombre, situacion, sancion, profesion, provincia, emisor}), lectura_id (conector "api", la consulta al registro) y fuente; el plugin decide vigente u observada y fija la observaci\xF3n (sin_matricula, no_figura, otra_persona, inhabilitada, sancion); `descartar` con motivo si el profesional ya no est\xE1 activo.',
40065
+ 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 de la instituci\xF3n 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. En `facturacion_pendiente` (solo lee): `observar` con bono_id, bono_estado, fecha_prestacion, obra_social, lectura_id (conector "base") y fuente; `comprobar` con bono_estado_leido y lectura_id (facturado/refacturado \u2192 facturada; prefacturado \u2192 en prefactura; si no, sigue por presentar); `descartar` con motivo. En `cobranza_financiador`, `circular_aranceles`, `internacion_al_dia` y los de honorarios los datos de cada v\xEDa est\xE1n en la skill del puesto (cobranzas, aranceles, internaciones, honorarios): el agente informa lo que ley\xF3 del HIS o del documento tal cual y el plugin decide qu\xE9 se reclama o se carga. En `demanda_pendiente`: `contactar` (nivel ejecuta; datos: canal igual al de la regla y accion_id de la escritura registrada; el plugin controla regla activa, intentos, espera entre intentos y horario), `responder` (respuesta: acepta|rechaza|no_contesta), `comprobar` (lectura_id de la relectura del HIS, turno_id y turno_estado del turno encontrado), `cerrar` (motivo; solo con los intentos agotados o el plazo vencido), `descartar` (motivo). `credencial_profesional` (solo lee): `verificar` con profesional_id, matricula y tipo_matricula (nacional|provincial) si hay matr\xEDcula, resultado = el objeto que devuelve verificar-matriculas.mjs tal cual ({sin_matricula, encontrada, coincide_nombre, situacion, sancion, profesion, provincia, emisor}), lectura_id (conector "api", la consulta al registro) y fuente; el plugin decide vigente u observada y fija la observaci\xF3n (sin_matricula, no_figura, otra_persona, inhabilitada, sancion); `descartar` con motivo si el profesional ya no est\xE1 activo.',
40066
40066
  parametersSchema: {
40067
40067
  type: "object",
40068
40068
  properties: {
@@ -40302,6 +40302,14 @@ var manifest = {
40302
40302
  capability: "api.routes.register",
40303
40303
  companyResolution: { from: "body", key: "companyId" }
40304
40304
  },
40305
+ {
40306
+ routeKey: "envio-liquidacion",
40307
+ method: "POST",
40308
+ path: "/casos/:casoId/envio-liquidacion",
40309
+ auth: "board",
40310
+ capability: "api.routes.register",
40311
+ companyResolution: { from: "body", key: "companyId" }
40312
+ },
40305
40313
  {
40306
40314
  routeKey: "respuesta-financiador",
40307
40315
  method: "POST",
@@ -40482,8 +40490,8 @@ function mediana(v) {
40482
40490
  const m = Math.floor(s.length / 2);
40483
40491
  return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;
40484
40492
  }
40485
- function sumarDias(fecha3, dias) {
40486
- const d = /* @__PURE__ */ new Date(`${fecha3}T00:00:00Z`);
40493
+ function sumarDias(fecha4, dias) {
40494
+ const d = /* @__PURE__ */ new Date(`${fecha4}T00:00:00Z`);
40487
40495
  d.setUTCDate(d.getUTCDate() + dias);
40488
40496
  return d.toISOString().slice(0, 10);
40489
40497
  }
@@ -40675,8 +40683,8 @@ var REGLAS_INTERNACION = {
40675
40683
  }
40676
40684
  };
40677
40685
  var fecha = (iso5) => `${iso5.slice(8, 10)}/${iso5.slice(5, 7)}`;
40678
- function sumarDias2(dia3, n) {
40679
- const d = /* @__PURE__ */ new Date(`${dia3}T12:00:00Z`);
40686
+ function sumarDias2(dia4, n) {
40687
+ const d = /* @__PURE__ */ new Date(`${dia4}T12:00:00Z`);
40680
40688
  d.setUTCDate(d.getUTCDate() + n);
40681
40689
  return d.toISOString().slice(0, 10);
40682
40690
  }
@@ -40698,8 +40706,8 @@ function verdad(v) {
40698
40706
  function leerLecturaInternacion(v) {
40699
40707
  if (!v || typeof v !== "object" || Array.isArray(v)) return { error: "lectura tiene que ser un objeto con la internaci\xF3n tal como la devuelve revisar-internaciones.mjs" };
40700
40708
  const r = v;
40701
- const id = texto(r.internacion_id);
40702
- if (!id || !/^\d{1,12}$/.test(id)) return { error: "lectura.internacion_id: el id num\xE9rico de la internaci\xF3n en el HIS" };
40709
+ const id2 = texto(r.internacion_id);
40710
+ if (!id2 || !/^\d{1,12}$/.test(id2)) return { error: "lectura.internacion_id: el id num\xE9rico de la internaci\xF3n en el HIS" };
40703
40711
  const ingreso = fechaHora(r.ingreso);
40704
40712
  if (!ingreso) return { error: "lectura.ingreso: fecha y hora del ingreso (AAAA-MM-DD HH:MM)" };
40705
40713
  const egreso = r.egreso == null || r.egreso === "" ? null : fechaHora(r.egreso);
@@ -40724,7 +40732,7 @@ function leerLecturaInternacion(v) {
40724
40732
  }
40725
40733
  return {
40726
40734
  lectura: {
40727
- internacion_id: id,
40735
+ internacion_id: id2,
40728
40736
  ingreso,
40729
40737
  egreso,
40730
40738
  evoluciones: [...new Set(evoluciones)].sort(),
@@ -40780,6 +40788,207 @@ function estadoInternacion(e) {
40780
40788
  return e.egresada ? "egresada" : e.pendientes.length ? "con_pendientes" : "al_dia";
40781
40789
  }
40782
40790
 
40791
+ // src/honorarios.ts
40792
+ var redondear2 = (n) => Math.round(n * 100) / 100;
40793
+ var pesos2 = (n) => `$ ${n.toLocaleString("es-AR", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
40794
+ var fecha2 = (iso5) => `${iso5.slice(8, 10)}/${iso5.slice(5, 7)}/${iso5.slice(0, 4)}`;
40795
+ function texto2(v) {
40796
+ return typeof v === "string" && v.trim() ? v.trim() : typeof v === "number" && Number.isFinite(v) ? String(v) : null;
40797
+ }
40798
+ function num(v) {
40799
+ if (typeof v === "number" && Number.isFinite(v)) return v;
40800
+ if (typeof v === "string" && v.trim() !== "" && Number.isFinite(Number(v))) return Number(v);
40801
+ return null;
40802
+ }
40803
+ function dia(v) {
40804
+ const s = texto2(v);
40805
+ return s && /^\d{4}-\d{2}-\d{2}/.test(s) ? s.slice(0, 10) : null;
40806
+ }
40807
+ function verdad2(v) {
40808
+ return v === true || v === 1 || v === "1" || v === "true";
40809
+ }
40810
+ function id(v) {
40811
+ const s = texto2(v);
40812
+ return s && /^\d{1,12}$/.test(s) ? s : null;
40813
+ }
40814
+ function leerProfesional(v) {
40815
+ if (!v || typeof v !== "object") return null;
40816
+ const r = v;
40817
+ const pid = id(r.id);
40818
+ return pid ? { id: pid, nombre: texto2(r.nombre)?.slice(0, 120) ?? null } : null;
40819
+ }
40820
+ function leerRegla(v) {
40821
+ if (!v || typeof v !== "object") return null;
40822
+ const r = v;
40823
+ const rid = id(r.id);
40824
+ if (!rid) return null;
40825
+ const prof = num(r.prof);
40826
+ const inst = num(r.inst);
40827
+ return { id: rid, prof: prof === null ? null : redondear2(prof), inst: inst === null ? null : redondear2(inst) };
40828
+ }
40829
+ function honorarioDe(input2) {
40830
+ const { regla, monto, cantidad } = input2;
40831
+ if (!regla) return 0;
40832
+ if (regla.prof !== null) return redondear2(regla.prof * cantidad);
40833
+ return redondear2(monto * cantidad * ((regla.inst ?? 0) / 100));
40834
+ }
40835
+ function motivoCero(regla, honorario) {
40836
+ if (honorario > 0) return null;
40837
+ return regla ? "regla_sin_valor" : "sin_regla";
40838
+ }
40839
+ function leerPrestaciones(v) {
40840
+ if (!Array.isArray(v)) return { error: "prestaciones tiene que ser la lista que devuelve leer-honorarios.mjs" };
40841
+ const out = [];
40842
+ for (const [i, e] of v.entries()) {
40843
+ if (!e || typeof e !== "object") return { error: `prestaciones[${i}] no es un objeto` };
40844
+ const r = e;
40845
+ const item = id(r.item_id);
40846
+ const bono = id(r.bono_id);
40847
+ const f = dia(r.fecha);
40848
+ const monto = num(r.monto);
40849
+ const cantidad = num(r.cantidad) ?? 1;
40850
+ if (!item || !bono || !f || monto === null) return { error: `prestaciones[${i}]: faltan item_id, bono_id, fecha o monto` };
40851
+ if (r.regla !== null && r.regla !== void 0 && !leerRegla(r.regla)) return { error: `prestaciones[${i}].regla: tiene que ser {id, prof, inst} o null` };
40852
+ out.push({ item_id: item, bono_id: bono, fecha: f, prestacion: texto2(r.prestacion)?.slice(0, 160) ?? "Prestaci\xF3n", obra_social: texto2(r.obra_social)?.slice(0, 120) ?? null, monto: redondear2(monto), cantidad: cantidad > 0 ? cantidad : 1, a_liquidar: verdad2(r.a_liquidar), liquidada: verdad2(r.liquidada), regla: leerRegla(r.regla) });
40853
+ }
40854
+ return { prestaciones: out };
40855
+ }
40856
+ function prestacionesEnCero(ps) {
40857
+ const items = [];
40858
+ for (const p of ps) {
40859
+ if (!p.a_liquidar || p.liquidada) continue;
40860
+ const motivo = motivoCero(p.regla, honorarioDe(p));
40861
+ if (motivo) items.push({ ...p, motivo });
40862
+ }
40863
+ items.sort((a, b) => a.fecha.localeCompare(b.fecha) || a.item_id.localeCompare(b.item_id));
40864
+ const fechas = items.map((p) => p.fecha).sort();
40865
+ return {
40866
+ items,
40867
+ resumen: {
40868
+ prestaciones: items.length,
40869
+ sin_regla: items.filter((p) => p.motivo === "sin_regla").length,
40870
+ regla_sin_valor: items.filter((p) => p.motivo === "regla_sin_valor").length,
40871
+ monto: redondear2(items.reduce((a, p) => a + p.monto * p.cantidad, 0)),
40872
+ obras_sociales: [...new Set(items.map((p) => p.obra_social).filter((x) => Boolean(x)))].sort(),
40873
+ desde: fechas[0] ?? null,
40874
+ hasta: fechas[fechas.length - 1] ?? null
40875
+ }
40876
+ };
40877
+ }
40878
+ function leerDebitos(v) {
40879
+ if (!Array.isArray(v)) return { error: "debitos tiene que ser la lista que devuelve leer-honorarios.mjs" };
40880
+ const out = [];
40881
+ for (const [i, e] of v.entries()) {
40882
+ if (!e || typeof e !== "object") return { error: `debitos[${i}] no es un objeto` };
40883
+ const r = e;
40884
+ const item = id(r.item_id);
40885
+ const bono = id(r.bono_id);
40886
+ const monto = num(r.monto_debitado);
40887
+ const nc = r.nota_credito && typeof r.nota_credito === "object" ? r.nota_credito : null;
40888
+ const ncId = nc ? id(nc.id) : null;
40889
+ if (!item || !bono || monto === null || !ncId) return { error: `debitos[${i}]: faltan item_id, bono_id, monto_debitado o nota_credito.id` };
40890
+ const montoItem = num(r.monto) ?? 0;
40891
+ const cantidad = num(r.cantidad) ?? 1;
40892
+ const regla = leerRegla(r.regla);
40893
+ const liquidada = verdad2(r.liquidada);
40894
+ const hon = liquidada ? honorarioDe({ regla, monto: montoItem, cantidad }) : null;
40895
+ const imp = liquidada ? redondear2(montoItem * cantidad) : null;
40896
+ out.push({
40897
+ item_id: item,
40898
+ bono_id: bono,
40899
+ prestacion: texto2(r.prestacion)?.slice(0, 160) ?? "Prestaci\xF3n",
40900
+ fecha_prestacion: dia(r.fecha_prestacion),
40901
+ obra_social: texto2(r.obra_social)?.slice(0, 120) ?? null,
40902
+ nota_credito: { id: ncId, numero: texto2(nc?.numero), fecha: dia(nc?.fecha), motivo: texto2(nc?.motivo)?.slice(0, 300) ?? null },
40903
+ monto_debitado: redondear2(Math.abs(monto)),
40904
+ liquidada,
40905
+ monto: redondear2(montoItem),
40906
+ cantidad: cantidad > 0 ? cantidad : 1,
40907
+ regla,
40908
+ liquidado: hon !== null && imp !== null ? { honorario: hon, importe: imp } : null,
40909
+ ya_trasladado: redondear2(Math.abs(num(r.ya_trasladado) ?? 0))
40910
+ });
40911
+ }
40912
+ return { debitos: out };
40913
+ }
40914
+ function evaluarDebito(d) {
40915
+ if (!d.liquidado) return { ...d, estado: "sin_liquidar", a_descontar: 0 };
40916
+ if (d.liquidado.importe <= 0 || d.liquidado.honorario <= 0 || d.monto_debitado <= 0) return { ...d, estado: "sin_monto", a_descontar: 0 };
40917
+ const proporcional = Math.min(d.liquidado.honorario, d.liquidado.honorario * d.monto_debitado / d.liquidado.importe);
40918
+ const falta = redondear2(proporcional - d.ya_trasladado);
40919
+ return falta >= 0.01 ? { ...d, estado: "a_trasladar", a_descontar: falta } : { ...d, estado: "ya_trasladado", a_descontar: 0 };
40920
+ }
40921
+ function resumenDebitos(ds) {
40922
+ const a = ds.filter((d) => d.estado === "a_trasladar");
40923
+ return { a_trasladar: a.length, total: redondear2(a.reduce((s, d) => s + d.a_descontar, 0)), sin_liquidar: ds.filter((d) => d.estado === "sin_liquidar").length, ya_trasladados: ds.filter((d) => d.estado === "ya_trasladado").length };
40924
+ }
40925
+ function leerLineasLiquidacion(v) {
40926
+ if (!Array.isArray(v) || v.length === 0) return { error: "lineas tiene que ser la lista (no vac\xEDa) de bonos de la liquidaci\xF3n, como la devuelve leer-honorarios.mjs" };
40927
+ const out = [];
40928
+ for (const [i, e] of v.entries()) {
40929
+ if (!e || typeof e !== "object") return { error: `lineas[${i}] no es un objeto` };
40930
+ const r = e;
40931
+ const bono = id(r.bono_id);
40932
+ if (!bono || !Array.isArray(r.items) || r.items.length === 0) return { error: `lineas[${i}]: faltan bono_id o items [{monto, cantidad, regla}]` };
40933
+ let importe = 0;
40934
+ let honorario = 0;
40935
+ let enCero = 0;
40936
+ for (const it of r.items) {
40937
+ const x = it && typeof it === "object" ? it : {};
40938
+ const monto = num(x.monto) ?? 0;
40939
+ const cantidad = num(x.cantidad) ?? 1;
40940
+ const regla = leerRegla(x.regla);
40941
+ const h = honorarioDe({ regla, monto, cantidad });
40942
+ importe += monto * cantidad;
40943
+ honorario += h;
40944
+ if (h <= 0) enCero += 1;
40945
+ }
40946
+ out.push({ bono_id: bono, fecha: dia(r.fecha), obra_social: texto2(r.obra_social)?.slice(0, 120) ?? null, importe: redondear2(importe), honorario: redondear2(honorario), en_cero: enCero });
40947
+ }
40948
+ return { lineas: out };
40949
+ }
40950
+ function resumirLiquidacion(lineas) {
40951
+ const por = /* @__PURE__ */ new Map();
40952
+ for (const l of lineas) {
40953
+ const k = l.obra_social ?? "Particular / sin obra social";
40954
+ const e = por.get(k) ?? { bonos: 0, honorario: 0 };
40955
+ e.bonos += 1;
40956
+ e.honorario = redondear2(e.honorario + l.honorario);
40957
+ por.set(k, e);
40958
+ }
40959
+ const fechas = lineas.map((l) => l.fecha).filter((x) => Boolean(x)).sort();
40960
+ return {
40961
+ bonos: lineas.length,
40962
+ honorario: redondear2(lineas.reduce((a, l) => a + l.honorario, 0)),
40963
+ importe: redondear2(lineas.reduce((a, l) => a + l.importe, 0)),
40964
+ en_cero: lineas.reduce((a, l) => a + l.en_cero, 0),
40965
+ por_obra_social: [...por.entries()].map(([obra_social, e]) => ({ obra_social, ...e })).sort((a, b) => b.honorario - a.honorario),
40966
+ desde: fechas[0] ?? null,
40967
+ hasta: fechas[fechas.length - 1] ?? null
40968
+ };
40969
+ }
40970
+ function redactarLiquidacion(input2) {
40971
+ const r = input2.resumen;
40972
+ const quien = input2.profesional.nombre ?? "Profesional";
40973
+ const periodo = r.desde && r.hasta ? ` (prestaciones del ${fecha2(r.desde)} al ${fecha2(r.hasta)})` : "";
40974
+ const asunto = `Liquidaci\xF3n de honorarios \xB7 ${input2.institucion} \xB7 ${fecha2(input2.fechaLiquidacion)} \xB7 ${pesos2(r.honorario)}`;
40975
+ const lineas = [
40976
+ `${quien}:`,
40977
+ "",
40978
+ `${input2.institucion} liquid\xF3 tus honorarios el ${fecha2(input2.fechaLiquidacion)}${periodo}.`,
40979
+ "",
40980
+ ...r.por_obra_social.map((o) => `- ${o.obra_social}: ${o.bonos} ${o.bonos === 1 ? "prestaci\xF3n" : "prestaciones"}, ${pesos2(o.honorario)}`),
40981
+ "",
40982
+ `Total: ${pesos2(r.honorario)} en ${r.bonos} ${r.bonos === 1 ? "prestaci\xF3n" : "prestaciones"}.`,
40983
+ ...input2.debitos ? ["", `Incluye d\xE9bitos de obras sociales por ${pesos2(input2.debitos)}.`] : [],
40984
+ "",
40985
+ "Si algo no coincide con lo que atendiste, respond\xE9 este correo y lo revisamos.",
40986
+ "",
40987
+ `${input2.institucion} \xB7 liquidaci\xF3n de honorarios`
40988
+ ];
40989
+ return { asunto, texto: lineas.join("\n") };
40990
+ }
40991
+
40783
40992
  // src/cobranzas.ts
40784
40993
  var PLAZO_PAGO_POR_DEFECTO = 60;
40785
40994
  var SALDO_MINIMO = 1;
@@ -40787,20 +40996,20 @@ var ATRASO_EXCEPCION = 365;
40787
40996
  var MAX_RECLAMOS_POR_DEFECTO = 2;
40788
40997
  var DIAS_ENTRE_RECLAMOS_POR_DEFECTO = 15;
40789
40998
  var GRACIA_COMPROMISO = 7;
40790
- var redondear2 = (n) => Math.round(n * 100) / 100;
40791
- var pesos2 = (n) => `$ ${n.toLocaleString("es-AR", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
40792
- var fecha2 = (iso5) => `${iso5.slice(8, 10)}/${iso5.slice(5, 7)}/${iso5.slice(0, 4)}`;
40999
+ var redondear3 = (n) => Math.round(n * 100) / 100;
41000
+ var pesos3 = (n) => `$ ${n.toLocaleString("es-AR", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
41001
+ var fecha3 = (iso5) => `${iso5.slice(8, 10)}/${iso5.slice(5, 7)}/${iso5.slice(0, 4)}`;
40793
41002
  var normalizar = (s) => s.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/\s+/g, " ").trim();
40794
- function num(v) {
41003
+ function num2(v) {
40795
41004
  if (typeof v === "number" && Number.isFinite(v)) return v;
40796
41005
  if (typeof v === "string" && v.trim() !== "" && Number.isFinite(Number(v))) return Number(v);
40797
41006
  return null;
40798
41007
  }
40799
- function texto2(v) {
41008
+ function texto3(v) {
40800
41009
  return typeof v === "string" && v.trim() ? v.trim() : typeof v === "number" ? String(v) : null;
40801
41010
  }
40802
- function dia(v) {
40803
- const s = texto2(v);
41011
+ function dia2(v) {
41012
+ const s = texto3(v);
40804
41013
  return s && /^\d{4}-\d{2}-\d{2}/.test(s) ? s.slice(0, 10) : null;
40805
41014
  }
40806
41015
  function sumarDias3(fechaIso, dias) {
@@ -40818,16 +41027,16 @@ function leerFacturas(v) {
40818
41027
  for (const [i, e] of v.entries()) {
40819
41028
  if (!e || typeof e !== "object") return { error: `facturas[${i}] no es una factura` };
40820
41029
  const r = e;
40821
- const id = texto2(r.factura_id);
40822
- const emision = dia(r.fecha_emision);
40823
- const monto = num(r.monto_pesos);
40824
- const saldo = num(r.saldo_pesos);
40825
- if (!id) return { error: `facturas[${i}]: falta factura_id` };
40826
- if (vistas.has(id)) return { error: `la factura ${id} est\xE1 repetida` };
40827
- vistas.add(id);
40828
- if (!emision) return { error: `factura ${id}: fecha_emision tiene que ser AAAA-MM-DD` };
40829
- if (monto === null || saldo === null) return { error: `factura ${id}: monto_pesos y saldo_pesos tienen que ser n\xFAmeros` };
40830
- out.push({ factura_id: id, numero_comprobante: texto2(r.numero_comprobante) ?? id, fecha_emision: emision, periodo_desde: dia(r.periodo_desde), periodo_hasta: dia(r.periodo_hasta), monto_pesos: redondear2(monto), saldo_pesos: redondear2(saldo), anulada: r.anulada === true || r.anulada === 1 || r.anulada === "1" });
41030
+ const id2 = texto3(r.factura_id);
41031
+ const emision = dia2(r.fecha_emision);
41032
+ const monto = num2(r.monto_pesos);
41033
+ const saldo = num2(r.saldo_pesos);
41034
+ if (!id2) return { error: `facturas[${i}]: falta factura_id` };
41035
+ if (vistas.has(id2)) return { error: `la factura ${id2} est\xE1 repetida` };
41036
+ vistas.add(id2);
41037
+ if (!emision) return { error: `factura ${id2}: fecha_emision tiene que ser AAAA-MM-DD` };
41038
+ if (monto === null || saldo === null) return { error: `factura ${id2}: monto_pesos y saldo_pesos tienen que ser n\xFAmeros` };
41039
+ out.push({ factura_id: id2, numero_comprobante: texto3(r.numero_comprobante) ?? id2, fecha_emision: emision, periodo_desde: dia2(r.periodo_desde), periodo_hasta: dia2(r.periodo_hasta), monto_pesos: redondear3(monto), saldo_pesos: redondear3(saldo), anulada: r.anulada === true || r.anulada === 1 || r.anulada === "1" });
40831
41040
  }
40832
41041
  return { facturas: out };
40833
41042
  }
@@ -40847,7 +41056,7 @@ function evaluarFacturas(input2) {
40847
41056
  factura_id: f.factura_id,
40848
41057
  numero_comprobante: f.numero_comprobante,
40849
41058
  fecha_emision: f.fecha_emision,
40850
- periodo: f.periodo_desde && f.periodo_hasta ? `${fecha2(f.periodo_desde)} al ${fecha2(f.periodo_hasta)}` : null,
41059
+ periodo: f.periodo_desde && f.periodo_hasta ? `${fecha3(f.periodo_desde)} al ${fecha3(f.periodo_hasta)}` : null,
40851
41060
  monto_pesos: f.monto_pesos,
40852
41061
  saldo_inicial: f.saldo_pesos,
40853
41062
  saldo_pesos: f.saldo_pesos,
@@ -40859,7 +41068,7 @@ function evaluarFacturas(input2) {
40859
41068
  };
40860
41069
  });
40861
41070
  const reclamadas = items.filter((i) => i.estado === "reclamada").sort((a, b) => b.dias_atraso - a.dias_atraso);
40862
- const total = redondear2(reclamadas.reduce((s, i) => s + i.saldo_pesos, 0));
41071
+ const total = redondear3(reclamadas.reduce((s, i) => s + i.saldo_pesos, 0));
40863
41072
  return {
40864
41073
  items: [...reclamadas, ...items.filter((i) => i.estado !== "reclamada")],
40865
41074
  resumen: {
@@ -40878,17 +41087,17 @@ function evaluarFacturas(input2) {
40878
41087
  }
40879
41088
  function redactarReclamo(input2) {
40880
41089
  const reclamadas = input2.items.filter((i) => i.estado === "reclamada" && i.cobro !== "cobrada");
40881
- const total = redondear2(reclamadas.reduce((s, i) => s + i.saldo_pesos, 0));
40882
- const asunto = `${input2.numero > 1 ? "Segundo reclamo" : "Reclamo"} de pago \xB7 ${input2.institucion} \xB7 ${reclamadas.length} ${reclamadas.length === 1 ? "factura" : "facturas"} \xB7 ${pesos2(total)}`;
40883
- const lineas = reclamadas.map((i) => `- Factura ${i.numero_comprobante} del ${fecha2(i.fecha_emision)}${i.periodo ? ` (per\xEDodo ${i.periodo})` : ""}: saldo ${pesos2(i.saldo_pesos)}, vencida hace ${i.dias_atraso} d\xEDas.`);
41090
+ const total = redondear3(reclamadas.reduce((s, i) => s + i.saldo_pesos, 0));
41091
+ const asunto = `${input2.numero > 1 ? "Segundo reclamo" : "Reclamo"} de pago \xB7 ${input2.institucion} \xB7 ${reclamadas.length} ${reclamadas.length === 1 ? "factura" : "facturas"} \xB7 ${pesos3(total)}`;
41092
+ const lineas = reclamadas.map((i) => `- Factura ${i.numero_comprobante} del ${fecha3(i.fecha_emision)}${i.periodo ? ` (per\xEDodo ${i.periodo})` : ""}: saldo ${pesos3(i.saldo_pesos)}, vencida hace ${i.dias_atraso} d\xEDas.`);
40884
41093
  const cuerpo = [
40885
41094
  `A ${input2.obraSocial}, \xE1rea de cuentas a pagar a prestadores:`,
40886
41095
  "",
40887
- `${input2.institucion} ${input2.numero > 1 ? "reitera el reclamo de" : "reclama"} el pago de las siguientes facturas, vencidas al ${fecha2(input2.hoy)}:`,
41096
+ `${input2.institucion} ${input2.numero > 1 ? "reitera el reclamo de" : "reclama"} el pago de las siguientes facturas, vencidas al ${fecha3(input2.hoy)}:`,
40888
41097
  "",
40889
41098
  ...lineas,
40890
41099
  "",
40891
- `Total adeudado: ${pesos2(total)}.`,
41100
+ `Total adeudado: ${pesos3(total)}.`,
40892
41101
  "",
40893
41102
  "Les pedimos que nos informen la fecha de pago o, si alguna factura tiene observaciones, el detalle para corregirla.",
40894
41103
  "",
@@ -40901,10 +41110,10 @@ function leerSaldos(v) {
40901
41110
  const saldos = /* @__PURE__ */ new Map();
40902
41111
  for (const [i, e] of v.entries()) {
40903
41112
  const r = e ?? {};
40904
- const id = texto2(r.factura_id);
40905
- const saldo = num(r.saldo_pesos);
40906
- if (!id || saldo === null) return { error: `leidos[${i}]: hace falta factura_id y saldo_pesos` };
40907
- saldos.set(id, { saldo: redondear2(saldo), notasCredito: redondear2(num(r.notas_credito_pesos) ?? 0), recibos: redondear2(num(r.recibos_aplicados_pesos) ?? 0) });
41113
+ const id2 = texto3(r.factura_id);
41114
+ const saldo = num2(r.saldo_pesos);
41115
+ if (!id2 || saldo === null) return { error: `leidos[${i}]: hace falta factura_id y saldo_pesos` };
41116
+ saldos.set(id2, { saldo: redondear3(saldo), notasCredito: redondear3(num2(r.notas_credito_pesos) ?? 0), recibos: redondear3(num2(r.recibos_aplicados_pesos) ?? 0) });
40908
41117
  }
40909
41118
  return { saldos };
40910
41119
  }
@@ -40920,14 +41129,14 @@ function compararSaldos(items, resumen, leidos, notasCreditoAntes = {}) {
40920
41129
  return i;
40921
41130
  }
40922
41131
  const saldo = Math.max(0, s.saldo);
40923
- const nc = Math.max(0, redondear2(s.notasCredito - (notasCreditoAntes[i.factura_id] ?? 0)));
41132
+ const nc = Math.max(0, redondear3(s.notasCredito - (notasCreditoAntes[i.factura_id] ?? 0)));
40924
41133
  const cobro = saldo <= SALDO_MINIMO ? "cobrada" : saldo < i.saldo_inicial - SALDO_MINIMO ? "parcial" : "pendiente";
40925
41134
  return { ...i, saldo_pesos: saldo, cobro, notas_credito_nuevas: nc };
40926
41135
  });
40927
41136
  const reclamadas = nuevos.filter((i) => i.estado === "reclamada");
40928
- const pendiente = redondear2(reclamadas.reduce((s, i) => s + (i.cobro === "cobrada" ? 0 : i.saldo_pesos), 0));
40929
- const debitos = redondear2(reclamadas.reduce((s, i) => s + i.notas_credito_nuevas, 0));
40930
- const cobrado = redondear2(Math.max(0, resumen.total_reclamado - pendiente - debitos));
41137
+ const pendiente = redondear3(reclamadas.reduce((s, i) => s + (i.cobro === "cobrada" ? 0 : i.saldo_pesos), 0));
41138
+ const debitos = redondear3(reclamadas.reduce((s, i) => s + i.notas_credito_nuevas, 0));
41139
+ const cobrado = redondear3(Math.max(0, resumen.total_reclamado - pendiente - debitos));
40931
41140
  return { items: nuevos, resumen: { ...resumen, cobrado, pendiente, posibles_debitos: debitos }, todoCobrado: reclamadas.length > 0 && reclamadas.every((i) => i.cobro === "cobrada") && faltan.length === 0, faltan };
40932
41141
  }
40933
41142
  var RESPUESTAS_FINANCIADOR = ["paga", "observa", "no_responde"];
@@ -40935,7 +41144,7 @@ var RESPUESTAS_FINANCIADOR = ["paga", "observa", "no_responde"];
40935
41144
  // src/workflows.ts
40936
41145
  var MODOS = ["corte", "observa", "propone", "ejecuta", "autonomo"];
40937
41146
  var MODO_POR_DEFECTO = "propone";
40938
- function num2(v) {
41147
+ function num3(v) {
40939
41148
  if (typeof v === "number" && Number.isFinite(v)) return v;
40940
41149
  if (typeof v === "string" && v.trim() !== "" && Number.isFinite(Number(v))) return Number(v);
40941
41150
  return null;
@@ -40943,7 +41152,7 @@ function num2(v) {
40943
41152
  function fechaISO(v) {
40944
41153
  return typeof v === "string" && /^\d{4}-\d{2}-\d{2}$/.test(v) && !Number.isNaN(Date.parse(v));
40945
41154
  }
40946
- function texto3(v) {
41155
+ function texto4(v) {
40947
41156
  return typeof v === "string" && v.trim().length > 0 ? v.trim() : null;
40948
41157
  }
40949
41158
  var ok = (regla, detalle) => ({ regla, ok: true, detalle });
@@ -40980,14 +41189,14 @@ var actualizacionArancel = {
40980
41189
  descripcion: "Proponer el nuevo valor con vigencia y fuente.",
40981
41190
  validar: (caso, datos) => {
40982
41191
  const out = [];
40983
- const nuevo = num2(datos.valor_nuevo);
40984
- const actual = num2(datos.valor_actual ?? caso.datos.valor_actual);
41192
+ const nuevo = num3(datos.valor_nuevo);
41193
+ const actual = num3(datos.valor_actual ?? caso.datos.valor_actual);
40985
41194
  out.push(nuevo !== null && nuevo > 0 ? ok("valor_nuevo_positivo") : falla("valor_nuevo_positivo", "valor_nuevo debe ser un n\xFAmero mayor a 0"));
40986
41195
  out.push(fechaISO(datos.vigencia_desde) ? ok("vigencia_valida") : falla("vigencia_valida", "vigencia_desde debe ser una fecha AAAA-MM-DD"));
40987
- out.push(texto3(datos.fuente) ? ok("fuente_presente") : falla("fuente_presente", "fuente (documento, circular o pantalla) es obligatoria"));
41196
+ out.push(texto4(datos.fuente) ? ok("fuente_presente") : falla("fuente_presente", "fuente (documento, circular o pantalla) es obligatoria"));
40988
41197
  if (nuevo !== null && actual !== null && actual > 0) {
40989
41198
  const variacion = Math.abs(nuevo - actual) / actual;
40990
- if (variacion > VARIACION_MAX_SIN_JUSTIFICACION && !texto3(datos.justificacion)) {
41199
+ if (variacion > VARIACION_MAX_SIN_JUSTIFICACION && !texto4(datos.justificacion)) {
40991
41200
  out.push(falla("variacion_razonable", `variaci\xF3n de ${(variacion * 100).toFixed(0)}% supera el ${VARIACION_MAX_SIN_JUSTIFICACION * 100}% y no trae justificaci\xF3n`));
40992
41201
  } else {
40993
41202
  out.push(ok("variacion_razonable", `${(variacion * 100).toFixed(1)}%`));
@@ -40998,8 +41207,8 @@ var actualizacionArancel = {
40998
41207
  autonomia: {
40999
41208
  aSinExcepcion: "aprobado",
41000
41209
  excepciones: (caso, datos) => {
41001
- const nuevo = num2(datos.valor_nuevo);
41002
- const actual = num2(datos.valor_actual ?? caso.datos.valor_actual);
41210
+ const nuevo = num3(datos.valor_nuevo);
41211
+ const actual = num3(datos.valor_actual ?? caso.datos.valor_actual);
41003
41212
  const variacion = nuevo !== null && actual !== null && actual > 0 ? Math.abs(nuevo - actual) / actual : null;
41004
41213
  return [
41005
41214
  excepcion("variacion_supera_umbral", variacion !== null && variacion > VARIACION_MAX_AUTONOMA, variacion === null ? "sin valor actual para comparar" : `${(variacion * 100).toFixed(1)}% (umbral ${VARIACION_MAX_AUTONOMA * 100}%)`),
@@ -41023,7 +41232,7 @@ var actualizacionArancel = {
41023
41232
  a: "rechazado",
41024
41233
  actor: ["humano"],
41025
41234
  descripcion: "Rechazo con motivo.",
41026
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "el rechazo requiere motivo")]
41235
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "el rechazo requiere motivo")]
41027
41236
  },
41028
41237
  {
41029
41238
  via: "aplicar",
@@ -41034,17 +41243,17 @@ var actualizacionArancel = {
41034
41243
  cargaManual: true,
41035
41244
  descripcion: "Cargar el valor aprobado en el sistema de gesti\xF3n y registrar la acci\xF3n.",
41036
41245
  validar: (_caso, datos) => [
41037
- texto3(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "aplicar requiere accion_id de la escritura registrada con ops_registrar_accion")
41246
+ texto4(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "aplicar requiere accion_id de la escritura registrada con ops_registrar_accion")
41038
41247
  ]
41039
41248
  },
41040
41249
  {
41041
41250
  via: "verificar",
41042
41251
  de: ["aplicado"],
41043
- a: (caso, datos) => num2(datos.valor_leido) === num2(caso.datos.valor_nuevo) ? "verificado" : "con_diferencias",
41252
+ a: (caso, datos) => num3(datos.valor_leido) === num3(caso.datos.valor_nuevo) ? "verificado" : "con_diferencias",
41044
41253
  actor: ["agente", "humano", "sistema"],
41045
41254
  nivelRequerido: "observa",
41046
41255
  descripcion: "Releer el valor en el sistema y compararlo con el aprobado. Si no coincide, el caso queda con diferencias.",
41047
- validar: (_caso, datos) => [num2(datos.valor_leido) !== null ? ok("valor_leido_presente") : falla("valor_leido_presente", "verificar requiere valor_leido num\xE9rico")]
41256
+ validar: (_caso, datos) => [num3(datos.valor_leido) !== null ? ok("valor_leido_presente") : falla("valor_leido_presente", "verificar requiere valor_leido num\xE9rico")]
41048
41257
  },
41049
41258
  {
41050
41259
  // Una carga manual que no coincidió se corrige en el sistema y se vuelve a comprobar:
@@ -41057,7 +41266,7 @@ var actualizacionArancel = {
41057
41266
  cargaManual: true,
41058
41267
  descripcion: "Corregir a mano la carga en el sistema de gesti\xF3n (el valor aprobado no cambia) y volver a comprobar.",
41059
41268
  validar: (_caso, datos) => [
41060
- texto3(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "corregir requiere accion_id de la escritura registrada con la carga corregida")
41269
+ texto4(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "corregir requiere accion_id de la escritura registrada con la carga corregida")
41061
41270
  ]
41062
41271
  },
41063
41272
  {
@@ -41066,7 +41275,7 @@ var actualizacionArancel = {
41066
41275
  a: "cancelado",
41067
41276
  actor: ["humano"],
41068
41277
  descripcion: "Cancelaci\xF3n manual.",
41069
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "la cancelaci\xF3n requiere motivo")]
41278
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "la cancelaci\xF3n requiere motivo")]
41070
41279
  }
41071
41280
  ]
41072
41281
  };
@@ -41089,10 +41298,10 @@ var tareaOperativa = {
41089
41298
  actor: ["agente", "humano"],
41090
41299
  nivelRequerido: "propone",
41091
41300
  descripcion: "Proponer el resultado para aprobaci\xF3n.",
41092
- validar: (_caso, datos) => [texto3(datos.resultado) ? ok("resultado_presente") : falla("resultado_presente", "proponer requiere un resultado descripto")],
41301
+ validar: (_caso, datos) => [texto4(datos.resultado) ? ok("resultado_presente") : falla("resultado_presente", "proponer requiere un resultado descripto")],
41093
41302
  autonomia: {
41094
41303
  aSinExcepcion: "cerrada",
41095
- excepciones: (_caso, datos) => [excepcion("resultado_con_observaciones", Boolean(texto3(datos.observaciones)), texto3(datos.observaciones) ? "el resultado trae observaciones para una persona" : "sin observaciones")]
41304
+ excepciones: (_caso, datos) => [excepcion("resultado_con_observaciones", Boolean(texto4(datos.observaciones)), texto4(datos.observaciones) ? "el resultado trae observaciones para una persona" : "sin observaciones")]
41096
41305
  }
41097
41306
  },
41098
41307
  { via: "aprobar", de: ["pendiente_aprobacion"], a: "cerrada", actor: ["humano"], descripcion: "Aprobaci\xF3n y cierre." },
@@ -41102,7 +41311,7 @@ var tareaOperativa = {
41102
41311
  a: "rechazada",
41103
41312
  actor: ["humano"],
41104
41313
  descripcion: "Rechazo con motivo.",
41105
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "el rechazo requiere motivo")]
41314
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "el rechazo requiere motivo")]
41106
41315
  },
41107
41316
  { via: "cancelar", de: ["abierta", "en_curso", "pendiente_aprobacion"], a: "cancelada", actor: ["humano"], descripcion: "Cancelaci\xF3n manual." }
41108
41317
  ]
@@ -41110,13 +41319,13 @@ var tareaOperativa = {
41110
41319
  var TOPE_DIARIO_RECUPERO = 20;
41111
41320
  var TITULOS = /* @__PURE__ */ new Set(["dr", "dra", "doctor", "doctora", "lic", "licenciado", "licenciada", "prof"]);
41112
41321
  function normalizarNombre(v) {
41113
- const s = texto3(v);
41322
+ const s = texto4(v);
41114
41323
  if (!s) return null;
41115
41324
  const palabras = s.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, " ").split(" ").filter((p) => p && !TITULOS.has(p));
41116
41325
  return palabras.length ? palabras.sort().join(" ") : null;
41117
41326
  }
41118
41327
  function horaHM(v) {
41119
- const s = texto3(v);
41328
+ const s = texto4(v);
41120
41329
  const m = s ? /^(\d{1,2}):(\d{2})(?::\d{2})?$/.exec(s) : null;
41121
41330
  if (!m) return null;
41122
41331
  const h = Number(m[1]);
@@ -41125,10 +41334,10 @@ function horaHM(v) {
41125
41334
  }
41126
41335
  function refExterna(v) {
41127
41336
  if (typeof v === "number" && Number.isFinite(v)) return String(v);
41128
- return texto3(v);
41337
+ return texto4(v);
41129
41338
  }
41130
41339
  function fechaAISO(v) {
41131
- const s = texto3(v);
41340
+ const s = texto4(v);
41132
41341
  if (!s) return null;
41133
41342
  if (fechaISO(s.slice(0, 10))) return s.slice(0, 10);
41134
41343
  const m = /^(\d{1,2})\/(\d{1,2})\/(\d{4})/.exec(s);
@@ -41142,9 +41351,9 @@ function leerCola(v) {
41142
41351
  for (const e of v) {
41143
41352
  if (!e || typeof e !== "object") return null;
41144
41353
  const r = e;
41145
- const id = refExterna(r.solicitud_id);
41146
- if (!id) return null;
41147
- out.push({ solicitud_id: id, prioridad: texto3(r.prioridad), alta: fechaAISO(r.alta) });
41354
+ const id2 = refExterna(r.solicitud_id);
41355
+ if (!id2) return null;
41356
+ out.push({ solicitud_id: id2, prioridad: texto4(r.prioridad), alta: fechaAISO(r.alta) });
41148
41357
  }
41149
41358
  return out;
41150
41359
  }
@@ -41190,20 +41399,20 @@ function declinadas(caso) {
41190
41399
  }
41191
41400
  function validarLugar(caso, datos, contexto) {
41192
41401
  const l = { ...caso.datos, ...datos };
41193
- const completo = fechaISO(l.fecha) && horaHM(l.hora) !== null && texto3(l.profesional) !== null && texto3(l.especialidad) !== null;
41402
+ const completo = fechaISO(l.fecha) && horaHM(l.hora) !== null && texto4(l.profesional) !== null && texto4(l.especialidad) !== null;
41194
41403
  const out = [completo ? ok("lugar_completo") : falla("lugar_completo", "el turno liberado necesita fecha (AAAA-MM-DD), hora (HH:MM), profesional y especialidad")];
41195
41404
  if (fechaISO(l.fecha) && contexto.hoy) {
41196
- const fecha3 = String(l.fecha);
41405
+ const fecha4 = String(l.fecha);
41197
41406
  const hora = horaHM(l.hora);
41198
- const futuro = fecha3 > contexto.hoy || fecha3 === contexto.hoy && (!contexto.horaActual || hora !== null && hora > contexto.horaActual);
41199
- out.push(futuro ? ok("lugar_futuro") : falla("lugar_futuro", `el turno del ${fecha3}${hora ? ` a las ${hora}` : ""} ya pas\xF3: no se puede recuperar`));
41407
+ const futuro = fecha4 > contexto.hoy || fecha4 === contexto.hoy && (!contexto.horaActual || hora !== null && hora > contexto.horaActual);
41408
+ out.push(futuro ? ok("lugar_futuro") : falla("lugar_futuro", `el turno del ${fecha4}${hora ? ` a las ${hora}` : ""} ya pas\xF3: no se puede recuperar`));
41200
41409
  }
41201
41410
  return out;
41202
41411
  }
41203
41412
  var recuperoTurno = {
41204
41413
  clave: "recupero_turno",
41205
41414
  nombre: "Recupero de citas",
41206
- puesto: "Pacientes y agenda",
41415
+ puesto: "Operaciones",
41207
41416
  descripcion: "Detecta un turno que se liber\xF3 en la agenda, elige de la lista de espera (solicitudes de turno) a quien corresponde por especialidad, prioridad y antig\xFCedad, le asigna el turno en el sistema de gesti\xF3n y comprueba reley\xE9ndolo que qued\xF3 asignado.",
41208
41417
  inicial: "detectado",
41209
41418
  estados: [
@@ -41236,10 +41445,10 @@ var recuperoTurno = {
41236
41445
  const out = validarLugar(caso, datos, contexto);
41237
41446
  out.push(refExterna(datos.solicitud_id) ? ok("solicitud_presente") : falla("solicitud_presente", "proponer requiere solicitud_id: la solicitud de turno de la lista de espera"));
41238
41447
  const estado = normalizarNombre(datos.solicitud_estado);
41239
- out.push(estado === "pendiente" ? ok("solicitud_pendiente") : falla("solicitud_pendiente", `la solicitud tiene que estar pendiente (est\xE1: ${texto3(datos.solicitud_estado) ?? "sin informar"})`));
41448
+ out.push(estado === "pendiente" ? ok("solicitud_pendiente") : falla("solicitud_pendiente", `la solicitud tiene que estar pendiente (est\xE1: ${texto4(datos.solicitud_estado) ?? "sin informar"})`));
41240
41449
  const esp = normalizarNombre(l.especialidad);
41241
41450
  const espSolicitud = normalizarNombre(datos.solicitud_especialidad);
41242
- out.push(esp && espSolicitud && esp === espSolicitud ? ok("especialidad_coincide") : falla("especialidad_coincide", `la solicitud es de ${texto3(datos.solicitud_especialidad) ?? "(sin especialidad)"} y el turno es de ${texto3(l.especialidad) ?? "(sin especialidad)"}`));
41451
+ out.push(esp && espSolicitud && esp === espSolicitud ? ok("especialidad_coincide") : falla("especialidad_coincide", `la solicitud es de ${texto4(datos.solicitud_especialidad) ?? "(sin especialidad)"} y el turno es de ${texto4(l.especialidad) ?? "(sin especialidad)"}`));
41243
41452
  out.push(contexto.solicitudEnOtroCaso ? falla("solicitud_libre", `esa solicitud ya tiene otro recupero en curso o asignado (${contexto.solicitudEnOtroCaso})`) : ok("solicitud_libre"));
41244
41453
  const yaNo = declinadas(caso);
41245
41454
  const elegida = refExterna(datos.solicitud_id);
@@ -41247,9 +41456,9 @@ var recuperoTurno = {
41247
41456
  const { posicion, total } = posicionEnCola(datos, [...contexto.solicitudesEnCurso ?? [], ...yaNo]);
41248
41457
  if (!leerCola(datos.cola)) out.push(falla("orden_de_la_cola", "cola es obligatoria: la lista de espera pendiente de esa especialidad tal como se vio, [{solicitud_id, prioridad, alta}]"));
41249
41458
  else if (posicion === null) out.push(falla("orden_de_la_cola", "la solicitud elegida no est\xE1 en la cola informada"));
41250
- else if (posicion > 1 && !texto3(datos.justificacion)) out.push(falla("orden_de_la_cola", `es la ${posicion}.\xAA de ${total} en la cola: pasarla adelante de las anteriores requiere justificacion`));
41459
+ else if (posicion > 1 && !texto4(datos.justificacion)) out.push(falla("orden_de_la_cola", `es la ${posicion}.\xAA de ${total} en la cola: pasarla adelante de las anteriores requiere justificacion`));
41251
41460
  else out.push(ok("orden_de_la_cola", posicion === 1 ? `primera de ${total} en la cola` : `${posicion}.\xAA de ${total} en la cola, con justificaci\xF3n`));
41252
- out.push(texto3(datos.fuente) ? ok("fuente_presente") : falla("fuente_presente", "fuente (pantalla donde se vio el turno libre y la solicitud) es obligatoria"));
41461
+ out.push(texto4(datos.fuente) ? ok("fuente_presente") : falla("fuente_presente", "fuente (pantalla donde se vio el turno libre y la solicitud) es obligatoria"));
41253
41462
  return out;
41254
41463
  },
41255
41464
  autonomia: {
@@ -41264,8 +41473,8 @@ var recuperoTurno = {
41264
41473
  const fuera = fueraDePreferencia(datos.solicitud_preferencia_horaria, horaHM(l.hora));
41265
41474
  return [
41266
41475
  excepcion("saltea_la_cola", posicion !== null && posicion > 1, posicion !== null && posicion > 1 ? `es la ${posicion}.\xAA de ${total} en la cola` : "primera de la cola"),
41267
- excepcion("profesional_distinto", Boolean(pedido && profesional && pedido !== profesional), pedido ? pedido === profesional ? "es el profesional que pidi\xF3" : `pidi\xF3 a ${texto3(datos.solicitud_profesional)}` : "no pidi\xF3 un profesional en particular"),
41268
- excepcion("fuera_de_preferencia_horaria", fuera, fuera ? `prefiere ${texto3(datos.solicitud_preferencia_horaria)} y el turno es a las ${horaHM(l.hora)}` : "dentro de su preferencia o sin preferencia"),
41476
+ excepcion("profesional_distinto", Boolean(pedido && profesional && pedido !== profesional), pedido ? pedido === profesional ? "es el profesional que pidi\xF3" : `pidi\xF3 a ${texto4(datos.solicitud_profesional)}` : "no pidi\xF3 un profesional en particular"),
41477
+ excepcion("fuera_de_preferencia_horaria", fuera, fuera ? `prefiere ${texto4(datos.solicitud_preferencia_horaria)} y el turno es a las ${horaHM(l.hora)}` : "dentro de su preferencia o sin preferencia"),
41269
41478
  excepcion("turno_para_hoy", paraHoy, paraHoy ? "el turno es para hoy" : "no es para hoy"),
41270
41479
  excepcion("sobreturno", l.sobreturno === true, l.sobreturno === true ? "es un sobreturno" : "turno de la grilla"),
41271
41480
  excepcion("reintento_tras_diferencias", caso.estado === "con_diferencias", caso.estado === "con_diferencias" ? "la asignaci\xF3n anterior no coincidi\xF3 al comprobar" : "primer intento"),
@@ -41287,7 +41496,7 @@ var recuperoTurno = {
41287
41496
  a: "rechazado",
41288
41497
  actor: ["humano"],
41289
41498
  descripcion: "Rechazo con motivo.",
41290
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "el rechazo requiere motivo")]
41499
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "el rechazo requiere motivo")]
41291
41500
  },
41292
41501
  {
41293
41502
  // Paso opcional: donde el hospital quiere que el paciente acepte antes de asignarle el turno.
@@ -41298,7 +41507,7 @@ var recuperoTurno = {
41298
41507
  nivelRequerido: "ejecuta",
41299
41508
  descripcion: "Ofrecerle la cita al paciente antes de asignarla (obligatorio donde la instituci\xF3n pide consulta previa).",
41300
41509
  validar: (caso, datos, contexto) => [
41301
- texto3(datos.canal) ? ok("canal_informado") : falla("canal_informado", "ofrecer requiere canal (tel\xE9fono, WhatsApp, correo)"),
41510
+ texto4(datos.canal) ? ok("canal_informado") : falla("canal_informado", "ofrecer requiere canal (tel\xE9fono, WhatsApp, correo)"),
41302
41511
  validarMargen(caso, contexto)
41303
41512
  ]
41304
41513
  },
@@ -41309,7 +41518,7 @@ var recuperoTurno = {
41309
41518
  actor: ["agente", "humano"],
41310
41519
  nivelRequerido: "observa",
41311
41520
  descripcion: "El paciente acept\xF3 el turno ofrecido.",
41312
- validar: (_caso, datos) => [texto3(datos.respuesta) ? ok("respuesta_registrada") : falla("respuesta_registrada", "aceptar requiere la respuesta del paciente")]
41521
+ validar: (_caso, datos) => [texto4(datos.respuesta) ? ok("respuesta_registrada") : falla("respuesta_registrada", "aceptar requiere la respuesta del paciente")]
41313
41522
  },
41314
41523
  {
41315
41524
  via: "no_acepta",
@@ -41318,7 +41527,7 @@ var recuperoTurno = {
41318
41527
  actor: ["agente", "humano"],
41319
41528
  nivelRequerido: "observa",
41320
41529
  descripcion: "El paciente no acept\xF3 o no respondi\xF3: el turno vuelve a buscar candidato.",
41321
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "no_acepta requiere motivo (no contest\xF3, no puede ese d\xEDa\u2026)")]
41530
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "no_acepta requiere motivo (no contest\xF3, no puede ese d\xEDa\u2026)")]
41322
41531
  },
41323
41532
  {
41324
41533
  // El plugin autoriza ANTES de que se escriba en el sistema del hospital: la cita está a tiempo
@@ -41346,7 +41555,7 @@ var recuperoTurno = {
41346
41555
  cargaManual: true,
41347
41556
  descripcion: "Registrar la cita asignada en el sistema de gesti\xF3n, con la acci\xF3n de escritura.",
41348
41557
  validar: (caso, datos, contexto) => [
41349
- texto3(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "asignar requiere accion_id de la escritura registrada con ops_registrar_accion"),
41558
+ texto4(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "asignar requiere accion_id de la escritura registrada con ops_registrar_accion"),
41350
41559
  contexto.actor === "agente" && caso.estado !== "asignando" ? falla("escritura_autorizada", "un agente tiene que pedir autorizar antes de escribir en el sistema") : ok("escritura_autorizada"),
41351
41560
  ...caso.estado === "asignando" ? [] : [validarPacienteAcepto(caso, contexto)]
41352
41561
  ]
@@ -41356,14 +41565,14 @@ var recuperoTurno = {
41356
41565
  de: ["asignado"],
41357
41566
  a: (caso, datos) => {
41358
41567
  const l = caso.datos;
41359
- const coincide = texto3(datos.leido_fecha) === texto3(l.fecha) && horaHM(datos.leido_hora) === horaHM(l.hora) && normalizarNombre(datos.leido_profesional) === normalizarNombre(l.profesional) && (refExterna(datos.leido_solicitud_id) === null || refExterna(datos.leido_solicitud_id) === refExterna(l.solicitud_id));
41568
+ const coincide = texto4(datos.leido_fecha) === texto4(l.fecha) && horaHM(datos.leido_hora) === horaHM(l.hora) && normalizarNombre(datos.leido_profesional) === normalizarNombre(l.profesional) && (refExterna(datos.leido_solicitud_id) === null || refExterna(datos.leido_solicitud_id) === refExterna(l.solicitud_id));
41360
41569
  return coincide ? "verificado" : "con_diferencias";
41361
41570
  },
41362
41571
  actor: ["agente", "humano", "sistema"],
41363
41572
  nivelRequerido: "observa",
41364
41573
  descripcion: "Releer en el sistema el turno de la solicitud y compararlo con el aprobado (fecha, hora y profesional). Si no coincide, el caso queda con diferencias.",
41365
41574
  validar: (_caso, datos) => [
41366
- fechaISO(datos.leido_fecha) && horaHM(datos.leido_hora) !== null && texto3(datos.leido_profesional) ? ok("turno_leido_presente") : falla("turno_leido_presente", "verificar requiere leido_fecha (AAAA-MM-DD), leido_hora (HH:MM) y leido_profesional, rele\xEDdos en el sistema")
41575
+ fechaISO(datos.leido_fecha) && horaHM(datos.leido_hora) !== null && texto4(datos.leido_profesional) ? ok("turno_leido_presente") : falla("turno_leido_presente", "verificar requiere leido_fecha (AAAA-MM-DD), leido_hora (HH:MM) y leido_profesional, rele\xEDdos en el sistema")
41367
41576
  ]
41368
41577
  },
41369
41578
  {
@@ -41374,7 +41583,7 @@ var recuperoTurno = {
41374
41583
  cargaManual: true,
41375
41584
  descripcion: "Corregir a mano el turno en el sistema de gesti\xF3n (lo aprobado no cambia) y volver a comprobar.",
41376
41585
  validar: (_caso, datos) => [
41377
- texto3(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "corregir requiere accion_id de la escritura registrada con la correcci\xF3n")
41586
+ texto4(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "corregir requiere accion_id de la escritura registrada con la correcci\xF3n")
41378
41587
  ]
41379
41588
  },
41380
41589
  {
@@ -41384,7 +41593,7 @@ var recuperoTurno = {
41384
41593
  actor: ["agente", "humano"],
41385
41594
  nivelRequerido: "observa",
41386
41595
  descripcion: "No hay solicitudes pendientes que puedan tomar el turno liberado: queda libre.",
41387
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "sin_candidato requiere motivo (qu\xE9 se busc\xF3 y por qu\xE9 no hay a qui\xE9n darlo)")]
41596
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "sin_candidato requiere motivo (qu\xE9 se busc\xF3 y por qu\xE9 no hay a qui\xE9n darlo)")]
41388
41597
  },
41389
41598
  {
41390
41599
  via: "descartar",
@@ -41393,7 +41602,7 @@ var recuperoTurno = {
41393
41602
  actor: ["agente", "humano"],
41394
41603
  nivelRequerido: "observa",
41395
41604
  descripcion: "El turno ya no est\xE1 libre (lo ocup\xF3 otra persona, se anul\xF3 la agenda o pas\xF3 la hora): se cierra sin asignar.",
41396
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "descartar requiere motivo")]
41605
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "descartar requiere motivo")]
41397
41606
  }
41398
41607
  ]
41399
41608
  };
@@ -41428,13 +41637,13 @@ var BONO_FACTURADO = ["facturado", "refacturado"];
41428
41637
  function leerResponsable(v) {
41429
41638
  if (!v || typeof v !== "object") return null;
41430
41639
  const r = v;
41431
- const tipo = texto3(r.tipo);
41640
+ const tipo = texto4(r.tipo);
41432
41641
  if (tipo !== "profesional" && tipo !== "rol") return null;
41433
- const id = refExterna(r.id);
41434
- const nombre = texto3(r.nombre)?.slice(0, 120) ?? null;
41435
- if (tipo === "profesional" && !id) return null;
41436
- if (tipo === "rol" && !id) return null;
41437
- return { tipo, id, nombre };
41642
+ const id2 = refExterna(r.id);
41643
+ const nombre = texto4(r.nombre)?.slice(0, 120) ?? null;
41644
+ if (tipo === "profesional" && !id2) return null;
41645
+ if (tipo === "rol" && !id2) return null;
41646
+ return { tipo, id: id2, nombre };
41438
41647
  }
41439
41648
  function leerFaltantes(v) {
41440
41649
  if (!Array.isArray(v)) return null;
@@ -41442,8 +41651,8 @@ function leerFaltantes(v) {
41442
41651
  for (const e of v) {
41443
41652
  if (!e || typeof e !== "object") return null;
41444
41653
  const r = e;
41445
- const regla = texto3(r.regla);
41446
- const detalle = texto3(r.detalle);
41654
+ const regla = texto4(r.regla);
41655
+ const detalle = texto4(r.detalle);
41447
41656
  if (!regla || !REGLAS_CUENTA[regla] || !detalle) return null;
41448
41657
  const responsable = leerResponsable(r.responsable);
41449
41658
  out.push(responsable ? { regla, detalle, item: refExterna(r.item), responsable } : { regla, detalle, item: refExterna(r.item) });
@@ -41459,7 +41668,7 @@ function validarFaltantes(campo, v, alMenosUno) {
41459
41668
  return ok("faltantes_validos", lista2.length === 0 ? "sin faltantes" : lista2.length === 1 ? "1 faltante" : `${lista2.length} faltantes`);
41460
41669
  }
41461
41670
  function estadoBono(v) {
41462
- const s = texto3(v);
41671
+ const s = texto4(v);
41463
41672
  return s ? s.toLowerCase().replace(/[\s-]+/g, "_") : null;
41464
41673
  }
41465
41674
  var cuentaCompleta = {
@@ -41485,10 +41694,10 @@ var cuentaCompleta = {
41485
41694
  const estado = estadoBono(datos.bono_estado);
41486
41695
  return [
41487
41696
  refExterna(l.bono_id) ? ok("bono_presente") : falla("bono_presente", "observar requiere bono_id: el n\xFAmero de bono en el HIS"),
41488
- 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: ${texto3(datos.bono_estado) ?? "sin informar"}`),
41697
+ 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: ${texto4(datos.bono_estado) ?? "sin informar"}`),
41489
41698
  validarFaltantes("faltantes", datos.faltantes, true),
41490
- texto3(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "observar requiere lectura_id: la lectura de la base registrada con ops_registrar_accion"),
41491
- texto3(datos.fuente) ? ok("fuente_presente") : falla("fuente_presente", "fuente (base y consulta de donde salen los faltantes) es obligatoria")
41699
+ texto4(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "observar requiere lectura_id: la lectura de la base registrada con ops_registrar_accion"),
41700
+ texto4(datos.fuente) ? ok("fuente_presente") : falla("fuente_presente", "fuente (base y consulta de donde salen los faltantes) es obligatoria")
41492
41701
  ];
41493
41702
  }
41494
41703
  },
@@ -41500,7 +41709,7 @@ var cuentaCompleta = {
41500
41709
  cargaManual: true,
41501
41710
  descripcion: "Una persona de la instituci\xF3n complet\xF3 en el HIS lo que faltaba. El puesto lo comprueba volviendo a leer.",
41502
41711
  validar: (_caso, datos) => [
41503
- texto3(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "completar requiere accion_id de la carga registrada")
41712
+ texto4(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "completar requiere accion_id de la carga registrada")
41504
41713
  ]
41505
41714
  },
41506
41715
  {
@@ -41521,7 +41730,7 @@ var cuentaCompleta = {
41521
41730
  return [
41522
41731
  validarFaltantes("faltantes_leidos", datos.faltantes_leidos, false),
41523
41732
  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)`),
41524
- texto3(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "comprobar requiere lectura_id: la lectura de la base registrada con ops_registrar_accion")
41733
+ texto4(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "comprobar requiere lectura_id: la lectura de la base registrada con ops_registrar_accion")
41525
41734
  ];
41526
41735
  }
41527
41736
  },
@@ -41531,7 +41740,7 @@ var cuentaCompleta = {
41531
41740
  a: "no_corresponde",
41532
41741
  actor: ["humano"],
41533
41742
  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.",
41534
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "no_corresponde requiere motivo")]
41743
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "no_corresponde requiere motivo")]
41535
41744
  },
41536
41745
  {
41537
41746
  via: "descartar",
@@ -41540,13 +41749,13 @@ var cuentaCompleta = {
41540
41749
  actor: ["agente", "humano"],
41541
41750
  nivelRequerido: "observa",
41542
41751
  descripcion: "El bono se elimin\xF3, se anul\xF3 o qued\xF3 como no cobrable: ya no hay nada que completar.",
41543
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "descartar requiere motivo")]
41752
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "descartar requiere motivo")]
41544
41753
  }
41545
41754
  ]
41546
41755
  };
41547
41756
  var PLAZO_PRESENTACION_POR_DEFECTO = 60;
41548
- function sumarDias4(fecha3, dias) {
41549
- const d = /* @__PURE__ */ new Date(`${fecha3}T00:00:00Z`);
41757
+ function sumarDias4(fecha4, dias) {
41758
+ const d = /* @__PURE__ */ new Date(`${fecha4}T00:00:00Z`);
41550
41759
  d.setUTCDate(d.getUTCDate() + dias);
41551
41760
  return d.toISOString().slice(0, 10);
41552
41761
  }
@@ -41577,14 +41786,14 @@ var facturacionPendiente = {
41577
41786
  validar: (caso, datos, contexto) => {
41578
41787
  const l = { ...caso.datos, ...datos };
41579
41788
  const estado = estadoBono(datos.bono_estado);
41580
- const fecha3 = fechaISO(l.fecha_prestacion) ? String(l.fecha_prestacion) : null;
41789
+ const fecha4 = fechaISO(l.fecha_prestacion) ? String(l.fecha_prestacion) : null;
41581
41790
  return [
41582
41791
  refExterna(l.bono_id) ? ok("bono_presente") : falla("bono_presente", "observar requiere bono_id: el n\xFAmero de bono en el HIS"),
41583
- 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: ${texto3(datos.bono_estado) ?? "sin informar"}`),
41584
- fecha3 && (!contexto.hoy || fecha3 <= contexto.hoy) ? ok("fecha_prestacion_valida", fecha3) : falla("fecha_prestacion_valida", "fecha_prestacion (AAAA-MM-DD) es obligatoria y no puede ser futura"),
41585
- texto3(l.obra_social) ? ok("obra_social_presente") : falla("obra_social_presente", "obra_social es obligatoria: con ella se busca el plazo de presentaci\xF3n"),
41586
- texto3(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "observar requiere lectura_id: la lectura de la base registrada con ops_registrar_accion"),
41587
- texto3(datos.fuente) ? ok("fuente_presente") : falla("fuente_presente", "fuente (base y consulta de donde sale la prestaci\xF3n) es obligatoria")
41792
+ 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: ${texto4(datos.bono_estado) ?? "sin informar"}`),
41793
+ fecha4 && (!contexto.hoy || fecha4 <= contexto.hoy) ? ok("fecha_prestacion_valida", fecha4) : falla("fecha_prestacion_valida", "fecha_prestacion (AAAA-MM-DD) es obligatoria y no puede ser futura"),
41794
+ texto4(l.obra_social) ? ok("obra_social_presente") : falla("obra_social_presente", "obra_social es obligatoria: con ella se busca el plazo de presentaci\xF3n"),
41795
+ texto4(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "observar requiere lectura_id: la lectura de la base registrada con ops_registrar_accion"),
41796
+ texto4(datos.fuente) ? ok("fuente_presente") : falla("fuente_presente", "fuente (base y consulta de donde sale la prestaci\xF3n) es obligatoria")
41588
41797
  ];
41589
41798
  }
41590
41799
  },
@@ -41596,7 +41805,7 @@ var facturacionPendiente = {
41596
41805
  cargaManual: true,
41597
41806
  descripcion: "Una persona de la instituci\xF3n present\xF3 la prestaci\xF3n (la prefactur\xF3 y factur\xF3). El puesto lo comprueba volviendo a leer.",
41598
41807
  validar: (_caso, datos) => [
41599
- texto3(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "presentar requiere accion_id de la carga registrada")
41808
+ texto4(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "presentar requiere accion_id de la carga registrada")
41600
41809
  ]
41601
41810
  },
41602
41811
  {
@@ -41615,7 +41824,7 @@ var facturacionPendiente = {
41615
41824
  const estado = estadoBono(datos.bono_estado_leido);
41616
41825
  return [
41617
41826
  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)`),
41618
- texto3(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "comprobar requiere lectura_id: la lectura de la base registrada con ops_registrar_accion")
41827
+ texto4(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "comprobar requiere lectura_id: la lectura de la base registrada con ops_registrar_accion")
41619
41828
  ];
41620
41829
  }
41621
41830
  },
@@ -41625,7 +41834,7 @@ var facturacionPendiente = {
41625
41834
  a: "no_corresponde",
41626
41835
  actor: ["humano"],
41627
41836
  descripcion: "El equipo indica que esta prestaci\xF3n no se presenta al financiador (por ejemplo, la pag\xF3 el paciente o no es facturable). Queda registrado con el motivo.",
41628
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "no_corresponde requiere motivo")]
41837
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "no_corresponde requiere motivo")]
41629
41838
  },
41630
41839
  {
41631
41840
  via: "descartar",
@@ -41634,7 +41843,7 @@ var facturacionPendiente = {
41634
41843
  actor: ["agente", "humano"],
41635
41844
  nivelRequerido: "observa",
41636
41845
  descripcion: "El bono se elimin\xF3, se anul\xF3 o qued\xF3 como no cobrable: ya no hay nada que presentar.",
41637
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "descartar requiere motivo")]
41846
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "descartar requiere motivo")]
41638
41847
  }
41639
41848
  ]
41640
41849
  };
@@ -41652,9 +41861,9 @@ function leerResultadoRegistro(v) {
41652
41861
  coincide_nombre: typeof r.coincide_nombre === "boolean" ? r.coincide_nombre : null,
41653
41862
  situacion,
41654
41863
  sancion: r.sancion === true,
41655
- profesion: texto3(r.profesion),
41656
- provincia: texto3(r.provincia),
41657
- emisor: texto3(r.emisor)
41864
+ profesion: texto4(r.profesion),
41865
+ provincia: texto4(r.provincia),
41866
+ emisor: texto4(r.emisor)
41658
41867
  };
41659
41868
  }
41660
41869
  function observacionDe(r) {
@@ -41689,13 +41898,13 @@ var credencialProfesional = {
41689
41898
  validar: (caso, datos) => {
41690
41899
  const l = { ...caso.datos, ...datos };
41691
41900
  const r = leerResultadoRegistro(datos.resultado);
41692
- const tipo = texto3(datos.tipo_matricula);
41901
+ const tipo = texto4(datos.tipo_matricula);
41693
41902
  return [
41694
41903
  refExterna(l.profesional_id) ? ok("profesional_presente") : falla("profesional_presente", "verificar requiere profesional_id: el id del profesional en el HIS"),
41695
41904
  r ? ok("resultado_valido", r.sin_matricula ? "sin matr\xEDcula cargada" : r.encontrada ? `encontrada \xB7 ${r.situacion}` : "no encontrada") : falla("resultado_valido", "resultado tiene que ser el objeto que devuelve verificar-matriculas.mjs: {sin_matricula, encontrada, coincide_nombre, situacion, sancion, profesion, provincia, emisor}"),
41696
41905
  r && !r.sin_matricula && !(refExterna(datos.matricula) && tipo && TIPOS_MATRICULA.includes(tipo)) ? falla("matricula_consultada", `con matr\xEDcula cargada hacen falta matricula y tipo_matricula (${TIPOS_MATRICULA.join(" o ")})`) : ok("matricula_consultada"),
41697
- texto3(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "verificar requiere lectura_id: la consulta al registro registrada con ops_registrar_accion"),
41698
- texto3(datos.fuente) ? ok("fuente_presente") : falla("fuente_presente", "fuente (registro consultado y fecha) es obligatoria")
41906
+ texto4(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "verificar requiere lectura_id: la consulta al registro registrada con ops_registrar_accion"),
41907
+ texto4(datos.fuente) ? ok("fuente_presente") : falla("fuente_presente", "fuente (registro consultado y fecha) es obligatoria")
41699
41908
  ];
41700
41909
  }
41701
41910
  },
@@ -41707,7 +41916,7 @@ var credencialProfesional = {
41707
41916
  cargaManual: true,
41708
41917
  descripcion: "Una persona de la instituci\xF3n corrigi\xF3 la ficha del profesional en el HIS. El puesto vuelve a verificar.",
41709
41918
  validar: (_caso, datos) => [
41710
- texto3(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "corregir requiere accion_id de la carga registrada")
41919
+ texto4(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "corregir requiere accion_id de la carga registrada")
41711
41920
  ]
41712
41921
  },
41713
41922
  {
@@ -41716,7 +41925,7 @@ var credencialProfesional = {
41716
41925
  a: "no_corresponde",
41717
41926
  actor: ["humano"],
41718
41927
  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.",
41719
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "no_corresponde requiere motivo")]
41928
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "no_corresponde requiere motivo")]
41720
41929
  },
41721
41930
  {
41722
41931
  via: "descartar",
@@ -41725,7 +41934,7 @@ var credencialProfesional = {
41725
41934
  actor: ["agente", "humano"],
41726
41935
  nivelRequerido: "observa",
41727
41936
  descripcion: "El profesional ya no est\xE1 activo en el sistema o no tiene agenda: no hay nada que verificar.",
41728
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "descartar requiere motivo")]
41937
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "descartar requiere motivo")]
41729
41938
  }
41730
41939
  ]
41731
41940
  };
@@ -41747,7 +41956,7 @@ function horaDentro(hora, desde, hasta) {
41747
41956
  return h >= d && h <= t5;
41748
41957
  }
41749
41958
  function codigoContacto(v) {
41750
- const s = texto3(v);
41959
+ const s = texto4(v);
41751
41960
  return s ? s.toLowerCase().replace(/\s+/g, "_") : null;
41752
41961
  }
41753
41962
  function respuestaContacto(v) {
@@ -41761,7 +41970,7 @@ function canalContacto(v) {
41761
41970
  var demandaPendiente = {
41762
41971
  clave: "demanda_pendiente",
41763
41972
  nombre: "Demanda pendiente",
41764
- puesto: "Pacientes y agenda",
41973
+ puesto: "Operaciones",
41765
41974
  descripcion: "Mueve la demanda que el hospital ya gener\xF3 y no se ejecut\xF3: \xF3rdenes de estudio sin turno, solicitudes de turno pendientes y controles peri\xF3dicos vencidos. Las reglas las arma el hospital en el portal; el plugin las aplica en cada contacto; el caso se cierra cuando el turno queda agendado.",
41766
41975
  inicial: "detectado",
41767
41976
  estados: [
@@ -41805,7 +42014,7 @@ var demandaPendiente = {
41805
42014
  out.push(horaDentro(contexto.horaActual, regla.contacto.hora_desde, regla.contacto.hora_hasta) ? ok("horario_permitido") : falla("horario_permitido", `son las ${contexto.horaActual ?? "?"} y la regla contacta de ${regla.contacto.hora_desde} a ${regla.contacto.hora_hasta}`));
41806
42015
  }
41807
42016
  }
41808
- out.push(texto3(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "contactar requiere accion_id: la escritura (mensaje enviado o llamada hecha) registrada antes"));
42017
+ out.push(texto4(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "contactar requiere accion_id: la escritura (mensaje enviado o llamada hecha) registrada antes"));
41809
42018
  return out;
41810
42019
  }
41811
42020
  },
@@ -41831,7 +42040,7 @@ var demandaPendiente = {
41831
42040
  nivelRequerido: "observa",
41832
42041
  descripcion: "Releer el HIS y encontrar el turno de esa orden, solicitud o control: con el turno, el caso se cierra como movido.",
41833
42042
  validar: (_caso, datos) => [
41834
- texto3(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "comprobar requiere lectura_id: la relectura del HIS registrada antes"),
42043
+ texto4(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "comprobar requiere lectura_id: la relectura del HIS registrada antes"),
41835
42044
  refExterna(datos.turno_id) ? ok("turno_presente") : falla("turno_presente", "comprobar requiere turno_id: el turno encontrado en el HIS; sin turno no hay nada que comprobar")
41836
42045
  ]
41837
42046
  },
@@ -41843,7 +42052,7 @@ var demandaPendiente = {
41843
42052
  nivelRequerido: "observa",
41844
42053
  descripcion: "Cerrar sin turno: solo cuando se agotaron los intentos o venci\xF3 el plazo de la regla.",
41845
42054
  validar: (_caso, datos, contexto) => {
41846
- const out = [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "cerrar requiere motivo")];
42055
+ const out = [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "cerrar requiere motivo")];
41847
42056
  const regla = contexto.regla ?? null;
41848
42057
  if (regla) {
41849
42058
  const hechos = contexto.intentosContacto ?? 0;
@@ -41862,7 +42071,7 @@ var demandaPendiente = {
41862
42071
  actor: ["agente", "humano"],
41863
42072
  nivelRequerido: "observa",
41864
42073
  descripcion: "Descartar con motivo: el dato era err\xF3neo, el paciente ya lo hizo afuera, falleci\xF3 o pidi\xF3 no ser contactado.",
41865
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "descartar requiere motivo")]
42074
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "descartar requiere motivo")]
41866
42075
  },
41867
42076
  {
41868
42077
  via: "no_corresponde",
@@ -41870,7 +42079,7 @@ var demandaPendiente = {
41870
42079
  a: "no_corresponde",
41871
42080
  actor: ["humano"],
41872
42081
  descripcion: "Una persona de la instituci\xF3n decide que este caso no corresponde a la regla.",
41873
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "no_corresponde requiere motivo")]
42082
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "no_corresponde requiere motivo")]
41874
42083
  }
41875
42084
  ]
41876
42085
  };
@@ -41902,16 +42111,16 @@ var circularAranceles = {
41902
42111
  extraccionA: datos.extraccion_a,
41903
42112
  extraccionB: datos.extraccion_b,
41904
42113
  actual: datos.actual,
41905
- filasDeclaradas: num2(l.filas_declaradas),
41906
- porcentajeDeclarado: num2(l.porcentaje_declarado),
42114
+ filasDeclaradas: num3(l.filas_declaradas),
42115
+ porcentajeDeclarado: num3(l.porcentaje_declarado),
41907
42116
  vigenciaDesde: l.vigencia_desde,
41908
42117
  hoy: contexto.hoy ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
41909
42118
  topeVariacion: contexto.topeVariacion ?? null
41910
42119
  });
41911
42120
  return [
41912
- texto3(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "extraer requiere lectura_id: la lectura del convenio en el HIS registrada con ops_registrar_accion"),
41913
- texto3(datos.lectura_circular_id) ? ok("lectura_circular_registrada") : falla("lectura_circular_registrada", "extraer requiere lectura_circular_id: la lectura de la circular (conector archivo) registrada con ops_registrar_accion"),
41914
- texto3(datos.fuente) ? ok("fuente_presente") : falla("fuente_presente", "fuente (la circular: nombre del archivo y de d\xF3nde vino) es obligatoria"),
42121
+ texto4(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "extraer requiere lectura_id: la lectura del convenio en el HIS registrada con ops_registrar_accion"),
42122
+ texto4(datos.lectura_circular_id) ? ok("lectura_circular_registrada") : falla("lectura_circular_registrada", "extraer requiere lectura_circular_id: la lectura de la circular (conector archivo) registrada con ops_registrar_accion"),
42123
+ texto4(datos.fuente) ? ok("fuente_presente") : falla("fuente_presente", "fuente (la circular: nombre del archivo y de d\xF3nde vino) es obligatoria"),
41915
42124
  cruce.ok ? ok("cruce_circular", `${cruce.resumen.propuestas} propuestas, ${cruce.resumen.excepciones} excepciones, ${cruce.resumen.revisar} a revisar, ${cruce.resumen.sin_convenio} sin convenio`) : falla("cruce_circular", cruce.errores.join(" \xB7 "))
41916
42125
  ];
41917
42126
  }
@@ -41931,7 +42140,7 @@ var circularAranceles = {
41931
42140
  aSinExcepcion: "aprobada",
41932
42141
  excepciones: (caso, _datos, contexto) => {
41933
42142
  const r = resumenDe(caso);
41934
- const vigencia = texto3(caso.datos.vigencia_desde);
42143
+ const vigencia = texto4(caso.datos.vigencia_desde);
41935
42144
  return [
41936
42145
  excepcion("practicas_con_excepcion", (r?.excepciones ?? 0) > 0, `${r?.excepciones ?? 0} pr\xE1cticas con baja, suba sobre el tope o desv\xEDo`),
41937
42146
  excepcion("lecturas_que_no_coinciden", (r?.revisar ?? 0) > 0, `${r?.revisar ?? 0} pr\xE1cticas a revisar`),
@@ -41967,7 +42176,7 @@ var circularAranceles = {
41967
42176
  a: "rechazada",
41968
42177
  actor: ["humano"],
41969
42178
  descripcion: "Rechazo con motivo.",
41970
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "el rechazo requiere motivo")]
42179
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "el rechazo requiere motivo")]
41971
42180
  },
41972
42181
  {
41973
42182
  via: "aplicar",
@@ -41978,10 +42187,10 @@ var circularAranceles = {
41978
42187
  cargaManual: true,
41979
42188
  descripcion: "Cargar en el HIS el archivo que gener\xF3 el plugin (Actualizaci\xF3n con archivo) y registrarlo, con el hash del archivo cargado.",
41980
42189
  validar: (caso, datos) => {
41981
- const esperado = texto3(caso.datos.archivo_csv?.hash);
41982
- const informado = texto3(datos.archivo_hash);
42190
+ const esperado = texto4(caso.datos.archivo_csv?.hash);
42191
+ const informado = texto4(datos.archivo_hash);
41983
42192
  return [
41984
- texto3(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "aplicar requiere accion_id de la carga registrada"),
42193
+ texto4(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "aplicar requiere accion_id de la carga registrada"),
41985
42194
  esperado && informado === esperado ? ok("archivo_aprobado") : falla("archivo_aprobado", esperado ? "el archivo cargado no es el que gener\xF3 el plugin para esta aprobaci\xF3n (archivo_hash distinto): descargarlo de nuevo y cargar ese" : "la circular no tiene archivo generado")
41986
42195
  ];
41987
42196
  }
@@ -41999,7 +42208,7 @@ var circularAranceles = {
41999
42208
  validar: (_caso, datos) => {
42000
42209
  const r = compararRelectura([], datos.leidos);
42001
42210
  return [
42002
- texto3(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "verificar requiere lectura_id: la relectura del convenio registrada"),
42211
+ texto4(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "verificar requiere lectura_id: la relectura del convenio registrada"),
42003
42212
  "error" in r ? falla("leidos_validos", r.error) : ok("leidos_validos")
42004
42213
  ];
42005
42214
  }
@@ -42011,7 +42220,7 @@ var circularAranceles = {
42011
42220
  actor: ["humano"],
42012
42221
  cargaManual: true,
42013
42222
  descripcion: "Corregir en el HIS las pr\xE1cticas que no coincidieron y volver a comprobar.",
42014
- validar: (_caso, datos) => [texto3(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "corregir requiere accion_id de la correcci\xF3n registrada")]
42223
+ validar: (_caso, datos) => [texto4(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "corregir requiere accion_id de la correcci\xF3n registrada")]
42015
42224
  },
42016
42225
  {
42017
42226
  via: "cancelar",
@@ -42020,7 +42229,7 @@ var circularAranceles = {
42020
42229
  actor: ["humano", "agente"],
42021
42230
  nivelRequerido: "observa",
42022
42231
  descripcion: "Cancelar la circular (repetida, de otra regi\xF3n, ilegible).",
42023
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "la cancelaci\xF3n requiere motivo")]
42232
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "la cancelaci\xF3n requiere motivo")]
42024
42233
  }
42025
42234
  ]
42026
42235
  };
@@ -42032,7 +42241,7 @@ function resumenCobranzaDe(caso) {
42032
42241
  function evaluarPropuestaCobranza(caso, datos, contexto) {
42033
42242
  const l = leerFacturas(datos.facturas);
42034
42243
  if ("error" in l) return l;
42035
- return evaluarFacturas({ facturas: l.facturas, obraSocial: texto3(caso.datos.obra_social) ?? "", plazos: contexto.plazosPago ?? {}, hoy: contexto.hoy ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10), enOtroReclamo: contexto.facturasEnOtroReclamo ?? [] });
42244
+ return evaluarFacturas({ facturas: l.facturas, obraSocial: texto4(caso.datos.obra_social) ?? "", plazos: contexto.plazosPago ?? {}, hoy: contexto.hoy ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10), enOtroReclamo: contexto.facturasEnOtroReclamo ?? [] });
42036
42245
  }
42037
42246
  var cobranzaFinanciador = {
42038
42247
  clave: "cobranza_financiador",
@@ -42055,7 +42264,7 @@ var cobranzaFinanciador = {
42055
42264
  validar: (caso, datos, contexto) => {
42056
42265
  const r = evaluarPropuestaCobranza(caso, datos, contexto);
42057
42266
  return [
42058
- texto3(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "proponer requiere lectura_id: la lectura de las facturas registrada con ops_registrar_accion"),
42267
+ texto4(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "proponer requiere lectura_id: la lectura de las facturas registrada con ops_registrar_accion"),
42059
42268
  "error" in r ? falla("facturas_validas", r.error) : ok("facturas_validas", `${r.items.length} facturas le\xEDdas`),
42060
42269
  "error" in r ? falla("hay_que_reclamar", "sin facturas v\xE1lidas") : r.resumen.facturas_reclamadas > 0 ? ok("hay_que_reclamar", `${r.resumen.facturas_reclamadas} vencidas`) : falla("hay_que_reclamar", "no hay facturas vencidas con saldo para reclamar: descartar el caso")
42061
42270
  ];
@@ -42082,7 +42291,7 @@ var cobranzaFinanciador = {
42082
42291
  a: "rechazado",
42083
42292
  actor: ["humano"],
42084
42293
  descripcion: "Rechazo con motivo (no se reclama).",
42085
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "el rechazo requiere motivo")]
42294
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "el rechazo requiere motivo")]
42086
42295
  },
42087
42296
  {
42088
42297
  via: "enviar",
@@ -42097,7 +42306,7 @@ var cobranzaFinanciador = {
42097
42306
  const espera = contexto.diasEntreReclamos ?? DIAS_ENTRE_RECLAMOS_POR_DEFECTO;
42098
42307
  const desde = contexto.ultimoReclamo && contexto.hoy ? diasEntre2(contexto.ultimoReclamo, contexto.hoy) : null;
42099
42308
  return [
42100
- texto3(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "enviar requiere accion_id del env\xEDo registrado"),
42309
+ texto4(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "enviar requiere accion_id del env\xEDo registrado"),
42101
42310
  hechos < max ? ok("reclamos_disponibles", `reclamo ${hechos + 1} de ${max}`) : falla("reclamos_disponibles", `ya se hicieron los ${max} reclamos: el caso va a la direcci\xF3n`),
42102
42311
  caso.estado === "aprobado" || desde === null || desde >= espera ? ok("espera_cumplida") : falla("espera_cumplida", `el \xFAltimo reclamo fue hace ${desde} d\xEDas; el pr\xF3ximo va a partir de los ${espera}`)
42103
42312
  ];
@@ -42110,13 +42319,13 @@ var cobranzaFinanciador = {
42110
42319
  actor: ["humano"],
42111
42320
  descripcion: "Registrar la respuesta del financiador: paga en una fecha, observa facturas o no responde.",
42112
42321
  validar: (_caso, datos, contexto) => {
42113
- const r = texto3(datos.respuesta);
42322
+ const r = texto4(datos.respuesta);
42114
42323
  const out = [RESPUESTAS_FINANCIADOR.includes(r ?? "") ? ok("respuesta_valida") : falla("respuesta_valida", `respuesta tiene que ser: ${RESPUESTAS_FINANCIADOR.join(", ")}`)];
42115
42324
  if (r === "paga") {
42116
- const f = texto3(datos.fecha_compromiso);
42325
+ const f = texto4(datos.fecha_compromiso);
42117
42326
  out.push(f && fechaISO(f) && (!contexto.hoy || f >= sumarDias3(contexto.hoy, -1)) ? ok("fecha_compromiso") : falla("fecha_compromiso", "si paga, hace falta la fecha de pago (AAAA-MM-DD, desde hoy)"));
42118
42327
  }
42119
- if (r === "observa") out.push(texto3(datos.detalle) ? ok("detalle_presente") : falla("detalle_presente", "si observa facturas, anot\xE1 cu\xE1les y por qu\xE9"));
42328
+ if (r === "observa") out.push(texto4(datos.detalle) ? ok("detalle_presente") : falla("detalle_presente", "si observa facturas, anot\xE1 cu\xE1les y por qu\xE9"));
42120
42329
  return out;
42121
42330
  }
42122
42331
  },
@@ -42135,7 +42344,7 @@ var cobranzaFinanciador = {
42135
42344
  validar: (_caso, datos) => {
42136
42345
  const r = leerSaldos(datos.leidos);
42137
42346
  return [
42138
- texto3(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "comprobar requiere lectura_id: la relectura de las facturas registrada"),
42347
+ texto4(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "comprobar requiere lectura_id: la relectura de las facturas registrada"),
42139
42348
  "error" in r ? falla("leidos_validos", r.error) : ok("leidos_validos", `${r.saldos.size} facturas`)
42140
42349
  ];
42141
42350
  }
@@ -42148,7 +42357,7 @@ var cobranzaFinanciador = {
42148
42357
  nivelRequerido: "observa",
42149
42358
  descripcion: "La fecha de pago comprometida pas\xF3 (m\xE1s 7 d\xEDas de gracia) y no entr\xF3 el cobro: se vuelve a reclamar.",
42150
42359
  validar: (caso, _datos, contexto) => {
42151
- const f = texto3(caso.datos.fecha_compromiso);
42360
+ const f = texto4(caso.datos.fecha_compromiso);
42152
42361
  return [f && contexto.hoy && sumarDias3(f, GRACIA_COMPROMISO) < contexto.hoy ? ok("compromiso_vencido") : falla("compromiso_vencido", f ? `el financiador comprometi\xF3 pagar el ${f}; se espera hasta ${sumarDias3(f, GRACIA_COMPROMISO)}` : "no hay fecha comprometida")];
42153
42362
  }
42154
42363
  },
@@ -42173,7 +42382,7 @@ var cobranzaFinanciador = {
42173
42382
  a: "cerrado",
42174
42383
  actor: ["humano"],
42175
42384
  descripcion: "La direcci\xF3n cierra el caso (gesti\xF3n legal, acuerdo, incobrable).",
42176
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "cerrar requiere motivo")]
42385
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "cerrar requiere motivo")]
42177
42386
  },
42178
42387
  {
42179
42388
  via: "descartar",
@@ -42182,7 +42391,7 @@ var cobranzaFinanciador = {
42182
42391
  actor: ["agente", "humano"],
42183
42392
  nivelRequerido: "observa",
42184
42393
  descripcion: "No queda nada vencido para reclamar.",
42185
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "descartar requiere motivo")]
42394
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "descartar requiere motivo")]
42186
42395
  }
42187
42396
  ]
42188
42397
  };
@@ -42195,11 +42404,11 @@ function numeros(v) {
42195
42404
  }
42196
42405
  function validarLecturaInternacion(caso, datos, contexto) {
42197
42406
  const r = contexto.internacion;
42198
- const propia = texto3(caso.datos.internacion_id);
42407
+ const propia = texto4(caso.datos.internacion_id);
42199
42408
  return [
42200
42409
  !r ? falla("lectura_valida", "falta lectura: la internaci\xF3n tal como la devuelve revisar-internaciones.mjs") : "error" in r ? falla("lectura_valida", r.error) : ok("lectura_valida", `${r.evaluacion.pendientes.length} pendientes, ${r.evaluacion.dias_sin_evolucion.length} d\xEDas sin evoluci\xF3n`),
42201
42410
  r && !("error" in r) && propia && r.internacionId !== propia ? falla("misma_internacion", `la lectura es de la internaci\xF3n ${r.internacionId} y el caso es de la ${propia}`) : ok("misma_internacion"),
42202
- texto3(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "hace falta lectura_id: la lectura de la base registrada con ops_registrar_accion")
42411
+ texto4(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "hace falta lectura_id: la lectura de la base registrada con ops_registrar_accion")
42203
42412
  ];
42204
42413
  }
42205
42414
  var destinoInternacion = (_caso, _datos, contexto) => {
@@ -42224,7 +42433,7 @@ var internacionAlDia = {
42224
42433
  actor: ["agente", "humano", "sistema"],
42225
42434
  nivelRequerido: "observa",
42226
42435
  descripcion: "Primera lectura de la internaci\xF3n. El plugin decide los pendientes de hoy, los d\xEDas sin evoluci\xF3n y el estado.",
42227
- validar: (caso, datos, contexto) => [...validarLecturaInternacion(caso, datos, contexto), texto3(datos.fuente) ? ok("fuente_presente") : falla("fuente_presente", "fuente (base y consulta de donde sale la lectura) es obligatoria")]
42436
+ validar: (caso, datos, contexto) => [...validarLecturaInternacion(caso, datos, contexto), texto4(datos.fuente) ? ok("fuente_presente") : falla("fuente_presente", "fuente (base y consulta de donde sale la lectura) es obligatoria")]
42228
42437
  },
42229
42438
  {
42230
42439
  via: "comprobar",
@@ -42242,7 +42451,7 @@ var internacionAlDia = {
42242
42451
  actor: ["humano"],
42243
42452
  cargaManual: true,
42244
42453
  descripcion: "Una persona de la instituci\xF3n indica que lo resolvi\xF3 en el HIS. El puesto lo comprueba volviendo a leer.",
42245
- validar: (_caso, datos) => [texto3(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "completar requiere accion_id de la carga registrada")]
42454
+ validar: (_caso, datos) => [texto4(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "completar requiere accion_id de la carga registrada")]
42246
42455
  },
42247
42456
  {
42248
42457
  via: "descartar",
@@ -42251,11 +42460,259 @@ var internacionAlDia = {
42251
42460
  actor: ["agente", "humano"],
42252
42461
  nivelRequerido: "observa",
42253
42462
  descripcion: "La internaci\xF3n se anul\xF3 o se borr\xF3 en el HIS.",
42254
- validar: (_caso, datos) => [texto3(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "descartar requiere motivo")]
42463
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "descartar requiere motivo")]
42464
+ }
42465
+ ]
42466
+ };
42467
+ function leerItemsDebito(v) {
42468
+ return Array.isArray(v) ? v.filter((x) => x && typeof x === "object" && typeof x.item_id === "string") : [];
42469
+ }
42470
+ function faltaTrasladar(items, leidos) {
42471
+ const l = leerDebitos(leidos);
42472
+ if ("error" in l) return { faltan: [], error: l.error };
42473
+ const cargado = new Map(l.debitos.map((d) => [d.item_id, d.ya_trasladado]));
42474
+ const faltan = items.filter((i) => i.estado === "a_trasladar").filter((i) => (cargado.get(i.item_id) ?? 0) + 5e-3 < i.ya_trasladado + i.a_descontar).map((i) => i.item_id);
42475
+ return { faltan };
42476
+ }
42477
+ var honorarioEnCero = {
42478
+ clave: "honorario_en_cero",
42479
+ nombre: "Honorarios que se liquidar\xEDan en $0",
42480
+ puesto: "Control de honorarios",
42481
+ descripcion: "Lee en el HIS las prestaciones de cada profesional que todav\xEDa no se liquidaron y marca las que el HIS liquidar\xEDa en $0 porque no tienen regla de honorario (o la regla no tiene valores). El equipo carga la regla y el puesto lo comprueba volviendo a leer. El puesto no escribe en el sistema.",
42482
+ inicial: "detectado",
42483
+ estados: ["detectado", "para_cargar", "completado", "resuelto", "no_corresponde", "descartado"],
42484
+ finalesOk: ["resuelto"],
42485
+ finalesNoOk: ["no_corresponde", "descartado"],
42486
+ minutosAbsorbidos: 15,
42487
+ transiciones: [
42488
+ {
42489
+ via: "observar",
42490
+ de: ["detectado"],
42491
+ a: "para_cargar",
42492
+ actor: ["agente", "humano"],
42493
+ nivelRequerido: "observa",
42494
+ descripcion: "Informar las prestaciones del profesional como las lee el HIS, con su regla. El plugin calcula el honorario como el HIS y decide cu\xE1les quedan en $0.",
42495
+ validar: (_caso, datos) => {
42496
+ const l = leerPrestaciones(datos.prestaciones);
42497
+ const r = "error" in l ? null : prestacionesEnCero(l.prestaciones);
42498
+ return [
42499
+ texto4(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "observar requiere lectura_id: la lectura de la base registrada con ops_registrar_accion"),
42500
+ "error" in l ? falla("prestaciones_validas", l.error) : ok("prestaciones_validas", `${l.prestaciones.length} prestaciones le\xEDdas`),
42501
+ !r ? falla("hay_en_cero", "sin prestaciones v\xE1lidas") : r.resumen.prestaciones > 0 ? ok("hay_en_cero", `${r.resumen.prestaciones} en $0`) : falla("hay_en_cero", "no hay prestaciones que se liquiden en $0: descartar el caso")
42502
+ ];
42503
+ }
42504
+ },
42505
+ {
42506
+ via: "completar",
42507
+ de: ["para_cargar"],
42508
+ a: "completado",
42509
+ actor: ["humano"],
42510
+ cargaManual: true,
42511
+ descripcion: "Una persona de la instituci\xF3n carg\xF3 en el HIS las reglas que faltaban. El puesto lo comprueba volviendo a leer.",
42512
+ validar: (_caso, datos) => [texto4(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "completar requiere accion_id de la carga registrada")]
42513
+ },
42514
+ {
42515
+ via: "comprobar",
42516
+ de: ["para_cargar", "completado"],
42517
+ a: (caso, datos) => {
42518
+ const l = leerPrestaciones(datos.prestaciones);
42519
+ if ("error" in l) return caso.estado;
42520
+ return prestacionesEnCero(l.prestaciones).resumen.prestaciones === 0 ? "resuelto" : "para_cargar";
42521
+ },
42522
+ actor: ["agente", "humano", "sistema"],
42523
+ nivelRequerido: "observa",
42524
+ descripcion: "Volver a leer las prestaciones del profesional. El plugin decide: resuelto (ninguna en $0) o sigue para cargar.",
42525
+ validar: (_caso, datos) => {
42526
+ const l = leerPrestaciones(datos.prestaciones);
42527
+ return [
42528
+ "error" in l ? falla("prestaciones_validas", l.error) : ok("prestaciones_validas", `${l.prestaciones.length} prestaciones le\xEDdas`),
42529
+ texto4(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "comprobar requiere lectura_id")
42530
+ ];
42531
+ }
42532
+ },
42533
+ {
42534
+ via: "no_corresponde",
42535
+ de: ["para_cargar", "completado"],
42536
+ a: "no_corresponde",
42537
+ actor: ["humano"],
42538
+ descripcion: "El equipo indica que esas prestaciones no se le liquidan a este profesional (por ejemplo, es personal de la instituci\xF3n). Queda con el motivo.",
42539
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "no_corresponde requiere motivo")]
42540
+ },
42541
+ {
42542
+ via: "descartar",
42543
+ de: ["detectado", "para_cargar", "completado"],
42544
+ a: "descartado",
42545
+ actor: ["agente", "humano"],
42546
+ nivelRequerido: "observa",
42547
+ descripcion: "No quedan prestaciones en $0 para este profesional.",
42548
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "descartar requiere motivo")]
42549
+ }
42550
+ ]
42551
+ };
42552
+ function evaluarPropuestaDebito(datos) {
42553
+ const l = leerDebitos(datos.items);
42554
+ if ("error" in l) return l;
42555
+ const items = l.debitos.map(evaluarDebito);
42556
+ return { items, resumen: resumenDebitos(items) };
42557
+ }
42558
+ var debitoProfesional = {
42559
+ clave: "debito_profesional",
42560
+ nombre: "D\xE9bitos al profesional",
42561
+ puesto: "Control de honorarios",
42562
+ descripcion: "Cruza las notas de cr\xE9dito de las obras sociales con las prestaciones ya liquidadas a cada profesional y propone descontarle la parte de su honorario que la obra social debit\xF3. La direcci\xF3n aprueba, el equipo carga el d\xE9bito en el HIS y el puesto lo comprueba.",
42563
+ inicial: "detectado",
42564
+ estados: ["detectado", "pendiente_aprobacion", "aprobado", "aplicado", "verificado", "con_diferencias", "rechazado", "descartado"],
42565
+ finalesOk: ["verificado"],
42566
+ finalesNoOk: ["rechazado", "descartado"],
42567
+ minutosAbsorbidos: 20,
42568
+ transiciones: [
42569
+ {
42570
+ via: "proponer",
42571
+ de: ["detectado"],
42572
+ a: "pendiente_aprobacion",
42573
+ actor: ["agente", "humano"],
42574
+ nivelRequerido: "propone",
42575
+ descripcion: "Informar las prestaciones de la nota de cr\xE9dito como las lee el HIS (monto debitado, regla, si ya se liquid\xF3 y lo ya descontado). El plugin calcula cu\xE1nto se le descuenta al profesional.",
42576
+ validar: (_caso, datos) => {
42577
+ const r = evaluarPropuestaDebito(datos);
42578
+ return [
42579
+ texto4(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "proponer requiere lectura_id: la lectura de la base registrada con ops_registrar_accion"),
42580
+ "error" in r ? falla("items_validos", r.error) : ok("items_validos", `${r.items.length} prestaciones le\xEDdas`),
42581
+ "error" in r ? falla("hay_que_trasladar", "sin prestaciones v\xE1lidas") : r.resumen.a_trasladar > 0 ? ok("hay_que_trasladar", `${r.resumen.a_trasladar} prestaciones`) : falla("hay_que_trasladar", `no hay nada para descontar todav\xEDa (${r.resumen.sin_liquidar} sin liquidar, ${r.resumen.ya_trasladados} ya descontadas): descartar el caso`)
42582
+ ];
42583
+ },
42584
+ autonomia: {
42585
+ aSinExcepcion: "aprobado",
42586
+ excepciones: (_caso, datos, contexto) => {
42587
+ const r = evaluarPropuestaDebito(datos);
42588
+ const total = "error" in r ? 0 : r.resumen.total;
42589
+ const umbral = contexto.umbralAprobacion ?? 0;
42590
+ return [excepcion("monto_sobre_umbral", umbral > 0 && total > umbral, umbral > 0 ? `umbral ${umbral}` : "sin umbral")];
42591
+ }
42592
+ }
42593
+ },
42594
+ { via: "aprobar", de: ["pendiente_aprobacion"], a: "aprobado", actor: ["humano"], descripcion: "La direcci\xF3n aprueba descontarle al profesional." },
42595
+ {
42596
+ via: "rechazar",
42597
+ de: ["pendiente_aprobacion"],
42598
+ a: "rechazado",
42599
+ actor: ["humano"],
42600
+ descripcion: "La direcci\xF3n decide no descont\xE1rselo (lo absorbe la instituci\xF3n).",
42601
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "rechazar requiere motivo")]
42602
+ },
42603
+ {
42604
+ via: "aplicar",
42605
+ de: ["aprobado"],
42606
+ a: "aplicado",
42607
+ actor: ["humano"],
42608
+ cargaManual: true,
42609
+ descripcion: "Una persona del equipo carg\xF3 el d\xE9bito en el HIS (Honorarios M\xE9dicos \u203A Liquidaci\xF3n \u203A D\xE9bitos y cr\xE9ditos). El puesto lo comprueba volviendo a leer.",
42610
+ validar: (_caso, datos) => [texto4(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "aplicar requiere accion_id de la carga registrada")]
42611
+ },
42612
+ {
42613
+ via: "comprobar",
42614
+ de: ["aplicado"],
42615
+ a: (caso, datos) => faltaTrasladar(leerItemsDebito(caso.datos.items), datos.leidos).faltan.length === 0 ? "verificado" : "con_diferencias",
42616
+ actor: ["agente", "humano", "sistema"],
42617
+ nivelRequerido: "observa",
42618
+ descripcion: "Volver a leer los d\xE9bitos cargados al profesional por esas prestaciones (leidos). El plugin compara con lo aprobado.",
42619
+ validar: (caso, datos) => {
42620
+ const f = faltaTrasladar(leerItemsDebito(caso.datos.items), datos.leidos);
42621
+ return [
42622
+ f.error ? falla("leidos_validos", f.error) : ok("leidos_validos"),
42623
+ texto4(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "comprobar requiere lectura_id")
42624
+ ];
42625
+ }
42626
+ },
42627
+ {
42628
+ via: "corregir",
42629
+ de: ["con_diferencias"],
42630
+ a: "aplicado",
42631
+ actor: ["humano"],
42632
+ cargaManual: true,
42633
+ descripcion: "El equipo corrigi\xF3 el d\xE9bito en el HIS. El puesto lo vuelve a comprobar.",
42634
+ validar: (_caso, datos) => [texto4(datos.accion_id) ? ok("accion_registrada") : falla("accion_registrada", "corregir requiere accion_id")]
42635
+ },
42636
+ {
42637
+ via: "descartar",
42638
+ de: ["detectado", "pendiente_aprobacion"],
42639
+ a: "descartado",
42640
+ actor: ["agente", "humano"],
42641
+ nivelRequerido: "observa",
42642
+ descripcion: "No hay nada para descontar (sin liquidar todav\xEDa o ya descontado).",
42643
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "descartar requiere motivo")]
42255
42644
  }
42256
42645
  ]
42257
42646
  };
42258
- var WORKFLOWS_SOLO_LECTURA = /* @__PURE__ */ new Set([cuentaCompleta.clave, facturacionPendiente.clave, credencialProfesional.clave, internacionAlDia.clave]);
42647
+ var liquidacionProfesional = {
42648
+ clave: "liquidacion_profesional",
42649
+ nombre: "Liquidaci\xF3n al profesional",
42650
+ puesto: "Control de honorarios",
42651
+ descripcion: "Cuando el HIS liquida los honorarios, arma para cada profesional el detalle de su liquidaci\xF3n (por obra social, sin datos de pacientes) y, con la aprobaci\xF3n de la direcci\xF3n, se lo manda. El puesto marca las prestaciones liquidadas en $0.",
42652
+ inicial: "detectado",
42653
+ estados: ["detectado", "pendiente_aprobacion", "aprobado", "enviada", "rechazado", "descartado"],
42654
+ finalesOk: ["enviada"],
42655
+ finalesNoOk: ["rechazado", "descartado"],
42656
+ minutosAbsorbidos: 10,
42657
+ transiciones: [
42658
+ {
42659
+ via: "preparar",
42660
+ de: ["detectado"],
42661
+ a: "pendiente_aprobacion",
42662
+ actor: ["agente", "humano"],
42663
+ nivelRequerido: "propone",
42664
+ descripcion: "Informar los bonos que el HIS liquid\xF3 al profesional ese d\xEDa, con sus prestaciones y su regla. El plugin calcula el honorario como el HIS y arma el mensaje.",
42665
+ validar: (_caso, datos) => {
42666
+ const l = leerLineasLiquidacion(datos.lineas);
42667
+ return [
42668
+ texto4(datos.lectura_id) ? ok("lectura_registrada") : falla("lectura_registrada", "preparar requiere lectura_id"),
42669
+ "error" in l ? falla("lineas_validas", l.error) : ok("lineas_validas", `${l.lineas.length} bonos`)
42670
+ ];
42671
+ },
42672
+ autonomia: {
42673
+ aSinExcepcion: "aprobado",
42674
+ excepciones: (_caso, datos, contexto) => {
42675
+ const l = leerLineasLiquidacion(datos.lineas);
42676
+ const enCero = "error" in l ? 0 : l.lineas.reduce((a, x) => a + x.en_cero, 0);
42677
+ return [
42678
+ excepcion("prestaciones_en_cero", enCero > 0, `${enCero} prestaciones en $0`),
42679
+ excepcion("profesional_sin_correo", contexto.profesionalConCorreo === false, contexto.profesionalConCorreo ? "con correo" : "sin correo")
42680
+ ];
42681
+ }
42682
+ }
42683
+ },
42684
+ { via: "aprobar", de: ["pendiente_aprobacion"], a: "aprobado", actor: ["humano"], descripcion: "La direcci\xF3n aprueba mandarle la liquidaci\xF3n al profesional." },
42685
+ {
42686
+ via: "rechazar",
42687
+ de: ["pendiente_aprobacion"],
42688
+ a: "rechazado",
42689
+ actor: ["humano"],
42690
+ descripcion: "No se le manda (por ejemplo, la liquidaci\xF3n se va a revertir).",
42691
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "rechazar requiere motivo")]
42692
+ },
42693
+ {
42694
+ via: "enviar",
42695
+ de: ["aprobado"],
42696
+ a: "enviada",
42697
+ actor: ["humano"],
42698
+ descripcion: "Se le mand\xF3 la liquidaci\xF3n al profesional (por correo desde el portal o por la v\xEDa habitual). Es un aviso, no una carga en el HIS: no hay nada que releer.",
42699
+ validar: (_caso, datos) => [
42700
+ texto4(datos.aviso_id) ? ok("envio_registrado") : falla("envio_registrado", "enviar requiere aviso_id: el env\xEDo registrado"),
42701
+ texto4(datos.canal) ? ok("canal_informado", String(datos.canal)) : falla("canal_informado", "enviar requiere el canal")
42702
+ ]
42703
+ },
42704
+ {
42705
+ via: "descartar",
42706
+ de: ["detectado", "pendiente_aprobacion"],
42707
+ a: "descartado",
42708
+ actor: ["agente", "humano"],
42709
+ nivelRequerido: "observa",
42710
+ descripcion: "La liquidaci\xF3n se revirti\xF3 o no corresponde mandarla.",
42711
+ validar: (_caso, datos) => [texto4(datos.motivo) ? ok("motivo_presente") : falla("motivo_presente", "descartar requiere motivo")]
42712
+ }
42713
+ ]
42714
+ };
42715
+ var WORKFLOWS_SOLO_LECTURA = /* @__PURE__ */ new Set([cuentaCompleta.clave, facturacionPendiente.clave, credencialProfesional.clave, internacionAlDia.clave, honorarioEnCero.clave]);
42259
42716
  var WORKFLOWS = {
42260
42717
  [actualizacionArancel.clave]: actualizacionArancel,
42261
42718
  [tareaOperativa.clave]: tareaOperativa,
@@ -42266,7 +42723,10 @@ var WORKFLOWS = {
42266
42723
  [demandaPendiente.clave]: demandaPendiente,
42267
42724
  [circularAranceles.clave]: circularAranceles,
42268
42725
  [cobranzaFinanciador.clave]: cobranzaFinanciador,
42269
- [internacionAlDia.clave]: internacionAlDia
42726
+ [internacionAlDia.clave]: internacionAlDia,
42727
+ [honorarioEnCero.clave]: honorarioEnCero,
42728
+ [debitoProfesional.clave]: debitoProfesional,
42729
+ [liquidacionProfesional.clave]: liquidacionProfesional
42270
42730
  };
42271
42731
  function getWorkflow(clave) {
42272
42732
  return WORKFLOWS[clave] ?? null;
@@ -42654,17 +43114,17 @@ async function listarReglas(ctx, companyId, filtro = {}) {
42654
43114
  const rows = await ctx.db.query(`SELECT ${COLS} FROM ${t(ctx, "regla")} WHERE ${where} ORDER BY created_at ASC`, params);
42655
43115
  return rows.map(mapRegla);
42656
43116
  }
42657
- async function leerRegla(ctx, companyId, id) {
42658
- const rows = await ctx.db.query(`SELECT ${COLS} FROM ${t(ctx, "regla")} WHERE company_id = $1 AND id = $2 LIMIT 1`, [companyId, id]);
43117
+ async function leerRegla2(ctx, companyId, id2) {
43118
+ const rows = await ctx.db.query(`SELECT ${COLS} FROM ${t(ctx, "regla")} WHERE company_id = $1 AND id = $2 LIMIT 1`, [companyId, id2]);
42659
43119
  return rows[0] ? mapRegla(rows[0]) : null;
42660
43120
  }
42661
- async function requerirRegla(ctx, companyId, id) {
42662
- const r = await leerRegla(ctx, companyId, id);
42663
- if (!r) throw new OpsError("regla_inexistente", `no existe la regla ${id} en esta instituci\xF3n`);
43121
+ async function requerirRegla(ctx, companyId, id2) {
43122
+ const r = await leerRegla2(ctx, companyId, id2);
43123
+ if (!r) throw new OpsError("regla_inexistente", `no existe la regla ${id2} en esta instituci\xF3n`);
42664
43124
  return r;
42665
43125
  }
42666
- function cambio(version2, actor, texto6) {
42667
- return { version: version2, fecha: (/* @__PURE__ */ new Date()).toISOString(), actorTipo: actor.tipo, actorId: actor.id, cambio: texto6 };
43126
+ function cambio(version2, actor, texto7) {
43127
+ return { version: version2, fecha: (/* @__PURE__ */ new Date()).toISOString(), actorTipo: actor.tipo, actorId: actor.id, cambio: texto7 };
42668
43128
  }
42669
43129
  function soloPersonas(actor, que) {
42670
43130
  if (actor.tipo !== "humano") throw new OpsError("actor_no_permitido", `${que} lo hace una persona de la instituci\xF3n desde el portal; el agente solo lee las reglas e informa la prueba`);
@@ -42673,15 +43133,15 @@ async function crearRegla(ctx, input2) {
42673
43133
  soloPersonas(input2.actor, "crear una regla");
42674
43134
  if (input2.workflow !== "demanda_pendiente") throw new OpsError("workflow_sin_reglas", `el puesto ${input2.workflow} no tiene reglas configurables`);
42675
43135
  const v = validarRegla(input2);
42676
- const id = randomUUID();
43136
+ const id2 = randomUUID();
42677
43137
  const historial = [cambio(1, input2.actor, "creada")];
42678
43138
  await ctx.db.execute(
42679
43139
  `INSERT INTO ${t(ctx, "regla")} (id, company_id, workflow, nombre, tipo, parametros, contacto, cierre, estado, version, historial, actor_tipo, actor_id) VALUES ($1, $2, $3, $4, $5, $6::jsonb, $7::jsonb, $8::jsonb, $9, $10, $11::jsonb, $12, $13)`,
42680
- [id, input2.companyId, input2.workflow, v.nombre, v.tipo, JSON.stringify(v.parametros), JSON.stringify(v.contacto), JSON.stringify(v.cierre), "borrador", 1, JSON.stringify(historial), input2.actor.tipo, input2.actor.id]
43140
+ [id2, input2.companyId, input2.workflow, v.nombre, v.tipo, JSON.stringify(v.parametros), JSON.stringify(v.contacto), JSON.stringify(v.cierre), "borrador", 1, JSON.stringify(historial), input2.actor.tipo, input2.actor.id]
42681
43141
  );
42682
- await ctx.activity.log({ companyId: input2.companyId, message: `Autopilot Care: regla \xAB${v.nombre}\xBB creada (${v.tipo}, borrador)`, metadata: { reglaId: id, workflow: input2.workflow } });
43142
+ await ctx.activity.log({ companyId: input2.companyId, message: `Autopilot Care: regla \xAB${v.nombre}\xBB creada (${v.tipo}, borrador)`, metadata: { reglaId: id2, workflow: input2.workflow } });
42683
43143
  const now = (/* @__PURE__ */ new Date()).toISOString();
42684
- return { id, companyId: input2.companyId, workflow: input2.workflow, ...v, estado: "borrador", version: 1, historial, ultimaPrueba: null, actorTipo: input2.actor.tipo, actorId: input2.actor.id, createdAt: now, updatedAt: now };
43144
+ return { id: id2, companyId: input2.companyId, workflow: input2.workflow, ...v, estado: "borrador", version: 1, historial, ultimaPrueba: null, actorTipo: input2.actor.tipo, actorId: input2.actor.id, createdAt: now, updatedAt: now };
42685
43145
  }
42686
43146
  async function editarRegla(ctx, input2) {
42687
43147
  soloPersonas(input2.actor, "editar una regla");
@@ -43073,10 +43533,19 @@ async function abrirCaso(ctx, input2) {
43073
43533
  if (referencia !== `cobranza:${os}`) throw new OpsError("referencia_requerida", `en cobranza_financiador la referencia es obligatoria: cobranza:${os}`);
43074
43534
  if (!str2(d.obra_social) || !str2(d.institucion)) throw new OpsError("validacion", "cobranza_financiador necesita obra_social (nombre) e institucion (nombre de la instituci\xF3n para el reclamo)");
43075
43535
  }
43536
+ if (wf.clave === "honorario_en_cero" || wf.clave === "debito_profesional" || wf.clave === "liquidacion_profesional") {
43537
+ const d = input2.datos ?? {};
43538
+ const pid = str2(d.profesional_id);
43539
+ if (!pid || !/^\d{1,12}$/.test(pid)) throw new OpsError("validacion", `${wf.clave} necesita profesional_id (el id del profesional en el HIS)`);
43540
+ const esperada = wf.clave === "honorario_en_cero" ? `honorarios:${pid}` : wf.clave === "debito_profesional" ? `debito:${pid}:${str2(d.nota_credito_id) ?? ""}` : `liquidacion:${pid}:${str2(d.liquidado_el) ?? ""}`;
43541
+ if (wf.clave === "debito_profesional" && !/^\d{1,12}$/.test(str2(d.nota_credito_id) ?? "")) throw new OpsError("validacion", "debito_profesional necesita nota_credito_id");
43542
+ if (wf.clave === "liquidacion_profesional" && (!/^\d{4}-\d{2}-\d{2}$/.test(str2(d.liquidado_el) ?? "") || !str2(d.institucion))) throw new OpsError("validacion", "liquidacion_profesional necesita liquidado_el (AAAA-MM-DD) e institucion (nombre para el mensaje)");
43543
+ if (referencia !== esperada) throw new OpsError("referencia_requerida", `en ${wf.clave} la referencia es obligatoria: ${esperada}`);
43544
+ }
43076
43545
  if (wf.clave === "internacion_al_dia") {
43077
- const id2 = str2(input2.datos?.internacion_id);
43078
- if (!id2 || !/^\d{1,12}$/.test(id2)) throw new OpsError("validacion", "internacion_al_dia necesita internacion_id (el id de la internaci\xF3n en el HIS)");
43079
- if (referencia !== `internacion:${id2}`) throw new OpsError("referencia_requerida", `en internacion_al_dia la referencia es obligatoria: internacion:${id2}`);
43546
+ const id3 = str2(input2.datos?.internacion_id);
43547
+ if (!id3 || !/^\d{1,12}$/.test(id3)) throw new OpsError("validacion", "internacion_al_dia necesita internacion_id (el id de la internaci\xF3n en el HIS)");
43548
+ if (referencia !== `internacion:${id3}`) throw new OpsError("referencia_requerida", `en internacion_al_dia la referencia es obligatoria: internacion:${id3}`);
43080
43549
  }
43081
43550
  if (wf.clave === "circular_aranceles") {
43082
43551
  const d = input2.datos ?? {};
@@ -43086,13 +43555,17 @@ async function abrirCaso(ctx, input2) {
43086
43555
  if (!/^\d{4}-\d{2}-\d{2}$/.test(String(d.vigencia_desde))) throw new OpsError("validacion", "vigencia_desde: AAAA-MM-DD");
43087
43556
  }
43088
43557
  const extra = {};
43558
+ if (wf.clave === "honorario_en_cero" || wf.clave === "debito_profesional" || wf.clave === "liquidacion_profesional") {
43559
+ const p = leerProfesional(input2.datos?.profesional) ?? leerProfesional({ id: input2.datos?.profesional_id, nombre: input2.datos?.profesional });
43560
+ extra.profesional = p?.nombre ?? null;
43561
+ }
43089
43562
  if (wf.clave === "demanda_pendiente") {
43090
43563
  if (!referencia || !/^(orden|solicitud|control):\S+$/.test(referencia)) {
43091
43564
  throw new OpsError("referencia_requerida", "en demanda_pendiente la referencia es obligatoria: orden:<id>, solicitud:<id> o control:<persona_id>:<regla_id>");
43092
43565
  }
43093
43566
  const reglaId = str2(input2.datos?.regla_id);
43094
43567
  if (!reglaId) throw new OpsError("regla_requerida", "en demanda_pendiente datos.regla_id es obligatorio: la regla activa que detect\xF3 el caso");
43095
- const regla = await leerRegla(ctx, input2.companyId, reglaId);
43568
+ const regla = await leerRegla2(ctx, input2.companyId, reglaId);
43096
43569
  if (!regla || regla.workflow !== wf.clave) throw new OpsError("regla_inexistente", `no existe la regla ${reglaId} en esta instituci\xF3n`);
43097
43570
  if (regla.estado !== "activa") throw new OpsError("regla_inactiva", `la regla \xAB${regla.nombre}\xBB est\xE1 ${regla.estado}: no abre casos hasta que se active`);
43098
43571
  const { hoy } = ahoraEnHospital();
@@ -43111,17 +43584,17 @@ async function abrirCaso(ctx, input2) {
43111
43584
  );
43112
43585
  if (abiertos[0]) return { caso: mapCaso(abiertos[0]), creado: false };
43113
43586
  }
43114
- const id = randomUUID2();
43587
+ const id2 = randomUUID2();
43115
43588
  const datos = { ...input2.datos ?? {}, ...extra };
43116
43589
  await ctx.db.execute(
43117
43590
  `INSERT INTO ${t2(ctx, "caso")} (id, company_id, workflow, estado, referencia, titulo, datos, abierto_por_tipo, abierto_por_id, agente_id, issue_id, idempotency_key) VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb, $8, $9, $10, $11, $12)`,
43118
- [id, input2.companyId, wf.clave, wf.inicial, referencia, titulo, JSON.stringify(datos), input2.actor.tipo, input2.actor.id, input2.agenteId ?? null, input2.issueId ?? null, idem]
43591
+ [id2, input2.companyId, wf.clave, wf.inicial, referencia, titulo, JSON.stringify(datos), input2.actor.tipo, input2.actor.id, input2.agenteId ?? null, input2.issueId ?? null, idem]
43119
43592
  );
43120
43593
  const now = (/* @__PURE__ */ new Date()).toISOString();
43121
43594
  return {
43122
43595
  creado: true,
43123
43596
  caso: {
43124
- id,
43597
+ id: id2,
43125
43598
  companyId: input2.companyId,
43126
43599
  workflow: wf.clave,
43127
43600
  estado: wf.inicial,
@@ -43153,6 +43626,17 @@ async function contextoDe(ctx, companyId, caso, via, datos) {
43153
43626
  contexto.plazosPresentacion = leerPlazos((await obtenerOpciones(ctx, companyId, caso.workflow)).plazos);
43154
43627
  return contexto;
43155
43628
  }
43629
+ if (caso.workflow === "debito_profesional") {
43630
+ const op = await obtenerOpciones(ctx, companyId, caso.workflow);
43631
+ contexto.umbralAprobacion = typeof op.umbral_aprobacion === "number" && op.umbral_aprobacion > 0 ? op.umbral_aprobacion : 0;
43632
+ return contexto;
43633
+ }
43634
+ if (caso.workflow === "liquidacion_profesional") {
43635
+ const pid = str2(caso.datos.profesional_id);
43636
+ const contacto = pid ? (await ctx.db.query(`SELECT id, mail, activo FROM ${t2(ctx, "contacto")} WHERE company_id = $1 AND clave = $2 LIMIT 1`, [companyId, `profesional:${pid}`]))[0] : void 0;
43637
+ contexto.profesionalConCorreo = Boolean(contacto && contacto.activo !== false && contacto.mail || str2(datos.mail_his) || str2(caso.datos.mail_his));
43638
+ return contexto;
43639
+ }
43156
43640
  if (caso.workflow === "internacion_al_dia") {
43157
43641
  if (via === "observar" || via === "comprobar") {
43158
43642
  const op = await obtenerOpciones(ctx, companyId, caso.workflow);
@@ -43189,7 +43673,7 @@ async function contextoDe(ctx, companyId, caso, via, datos) {
43189
43673
  }
43190
43674
  if (caso.workflow === "demanda_pendiente") {
43191
43675
  const reglaId = str2(caso.datos.regla_id);
43192
- const regla = reglaId ? await leerRegla(ctx, companyId, reglaId) : null;
43676
+ const regla = reglaId ? await leerRegla2(ctx, companyId, reglaId) : null;
43193
43677
  contexto.regla = regla ? reglaParaContexto(regla) : null;
43194
43678
  const contactos = (await ctx.db.query(
43195
43679
  `SELECT caso_id, via, created_at FROM ${t2(ctx, "transicion")} WHERE company_id = $1 AND caso_id = $2 AND via = $3 ORDER BY created_at DESC LIMIT 50`,
@@ -43312,6 +43796,50 @@ async function transicionar(ctx, input2) {
43312
43796
  datos.verificada_el = contexto.hoy ?? null;
43313
43797
  }
43314
43798
  }
43799
+ if (caso.workflow === "honorario_en_cero") {
43800
+ for (const k of ["items", "resumen", "comprobado_el"]) delete datos[k];
43801
+ if (resultado.via === "observar" || resultado.via === "comprobar") {
43802
+ const l = leerPrestaciones(datos.prestaciones);
43803
+ if (!("error" in l)) {
43804
+ const e = prestacionesEnCero(l.prestaciones);
43805
+ datos.items = e.items;
43806
+ datos.resumen = e.resumen;
43807
+ datos.comprobado_el = `${contexto.hoy ?? ""} ${contexto.horaActual ?? ""}`.trim();
43808
+ }
43809
+ }
43810
+ delete datos.prestaciones;
43811
+ }
43812
+ if (caso.workflow === "debito_profesional") {
43813
+ for (const k of ["resumen", "faltan", "comprobado_el"]) delete datos[k];
43814
+ if (resultado.via === "proponer") {
43815
+ const l = leerDebitos(datos.items);
43816
+ if ("error" in l) delete datos.items;
43817
+ else {
43818
+ const items = l.debitos.map(evaluarDebito);
43819
+ datos.items = items;
43820
+ datos.resumen = resumenDebitos(items);
43821
+ }
43822
+ } else delete datos.items;
43823
+ if (resultado.via === "comprobar") {
43824
+ datos.faltan = faltaTrasladar(leerItemsDebito(caso.datos.items), datos.leidos).faltan;
43825
+ datos.comprobado_el = contexto.hoy ?? null;
43826
+ }
43827
+ delete datos.leidos;
43828
+ }
43829
+ if (caso.workflow === "liquidacion_profesional") {
43830
+ for (const k of ["resumen", "mensaje"]) delete datos[k];
43831
+ if (resultado.via === "preparar") {
43832
+ const l = leerLineasLiquidacion(datos.lineas);
43833
+ if ("error" in l) delete datos.lineas;
43834
+ else {
43835
+ const resumen = resumirLiquidacion(l.lineas);
43836
+ const profesional = leerProfesional({ id: caso.datos.profesional_id, nombre: caso.datos.profesional }) ?? { id: String(caso.datos.profesional_id ?? ""), nombre: str2(caso.datos.profesional) };
43837
+ datos.lineas = l.lineas;
43838
+ datos.resumen = resumen;
43839
+ datos.mensaje = redactarLiquidacion({ institucion: str2(caso.datos.institucion) ?? "La instituci\xF3n", profesional, fechaLiquidacion: str2(caso.datos.liquidado_el) ?? (contexto.hoy ?? ""), resumen });
43840
+ }
43841
+ } else delete datos.lineas;
43842
+ }
43315
43843
  if (caso.workflow === "internacion_al_dia") {
43316
43844
  for (const k of ["pendientes", "dias_sin_evolucion", "ultima_evolucion", "evoluciono_hoy", "egresada", "dias_internado", "comprobado_el", "ingreso", "egreso", "responsable", "servicio", "obra_social", "orden"]) delete datos[k];
43317
43845
  const r = contexto.internacion;
@@ -43397,8 +43925,8 @@ async function transicionar(ctx, input2) {
43397
43925
  }
43398
43926
  }
43399
43927
  if (caso.workflow === "facturacion_pendiente" && resultado.via === "observar") {
43400
- const fecha3 = String(datos.fecha_prestacion ?? caso.datos.fecha_prestacion ?? "");
43401
- Object.assign(datos, calcularVencimiento(fecha3, datos.obra_social ?? caso.datos.obra_social, contexto));
43928
+ const fecha4 = String(datos.fecha_prestacion ?? caso.datos.fecha_prestacion ?? "");
43929
+ Object.assign(datos, calcularVencimiento(fecha4, datos.obra_social ?? caso.datos.obra_social, contexto));
43402
43930
  }
43403
43931
  if (caso.workflow === "demanda_pendiente") {
43404
43932
  delete datos.intentos;
@@ -43489,7 +44017,7 @@ async function registrarAccion(ctx, input2) {
43489
44017
  const modo = await obtenerModo(ctx, input2.companyId, caso.workflow);
43490
44018
  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 HIS`);
43491
44019
  }
43492
- const id = randomUUID2();
44020
+ const id2 = randomUUID2();
43493
44021
  const evidencia = { ...input2.evidencia ?? {} };
43494
44022
  delete evidencia.fuera_de_flujo;
43495
44023
  if (caso.workflow === "recupero_turno" && input2.tipo === "escritura" && input2.actor.tipo === "agente" && caso.estado !== "asignando") {
@@ -43497,14 +44025,14 @@ async function registrarAccion(ctx, input2) {
43497
44025
  }
43498
44026
  await ctx.db.execute(
43499
44027
  `INSERT INTO ${t2(ctx, "accion")} (id, company_id, caso_id, tipo, conector, objetivo, resultado, evidencia, detalle, actor_tipo, actor_id, run_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9, $10, $11, $12)`,
43500
- [id, input2.companyId, caso.id, input2.tipo, input2.conector, objetivo, input2.resultado, JSON.stringify(evidencia), input2.detalle ?? null, input2.actor.tipo, input2.actor.id, input2.actor.runId ?? null]
44028
+ [id2, input2.companyId, caso.id, input2.tipo, input2.conector, objetivo, input2.resultado, JSON.stringify(evidencia), input2.detalle ?? null, input2.actor.tipo, input2.actor.id, input2.actor.runId ?? null]
43501
44029
  );
43502
44030
  await ctx.db.execute(
43503
44031
  `UPDATE ${t2(ctx, "caso")} SET updated_at = now() WHERE company_id = $1 AND id = $2`,
43504
44032
  [input2.companyId, caso.id]
43505
44033
  );
43506
44034
  return {
43507
- id,
44035
+ id: id2,
43508
44036
  casoId: caso.id,
43509
44037
  tipo: input2.tipo,
43510
44038
  conector: input2.conector,
@@ -43797,8 +44325,8 @@ async function serie(ctx, companyId, diasInput) {
43797
44325
  puntos.set(d, { dia: d, abiertos: 0, cerradosOk: 0, rechazados: 0, minutos: 0, acciones: 0 });
43798
44326
  }
43799
44327
  const descartado = { dia: "", abiertos: 0, cerradosOk: 0, rechazados: 0, minutos: 0, acciones: 0 };
43800
- const punto = (dia3) => {
43801
- const k = typeof dia3 === "string" ? dia3.slice(0, 10) : "";
44328
+ const punto = (dia4) => {
44329
+ const k = typeof dia4 === "string" ? dia4.slice(0, 10) : "";
43802
44330
  if (!/^\d{4}-\d{2}-\d{2}$/.test(k)) return descartado;
43803
44331
  if (!puntos.has(k)) puntos.set(k, { dia: k, abiertos: 0, cerradosOk: 0, rechazados: 0, minutos: 0, acciones: 0 });
43804
44332
  return puntos.get(k);
@@ -43854,6 +44382,27 @@ function errorParaAgente(err) {
43854
44382
  const message2 = err instanceof Error ? err.message : String(err);
43855
44383
  return { error: `error_interno: ${message2}`, data: { codigo: "error_interno" } };
43856
44384
  }
44385
+ async function registrarEnvioLiquidacion(ctx, input2) {
44386
+ const caso = await leerCaso(ctx, input2.companyId, input2.casoId);
44387
+ if (!caso) throw new OpsError("caso_inexistente", `no existe el caso ${input2.casoId} en esta instituci\xF3n`);
44388
+ if (caso.workflow !== "liquidacion_profesional") throw new OpsError("workflow_invalido", "solo las liquidaciones se env\xEDan al profesional");
44389
+ if (caso.estado !== "aprobado") throw new OpsError("estado_invalido", caso.estado === "enviada" ? "ya figura como enviada" : `la liquidaci\xF3n est\xE1 ${caso.estado}: se env\xEDa cuando la direcci\xF3n la aprueba`);
44390
+ if (input2.actor.tipo !== "humano") throw new OpsError("actor_no_permitido", "el env\xEDo lo registra una persona");
44391
+ const canal = canalReclamo(input2.canal);
44392
+ const destinatario = str2(input2.destinatario);
44393
+ const persona = str2(input2.persona);
44394
+ const accion = await registrarAccion(ctx, {
44395
+ companyId: input2.companyId,
44396
+ casoId: caso.id,
44397
+ tipo: "aviso",
44398
+ conector: canal === "correo" ? "mail" : "manual",
44399
+ objetivo: `Liquidaci\xF3n enviada a ${str2(caso.datos.profesional) ?? leerProfesional(caso.datos.profesional)?.nombre ?? "el profesional"}`,
44400
+ resultado: "ok",
44401
+ evidencia: { canal, ...destinatario ? { destinatario } : {}, ...persona ? { registrado_por: persona } : {} },
44402
+ actor: input2.actor
44403
+ });
44404
+ 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 });
44405
+ }
43857
44406
  function canalReclamo(v) {
43858
44407
  return typeof v === "string" && CANALES_RECLAMO.includes(v) ? v : "otro";
43859
44408
  }
@@ -43863,7 +44412,7 @@ import { randomUUID as randomUUID3 } from "node:crypto";
43863
44412
  function t3(ctx, table) {
43864
44413
  return `${ctx.db.namespace}.${table}`;
43865
44414
  }
43866
- function texto4(v) {
44415
+ function texto5(v) {
43867
44416
  return typeof v === "string" && v.trim().length > 0 ? v.trim() : typeof v === "number" ? String(v) : null;
43868
44417
  }
43869
44418
  function iso3(v) {
@@ -43871,7 +44420,7 @@ function iso3(v) {
43871
44420
  if (typeof v === "string" && v) return v;
43872
44421
  return null;
43873
44422
  }
43874
- function dia2(v) {
44423
+ function dia3(v) {
43875
44424
  if (v instanceof Date) return v.toISOString().slice(0, 10);
43876
44425
  return String(v ?? "").slice(0, 10);
43877
44426
  }
@@ -43892,13 +44441,16 @@ var ROLES = {
43892
44441
  aranceles: "Aranceles y convenios",
43893
44442
  facturacion: "Facturaci\xF3n",
43894
44443
  internacion: "Internaci\xF3n",
44444
+ honorarios: "Honorarios",
43895
44445
  personal: "Administraci\xF3n de personal"
43896
44446
  };
43897
44447
  var ESPERAN_PERSONA = {
43898
44448
  cuenta_completa: ["para_completar", "con_faltantes"],
43899
44449
  facturacion_pendiente: ["por_presentar"],
43900
44450
  credencial_profesional: ["observada"],
43901
- internacion_al_dia: ["con_pendientes"]
44451
+ internacion_al_dia: ["con_pendientes"],
44452
+ honorario_en_cero: ["para_cargar"],
44453
+ debito_profesional: ["aprobado", "con_diferencias"]
43902
44454
  };
43903
44455
  var CANALES_AVISO = ["mail", "whatsapp"];
43904
44456
  var HORARIO_AVISOS = { desde: "08:00", hasta: "18:00" };
@@ -43919,7 +44471,7 @@ function pendientesDe(caso, hoy) {
43919
44471
  const estados = ESPERAN_PERSONA[caso.workflow];
43920
44472
  if (!estados || !estados.includes(caso.estado)) return [];
43921
44473
  const d = caso.datos;
43922
- const bono = `Bono ${texto4(d.bono_numero) ?? texto4(d.bono_id) ?? "sin n\xFAmero"}${texto4(d.obra_social) ? ` \xB7 ${texto4(d.obra_social)}` : ""}`;
44474
+ const bono = `Bono ${texto5(d.bono_numero) ?? texto5(d.bono_id) ?? "sin n\xFAmero"}${texto5(d.obra_social) ? ` \xB7 ${texto5(d.obra_social)}` : ""}`;
43923
44475
  const base = { casoId: caso.id, workflow: caso.workflow, titulo: caso.titulo };
43924
44476
  if (caso.workflow === "cuenta_completa") {
43925
44477
  const out = [];
@@ -43927,7 +44479,7 @@ function pendientesDe(caso, hoy) {
43927
44479
  const nombreRegla = REGLAS_CUENTA[f.regla]?.nombre ?? f.regla;
43928
44480
  if (f.regla === "epicrisis_faltante") {
43929
44481
  const p = f.responsable?.tipo === "profesional" && f.responsable.id ? f.responsable : null;
43930
- const internacion = texto4(d.internacion_id) ? `Internaci\xF3n ${texto4(d.internacion_id)}` : bono;
44482
+ const internacion = texto5(d.internacion_id) ? `Internaci\xF3n ${texto5(d.internacion_id)}` : bono;
43931
44483
  out.push({
43932
44484
  ...base,
43933
44485
  que: `${internacion}: falta la epicrisis`,
@@ -43941,21 +44493,32 @@ function pendientesDe(caso, hoy) {
43941
44493
  }
43942
44494
  return out;
43943
44495
  }
44496
+ const profesionalH = texto5(d.profesional) ?? (d.profesional && typeof d.profesional === "object" ? texto5(d.profesional.nombre) : null);
44497
+ if (caso.workflow === "honorario_en_cero") {
44498
+ const r = d.resumen && typeof d.resumen === "object" ? d.resumen : {};
44499
+ const n = typeof r.prestaciones === "number" ? r.prestaciones : 0;
44500
+ return [{ ...base, que: `${profesionalH ?? "Un profesional"}: ${n === 1 ? "1 prestaci\xF3n se liquidar\xEDa" : `${n} prestaciones se liquidar\xEDan`} en $0 por falta de regla de honorario`, responsable: rol("honorarios") }];
44501
+ }
44502
+ if (caso.workflow === "debito_profesional") {
44503
+ const r = d.resumen && typeof d.resumen === "object" ? d.resumen : {};
44504
+ const total = typeof r.total === "number" ? r.total.toLocaleString("es-AR", { minimumFractionDigits: 2, maximumFractionDigits: 2 }) : "";
44505
+ return [{ ...base, que: `${profesionalH ?? "Un profesional"}: cargar un d\xE9bito de $ ${total} aprobado por la direcci\xF3n (nota de cr\xE9dito de ${texto5(d.obra_social) ?? "la obra social"})`, responsable: rol("honorarios") }];
44506
+ }
43944
44507
  if (caso.workflow === "internacion_al_dia") {
43945
- const internacion = `Internaci\xF3n ${texto4(d.internacion_id) ?? "sin n\xFAmero"}${texto4(d.servicio) ? ` (${texto4(d.servicio)})` : ""}`;
44508
+ const internacion = `Internaci\xF3n ${texto5(d.internacion_id) ?? "sin n\xFAmero"}${texto5(d.servicio) ? ` (${texto5(d.servicio)})` : ""}`;
43946
44509
  const resp = d.responsable && typeof d.responsable === "object" ? d.responsable : null;
43947
- const medicoId = resp ? texto4(resp.id) : null;
44510
+ const medicoId = resp ? texto5(resp.id) : null;
43948
44511
  const out = [];
43949
44512
  for (const p of Array.isArray(d.pendientes) ? d.pendientes : []) {
43950
- const regla = texto4(p.regla);
44513
+ const regla = texto5(p.regla);
43951
44514
  if (regla === "evolucion_de_hoy") {
43952
- const dia3 = texto4(p.dia);
43953
- if (!dia3 || hoy && dia3 !== hoy) continue;
44515
+ const dia4 = texto5(p.dia);
44516
+ if (!dia4 || hoy && dia4 !== hoy) continue;
43954
44517
  out.push({
43955
44518
  ...base,
43956
44519
  que: `${internacion}: todav\xEDa no tiene evoluci\xF3n hoy`,
43957
- responsable: medicoId ? { clave: `profesional:${medicoId}`, nombre: texto4(resp?.nombre) ?? `Profesional ${medicoId}`, reserva: "rol:internacion" } : rol("internacion"),
43958
- marca: `evolucion:${dia3}`
44520
+ responsable: medicoId ? { clave: `profesional:${medicoId}`, nombre: texto5(resp?.nombre) ?? `Profesional ${medicoId}`, reserva: "rol:internacion" } : rol("internacion"),
44521
+ marca: `evolucion:${dia4}`
43959
44522
  });
43960
44523
  } else if (regla === "alta_sin_registrar") {
43961
44524
  out.push({ ...base, que: `${internacion}: ${REGLAS_INTERNACION.alta_sin_registrar.nombre.toLowerCase()}`, responsable: rol("internacion") });
@@ -43966,23 +44529,23 @@ function pendientesDe(caso, hoy) {
43966
44529
  return out;
43967
44530
  }
43968
44531
  if (caso.workflow === "facturacion_pendiente") {
43969
- const vence = texto4(d.vence_el);
44532
+ const vence = texto5(d.vence_el);
43970
44533
  return [{ ...base, que: `${bono}: sin presentar${vence ? `, vence el ${vence.slice(8, 10)}/${vence.slice(5, 7)}` : ""}`, responsable: rol("facturacion") }];
43971
44534
  }
43972
44535
  if (caso.workflow === "credencial_profesional") {
43973
- const id = texto4(d.profesional_id);
43974
- const nombre = texto4(d.profesional) ?? (id ? `Profesional ${id}` : "Profesional");
43975
- const obs = texto4(d.observacion);
44536
+ const id2 = texto5(d.profesional_id);
44537
+ const nombre = texto5(d.profesional) ?? (id2 ? `Profesional ${id2}` : "Profesional");
44538
+ const obs = texto5(d.observacion);
43976
44539
  const que = `${nombre}: ${(obs && OBSERVACIONES_MATRICULA[obs]) ?? "la matr\xEDcula tiene una observaci\xF3n del registro nacional"}`;
43977
- return [{ ...base, que, responsable: id ? { clave: `profesional:${id}`, nombre, reserva: "rol:personal" } : rol("personal") }];
44540
+ return [{ ...base, que, responsable: id2 ? { clave: `profesional:${id2}`, nombre, reserva: "rol:personal" } : rol("personal") }];
43978
44541
  }
43979
44542
  return [];
43980
44543
  }
43981
- var CLAVE_RE = /^(profesional:[A-Za-z0-9_-]{1,40}|financiador:\d{1,12}|rol:(admision|aranceles|facturacion|internacion|personal))$/;
44544
+ var CLAVE_RE = /^(profesional:[A-Za-z0-9_-]{1,40}|financiador:\d{1,12}|rol:(admision|aranceles|facturacion|internacion|personal|honorarios))$/;
43982
44545
  var MAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
43983
44546
  var COLS_CONTACTO = "id, clave, nombre, mail, whatsapp, activo, updated_at";
43984
44547
  function mapContacto(r) {
43985
- return { id: String(r.id), clave: String(r.clave), nombre: String(r.nombre), mail: texto4(r.mail), whatsapp: texto4(r.whatsapp), activo: r.activo !== false, actualizadoEn: iso3(r.updated_at) };
44548
+ return { id: String(r.id), clave: String(r.clave), nombre: String(r.nombre), mail: texto5(r.mail), whatsapp: texto5(r.whatsapp), activo: r.activo !== false, actualizadoEn: iso3(r.updated_at) };
43986
44549
  }
43987
44550
  async function listarContactos(ctx, companyId) {
43988
44551
  const rows = await ctx.db.query(`SELECT ${COLS_CONTACTO} FROM ${t3(ctx, "contacto")} WHERE company_id = $1 ORDER BY nombre ASC`, [companyId]);
@@ -43996,15 +44559,15 @@ function leerWhatsapp(v) {
43996
44559
  }
43997
44560
  async function guardarContacto(ctx, input2) {
43998
44561
  if (input2.actor.tipo !== "humano") throw new OpsError("actor_no_permitido", "los contactos los carga una persona de la instituci\xF3n desde el portal");
43999
- const clave = texto4(input2.clave) ?? "";
44562
+ const clave = texto5(input2.clave) ?? "";
44000
44563
  if (!CLAVE_RE.test(clave)) throw new OpsError("validacion", "clave: tiene que ser profesional:<id>, financiador:<id> o rol:<admision|aranceles|facturacion|internacion|personal>");
44001
- const mail = texto4(input2.mail)?.toLowerCase() ?? null;
44564
+ const mail = texto5(input2.mail)?.toLowerCase() ?? null;
44002
44565
  if (mail && !MAIL_RE.test(mail)) throw new OpsError("validacion", "mail: no tiene formato de correo");
44003
44566
  const whatsapp = leerWhatsapp(input2.whatsapp);
44004
44567
  const activo = input2.activo !== false;
44005
44568
  if (activo && !mail && !whatsapp) throw new OpsError("validacion", "hace falta un mail o un WhatsApp para poder avisar");
44006
44569
  const existente = (await ctx.db.query(`SELECT ${COLS_CONTACTO} FROM ${t3(ctx, "contacto")} WHERE company_id = $1 AND clave = $2 LIMIT 1`, [input2.companyId, clave]))[0];
44007
- const nombre = texto4(input2.nombre)?.slice(0, 120) ?? (existente ? String(existente.nombre) : clave.startsWith("rol:") ? ROLES[clave.slice(4)] ?? clave : null);
44570
+ const nombre = texto5(input2.nombre)?.slice(0, 120) ?? (existente ? String(existente.nombre) : clave.startsWith("rol:") ? ROLES[clave.slice(4)] ?? clave : null);
44008
44571
  if (!nombre) throw new OpsError("validacion", "nombre: es obligatorio para un profesional nuevo");
44009
44572
  if (existente) {
44010
44573
  await ctx.db.execute(
@@ -44013,12 +44576,12 @@ async function guardarContacto(ctx, input2) {
44013
44576
  );
44014
44577
  return { id: String(existente.id), clave, nombre, mail, whatsapp, activo, actualizadoEn: (/* @__PURE__ */ new Date()).toISOString() };
44015
44578
  }
44016
- const id = randomUUID3();
44579
+ const id2 = randomUUID3();
44017
44580
  await ctx.db.execute(
44018
44581
  `INSERT INTO ${t3(ctx, "contacto")} (id, company_id, clave, nombre, mail, whatsapp, activo, actor_tipo, actor_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
44019
- [id, input2.companyId, clave, nombre, mail, whatsapp, activo, input2.actor.tipo, input2.actor.id]
44582
+ [id2, input2.companyId, clave, nombre, mail, whatsapp, activo, input2.actor.tipo, input2.actor.id]
44020
44583
  );
44021
- return { id, clave, nombre, mail, whatsapp, activo, actualizadoEn: (/* @__PURE__ */ new Date()).toISOString() };
44584
+ return { id: id2, clave, nombre, mail, whatsapp, activo, actualizadoEn: (/* @__PURE__ */ new Date()).toISOString() };
44022
44585
  }
44023
44586
  var COLS_AVISO = "id, clave, nombre, canal, destino, dia, casos, asunto, texto, estado, intentos_envio, error, proveedor_id, enviado_en, created_at";
44024
44587
  function mapAviso(r) {
@@ -44028,14 +44591,14 @@ function mapAviso(r) {
44028
44591
  nombre: String(r.nombre),
44029
44592
  canal: String(r.canal) === "whatsapp" ? "whatsapp" : "mail",
44030
44593
  destino: String(r.destino),
44031
- dia: dia2(r.dia),
44594
+ dia: dia3(r.dia),
44032
44595
  casos: lista(r.casos).map((c) => ({ casoId: String(c.casoId), workflow: String(c.workflow), que: String(c.que), intento: Number(c.intento) || 1, ...typeof c.marca === "string" ? { marca: c.marca } : {} })),
44033
44596
  asunto: String(r.asunto),
44034
44597
  texto: String(r.texto),
44035
44598
  estado: ["pendiente", "enviado", "fallido", "cancelado"].includes(String(r.estado)) ? String(r.estado) : "pendiente",
44036
44599
  intentosEnvio: Number(r.intentos_envio) || 0,
44037
- error: texto4(r.error),
44038
- proveedorId: texto4(r.proveedor_id),
44600
+ error: texto5(r.error),
44601
+ proveedorId: texto5(r.proveedor_id),
44039
44602
  enviadoEn: iso3(r.enviado_en),
44040
44603
  creadoEn: iso3(r.created_at)
44041
44604
  };
@@ -44079,7 +44642,7 @@ function redactarAviso(nombre, institucion, pendientes) {
44079
44642
  const repetidos = pendientes.filter((p) => p.intento > 1).length;
44080
44643
  const asunto = `${n === 1 ? "1 pendiente" : `${n} pendientes`} para resolver en el HIS \xB7 ${institucion}`;
44081
44644
  const lineas = pendientes.map((p) => `- ${p.que}${p.intento > 1 ? " (segundo aviso)" : ""}`);
44082
- const texto6 = [
44645
+ const texto7 = [
44083
44646
  `Hola ${nombre}:`,
44084
44647
  "",
44085
44648
  `Desde ${institucion}, Autopilot Opera te avisa que ${n === 1 ? "ten\xE9s 1 pendiente" : `ten\xE9s ${n} pendientes`} para resolver en el HIS:`,
@@ -44090,7 +44653,7 @@ function redactarAviso(nombre, institucion, pendientes) {
44090
44653
  "",
44091
44654
  "Autopilot Opera \xB7 avisos autom\xE1ticos de la administraci\xF3n"
44092
44655
  ].join("\n");
44093
- return { asunto, texto: texto6 };
44656
+ return { asunto, texto: texto7 };
44094
44657
  }
44095
44658
  async function generarAvisos(ctx, input2) {
44096
44659
  const { hoy, hora } = ahoraEnHospital(input2.ahora);
@@ -44148,12 +44711,12 @@ async function generarAvisos(ctx, input2) {
44148
44711
  const destino = canal === "mail" ? String(g.contacto.mail) : String(g.contacto.whatsapp);
44149
44712
  const { asunto, texto: cuerpo } = redactarAviso(g.contacto.nombre, input2.institucion, g.pendientes);
44150
44713
  const casos = g.pendientes.map(({ casoId, workflow, que, intento, marca }) => marca ? { casoId, workflow, que, intento, marca } : { casoId, workflow, que, intento });
44151
- const id = randomUUID3();
44714
+ const id2 = randomUUID3();
44152
44715
  await ctx.db.execute(
44153
44716
  `INSERT INTO ${t3(ctx, "aviso")} (id, company_id, clave, nombre, canal, destino, dia, casos, asunto, texto) VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9, $10)`,
44154
- [id, input2.companyId, g.contacto.clave, g.contacto.nombre, canal, destino, hoy, JSON.stringify(casos), asunto, cuerpo]
44717
+ [id2, input2.companyId, g.contacto.clave, g.contacto.nombre, canal, destino, hoy, JSON.stringify(casos), asunto, cuerpo]
44155
44718
  );
44156
- todos.push({ id, clave: g.contacto.clave, nombre: g.contacto.nombre, canal, destino, dia: hoy, casos, asunto, texto: cuerpo, estado: "pendiente", intentosEnvio: 0, error: null, proveedorId: null, enviadoEn: null, creadoEn: (/* @__PURE__ */ new Date()).toISOString() });
44719
+ todos.push({ id: id2, clave: g.contacto.clave, nombre: g.contacto.nombre, canal, destino, dia: hoy, casos, asunto, texto: cuerpo, estado: "pendiente", intentosEnvio: 0, error: null, proveedorId: null, enviadoEn: null, creadoEn: (/* @__PURE__ */ new Date()).toISOString() });
44157
44720
  generados += 1;
44158
44721
  }
44159
44722
  return { avisos: pendientesHoy(), generados, sinContacto, fueraDeHorario: false };
@@ -44167,7 +44730,7 @@ async function informarResultadoAviso(ctx, input2) {
44167
44730
  if (input2.resultado === "enviado") {
44168
44731
  await ctx.db.execute(
44169
44732
  `UPDATE ${t3(ctx, "aviso")} SET estado = $3, proveedor_id = $4, enviado_en = now(), intentos_envio = intentos_envio + 1, error = NULL, updated_at = now() WHERE company_id = $1 AND id = $2`,
44170
- [input2.companyId, aviso.id, "enviado", texto4(input2.proveedorId)]
44733
+ [input2.companyId, aviso.id, "enviado", texto5(input2.proveedorId)]
44171
44734
  );
44172
44735
  for (const c of aviso.casos) {
44173
44736
  await registrarAccion(ctx, {
@@ -44181,11 +44744,11 @@ async function informarResultadoAviso(ctx, input2) {
44181
44744
  actor
44182
44745
  });
44183
44746
  }
44184
- return { ...aviso, estado: "enviado", proveedorId: texto4(input2.proveedorId), enviadoEn: (/* @__PURE__ */ new Date()).toISOString(), intentosEnvio: aviso.intentosEnvio + 1, error: null };
44747
+ return { ...aviso, estado: "enviado", proveedorId: texto5(input2.proveedorId), enviadoEn: (/* @__PURE__ */ new Date()).toISOString(), intentosEnvio: aviso.intentosEnvio + 1, error: null };
44185
44748
  }
44186
44749
  const intentos = aviso.intentosEnvio + 1;
44187
44750
  const estado = intentos >= MAX_INTENTOS_ENVIO ? "fallido" : "pendiente";
44188
- const error62 = texto4(input2.error)?.slice(0, 300) ?? "no se pudo enviar";
44751
+ const error62 = texto5(input2.error)?.slice(0, 300) ?? "no se pudo enviar";
44189
44752
  await ctx.db.execute(
44190
44753
  `UPDATE ${t3(ctx, "aviso")} SET estado = $3, error = $4, intentos_envio = $5, updated_at = now() WHERE company_id = $1 AND id = $2`,
44191
44754
  [input2.companyId, aviso.id, estado, error62, intentos]
@@ -44233,8 +44796,8 @@ var METRICAS = [
44233
44796
  { id: "monto_pendiente_de_facturar", version: 1, estado: "validada", nombre: "Monto pendiente de facturar", unidad: "$", definicion: "Importe de los bonos pendientes de facturar del per\xEDodo, por fecha de la prestaci\xF3n." },
44234
44797
  { id: "debitos_financiador", version: 1, estado: "a_definir", nombre: "D\xE9bitos de financiadores", unidad: "$", definicion: "No se puede calcular desde Alephoo: una nota de cr\xE9dito puede responder a un d\xE9bito del financiador o a un error de facturaci\xF3n, y Alephoo no guarda cu\xE1l es (Federico Calle, 15/10/2026). Los tableros muestran \xABnotas de cr\xE9dito\xBB, que s\xED es certificada; este n\xFAmero no se publica como oficial." }
44235
44798
  ];
44236
- function metricaPorId(id) {
44237
- return METRICAS.find((m) => m.id === id) ?? null;
44799
+ function metricaPorId(id2) {
44800
+ return METRICAS.find((m) => m.id === id2) ?? null;
44238
44801
  }
44239
44802
 
44240
44803
  // src/tableros.ts
@@ -44262,7 +44825,7 @@ function arr(v) {
44262
44825
  }
44263
44826
  return [];
44264
44827
  }
44265
- function texto5(v, max, campo, problemas, obligatorio = false) {
44828
+ function texto6(v, max, campo, problemas, obligatorio = false) {
44266
44829
  if (v === void 0 || v === null || v === "") {
44267
44830
  if (obligatorio) problemas.push(`${campo} es obligatorio`);
44268
44831
  return void 0;
@@ -44312,17 +44875,17 @@ function leerCalculo(v, ref, problemas) {
44312
44875
  const metricas = [];
44313
44876
  lista2.slice(0, 12).forEach((m, j) => {
44314
44877
  const mo = m && typeof m === "object" ? m : {};
44315
- const id = typeof mo.id === "string" ? mo.id : "";
44878
+ const id2 = typeof mo.id === "string" ? mo.id : "";
44316
44879
  const version2 = Number(mo.version);
44317
- const def2 = metricaPorId(id);
44880
+ const def2 = metricaPorId(id2);
44318
44881
  if (!def2) {
44319
- problemas.push(`${ref}.calculo.metricas[${j}]: \xAB${id}\xBB no est\xE1 en el cat\xE1logo de m\xE9tricas; un n\xFAmero fuera del cat\xE1logo se publica sin calculo (queda como exploratorio)`);
44882
+ problemas.push(`${ref}.calculo.metricas[${j}]: \xAB${id2}\xBB no est\xE1 en el cat\xE1logo de m\xE9tricas; un n\xFAmero fuera del cat\xE1logo se publica sin calculo (queda como exploratorio)`);
44320
44883
  return;
44321
44884
  }
44322
- if (def2.version !== version2) problemas.push(`${ref}.calculo.metricas[${j}]: \xAB${id}\xBB versi\xF3n ${Number.isFinite(version2) ? version2 : "?"} no es la vigente (${def2.version}): recalcular con calcular.mjs`);
44323
- if (def2.estado === "a_definir") problemas.push(`${ref}.calculo.metricas[${j}]: \xAB${id}\xBB todav\xEDa no tiene definici\xF3n aprobada y no se publica como n\xFAmero oficial`);
44885
+ if (def2.version !== version2) problemas.push(`${ref}.calculo.metricas[${j}]: \xAB${id2}\xBB versi\xF3n ${Number.isFinite(version2) ? version2 : "?"} no es la vigente (${def2.version}): recalcular con calcular.mjs`);
44886
+ if (def2.estado === "a_definir") problemas.push(`${ref}.calculo.metricas[${j}]: \xAB${id2}\xBB todav\xEDa no tiene definici\xF3n aprobada y no se publica como n\xFAmero oficial`);
44324
44887
  if (def2.estado === "propuesta") propuesta = true;
44325
- metricas.push({ id, version: def2.version });
44888
+ metricas.push({ id: id2, version: def2.version });
44326
44889
  });
44327
44890
  const huella = typeof o.huella === "string" && /^[0-9a-f]{16}$/.test(o.huella) ? o.huella : "";
44328
44891
  if (!huella) problemas.push(`${ref}.calculo.huella falta o no tiene la forma de calcular.mjs (16 caracteres hexadecimales)`);
@@ -44373,24 +44936,24 @@ function validarWidgets(entrada) {
44373
44936
  const a = ancho(o.ancho);
44374
44937
  switch (tipo) {
44375
44938
  case "indicador": {
44376
- const etiqueta = texto5(o.etiqueta, 80, `${ref}.etiqueta`, problemas, true) ?? "";
44377
- const valor = typeof o.valor === "number" && Number.isFinite(o.valor) ? o.valor : texto5(o.valor, 40, `${ref}.valor`, problemas, true) ?? "";
44939
+ const etiqueta = texto6(o.etiqueta, 80, `${ref}.etiqueta`, problemas, true) ?? "";
44940
+ const valor = typeof o.valor === "number" && Number.isFinite(o.valor) ? o.valor : texto6(o.valor, 40, `${ref}.valor`, problemas, true) ?? "";
44378
44941
  const tono = typeof o.tono === "string" && TONOS.includes(o.tono) ? o.tono : void 0;
44379
44942
  if (o.tono !== void 0 && !tono) problemas.push(`${ref}.tono debe ser uno de ${TONOS.join(", ")}`);
44380
- const unidad = texto5(o.unidad, 16, `${ref}.unidad`, problemas);
44943
+ const unidad = texto6(o.unidad, 16, `${ref}.unidad`, problemas);
44381
44944
  if (unidad === "%" && !ES_VARIACION.test(etiqueta)) controlarPorcentaje(valor, `${ref}.valor`, problemas);
44382
44945
  const { calculo, origen } = leerCalculo(o.calculo, ref, problemas);
44383
- salida.push({ tipo, etiqueta, valor, unidad, contexto: texto5(o.contexto, 160, `${ref}.contexto`, problemas), tono, ancho: a, ...calculo ? { calculo } : {}, origen });
44946
+ salida.push({ tipo, etiqueta, valor, unidad, contexto: texto6(o.contexto, 160, `${ref}.contexto`, problemas), tono, ancho: a, ...calculo ? { calculo } : {}, origen });
44384
44947
  break;
44385
44948
  }
44386
44949
  case "barras": {
44387
- const titulo = texto5(o.titulo, 120, `${ref}.titulo`, problemas, true) ?? "";
44950
+ const titulo = texto6(o.titulo, 120, `${ref}.titulo`, problemas, true) ?? "";
44388
44951
  const series = arr(o.series);
44389
44952
  if (series.length === 0 || series.length > 40) problemas.push(`${ref}.series debe tener entre 1 y 40 barras`);
44390
- const unidad = texto5(o.unidad, 16, `${ref}.unidad`, problemas);
44953
+ const unidad = texto6(o.unidad, 16, `${ref}.unidad`, problemas);
44391
44954
  const barras = series.slice(0, 40).map((s, j) => {
44392
44955
  const so = s && typeof s === "object" ? s : {};
44393
- return { etiqueta: texto5(so.etiqueta, 60, `${ref}.series[${j}].etiqueta`, problemas, true) ?? "", valor: numero2(so.valor, `${ref}.series[${j}].valor`, problemas) };
44956
+ return { etiqueta: texto6(so.etiqueta, 60, `${ref}.series[${j}].etiqueta`, problemas, true) ?? "", valor: numero2(so.valor, `${ref}.series[${j}].valor`, problemas) };
44394
44957
  });
44395
44958
  if (unidad === "%" && !ES_VARIACION.test(titulo)) barras.forEach((b, j) => controlarPorcentaje(b.valor, `${ref}.series[${j}].valor`, problemas));
44396
44959
  const { calculo, origen } = leerCalculo(o.calculo, ref, problemas);
@@ -44398,13 +44961,13 @@ function validarWidgets(entrada) {
44398
44961
  break;
44399
44962
  }
44400
44963
  case "linea": {
44401
- const titulo = texto5(o.titulo, 120, `${ref}.titulo`, problemas, true) ?? "";
44964
+ const titulo = texto6(o.titulo, 120, `${ref}.titulo`, problemas, true) ?? "";
44402
44965
  const puntos = arr(o.puntos);
44403
44966
  if (puntos.length === 0 || puntos.length > 400) problemas.push(`${ref}.puntos debe tener entre 1 y 400 puntos`);
44404
- const unidad = texto5(o.unidad, 16, `${ref}.unidad`, problemas);
44967
+ const unidad = texto6(o.unidad, 16, `${ref}.unidad`, problemas);
44405
44968
  const serie2 = puntos.slice(0, 400).map((p, j) => {
44406
44969
  const po = p && typeof p === "object" ? p : {};
44407
- return { x: texto5(po.x, 40, `${ref}.puntos[${j}].x`, problemas, true) ?? "", y: numero2(po.y, `${ref}.puntos[${j}].y`, problemas) };
44970
+ return { x: texto6(po.x, 40, `${ref}.puntos[${j}].x`, problemas, true) ?? "", y: numero2(po.y, `${ref}.puntos[${j}].y`, problemas) };
44408
44971
  });
44409
44972
  if (unidad === "%" && !ES_VARIACION.test(titulo)) serie2.forEach((p, j) => controlarPorcentaje(p.y, `${ref}.puntos[${j}].y`, problemas));
44410
44973
  const { calculo, origen } = leerCalculo(o.calculo, ref, problemas);
@@ -44412,12 +44975,12 @@ function validarWidgets(entrada) {
44412
44975
  break;
44413
44976
  }
44414
44977
  case "tabla": {
44415
- const titulo = texto5(o.titulo, 120, `${ref}.titulo`, problemas, true) ?? "";
44978
+ const titulo = texto6(o.titulo, 120, `${ref}.titulo`, problemas, true) ?? "";
44416
44979
  const columnas = arr(o.columnas);
44417
44980
  if (columnas.length === 0 || columnas.length > 12) problemas.push(`${ref}.columnas debe tener entre 1 y 12 columnas`);
44418
44981
  const filas = arr(o.filas);
44419
44982
  if (filas.length > 200) problemas.push(`${ref}.filas admite hasta 200 filas`);
44420
- const cols = columnas.slice(0, 12).map((c, j) => texto5(c, 60, `${ref}.columnas[${j}]`, problemas, true) ?? "");
44983
+ const cols = columnas.slice(0, 12).map((c, j) => texto6(c, 60, `${ref}.columnas[${j}]`, problemas, true) ?? "");
44421
44984
  const celdasTabla = filas.slice(0, 200).map((f, j) => {
44422
44985
  const celdas = arr(f);
44423
44986
  if (celdas.length !== cols.length) problemas.push(`${ref}.filas[${j}] tiene ${celdas.length} celdas y la tabla ${cols.length} columnas`);
@@ -44433,7 +44996,7 @@ function validarWidgets(entrada) {
44433
44996
  break;
44434
44997
  }
44435
44998
  case "texto": {
44436
- salida.push({ tipo, titulo: texto5(o.titulo, 120, `${ref}.titulo`, problemas), texto: texto5(o.texto, 4e3, `${ref}.texto`, problemas, true) ?? "", ancho: a });
44999
+ salida.push({ tipo, titulo: texto6(o.titulo, 120, `${ref}.titulo`, problemas), texto: texto6(o.texto, 4e3, `${ref}.texto`, problemas, true) ?? "", ancho: a });
44437
45000
  break;
44438
45001
  }
44439
45002
  }
@@ -44492,15 +45055,15 @@ async function publicarTablero(ctx, input2) {
44492
45055
  tablero: { ...previo, titulo, descripcion: limpio(input2.descripcion, 600), pedido: limpio(input2.pedido, 1e3) ?? previo.pedido, periodo: limpio(input2.periodo, 80), fuentes, widgets, agenteId: input2.agenteId ?? previo.agenteId, issueId: input2.issueId ?? previo.issueId, publicadoPorTipo: input2.actor.tipo, publicadoPorId: input2.actor.id, versiones: previo.versiones + 1, updatedAt: now }
44493
45056
  };
44494
45057
  }
44495
- const id = randomUUID4();
45058
+ const id2 = randomUUID4();
44496
45059
  await ctx.db.execute(
44497
45060
  `INSERT INTO ${t4(ctx, "tablero")} (id, company_id, clave, titulo, descripcion, pedido, periodo, fuentes, widgets, agente_id, issue_id, publicado_por_tipo, publicado_por_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9::jsonb, $10, $11, $12, $13)`,
44498
- [id, input2.companyId, clave, titulo, limpio(input2.descripcion, 600), limpio(input2.pedido, 1e3), limpio(input2.periodo, 80), JSON.stringify(fuentes), JSON.stringify(widgets), input2.agenteId ?? null, input2.issueId ?? null, input2.actor.tipo, input2.actor.id]
45061
+ [id2, input2.companyId, clave, titulo, limpio(input2.descripcion, 600), limpio(input2.pedido, 1e3), limpio(input2.periodo, 80), JSON.stringify(fuentes), JSON.stringify(widgets), input2.agenteId ?? null, input2.issueId ?? null, input2.actor.tipo, input2.actor.id]
44499
45062
  );
44500
45063
  await ctx.activity.log({ companyId: input2.companyId, message: `Autopilot Care: tablero \xAB${titulo}\xBB publicado (${clave})`, metadata: { clave, widgets: widgets.length, agentId: input2.agenteId ?? null, issueId: input2.issueId ?? null } });
44501
45064
  return {
44502
45065
  creado: true,
44503
- tablero: { id, companyId: input2.companyId, clave, titulo, descripcion: limpio(input2.descripcion, 600), pedido: limpio(input2.pedido, 1e3), periodo: limpio(input2.periodo, 80), fuentes, widgets, agenteId: input2.agenteId ?? null, issueId: input2.issueId ?? null, publicadoPorTipo: input2.actor.tipo, publicadoPorId: input2.actor.id, versiones: 1, createdAt: now, updatedAt: now }
45066
+ tablero: { id: id2, companyId: input2.companyId, clave, titulo, descripcion: limpio(input2.descripcion, 600), pedido: limpio(input2.pedido, 1e3), periodo: limpio(input2.periodo, 80), fuentes, widgets, agenteId: input2.agenteId ?? null, issueId: input2.issueId ?? null, publicadoPorTipo: input2.actor.tipo, publicadoPorId: input2.actor.id, versiones: 1, createdAt: now, updatedAt: now }
44504
45067
  };
44505
45068
  }
44506
45069
 
@@ -44774,7 +45337,7 @@ async function manejarApi(ctx, input2) {
44774
45337
  return respuesta(200, await transicionar(ctx, { companyId, casoId: input2.params.casoId ?? "", via: "no_corresponde", motivo: motivoConPersona(str3(body.motivo)), datos: conPersona(obj(body.datos)), idempotencyKey: str3(body.idempotencyKey), actor }));
44775
45338
  }
44776
45339
  case "version":
44777
- return respuesta(200, { version: manifest_default.version, capacidades: ["carga-manual", "recupero-turnos", "ofrecer-primero", "cuenta-completa", "metricas-certificadas", "facturacion-pendiente", "credenciales", "demanda-pendiente", "reglas", "avisos", "circular-aranceles", "cobranzas", "internaciones"], workflows: listarWorkflows().map((w) => w.clave) });
45340
+ return respuesta(200, { version: manifest_default.version, capacidades: ["carga-manual", "recupero-turnos", "ofrecer-primero", "cuenta-completa", "metricas-certificadas", "facturacion-pendiente", "credenciales", "demanda-pendiente", "reglas", "avisos", "circular-aranceles", "cobranzas", "internaciones", "honorarios"], workflows: listarWorkflows().map((w) => w.clave) });
44778
45341
  case "politicas":
44779
45342
  return respuesta(200, { politicas: await listarPoliticas(ctx, companyId) });
44780
45343
  case "serie":
@@ -44810,6 +45373,10 @@ async function manejarApi(ctx, input2) {
44810
45373
  }
44811
45374
  case "contacto":
44812
45375
  return respuesta(200, await registrarContacto(ctx, { companyId, casoId: input2.params.casoId ?? "", canal: body.canal, respuesta: body.respuesta, comentario: str3(body.comentario), persona: decididoPor, idempotencyKey: str3(body.idempotencyKey), actor }));
45376
+ case "envio-liquidacion": {
45377
+ if (actor.tipo !== "humano") return respuesta(403, { error: "actor_no_permitido", motivo: "el env\xEDo lo registra una persona" });
45378
+ return respuesta(200, await registrarEnvioLiquidacion(ctx, { companyId, casoId: input2.params.casoId ?? "", canal: body.canal, destinatario: str3(body.destinatario), persona: decididoPor, actor }));
45379
+ }
44813
45380
  case "respuesta-financiador": {
44814
45381
  if (actor.tipo !== "humano") return respuesta(403, { error: "actor_no_permitido", motivo: "la respuesta del financiador la registra una persona" });
44815
45382
  if (str3(body.respuesta) === "cerrar") {