{"version":3,"sources":["../src/catalogs.ts","../src/testing.ts"],"names":[],"mappings":"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","file":"testing.cjs","sourcesContent":["/**\n * AFIP/ARCA WSFE catalogs — the canonical IDs you pass to `solicitarCAE` for\n * comprobante type, document type, IVA rate, concept, and currency.\n *\n * These are stable AFIP constants (some date back to RG 100/1998); they don't\n * change. Mirroring them here lets agents resolve a human-readable label\n * (e.g. \"Factura C\" or \"21%\") to its WSFE numeric code WITHOUT a network\n * round-trip to AFIP's `FEParamGetTipos*` endpoints.\n *\n * For the authoritative live list, use `getTiposCbte()`, `getTiposDoc()`,\n * `getTiposIva()`, `getTiposConcepto()` from `wsfe.ts` — they hit AFIP in\n * real time and pick up newly-added codes (e.g., FCE MiPyMEs 2018).\n */\n\n/**\n * Tipo de comprobante (CbteTipo). The first thing you pick when emitting:\n * what kind of fiscal document is this?\n *\n * The choice depends on (a) your tax condition as the issuer and (b) the\n * receiver's tax condition. Common matrix:\n *\n * | Issuer ↓ / Receiver →   | RI       | Mono     | Cons. Final | Exento | Exterior |\n * | ----------------------- | -------- | -------- | ----------- | ------ | -------- |\n * | Responsable Inscripto   | A (1)    | A (1)    | B (6)       | B (6)  | E (19)   |\n * | Monotributista          | C (11)   | C (11)   | C (11)      | C (11) | E (19)   |\n * | Exento                  | C (11)   | C (11)   | C (11)      | C (11) | E (19)   |\n *\n * For credit/debit notes, the rule is: same letter as the original invoice.\n *\n * Common pitfall: you can't issue Factura M unless AFIP has flagged your CUIT\n * as \"Sujeto No Categorizado\" — for normal flows ignore tipo 51.\n */\nexport const CbteTipo = {\n  FACTURA_A: 1,\n  NOTA_DEBITO_A: 2,\n  NOTA_CREDITO_A: 3,\n  RECIBO_A: 4,\n  NOTA_VENTA_AL_CONTADO_A: 5,\n  FACTURA_B: 6,\n  NOTA_DEBITO_B: 7,\n  NOTA_CREDITO_B: 8,\n  RECIBO_B: 9,\n  NOTA_VENTA_AL_CONTADO_B: 10,\n  FACTURA_C: 11,\n  NOTA_DEBITO_C: 12,\n  NOTA_CREDITO_C: 13,\n  RECIBO_C: 15,\n  FACTURA_M: 51,\n  NOTA_DEBITO_M: 52,\n  NOTA_CREDITO_M: 53,\n  RECIBO_M: 54,\n  // FCE MiPyMEs (Factura de Crédito Electrónica) — RG 4367/2018\n  FCE_FACTURA_A: 201,\n  FCE_NOTA_DEBITO_A: 202,\n  FCE_NOTA_CREDITO_A: 203,\n  FCE_FACTURA_B: 206,\n  FCE_NOTA_DEBITO_B: 207,\n  FCE_NOTA_CREDITO_B: 208,\n  FCE_FACTURA_C: 211,\n  FCE_NOTA_DEBITO_C: 212,\n  FCE_NOTA_CREDITO_C: 213,\n  // Comprobantes E (exportación)\n  FACTURA_E: 19,\n  NOTA_DEBITO_E: 20,\n  NOTA_CREDITO_E: 21,\n} as const;\n\nexport type CbteTipoCode = (typeof CbteTipo)[keyof typeof CbteTipo];\n\n/**\n * Tipo de documento (DocTipo) — what kind of identifier the receiver is\n * presenting. CUIT is the most common for B2B; DNI for consumer-facing flows.\n */\nexport const DocTipo = {\n  CUIT: 80,\n  CUIL: 86,\n  CDI: 87,\n  LE: 89,\n  LC: 90,\n  CI_EXTRANJERA: 91,\n  EN_TRAMITE: 92,\n  ACTA_NACIMIENTO: 93,\n  PASAPORTE: 94,\n  CI_BS_AS_RNP: 95,\n  DNI: 96,\n  /**\n   * Special \"no identification\" code for consumer-facing sales below the AFIP\n   * threshold (currently ~$417k as of 2026). Pair with `DocNro: 0`.\n   */\n  CONSUMIDOR_FINAL: 99,\n} as const;\n\nexport type DocTipoCode = (typeof DocTipo)[keyof typeof DocTipo];\n\n/**\n * Condición frente al IVA del receptor — MANDATORY in FECAESolicitar since\n * AFIP Resolución General 5616 (request rejected with observación 10246 if\n * absent). Codes from AFIP's `FEParamGetCondicionIvaReceptor` catalog. For\n * a Factura C (monotributista emisor) to a walk-in buyer use\n * `CONSUMIDOR_FINAL` (5) with `DocTipo.CONSUMIDOR_FINAL` + `DocNro 0`.\n */\nexport const CondicionIvaReceptor = {\n  RESPONSABLE_INSCRIPTO: 1,\n  SUJETO_EXENTO: 4,\n  CONSUMIDOR_FINAL: 5,\n  RESPONSABLE_MONOTRIBUTO: 6,\n  SUJETO_NO_CATEGORIZADO: 7,\n  PROVEEDOR_DEL_EXTERIOR: 8,\n  CLIENTE_DEL_EXTERIOR: 9,\n  IVA_LIBERADO_LEY_19640: 10,\n  MONOTRIBUTISTA_SOCIAL: 13,\n  IVA_NO_ALCANZADO: 15,\n  MONOTRIBUTO_TRABAJADOR_INDEPENDIENTE_PROMOVIDO: 16,\n} as const;\n\nexport type CondicionIvaReceptorCode =\n  (typeof CondicionIvaReceptor)[keyof typeof CondicionIvaReceptor];\n\n/**\n * Concepto del comprobante. Determines whether the `FchServDesde`,\n * `FchServHasta`, and `FchVtoPago` fields are required:\n *\n * - **Productos (1)**: dates not required.\n * - **Servicios (2)**: dates REQUIRED — represents the service period and\n *   the payment due date.\n * - **Productos y Servicios (3)**: dates required.\n *\n * For SaaS subscriptions, use `SERVICIOS` and pass the billing period.\n */\nexport const Concepto = {\n  PRODUCTOS: 1,\n  SERVICIOS: 2,\n  PRODUCTOS_Y_SERVICIOS: 3,\n} as const;\n\nexport type ConceptoCode = (typeof Concepto)[keyof typeof Concepto];\n\n/**\n * Alícuotas de IVA. The numeric code goes inside the `<Iva><AlicIva><Id>`\n * element of the request; the percentage is what your customer sees.\n *\n * For monotributistas (Factura C), do NOT include any `<Iva>` items — the\n * concept of IVA discrimination doesn't apply. `ImpIVA` must be 0.\n */\nexport const AlicuotaIva = {\n  CERO: { id: 3, percent: 0 },\n  DOS_CINCO: { id: 9, percent: 2.5 },\n  CINCO: { id: 8, percent: 5 },\n  DIEZ_CINCO: { id: 4, percent: 10.5 },\n  VEINTIUNO: { id: 5, percent: 21 },\n  VEINTISIETE: { id: 6, percent: 27 },\n} as const;\n\nexport type AlicuotaIvaCode =\n  (typeof AlicuotaIva)[keyof typeof AlicuotaIva][\"id\"];\n\n/**\n * Result code from a `solicitarCAE` call.\n *\n * - **A — Aprobado**: CAE issued. Persist `cae` + `caeFchVto`.\n * - **R — Rechazado**: errors returned. Inspect `observaciones` and `errors`.\n * - **P — Parcial**: at least one detail rejected (rare with `CantReg=1`).\n */\nexport type WsfeResultado = \"A\" | \"R\" | \"P\";\n\n/**\n * Currency code (MonId). PES = Pesos Argentinos, the default. Use other codes\n * for export invoices (Factura E) or multi-currency invoices.\n */\nexport const Moneda = {\n  PESOS: \"PES\",\n  DOLAR: \"DOL\",\n  EURO: \"060\",\n  REAL: \"012\",\n} as const;\n\nexport type MonedaCode = (typeof Moneda)[keyof typeof Moneda];\n\n/**\n * Human-readable label for a comprobante type code. Use to render UI or to\n * surface the result of `consultarUltimoAutorizado()` to end users.\n */\nexport function describeCbteTipo(code: number): string {\n  const map: Record<number, string> = {\n    1: \"Factura A\",\n    2: \"Nota de Débito A\",\n    3: \"Nota de Crédito A\",\n    4: \"Recibo A\",\n    5: \"Nota de Venta al Contado A\",\n    6: \"Factura B\",\n    7: \"Nota de Débito B\",\n    8: \"Nota de Crédito B\",\n    9: \"Recibo B\",\n    10: \"Nota de Venta al Contado B\",\n    11: \"Factura C\",\n    12: \"Nota de Débito C\",\n    13: \"Nota de Crédito C\",\n    15: \"Recibo C\",\n    19: \"Factura E (exportación)\",\n    20: \"Nota de Débito E\",\n    21: \"Nota de Crédito E\",\n    51: \"Factura M\",\n    52: \"Nota de Débito M\",\n    53: \"Nota de Crédito M\",\n    54: \"Recibo M\",\n    201: \"FCE Factura A\",\n    202: \"FCE Nota de Débito A\",\n    203: \"FCE Nota de Crédito A\",\n    206: \"FCE Factura B\",\n    207: \"FCE Nota de Débito B\",\n    208: \"FCE Nota de Crédito B\",\n    211: \"FCE Factura C\",\n    212: \"FCE Nota de Débito C\",\n    213: \"FCE Nota de Crédito C\",\n  };\n  return map[code] ?? `Comprobante tipo ${code}`;\n}\n","/**\n * `@ar-agents/facturacion/testing` — fixtures + mock WSFE client for tests.\n *\n * Mocks the AFIP/ARCA WSFE surface so cookbook recipes, agent loops, and\n * downstream apps can be tested without a real ARCA cert + WSAA token round-\n * trip.\n *\n * What you get:\n *\n *   - **`MockWsfeClient`** — public-method-compatible stand-in for `WsfeClient`.\n *     Pass it to `facturacionTools({ wsfe: mock as unknown as WsfeClient })`.\n *     Calls are recorded in `.calls` for assertion. Seed responses with\n *     `seedSolicitarCAE`, `seedUltimoAutorizado`, `seedConsultarComprobante`,\n *     `seedDummy`.\n *\n *   - **Factories** for the result shapes:\n *     `mockSolicitarCaeApproved`, `mockSolicitarCaeRejected`,\n *     `mockUltimoComprobante`, `mockConsultarComprobante`,\n *     `mockDummyOk`, `mockDummyDown`.\n *\n * The `validator.ts` tests don't need this — that module is pure.\n */\n\nimport { CbteTipo, type CbteTipoCode, DocTipo, type DocTipoCode } from \"./catalogs\";\nimport type {\n  ConsultarComprobanteResult,\n  DummyResult,\n  SolicitarCaeInput,\n  SolicitarCaeResult,\n  UltimoComprobanteResult,\n} from \"./types\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst todayYmd = (): string => {\n  const d = new Date();\n  const y = d.getFullYear();\n  const m = String(d.getMonth() + 1).padStart(2, \"0\");\n  const day = String(d.getDate()).padStart(2, \"0\");\n  return `${y}${m}${day}`;\n};\n\nconst plusDaysYmd = (days: number): string => {\n  const d = new Date();\n  d.setDate(d.getDate() + days);\n  const y = d.getFullYear();\n  const m = String(d.getMonth() + 1).padStart(2, \"0\");\n  const day = String(d.getDate()).padStart(2, \"0\");\n  return `${y}${m}${day}`;\n};\n\nconst synthCae = (cbteNro: number): string => {\n  // 14 digits — first two YY, next 10 padded cbteNro, last 2 random-ish\n  const yy = String(new Date().getFullYear()).slice(2);\n  const nroPad = String(cbteNro).padStart(10, \"0\");\n  const tail = String((cbteNro * 7) % 100).padStart(2, \"0\");\n  return `${yy}${nroPad}${tail}`;\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Factories\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Approved factura — CAE issued, no observaciones, no errors.\n *\n * Defaults to a Factura B (1 unit, $100k, 21% IVA) but the caller can override\n * any field. Useful for happy-path agent-loop tests.\n */\nexport function mockSolicitarCaeApproved(\n  overrides: Partial<SolicitarCaeResult> = {},\n): SolicitarCaeResult {\n  const cbteDesde = overrides.cbteDesde ?? 1;\n  const cbteHasta = overrides.cbteHasta ?? cbteDesde;\n  return {\n    resultado: \"A\",\n    cae: synthCae(cbteDesde),\n    caeFchVto: plusDaysYmd(10),\n    ptoVta: overrides.ptoVta ?? 1,\n    cbteTipo: overrides.cbteTipo ?? CbteTipo.FACTURA_B,\n    cbteDesde,\n    cbteHasta,\n    cbteFch: overrides.cbteFch ?? todayYmd(),\n    fchProceso: overrides.fchProceso ?? todayYmd(),\n    observaciones: overrides.observaciones ?? [],\n    errors: overrides.errors ?? [],\n    eventos: overrides.eventos ?? [],\n  };\n}\n\n/**\n * Rejected factura — no CAE, with `errors` populated. Default error code 10015\n * is \"Factura B con receptor que no es Consumidor Final\" — a common rejection\n * the validator catches but tests need to simulate the AFIP-side path too.\n */\nexport function mockSolicitarCaeRejected(\n  args: {\n    code?: number;\n    msg?: string;\n    ptoVta?: number;\n    cbteTipo?: CbteTipoCode;\n    cbteDesde?: number;\n  } = {},\n): SolicitarCaeResult {\n  const cbteDesde = args.cbteDesde ?? 1;\n  return {\n    resultado: \"R\",\n    cae: null,\n    caeFchVto: null,\n    ptoVta: args.ptoVta ?? 1,\n    cbteTipo: args.cbteTipo ?? CbteTipo.FACTURA_B,\n    cbteDesde,\n    cbteHasta: cbteDesde,\n    cbteFch: todayYmd(),\n    fchProceso: todayYmd(),\n    observaciones: [],\n    errors: [\n      {\n        code: args.code ?? 10015,\n        msg:\n          args.msg ??\n          \"El receptor de una Factura B debe ser Consumidor Final.\",\n      },\n    ],\n    eventos: [],\n  };\n}\n\n/** Last authorized comprobante — defaults to \"no comprobante yet\" (cbteNro 0). */\nexport function mockUltimoComprobante(\n  ptoVta = 1,\n  cbteTipo: CbteTipoCode = CbteTipo.FACTURA_B,\n  cbteNro = 0,\n): UltimoComprobanteResult {\n  return { ptoVta, cbteTipo, cbteNro };\n}\n\n/** Echo of an authorized comprobante. */\nexport function mockConsultarComprobante(\n  args: {\n    found?: boolean;\n    ptoVta?: number;\n    cbteTipo?: CbteTipoCode;\n    cbteNro?: number;\n    docTipo?: DocTipoCode;\n    docNro?: string;\n    impTotal?: number;\n    impNeto?: number;\n    impIVA?: number;\n  } = {},\n): ConsultarComprobanteResult {\n  const cbteNro = args.cbteNro ?? 1;\n  const ptoVta = args.ptoVta ?? 1;\n  return {\n    found: args.found ?? true,\n    ptoVta,\n    cbteTipo: args.cbteTipo ?? CbteTipo.FACTURA_B,\n    cbteDesde: cbteNro,\n    cbteHasta: cbteNro,\n    cbteFch: todayYmd(),\n    cae: synthCae(cbteNro),\n    caeFchVto: plusDaysYmd(10),\n    resultado: \"A\",\n    emisionTipo: \"CAE\",\n    docTipo: args.docTipo ?? DocTipo.CUIT,\n    docNro: args.docNro ?? \"30000000007\",\n    impTotal: args.impTotal ?? 121_000,\n    impNeto: args.impNeto ?? 100_000,\n    impIVA: args.impIVA ?? 21_000,\n    observaciones: [],\n  };\n}\n\n/** AFIP servers all healthy. */\nexport function mockDummyOk(): DummyResult {\n  return { appServer: \"OK\", dbServer: \"OK\", authServer: \"OK\" };\n}\n\n/** AFIP DB server down — simulates planned-maintenance window. */\nexport function mockDummyDown(\n  which: \"appServer\" | \"dbServer\" | \"authServer\" = \"dbServer\",\n): DummyResult {\n  const base: DummyResult = { appServer: \"OK\", dbServer: \"OK\", authServer: \"OK\" };\n  base[which] = \"DOWN\";\n  return base;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// MockWsfeClient\n// ─────────────────────────────────────────────────────────────────────────────\n\ntype CallLogEntry =\n  | { method: \"dummy\" }\n  | { method: \"consultarUltimoAutorizado\"; ptoVta: number; cbteTipo: CbteTipoCode }\n  | { method: \"consultarComprobante\"; ptoVta: number; cbteTipo: CbteTipoCode; cbteNro: number }\n  | { method: \"solicitarCAE\"; input: SolicitarCaeInput }\n  | { method: \"getTiposCbte\" | \"getTiposDoc\" | \"getTiposIva\" | \"getTiposConcepto\" | \"getTiposMonedas\" }\n  | { method: \"getCotizacion\"; monId: string };\n\n/**\n * Stand-in for `WsfeClient`. Public-method compatible — pass to\n * `facturacionTools()` with a single cast:\n *\n * ```ts\n * import { MockWsfeClient, mockSolicitarCaeApproved } from \"@ar-agents/facturacion/testing\";\n * import type { WsfeClient } from \"@ar-agents/facturacion\";\n * import { facturacionTools } from \"@ar-agents/facturacion\";\n *\n * const mock = new MockWsfeClient()\n *   .seedSolicitarCAE(mockSolicitarCaeApproved({ cbteDesde: 42 }));\n *\n * const tools = facturacionTools({ wsfe: mock as unknown as WsfeClient });\n * ```\n */\nexport class MockWsfeClient {\n  private solicitarCaeQueue: SolicitarCaeResult[] = [];\n  private ultimoByKey = new Map<string, UltimoComprobanteResult>();\n  private consultarByKey = new Map<string, ConsultarComprobanteResult>();\n  private dummyResult: DummyResult = mockDummyOk();\n  private cotizacionByMonId = new Map<string, { monId: string; monCotiz: number; fchCotiz: string }>();\n  private tiposCbte: Array<{ id: number; desc: string }> = [];\n  private tiposDoc: Array<{ id: number; desc: string }> = [];\n  private tiposIva: Array<{ id: number; desc: string }> = [];\n  private tiposConcepto: Array<{ id: number; desc: string }> = [];\n  private tiposMonedas: Array<{ id: string; desc: string }> = [];\n\n  /** Append-only call log for assertions. */\n  readonly calls: CallLogEntry[] = [];\n\n  /** Queue a solicitarCAE response. Pops FIFO; falls back to a synthesized approval. */\n  seedSolicitarCAE(result: SolicitarCaeResult): this {\n    this.solicitarCaeQueue.push(result);\n    return this;\n  }\n\n  seedSolicitarCAEMany(results: SolicitarCaeResult[]): this {\n    this.solicitarCaeQueue.push(...results);\n    return this;\n  }\n\n  /** Seed the \"last authorized\" lookup for a (ptoVta, cbteTipo) pair. */\n  seedUltimoAutorizado(\n    ptoVta: number,\n    cbteTipo: CbteTipoCode,\n    cbteNro: number,\n  ): this {\n    this.ultimoByKey.set(`${ptoVta}|${cbteTipo}`, { ptoVta, cbteTipo, cbteNro });\n    return this;\n  }\n\n  /** Seed a \"consultar comprobante\" echo. */\n  seedConsultarComprobante(\n    ptoVta: number,\n    cbteTipo: CbteTipoCode,\n    cbteNro: number,\n    result: ConsultarComprobanteResult,\n  ): this {\n    this.consultarByKey.set(`${ptoVta}|${cbteTipo}|${cbteNro}`, result);\n    return this;\n  }\n\n  /** Set the dummy() health-check response. Defaults to all-OK. */\n  seedDummy(result: DummyResult): this {\n    this.dummyResult = result;\n    return this;\n  }\n\n  /** Seed a foreign-currency cotización. */\n  seedCotizacion(monId: string, monCotiz: number): this {\n    this.cotizacionByMonId.set(monId, {\n      monId,\n      monCotiz,\n      fchCotiz: todayYmd(),\n    });\n    return this;\n  }\n\n  /** Provide a custom catalog (defaults to empty array). */\n  setTiposCbte(items: Array<{ id: number; desc: string }>): this {\n    this.tiposCbte = items;\n    return this;\n  }\n  setTiposDoc(items: Array<{ id: number; desc: string }>): this {\n    this.tiposDoc = items;\n    return this;\n  }\n  setTiposIva(items: Array<{ id: number; desc: string }>): this {\n    this.tiposIva = items;\n    return this;\n  }\n  setTiposConcepto(items: Array<{ id: number; desc: string }>): this {\n    this.tiposConcepto = items;\n    return this;\n  }\n  setTiposMonedas(items: Array<{ id: string; desc: string }>): this {\n    this.tiposMonedas = items;\n    return this;\n  }\n\n  /** Clear `.calls` (does NOT clear seeded data). */\n  reset(): this {\n    this.calls.length = 0;\n    return this;\n  }\n\n  /** Clear everything — seeded data + call log. */\n  clear(): this {\n    this.solicitarCaeQueue.length = 0;\n    this.ultimoByKey.clear();\n    this.consultarByKey.clear();\n    this.cotizacionByMonId.clear();\n    this.tiposCbte = [];\n    this.tiposDoc = [];\n    this.tiposIva = [];\n    this.tiposConcepto = [];\n    this.tiposMonedas = [];\n    this.dummyResult = mockDummyOk();\n    this.calls.length = 0;\n    return this;\n  }\n\n  // ── Public WSFE surface ───────────────────────────────────────────────────\n\n  async dummy(): Promise<DummyResult> {\n    this.calls.push({ method: \"dummy\" });\n    return this.dummyResult;\n  }\n\n  async consultarUltimoAutorizado(\n    ptoVta: number,\n    cbteTipo: CbteTipoCode,\n  ): Promise<UltimoComprobanteResult> {\n    this.calls.push({ method: \"consultarUltimoAutorizado\", ptoVta, cbteTipo });\n    return (\n      this.ultimoByKey.get(`${ptoVta}|${cbteTipo}`) ??\n      mockUltimoComprobante(ptoVta, cbteTipo, 0)\n    );\n  }\n\n  async consultarComprobante(\n    ptoVta: number,\n    cbteTipo: CbteTipoCode,\n    cbteNro: number,\n  ): Promise<ConsultarComprobanteResult> {\n    this.calls.push({\n      method: \"consultarComprobante\",\n      ptoVta,\n      cbteTipo,\n      cbteNro,\n    });\n    return (\n      this.consultarByKey.get(`${ptoVta}|${cbteTipo}|${cbteNro}`) ?? {\n        ...mockConsultarComprobante({ ptoVta, cbteTipo, cbteNro }),\n        found: false,\n      }\n    );\n  }\n\n  async solicitarCAE(input: SolicitarCaeInput): Promise<SolicitarCaeResult> {\n    this.calls.push({ method: \"solicitarCAE\", input });\n    const next = this.solicitarCaeQueue.shift();\n    if (next) return next;\n    // Fallback: synthesize an approval that echoes the input.\n    return mockSolicitarCaeApproved({\n      ptoVta: input.ptoVta,\n      cbteTipo: input.cbteTipo,\n      cbteDesde: input.cbteDesde,\n      cbteHasta: input.cbteHasta,\n      cbteFch: input.cbteFch,\n    });\n  }\n\n  async getTiposCbte() {\n    this.calls.push({ method: \"getTiposCbte\" });\n    return this.tiposCbte;\n  }\n  async getTiposDoc() {\n    this.calls.push({ method: \"getTiposDoc\" });\n    return this.tiposDoc;\n  }\n  async getTiposIva() {\n    this.calls.push({ method: \"getTiposIva\" });\n    return this.tiposIva;\n  }\n  async getTiposConcepto() {\n    this.calls.push({ method: \"getTiposConcepto\" });\n    return this.tiposConcepto;\n  }\n  async getTiposMonedas() {\n    this.calls.push({ method: \"getTiposMonedas\" });\n    return this.tiposMonedas;\n  }\n\n  async getCotizacion(monId: string) {\n    this.calls.push({ method: \"getCotizacion\", monId });\n    return (\n      this.cotizacionByMonId.get(monId) ?? {\n        monId,\n        monCotiz: 1,\n        fchCotiz: todayYmd(),\n      }\n    );\n  }\n}\n"]}