@fuego-systems/core 0.1.15 → 0.1.17

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.
@@ -1 +1 @@
1
- {"version":3,"file":"plan-definition-group.js","sourceRoot":"","sources":["../src/plan-definition-group.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Duration, PlanDefinition, PlanDefinitionAction } from '@medplum/fhirtypes'\nimport { PD_HEALTHCARE_SERVICE_EXTENSION_URL, PD_TYPE_PROTOCOL_GROUP, PD_TYPE_SYSTEM, SERVICE_TYPE_SYSTEM } from './constants'\n\n/**\n * `action.id` of the per-variant group that overrides the order-set PD's\n * default mandatory add-ons (the tipo-3 `getMandatoryAddonIds` path). It lives\n * as a direct child of a protocol-group variant action, kept structurally\n * separate from the variant's own add-on sub-actions (the tipo-2\n * `resolveProtocolSelection` path) so the two never conflate. Its group node\n * carries no `definitionCanonical`, so `resolveProtocolSelection`,\n * `getProtocolActions` and friends skip it and never descend into it.\n */\nexport const MANDATORY_ADDON_OVERRIDE_ACTION_ID = 'mandatory-addons'\n\n/**\n * FHIR-standard ActionType code system. Each override sub-action carries a\n * `type.coding` from this system: `create` = add the add-on to the variant's\n * mandatory set, `remove` = drop a PD-default mandatory add-on. `requiredBehavior`\n * is not used for this because FHIR's value set has no \"exclude\" member.\n */\nconst ACTION_TYPE_SYSTEM = 'http://terminology.hl7.org/CodeSystem/action-type'\nconst ACTION_TYPE_ADD = 'create'\nconst ACTION_TYPE_REMOVE = 'remove'\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/**\n * How a variant alters one order-set default mandatory add-on:\n * - `'add'` forces the add-on mandatory for this variant even if the order-set\n * PD marks it optional (or does not list it as mandatory).\n * - `'remove'` drops an add-on that the order-set PD marks mandatory by default.\n */\nexport type MandatoryAddonOverrideAction = 'add' | 'remove'\n\n/**\n * A single per-variant override of the order-set's default mandatory add-on set\n * (the tipo-3 path). Referenced by the add-on's `ActivityDefinition` canonical\n * (`${EGES_PRACTICA_SYSTEM}/{pra_id}`) — the same canonical the order-set PD\n * uses — so add/remove resolve by exact canonical match against the defaults.\n */\nexport interface MandatoryAddonOverride {\n /** Add-on `ActivityDefinition` canonical, e.g. `${EGES_PRACTICA_SYSTEM}/{pra_id}`. */\n readonly ref: string\n /** Whether the variant adds or removes this add-on relative to the PD default. */\n readonly action: MandatoryAddonOverrideAction\n /** Optional human label, for the admin editor. */\n readonly display?: string\n}\n\n/** Information about a single action inside a protocol-group PD. */\nexport interface ProtocolActionInfo {\n readonly actionId: string\n readonly isDefault: boolean\n /** Short label for the variant (e.g. \"Helicoidal\") */\n readonly label: string\n /** User-facing question to select this variant */\n readonly question: string\n readonly protocolRef: string\n readonly protocolDisplay: string\n readonly protocolCode: string\n readonly duration?: Duration\n /**\n * Whether this action is pre-selected in a **configured** protocol-group.\n * Set by {@link configureProtocolGroup} via FHIR `precheckBehavior`.\n * `undefined` means the PD has not been configured (use `isDefault` as fallback).\n */\n readonly prechecked?: boolean\n /**\n * Only meaningful on addon (sub-action) entries. When `true`, the addon is\n * always included whenever its parent action is selected — it is not shown\n * as a togglable option in the consumer UI. Encoded in FHIR as\n * `PlanDefinitionAction.requiredBehavior === 'must'`.\n */\n readonly mandatory?: boolean\n /** Optional sub-actions (addons) with `any` selection behavior. */\n readonly addons: readonly ProtocolActionInfo[]\n /**\n * Per-variant overrides of the order-set's default mandatory add-on set\n * (tipo-3 path). Empty when the variant inherits the PD defaults unchanged.\n * Only meaningful on top-level variant entries.\n */\n readonly mandatoryAddonOverrides: readonly MandatoryAddonOverride[]\n}\n\n/** Entry used to build a protocol-group PD action. */\nexport interface ProtocolGroupActionEntry {\n readonly id: string\n readonly isDefault: boolean\n readonly label: string\n readonly question: string\n readonly ref: string\n readonly display: string\n readonly code: string\n readonly duration?: Duration\n /**\n * Only meaningful on addon entries. When `true`, the addon is always\n * included with the parent action and is hidden from the consumer UI.\n */\n readonly mandatory?: boolean\n /** Optional sub-action entries (addons). */\n readonly addons?: readonly ProtocolGroupActionEntry[]\n /**\n * Per-variant overrides of the order-set's default mandatory add-on set\n * (tipo-3 path). Only meaningful on top-level variant entries; ignored on\n * addon entries.\n */\n readonly mandatoryAddonOverrides?: readonly MandatoryAddonOverride[]\n}\n\n// ─── Backward-compat aliases ────────────────────────────────────────────────\n\n/** @deprecated Use {@link ProtocolActionInfo} instead. */\nexport type ProtocolVariantInfo = ProtocolActionInfo\n\n/** @deprecated Use {@link ProtocolActionInfo} instead. */\nexport interface ProtocolDefaultInfo {\n readonly ref: string\n readonly display: string\n readonly code: string\n readonly duration?: Duration\n}\n\n// ─── Detection ───────────────────────────────────────────────────────────────\n\n/**\n * Returns `true` if the PlanDefinition is a protocol-group (wrapping multiple concrete PDs).\n *\n * @param pd - the PlanDefinition to check\n * @returns whether the PlanDefinition is a protocol-group\n */\nexport function isProtocolGroup (pd: PlanDefinition): boolean {\n return (pd.type?.coding ?? []).some(\n (c) => c.system === PD_TYPE_SYSTEM && c.code === PD_TYPE_PROTOCOL_GROUP\n )\n}\n\n// ─── Extraction ──────────────────────────────────────────────────────────────\n\n/**\n * Extracts all protocol actions from a protocol-group PD (preserving order).\n *\n * @param pd - the protocol-group PlanDefinition\n * @returns array of action info objects (the one with `isDefault === true` is the default)\n */\nexport function getProtocolActions (pd: PlanDefinition): ProtocolActionInfo[] {\n return (pd.action ?? [])\n .filter((a): a is PlanDefinitionAction & { definitionCanonical: string } =>\n Boolean(a.definitionCanonical)\n )\n .map((a) => extractActionInfo(a, a.id === 'default'))\n}\n\n/**\n * Extracts the default protocol action from a protocol-group PD.\n *\n * @param pd - the protocol-group PlanDefinition\n * @returns the default protocol info, or undefined if not found\n */\nexport function getDefaultProtocol (pd: PlanDefinition): ProtocolDefaultInfo | undefined {\n const action = (pd.action ?? []).find((a) => a.id === 'default')\n if (!action?.definitionCanonical) { return undefined }\n return {\n ref: action.definitionCanonical,\n display: action.title ?? '',\n code: getActionServiceCode(action),\n duration: action.timingDuration\n }\n}\n\n/**\n * Extracts the non-default variant actions from a protocol-group PD.\n *\n * @param pd - the protocol-group PlanDefinition\n * @returns array of variant info objects\n */\nexport function getProtocolVariants (pd: PlanDefinition): ProtocolActionInfo[] {\n return getProtocolActions(pd).filter((a) => !a.isDefault)\n}\n\n/**\n * Extracts the HealthcareService reference linked to a protocol-group PD.\n *\n * @param pd - the PlanDefinition to inspect\n * @returns the referenced HealthcareService, if present\n */\nexport function getProtocolGroupHealthcareServiceReference (pd: PlanDefinition): string | undefined {\n return pd.extension?.find((e) => e.url === PD_HEALTHCARE_SERVICE_EXTENSION_URL)?.valueReference?.reference\n}\n\n// ─── Construction ────────────────────────────────────────────────────────────\n\n/**\n * Builds a protocol-group PlanDefinition resource.\n *\n * @param title - human-readable title for the group (e.g. \"TAC de hombro — Protocolos\")\n * @param entries - protocol action entries (at least one should have `isDefault: true`)\n * @param existingId - optional ID to reuse when updating an existing group PD\n * @param hsReference - optional HealthcareService reference stored on the group PD\n * @returns the constructed protocol-group PlanDefinition\n */\nexport function buildProtocolGroup (\n title: string,\n entries: readonly ProtocolGroupActionEntry[],\n existingId?: string,\n hsReference?: string\n): PlanDefinition {\n const actions: PlanDefinitionAction[] = entries.map((e) => {\n const subActions = (e.addons ?? []).map((addon) =>\n buildAction(\n addon.id,\n addon.display,\n addon.ref,\n addon.code,\n addon.duration,\n addon.question,\n addon.label,\n addon.mandatory\n )\n )\n\n const action = buildAction(\n e.isDefault ? 'default' : e.id,\n e.display,\n e.ref,\n e.code,\n e.duration,\n e.question,\n e.label\n )\n\n // Top-level actions use exactly-one selection behavior\n action.selectionBehavior = 'exactly-one'\n\n const overrideGroup = buildMandatoryAddonOverrideGroup(e.mandatoryAddonOverrides)\n const childActions = overrideGroup ? [...subActions, overrideGroup] : subActions\n\n if (childActions.length > 0) {\n action.action = childActions\n // When an action has sub-actions (addons), they use `any` grouping\n action.groupingBehavior = 'logical-group'\n }\n\n return action\n })\n\n const pd: PlanDefinition = {\n resourceType: 'PlanDefinition',\n status: 'active',\n title,\n type: {\n coding: [{ system: PD_TYPE_SYSTEM, code: PD_TYPE_PROTOCOL_GROUP }]\n },\n action: actions\n }\n\n if (hsReference) {\n pd.extension = [\n {\n url: PD_HEALTHCARE_SERVICE_EXTENSION_URL,\n valueReference: { reference: hsReference }\n }\n ]\n }\n\n if (existingId) {\n pd.id = existingId\n }\n\n return pd\n}\n\n// ─── Selection / Configuration ──────────────────────────────────────────────\n\n/**\n * A user's selection within a protocol-group PlanDefinition.\n *\n * Represents the patient's choices when configuring a HealthcareService:\n * one main action (from the `exactly-one` selection) plus zero or more\n * addon sub-actions.\n */\nexport interface ProtocolSelection {\n /** The `action.id` of the chosen top-level action. */\n readonly actionId: string\n /** The `action.id`s of toggled-on addon sub-actions within the selected action. */\n readonly addonIds: readonly string[]\n}\n\n/** Resolved booking parameters for a single protocol action. */\nexport interface ResolvedProtocolAction {\n /** The `definitionCanonical` reference to the order-set PlanDefinition. */\n readonly protocolRef: string\n /** The service-type code for slot searching / billing. */\n readonly serviceType: string\n /** Estimated duration for this action. */\n readonly duration?: Duration\n}\n\n/** Fully resolved booking parameters produced by {@link resolveProtocolSelection}. */\nexport interface ResolvedProtocol {\n /** Resolved main action. */\n readonly main: ResolvedProtocolAction\n /** Resolved addon actions (empty when none selected). */\n readonly addons: readonly ResolvedProtocolAction[]\n}\n\n/**\n * Returns a **configured** copy of a protocol-group PlanDefinition by stamping\n * `precheckBehavior` on every action according to the given selection.\n *\n * - The selected top-level action gets `precheckBehavior: \"yes\"`, all others `\"no\"`.\n * - Within the selected action, each addon sub-action is stamped according to\n * whether its id appears in `selection.addonIds`. **Mandatory addons**\n * (`requiredBehavior === 'must'`) are always stamped `\"yes\"` regardless of\n * the caller-provided ids.\n * - Unselected top-level actions have all their sub-actions stamped as `\"no\"`.\n *\n * The returned PD is a shallow copy — the original is never mutated.\n *\n * @param pd - a protocol-group PlanDefinition\n * @param selection - the user's action + addon selection\n * @returns a new PlanDefinition with `precheckBehavior` set on every action\n * @throws if the selected `actionId` is not found in the PD\n */\nexport function configureProtocolGroup (\n pd: PlanDefinition,\n selection: ProtocolSelection\n): PlanDefinition {\n const actions = pd.action ?? []\n const found = actions.some((a) => a.id === selection.actionId)\n if (!found) {\n throw new Error(`Action \"${selection.actionId}\" not found in protocol-group PlanDefinition`)\n }\n\n const addonSet = new Set(selection.addonIds)\n\n return {\n ...pd,\n action: actions.map((a) => {\n const isSelected = a.id === selection.actionId\n const subActions = (a.action ?? []).map((sub) => {\n // The mandatory-addons override group is server-side configuration,\n // not a selectable addon — never stamp it as prechecked, even if a\n // (buggy) caller passes its id among the addonIds.\n const isOverrideGroup = sub.id === MANDATORY_ADDON_OVERRIDE_ACTION_ID\n const isMandatory = sub.requiredBehavior === 'must'\n const isOn = isSelected && !isOverrideGroup && (isMandatory || addonSet.has(sub.id ?? ''))\n return {\n ...sub,\n precheckBehavior: isOn ? 'yes' as const : 'no' as const\n }\n })\n\n return {\n ...a,\n precheckBehavior: isSelected ? 'yes' as const : 'no' as const,\n ...(a.action ? { action: subActions } : {})\n }\n })\n }\n}\n\n/**\n * Resolves a protocol-group PlanDefinition + selection into concrete booking\n * parameters (service-type codes, definitionCanonical references, durations).\n *\n * @param pd - a protocol-group PlanDefinition\n * @param selection - the user's action + addon selection\n * @returns the resolved main + addon protocol references and codes\n * @throws if the selected `actionId` is not found in the PD\n */\nexport function resolveProtocolSelection (\n pd: PlanDefinition,\n selection: ProtocolSelection\n): ResolvedProtocol {\n const actions = pd.action ?? []\n const selected = actions.find((a) => a.id === selection.actionId)\n if (!selected?.definitionCanonical) {\n throw new Error(`Action \"${selection.actionId}\" not found in protocol-group PlanDefinition`)\n }\n\n const addonSet = new Set(selection.addonIds)\n const resolvedAddons: ResolvedProtocolAction[] = (selected.action ?? [])\n .filter((sub): sub is PlanDefinitionAction & { definitionCanonical: string; id: string } => {\n if (!sub.id || !sub.definitionCanonical) { return false }\n const isMandatory = sub.requiredBehavior === 'must'\n return isMandatory || addonSet.has(sub.id)\n })\n .map((sub) => ({\n protocolRef: sub.definitionCanonical,\n serviceType: getActionServiceCode(sub),\n duration: sub.timingDuration\n }))\n\n return {\n main: {\n protocolRef: selected.definitionCanonical,\n serviceType: getActionServiceCode(selected),\n duration: selected.timingDuration\n },\n addons: resolvedAddons\n }\n}\n\n/**\n * Reads the current selection from a **configured** protocol-group PlanDefinition\n * (one whose actions have been stamped with `precheckBehavior` via\n * {@link configureProtocolGroup}).\n *\n * Falls back to `id === \"default\"` with mandatory addons of that default\n * action when no action has `precheckBehavior: \"yes\"`.\n *\n * @param pd - a (possibly configured) protocol-group PlanDefinition\n * @returns the selection encoded in the PD, or the default selection\n */\nexport function readProtocolSelection (pd: PlanDefinition): ProtocolSelection {\n const actions = pd.action ?? []\n\n // Look for an action explicitly marked as prechecked\n const prechecked = actions.find((a) => a.precheckBehavior === 'yes')\n if (prechecked?.id) {\n const addonIds = (prechecked.action ?? [])\n .filter((sub): sub is PlanDefinitionAction & { id: string } => {\n if (!sub.id || sub.id === MANDATORY_ADDON_OVERRIDE_ACTION_ID) { return false }\n if (sub.requiredBehavior === 'must') { return true }\n return sub.precheckBehavior === 'yes'\n })\n .map((sub) => sub.id)\n return { actionId: prechecked.id, addonIds }\n }\n\n // Fallback: default action with its mandatory addons (if any)\n const defaultAction = actions.find((a) => a.id === 'default') ?? actions[0]\n const mandatoryAddonIds = (defaultAction?.action ?? [])\n .filter((sub): sub is PlanDefinitionAction & { id: string } =>\n Boolean(sub.id) && sub.requiredBehavior === 'must'\n )\n .map((sub) => sub.id)\n return { actionId: defaultAction?.id ?? '', addonIds: mandatoryAddonIds }\n}\n\n// ─── Internal helpers ───────────────────────────────────────────────────────\n\nfunction getActionServiceCode (action: PlanDefinitionAction): string {\n const coding = (action.code ?? [])\n .flatMap((cc) => cc.coding ?? [])\n .find((c) => c.system === SERVICE_TYPE_SYSTEM)\n return coding?.code ?? ''\n}\n\nfunction precheckToBool (value: string | undefined): boolean | undefined {\n if (value === 'yes') { return true }\n if (value === 'no') { return false }\n return undefined\n}\n\nfunction extractActionInfo (a: PlanDefinitionAction & { definitionCanonical: string }, isDefault: boolean): ProtocolActionInfo {\n const subActions = (a.action ?? [])\n .filter((sub): sub is PlanDefinitionAction & { definitionCanonical: string } =>\n Boolean(sub.definitionCanonical) && sub.id !== MANDATORY_ADDON_OVERRIDE_ACTION_ID\n )\n .map((sub) => extractActionInfo(sub, false))\n\n return {\n actionId: a.id ?? '',\n isDefault,\n label: a.textEquivalent ?? a.title ?? '',\n question: a.description ?? '',\n protocolRef: a.definitionCanonical,\n protocolDisplay: a.title ?? '',\n protocolCode: getActionServiceCode(a),\n duration: a.timingDuration,\n prechecked: precheckToBool(a.precheckBehavior),\n mandatory: a.requiredBehavior === 'must' ? true : undefined,\n addons: subActions,\n mandatoryAddonOverrides: readMandatoryAddonOverrides(a)\n }\n}\n\n/**\n * Reads the per-variant mandatory-addon overrides out of a variant action's\n * `mandatory-addons` group. Returns `[]` when the variant declares none.\n *\n * @param variantAction - a protocol-group top-level variant action\n * @returns the variant's mandatory-addon overrides (empty when none)\n */\nexport function readMandatoryAddonOverrides (\n variantAction: PlanDefinitionAction\n): MandatoryAddonOverride[] {\n const group = (variantAction.action ?? []).find((sub) => sub.id === MANDATORY_ADDON_OVERRIDE_ACTION_ID)\n const result: MandatoryAddonOverride[] = []\n for (const sub of group?.action ?? []) {\n if (!sub.definitionCanonical) { continue }\n const action = overrideActionFromActionType(sub)\n if (!action) { continue }\n result.push(\n sub.title !== undefined\n ? { ref: sub.definitionCanonical, action, display: sub.title }\n : { ref: sub.definitionCanonical, action }\n )\n }\n return result\n}\n\n/**\n * Resolves the effective mandatory add-on canonicals for a selected variant:\n * the order-set PD defaults, plus the variant's `'add'` overrides, minus its\n * `'remove'` overrides. Order-set defaults and overrides are matched by exact\n * canonical string. Deduplicated; input order of the defaults is preserved,\n * with any added canonicals appended.\n *\n * @param defaultRefs - canonicals of the order-set PD's default mandatory add-ons\n * @param variantAction - the selected protocol-group variant action, or undefined\n * @returns the resolved set of mandatory add-on canonicals\n */\nexport function resolveVariantMandatoryAddons (\n defaultRefs: readonly string[],\n variantAction: PlanDefinitionAction | undefined\n): string[] {\n const resolved = new Set(defaultRefs)\n if (variantAction) {\n for (const override of readMandatoryAddonOverrides(variantAction)) {\n if (override.action === 'add') {\n resolved.add(override.ref)\n } else {\n resolved.delete(override.ref)\n }\n }\n }\n return Array.from(resolved)\n}\n\n/**\n * Maps an override sub-action's `type.coding` (ActionType) back to add/remove.\n *\n * @param sub - an override group sub-action\n * @returns `'add'` for `create`, `'remove'` for `remove`, else undefined\n */\nfunction overrideActionFromActionType (\n sub: PlanDefinitionAction\n): MandatoryAddonOverrideAction | undefined {\n const code = (sub.type?.coding ?? []).find((c) => c.system === ACTION_TYPE_SYSTEM)?.code\n if (code === ACTION_TYPE_ADD) { return 'add' }\n if (code === ACTION_TYPE_REMOVE) { return 'remove' }\n return undefined\n}\n\n/**\n * Builds the `mandatory-addons` override group child for a variant, or returns\n * `undefined` when the variant declares no overrides. Each override becomes a\n * sub-action referencing the add-on's canonical, with `requiredBehavior`\n * `'must'` (add) or `'prohibited'` (remove).\n *\n * @param overrides - the variant's mandatory-addon overrides (may be undefined)\n * @returns the override group action, or undefined when there are no overrides\n */\nfunction buildMandatoryAddonOverrideGroup (\n overrides: readonly MandatoryAddonOverride[] | undefined\n): PlanDefinitionAction | undefined {\n if (!overrides || overrides.length === 0) {\n return undefined\n }\n return {\n id: MANDATORY_ADDON_OVERRIDE_ACTION_ID,\n title: 'Adicionales obligatorios (override por variante)',\n selectionBehavior: 'any',\n action: overrides.map((o) => {\n const sub: PlanDefinitionAction = {\n definitionCanonical: o.ref,\n type: {\n coding: [{ system: ACTION_TYPE_SYSTEM, code: o.action === 'add' ? ACTION_TYPE_ADD : ACTION_TYPE_REMOVE }]\n }\n }\n if (o.display) {\n sub.title = o.display\n }\n return sub\n })\n }\n}\n\nfunction buildAction (\n id: string,\n title: string,\n ref: string,\n code: string,\n duration?: Duration,\n question?: string,\n labelOverride?: string,\n mandatory?: boolean\n): PlanDefinitionAction {\n const action: PlanDefinitionAction = {\n id,\n title,\n definitionCanonical: ref\n }\n if (code) {\n action.code = [{ coding: [{ system: SERVICE_TYPE_SYSTEM, code }] }]\n }\n if (duration) {\n action.timingDuration = duration\n }\n if (question) {\n action.description = question\n }\n if (labelOverride) {\n action.textEquivalent = labelOverride\n }\n if (mandatory) {\n action.requiredBehavior = 'must'\n }\n return action\n}\n"]}
1
+ {"version":3,"file":"plan-definition-group.js","sourceRoot":"","sources":["../src/plan-definition-group.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Duration, PlanDefinition, PlanDefinitionAction } from '@medplum/fhirtypes'\nimport { EGES_PRACTICA_SYSTEM, PD_HEALTHCARE_SERVICE_EXTENSION_URL, PD_TYPE_PROTOCOL_GROUP, PD_TYPE_SYSTEM, SERVICE_TYPE_SYSTEM } from './constants'\n\n/**\n * `action.id` of the per-variant group that overrides the order-set PD's\n * default mandatory add-ons (the tipo-3 `getMandatoryAddonIds` path). It lives\n * as a direct child of a protocol-group variant action, kept structurally\n * separate from the variant's own add-on sub-actions (the tipo-2\n * `resolveProtocolSelection` path) so the two never conflate. Its group node\n * carries no `definitionCanonical`, so `resolveProtocolSelection`,\n * `getProtocolActions` and friends skip it and never descend into it.\n */\nexport const MANDATORY_ADDON_OVERRIDE_ACTION_ID = 'mandatory-addons'\n\n/**\n * FHIR-standard ActionType code system. Each override sub-action carries a\n * `type.coding` from this system: `create` = add the add-on to the variant's\n * mandatory set, `remove` = drop a PD-default mandatory add-on. `requiredBehavior`\n * is not used for this because FHIR's value set has no \"exclude\" member.\n */\nconst ACTION_TYPE_SYSTEM = 'http://terminology.hl7.org/CodeSystem/action-type'\nconst ACTION_TYPE_ADD = 'create'\nconst ACTION_TYPE_REMOVE = 'remove'\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/**\n * How a variant alters one order-set default mandatory add-on:\n * - `'add'` forces the add-on mandatory for this variant even if the order-set\n * PD marks it optional (or does not list it as mandatory).\n * - `'remove'` drops an add-on that the order-set PD marks mandatory by default.\n */\nexport type MandatoryAddonOverrideAction = 'add' | 'remove'\n\n/**\n * A single per-variant override of the order-set's default mandatory add-on set\n * (the tipo-3 path). Referenced by the add-on's `ActivityDefinition` canonical\n * (`${EGES_PRACTICA_SYSTEM}/{pra_id}`) — the same canonical the order-set PD\n * uses — so add/remove resolve by exact canonical match against the defaults.\n */\nexport interface MandatoryAddonOverride {\n /** Add-on `ActivityDefinition` canonical, e.g. `${EGES_PRACTICA_SYSTEM}/{pra_id}`. */\n readonly ref: string\n /** Whether the variant adds or removes this add-on relative to the PD default. */\n readonly action: MandatoryAddonOverrideAction\n /** Optional human label, for the admin editor. */\n readonly display?: string\n}\n\n/** Information about a single action inside a protocol-group PD. */\nexport interface ProtocolActionInfo {\n readonly actionId: string\n readonly isDefault: boolean\n /** Short label for the variant (e.g. \"Helicoidal\") */\n readonly label: string\n /** User-facing question to select this variant */\n readonly question: string\n readonly protocolRef: string\n readonly protocolDisplay: string\n readonly protocolCode: string\n /**\n * EGES pra_id of the referenced práctica, when stamped on the action's\n * `code[]` (an `EGES_PRACTICA_SYSTEM` coding alongside the service-type\n * coding). Persisted by {@link buildProtocolGroup} so admin UIs can show\n * the id without re-reading each order-set PD.\n */\n readonly praId?: string\n readonly duration?: Duration\n /**\n * Whether this action is pre-selected in a **configured** protocol-group.\n * Set by {@link configureProtocolGroup} via FHIR `precheckBehavior`.\n * `undefined` means the PD has not been configured (use `isDefault` as fallback).\n */\n readonly prechecked?: boolean\n /**\n * Only meaningful on addon (sub-action) entries. When `true`, the addon is\n * always included whenever its parent action is selected — it is not shown\n * as a togglable option in the consumer UI. Encoded in FHIR as\n * `PlanDefinitionAction.requiredBehavior === 'must'`.\n */\n readonly mandatory?: boolean\n /** Optional sub-actions (addons) with `any` selection behavior. */\n readonly addons: readonly ProtocolActionInfo[]\n /**\n * Per-variant overrides of the order-set's default mandatory add-on set\n * (tipo-3 path). Empty when the variant inherits the PD defaults unchanged.\n * Only meaningful on top-level variant entries.\n */\n readonly mandatoryAddonOverrides: readonly MandatoryAddonOverride[]\n}\n\n/** Entry used to build a protocol-group PD action. */\nexport interface ProtocolGroupActionEntry {\n readonly id: string\n readonly isDefault: boolean\n readonly label: string\n readonly question: string\n readonly ref: string\n readonly display: string\n readonly code: string\n /** EGES pra_id of the referenced práctica, stamped on the action's `code[]`. */\n readonly praId?: string\n readonly duration?: Duration\n /**\n * Only meaningful on addon entries. When `true`, the addon is always\n * included with the parent action and is hidden from the consumer UI.\n */\n readonly mandatory?: boolean\n /** Optional sub-action entries (addons). */\n readonly addons?: readonly ProtocolGroupActionEntry[]\n /**\n * Per-variant overrides of the order-set's default mandatory add-on set\n * (tipo-3 path). Only meaningful on top-level variant entries; ignored on\n * addon entries.\n */\n readonly mandatoryAddonOverrides?: readonly MandatoryAddonOverride[]\n}\n\n// ─── Backward-compat aliases ────────────────────────────────────────────────\n\n/** @deprecated Use {@link ProtocolActionInfo} instead. */\nexport type ProtocolVariantInfo = ProtocolActionInfo\n\n/** @deprecated Use {@link ProtocolActionInfo} instead. */\nexport interface ProtocolDefaultInfo {\n readonly ref: string\n readonly display: string\n readonly code: string\n readonly duration?: Duration\n}\n\n// ─── Detection ───────────────────────────────────────────────────────────────\n\n/**\n * Returns `true` if the PlanDefinition is a protocol-group (wrapping multiple concrete PDs).\n *\n * @param pd - the PlanDefinition to check\n * @returns whether the PlanDefinition is a protocol-group\n */\nexport function isProtocolGroup (pd: PlanDefinition): boolean {\n return (pd.type?.coding ?? []).some(\n (c) => c.system === PD_TYPE_SYSTEM && c.code === PD_TYPE_PROTOCOL_GROUP\n )\n}\n\n// ─── Extraction ──────────────────────────────────────────────────────────────\n\n/**\n * Extracts all protocol actions from a protocol-group PD (preserving order).\n *\n * @param pd - the protocol-group PlanDefinition\n * @returns array of action info objects (the one with `isDefault === true` is the default)\n */\nexport function getProtocolActions (pd: PlanDefinition): ProtocolActionInfo[] {\n return (pd.action ?? [])\n .filter((a): a is PlanDefinitionAction & { definitionCanonical: string } =>\n Boolean(a.definitionCanonical)\n )\n .map((a) => extractActionInfo(a, a.id === 'default'))\n}\n\n/**\n * Extracts the default protocol action from a protocol-group PD.\n *\n * @param pd - the protocol-group PlanDefinition\n * @returns the default protocol info, or undefined if not found\n */\nexport function getDefaultProtocol (pd: PlanDefinition): ProtocolDefaultInfo | undefined {\n const action = (pd.action ?? []).find((a) => a.id === 'default')\n if (!action?.definitionCanonical) { return undefined }\n return {\n ref: action.definitionCanonical,\n display: action.title ?? '',\n code: getActionServiceCode(action),\n duration: action.timingDuration\n }\n}\n\n/**\n * Extracts the non-default variant actions from a protocol-group PD.\n *\n * @param pd - the protocol-group PlanDefinition\n * @returns array of variant info objects\n */\nexport function getProtocolVariants (pd: PlanDefinition): ProtocolActionInfo[] {\n return getProtocolActions(pd).filter((a) => !a.isDefault)\n}\n\n/**\n * Extracts the HealthcareService reference linked to a protocol-group PD.\n *\n * @param pd - the PlanDefinition to inspect\n * @returns the referenced HealthcareService, if present\n */\nexport function getProtocolGroupHealthcareServiceReference (pd: PlanDefinition): string | undefined {\n return pd.extension?.find((e) => e.url === PD_HEALTHCARE_SERVICE_EXTENSION_URL)?.valueReference?.reference\n}\n\n// ─── Construction ────────────────────────────────────────────────────────────\n\n/**\n * Builds a protocol-group PlanDefinition resource.\n *\n * @param title - human-readable title for the group (e.g. \"TAC de hombro — Protocolos\")\n * @param entries - protocol action entries (at least one should have `isDefault: true`)\n * @param existingId - optional ID to reuse when updating an existing group PD\n * @param hsReference - optional HealthcareService reference stored on the group PD\n * @returns the constructed protocol-group PlanDefinition\n */\nexport function buildProtocolGroup (\n title: string,\n entries: readonly ProtocolGroupActionEntry[],\n existingId?: string,\n hsReference?: string\n): PlanDefinition {\n const actions: PlanDefinitionAction[] = entries.map((e) => {\n const subActions = (e.addons ?? []).map((addon) =>\n buildAction(\n addon.id,\n addon.display,\n addon.ref,\n addon.code,\n addon.duration,\n addon.question,\n addon.label,\n addon.mandatory,\n addon.praId\n )\n )\n\n const action = buildAction(\n e.isDefault ? 'default' : e.id,\n e.display,\n e.ref,\n e.code,\n e.duration,\n e.question,\n e.label,\n undefined,\n e.praId\n )\n\n // Top-level actions use exactly-one selection behavior\n action.selectionBehavior = 'exactly-one'\n\n const overrideGroup = buildMandatoryAddonOverrideGroup(e.mandatoryAddonOverrides)\n const childActions = overrideGroup ? [...subActions, overrideGroup] : subActions\n\n if (childActions.length > 0) {\n action.action = childActions\n // When an action has sub-actions (addons), they use `any` grouping\n action.groupingBehavior = 'logical-group'\n }\n\n return action\n })\n\n const pd: PlanDefinition = {\n resourceType: 'PlanDefinition',\n status: 'active',\n title,\n type: {\n coding: [{ system: PD_TYPE_SYSTEM, code: PD_TYPE_PROTOCOL_GROUP }]\n },\n action: actions\n }\n\n if (hsReference) {\n pd.extension = [\n {\n url: PD_HEALTHCARE_SERVICE_EXTENSION_URL,\n valueReference: { reference: hsReference }\n }\n ]\n }\n\n if (existingId) {\n pd.id = existingId\n }\n\n return pd\n}\n\n// ─── Selection / Configuration ──────────────────────────────────────────────\n\n/**\n * A user's selection within a protocol-group PlanDefinition.\n *\n * Represents the patient's choices when configuring a HealthcareService:\n * one main action (from the `exactly-one` selection) plus zero or more\n * addon sub-actions.\n */\nexport interface ProtocolSelection {\n /** The `action.id` of the chosen top-level action. */\n readonly actionId: string\n /** The `action.id`s of toggled-on addon sub-actions within the selected action. */\n readonly addonIds: readonly string[]\n}\n\n/** Resolved booking parameters for a single protocol action. */\nexport interface ResolvedProtocolAction {\n /** The `definitionCanonical` reference to the order-set PlanDefinition. */\n readonly protocolRef: string\n /** The service-type code for slot searching / billing. */\n readonly serviceType: string\n /** Estimated duration for this action. */\n readonly duration?: Duration\n}\n\n/** Fully resolved booking parameters produced by {@link resolveProtocolSelection}. */\nexport interface ResolvedProtocol {\n /** Resolved main action. */\n readonly main: ResolvedProtocolAction\n /** Resolved addon actions (empty when none selected). */\n readonly addons: readonly ResolvedProtocolAction[]\n}\n\n/**\n * Returns a **configured** copy of a protocol-group PlanDefinition by stamping\n * `precheckBehavior` on every action according to the given selection.\n *\n * - The selected top-level action gets `precheckBehavior: \"yes\"`, all others `\"no\"`.\n * - Within the selected action, each addon sub-action is stamped according to\n * whether its id appears in `selection.addonIds`. **Mandatory addons**\n * (`requiredBehavior === 'must'`) are always stamped `\"yes\"` regardless of\n * the caller-provided ids.\n * - Unselected top-level actions have all their sub-actions stamped as `\"no\"`.\n *\n * The returned PD is a shallow copy — the original is never mutated.\n *\n * @param pd - a protocol-group PlanDefinition\n * @param selection - the user's action + addon selection\n * @returns a new PlanDefinition with `precheckBehavior` set on every action\n * @throws if the selected `actionId` is not found in the PD\n */\nexport function configureProtocolGroup (\n pd: PlanDefinition,\n selection: ProtocolSelection\n): PlanDefinition {\n const actions = pd.action ?? []\n const found = actions.some((a) => a.id === selection.actionId)\n if (!found) {\n throw new Error(`Action \"${selection.actionId}\" not found in protocol-group PlanDefinition`)\n }\n\n const addonSet = new Set(selection.addonIds)\n\n return {\n ...pd,\n action: actions.map((a) => {\n const isSelected = a.id === selection.actionId\n const subActions = (a.action ?? []).map((sub) => {\n // The mandatory-addons override group is server-side configuration,\n // not a selectable addon — never stamp it as prechecked, even if a\n // (buggy) caller passes its id among the addonIds.\n const isOverrideGroup = sub.id === MANDATORY_ADDON_OVERRIDE_ACTION_ID\n const isMandatory = sub.requiredBehavior === 'must'\n const isOn = isSelected && !isOverrideGroup && (isMandatory || addonSet.has(sub.id ?? ''))\n return {\n ...sub,\n precheckBehavior: isOn ? 'yes' as const : 'no' as const\n }\n })\n\n return {\n ...a,\n precheckBehavior: isSelected ? 'yes' as const : 'no' as const,\n ...(a.action ? { action: subActions } : {})\n }\n })\n }\n}\n\n/**\n * Resolves a protocol-group PlanDefinition + selection into concrete booking\n * parameters (service-type codes, definitionCanonical references, durations).\n *\n * @param pd - a protocol-group PlanDefinition\n * @param selection - the user's action + addon selection\n * @returns the resolved main + addon protocol references and codes\n * @throws if the selected `actionId` is not found in the PD\n */\nexport function resolveProtocolSelection (\n pd: PlanDefinition,\n selection: ProtocolSelection\n): ResolvedProtocol {\n const actions = pd.action ?? []\n const selected = actions.find((a) => a.id === selection.actionId)\n if (!selected?.definitionCanonical) {\n throw new Error(`Action \"${selection.actionId}\" not found in protocol-group PlanDefinition`)\n }\n\n const addonSet = new Set(selection.addonIds)\n const resolvedAddons: ResolvedProtocolAction[] = (selected.action ?? [])\n .filter((sub): sub is PlanDefinitionAction & { definitionCanonical: string; id: string } => {\n if (!sub.id || !sub.definitionCanonical) { return false }\n const isMandatory = sub.requiredBehavior === 'must'\n return isMandatory || addonSet.has(sub.id)\n })\n .map((sub) => ({\n protocolRef: sub.definitionCanonical,\n serviceType: getActionServiceCode(sub),\n duration: sub.timingDuration\n }))\n\n return {\n main: {\n protocolRef: selected.definitionCanonical,\n serviceType: getActionServiceCode(selected),\n duration: selected.timingDuration\n },\n addons: resolvedAddons\n }\n}\n\n/**\n * Reads the current selection from a **configured** protocol-group PlanDefinition\n * (one whose actions have been stamped with `precheckBehavior` via\n * {@link configureProtocolGroup}).\n *\n * Falls back to `id === \"default\"` with mandatory addons of that default\n * action when no action has `precheckBehavior: \"yes\"`.\n *\n * @param pd - a (possibly configured) protocol-group PlanDefinition\n * @returns the selection encoded in the PD, or the default selection\n */\nexport function readProtocolSelection (pd: PlanDefinition): ProtocolSelection {\n const actions = pd.action ?? []\n\n // Look for an action explicitly marked as prechecked\n const prechecked = actions.find((a) => a.precheckBehavior === 'yes')\n if (prechecked?.id) {\n const addonIds = (prechecked.action ?? [])\n .filter((sub): sub is PlanDefinitionAction & { id: string } => {\n if (!sub.id || sub.id === MANDATORY_ADDON_OVERRIDE_ACTION_ID) { return false }\n if (sub.requiredBehavior === 'must') { return true }\n return sub.precheckBehavior === 'yes'\n })\n .map((sub) => sub.id)\n return { actionId: prechecked.id, addonIds }\n }\n\n // Fallback: default action with its mandatory addons (if any)\n const defaultAction = actions.find((a) => a.id === 'default') ?? actions[0]\n const mandatoryAddonIds = (defaultAction?.action ?? [])\n .filter((sub): sub is PlanDefinitionAction & { id: string } =>\n Boolean(sub.id) && sub.requiredBehavior === 'must'\n )\n .map((sub) => sub.id)\n return { actionId: defaultAction?.id ?? '', addonIds: mandatoryAddonIds }\n}\n\n// ─── Internal helpers ───────────────────────────────────────────────────────\n\nfunction getActionServiceCode (action: PlanDefinitionAction): string {\n const coding = (action.code ?? [])\n .flatMap((cc) => cc.coding ?? [])\n .find((c) => c.system === SERVICE_TYPE_SYSTEM)\n return coding?.code ?? ''\n}\n\nfunction getActionPraId (action: PlanDefinitionAction): string | undefined {\n return (action.code ?? [])\n .flatMap((cc) => cc.coding ?? [])\n .find((c) => c.system === EGES_PRACTICA_SYSTEM)?.code\n}\n\nfunction precheckToBool (value: string | undefined): boolean | undefined {\n if (value === 'yes') { return true }\n if (value === 'no') { return false }\n return undefined\n}\n\nfunction extractActionInfo (a: PlanDefinitionAction & { definitionCanonical: string }, isDefault: boolean): ProtocolActionInfo {\n const subActions = (a.action ?? [])\n .filter((sub): sub is PlanDefinitionAction & { definitionCanonical: string } =>\n Boolean(sub.definitionCanonical) && sub.id !== MANDATORY_ADDON_OVERRIDE_ACTION_ID\n )\n .map((sub) => extractActionInfo(sub, false))\n\n return {\n actionId: a.id ?? '',\n isDefault,\n label: a.textEquivalent ?? a.title ?? '',\n question: a.description ?? '',\n protocolRef: a.definitionCanonical,\n protocolDisplay: a.title ?? '',\n protocolCode: getActionServiceCode(a),\n praId: getActionPraId(a),\n duration: a.timingDuration,\n prechecked: precheckToBool(a.precheckBehavior),\n mandatory: a.requiredBehavior === 'must' ? true : undefined,\n addons: subActions,\n mandatoryAddonOverrides: readMandatoryAddonOverrides(a)\n }\n}\n\n/**\n * Reads the per-variant mandatory-addon overrides out of a variant action's\n * `mandatory-addons` group. Returns `[]` when the variant declares none.\n *\n * @param variantAction - a protocol-group top-level variant action\n * @returns the variant's mandatory-addon overrides (empty when none)\n */\nexport function readMandatoryAddonOverrides (\n variantAction: PlanDefinitionAction\n): MandatoryAddonOverride[] {\n const group = (variantAction.action ?? []).find((sub) => sub.id === MANDATORY_ADDON_OVERRIDE_ACTION_ID)\n const result: MandatoryAddonOverride[] = []\n for (const sub of group?.action ?? []) {\n if (!sub.definitionCanonical) { continue }\n const action = overrideActionFromActionType(sub)\n if (!action) { continue }\n result.push(\n sub.title !== undefined\n ? { ref: sub.definitionCanonical, action, display: sub.title }\n : { ref: sub.definitionCanonical, action }\n )\n }\n return result\n}\n\n/**\n * Extracts the canonicals of an order-set PD's **default** mandatory add-ons:\n * the `action[id='addons']` sub-actions flagged `requiredBehavior: 'must'`.\n * These are the defaults that {@link resolveVariantMandatoryAddons} combines\n * with a selected variant's `mandatory-addons` overrides.\n *\n * @param orderSetPd - an order-set PlanDefinition\n * @returns canonicals of the default mandatory add-ons (empty when none)\n */\nexport function getOrderSetDefaultMandatoryRefs (orderSetPd: PlanDefinition): string[] {\n return (orderSetPd.action?.find((a) => a.id === 'addons')?.action ?? [])\n .filter((addon): addon is PlanDefinitionAction & { definitionCanonical: string } =>\n addon.requiredBehavior === 'must' && Boolean(addon.definitionCanonical)\n )\n .map((addon) => addon.definitionCanonical)\n}\n\n/**\n * Resolves the effective mandatory add-on canonicals for a selected variant:\n * the order-set PD defaults, plus the variant's `'add'` overrides, minus its\n * `'remove'` overrides. Order-set defaults and overrides are matched by exact\n * canonical string. Deduplicated; input order of the defaults is preserved,\n * with any added canonicals appended.\n *\n * @param defaultRefs - canonicals of the order-set PD's default mandatory add-ons\n * @param variantAction - the selected protocol-group variant action, or undefined\n * @returns the resolved set of mandatory add-on canonicals\n */\nexport function resolveVariantMandatoryAddons (\n defaultRefs: readonly string[],\n variantAction: PlanDefinitionAction | undefined\n): string[] {\n const resolved = new Set(defaultRefs)\n if (variantAction) {\n for (const override of readMandatoryAddonOverrides(variantAction)) {\n if (override.action === 'add') {\n resolved.add(override.ref)\n } else {\n resolved.delete(override.ref)\n }\n }\n }\n return Array.from(resolved)\n}\n\n/**\n * Maps an override sub-action's `type.coding` (ActionType) back to add/remove.\n *\n * @param sub - an override group sub-action\n * @returns `'add'` for `create`, `'remove'` for `remove`, else undefined\n */\nfunction overrideActionFromActionType (\n sub: PlanDefinitionAction\n): MandatoryAddonOverrideAction | undefined {\n const code = (sub.type?.coding ?? []).find((c) => c.system === ACTION_TYPE_SYSTEM)?.code\n if (code === ACTION_TYPE_ADD) { return 'add' }\n if (code === ACTION_TYPE_REMOVE) { return 'remove' }\n return undefined\n}\n\n/**\n * Builds the `mandatory-addons` override group child for a variant, or returns\n * `undefined` when the variant declares no overrides. Each override becomes a\n * sub-action referencing the add-on's canonical, with `requiredBehavior`\n * `'must'` (add) or `'prohibited'` (remove).\n *\n * @param overrides - the variant's mandatory-addon overrides (may be undefined)\n * @returns the override group action, or undefined when there are no overrides\n */\nfunction buildMandatoryAddonOverrideGroup (\n overrides: readonly MandatoryAddonOverride[] | undefined\n): PlanDefinitionAction | undefined {\n if (!overrides || overrides.length === 0) {\n return undefined\n }\n return {\n id: MANDATORY_ADDON_OVERRIDE_ACTION_ID,\n title: 'Adicionales obligatorios (override por variante)',\n selectionBehavior: 'any',\n action: overrides.map((o) => {\n const sub: PlanDefinitionAction = {\n definitionCanonical: o.ref,\n type: {\n coding: [{ system: ACTION_TYPE_SYSTEM, code: o.action === 'add' ? ACTION_TYPE_ADD : ACTION_TYPE_REMOVE }]\n }\n }\n if (o.display) {\n sub.title = o.display\n }\n return sub\n })\n }\n}\n\nfunction buildAction (\n id: string,\n title: string,\n ref: string,\n code: string,\n duration?: Duration,\n question?: string,\n labelOverride?: string,\n mandatory?: boolean,\n praId?: string\n): PlanDefinitionAction {\n const action: PlanDefinitionAction = {\n id,\n title,\n definitionCanonical: ref\n }\n if (code || praId) {\n action.code = [{\n coding: [\n ...(code ? [{ system: SERVICE_TYPE_SYSTEM, code }] : []),\n ...(praId ? [{ system: EGES_PRACTICA_SYSTEM, code: praId }] : [])\n ]\n }]\n }\n if (duration) {\n action.timingDuration = duration\n }\n if (question) {\n action.description = question\n }\n if (labelOverride) {\n action.textEquivalent = labelOverride\n }\n if (mandatory) {\n action.requiredBehavior = 'must'\n }\n return action\n}\n"]}
@@ -0,0 +1,108 @@
1
+ import type { ConceptMap, Range } from '@medplum/fhirtypes';
2
+ /** FHIR administrative gender codes accepted by mapping conditions. */
3
+ export type PracticaMappingSex = 'male' | 'female' | 'other' | 'unknown';
4
+ /**
5
+ * Conditions under which a mapping rule applies. All present conditions must
6
+ * match (logical AND); a rule with no conditions is an unconditional override.
7
+ */
8
+ export interface PracticaMappingCondition {
9
+ /**
10
+ * Reference to an `InsurancePlan` (plan tier) or a payer `Organization`
11
+ * (obra social tier), e.g. `InsurancePlan/123` / `Organization/45`.
12
+ */
13
+ readonly insuranceRef?: string;
14
+ /**
15
+ * Patient age range; bounds inclusive, either side may be open. Each bound
16
+ * Quantity may carry a UCUM code (`a` years, `mo` months, `d` days) —
17
+ * absent unit means years — and each bound is evaluated in its own unit.
18
+ */
19
+ readonly ageRange?: Range;
20
+ /** FHIR administrative gender. */
21
+ readonly sex?: PracticaMappingSex;
22
+ }
23
+ /** One práctica → práctica substitution rule from the mapping registry. */
24
+ export interface PracticaMappingRule {
25
+ /** EGES pra_id the rule applies to. */
26
+ readonly sourcePraId: number;
27
+ /** EGES pra_id substituted when the rule matches. */
28
+ readonly targetPraId: number;
29
+ readonly condition: PracticaMappingCondition;
30
+ /** Optional human label for the admin editor. */
31
+ readonly display?: string;
32
+ }
33
+ /** Units accepted on `ageRange` bounds (UCUM): years, months, days. */
34
+ export type PracticaAgeUnit = 'a' | 'mo' | 'd';
35
+ /**
36
+ * The patient's exact age at resolution time, floored per calendar unit, so
37
+ * `ageRange` bounds expressed in days, months, or years all compare exactly.
38
+ */
39
+ export interface PatientAge {
40
+ /** Completed calendar years. */
41
+ readonly years: number;
42
+ /** Completed calendar months. */
43
+ readonly months: number;
44
+ /** Completed days. */
45
+ readonly days: number;
46
+ }
47
+ /**
48
+ * The patient-side facts a rule's conditions are matched against. Resolved
49
+ * once per booking (see `resolvePracticaMappingContext`).
50
+ */
51
+ export interface PracticaMappingContext {
52
+ /** `InsurancePlan/{id}` reference of the patient's plan, when known. */
53
+ readonly insurancePlanRef?: string;
54
+ /** `Organization/{id}` reference of the plan's payer, when known. */
55
+ readonly insuranceOrgRef?: string;
56
+ /** Patient age at resolution time, when known. */
57
+ readonly age?: PatientAge;
58
+ readonly sex?: PracticaMappingSex;
59
+ }
60
+ /** Which condition dimensions a matching rule satisfied (for audit/UI). */
61
+ export type PracticaMappingMatchedCondition = 'insurance-plan' | 'insurance-org' | 'age' | 'sex';
62
+ /** A matched rule plus the dimensions it matched on. */
63
+ export interface PracticaMappingMatch {
64
+ readonly rule: PracticaMappingRule;
65
+ readonly matchedConditions: readonly PracticaMappingMatchedCondition[];
66
+ }
67
+ /**
68
+ * Builds the singleton práctica-mapping ConceptMap from a list of rules.
69
+ * Rule order is preserved (it is the final precedence tie-break).
70
+ *
71
+ * @param rules - the mapping rules to serialize
72
+ * @param existingId - optional resource id to reuse when updating
73
+ * @returns the ConceptMap resource ready to be saved
74
+ */
75
+ export declare function buildPracticaMappingConceptMap(rules: readonly PracticaMappingRule[], existingId?: string): ConceptMap;
76
+ /**
77
+ * Reads the mapping rules out of the práctica-mapping ConceptMap, preserving
78
+ * element/target order. Targets with a non-numeric code or an unreadable
79
+ * condition extension are skipped.
80
+ *
81
+ * @param conceptMap - the mapping registry ConceptMap (may be undefined)
82
+ * @returns the parsed rules (empty when the registry is absent or empty)
83
+ */
84
+ export declare function readPracticaMappingRules(conceptMap: ConceptMap | undefined): PracticaMappingRule[];
85
+ /**
86
+ * Finds the winning rule for a source práctica under the given context.
87
+ *
88
+ * Precedence among matching rules:
89
+ * 1. Most matched condition dimensions wins.
90
+ * 2. Insurance tier breaks ties: a plan-tier match beats an obra-social-tier match.
91
+ * 3. Registry order breaks remaining ties (first rule wins).
92
+ *
93
+ * @param rules - all registry rules (in registry order)
94
+ * @param praId - the source pra_id being resolved
95
+ * @param context - the patient-side facts to match against
96
+ * @returns the winning match, or undefined when no rule applies (identity)
97
+ */
98
+ export declare function matchPracticaMapping(rules: readonly PracticaMappingRule[], praId: number, context: PracticaMappingContext): PracticaMappingMatch | undefined;
99
+ /**
100
+ * Computes a patient's exact age (completed years, months, and days) at the
101
+ * given date, so `ageRange` bounds in any unit compare correctly.
102
+ *
103
+ * @param birthDate - ISO date string (`YYYY-MM-DD`)
104
+ * @param at - the reference date (defaults to now)
105
+ * @returns the age, or undefined for an unparsable or future birth date
106
+ */
107
+ export declare function computePatientAge(birthDate: string, at?: Date): PatientAge | undefined;
108
+ //# sourceMappingURL=practica-mapping.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"practica-mapping.d.ts","sourceRoot":"","sources":["../src/practica-mapping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAmE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAW5H,uEAAuE;AACvE,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAA;AAExE;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IACvC;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAA;IACzB,kCAAkC;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,kBAAkB,CAAA;CAClC;AAED,2EAA2E;AAC3E,MAAM,WAAW,mBAAmB;IAClC,uCAAuC;IACvC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,qDAAqD;IACrD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,SAAS,EAAE,wBAAwB,CAAA;IAC5C,iDAAiD;IACjD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,uEAAuE;AACvE,MAAM,MAAM,eAAe,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,CAAA;AAE9C;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,gCAAgC;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,iCAAiC;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,sBAAsB;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,wEAAwE;IACxE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;IAClC,qEAAqE;IACrE,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;IACjC,kDAAkD;IAClD,QAAQ,CAAC,GAAG,CAAC,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,GAAG,CAAC,EAAE,kBAAkB,CAAA;CAClC;AAED,2EAA2E;AAC3E,MAAM,MAAM,+BAA+B,GAAG,gBAAgB,GAAG,eAAe,GAAG,KAAK,GAAG,KAAK,CAAA;AAEhG,wDAAwD;AACxD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAA;IAClC,QAAQ,CAAC,iBAAiB,EAAE,SAAS,+BAA+B,EAAE,CAAA;CACvE;AAID;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,SAAS,mBAAmB,EAAE,EACrC,UAAU,CAAC,EAAE,MAAM,GAClB,UAAU,CAkCZ;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAE,UAAU,EAAE,UAAU,GAAG,SAAS,GAAG,mBAAmB,EAAE,CA0BnG;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,SAAS,mBAAmB,EAAE,EACrC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,sBAAsB,GAC9B,oBAAoB,GAAG,SAAS,CAiBlC;AA6DD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAE,SAAS,EAAE,MAAM,EAAE,EAAE,GAAE,IAAiB,GAAG,UAAU,GAAG,SAAS,CAcnG"}
@@ -0,0 +1,286 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildPracticaMappingConceptMap = buildPracticaMappingConceptMap;
4
+ exports.readPracticaMappingRules = readPracticaMappingRules;
5
+ exports.matchPracticaMapping = matchPracticaMapping;
6
+ exports.computePatientAge = computePatientAge;
7
+ const constants_1 = require("./constants");
8
+ // ─── ConceptMap serialization ────────────────────────────────────────────────
9
+ /**
10
+ * Builds the singleton práctica-mapping ConceptMap from a list of rules.
11
+ * Rule order is preserved (it is the final precedence tie-break).
12
+ *
13
+ * @param rules - the mapping rules to serialize
14
+ * @param existingId - optional resource id to reuse when updating
15
+ * @returns the ConceptMap resource ready to be saved
16
+ */
17
+ function buildPracticaMappingConceptMap(rules, existingId) {
18
+ var _a;
19
+ const elementsBySource = new Map();
20
+ for (const rule of rules) {
21
+ let element = elementsBySource.get(rule.sourcePraId);
22
+ if (!element) {
23
+ element = { code: String(rule.sourcePraId), target: [] };
24
+ elementsBySource.set(rule.sourcePraId, element);
25
+ }
26
+ (_a = element.target) === null || _a === void 0 ? void 0 : _a.push(buildTarget(rule));
27
+ }
28
+ const conceptMap = {
29
+ resourceType: 'ConceptMap',
30
+ url: constants_1.PRACTICA_MAPPING_CONCEPT_MAP_URL,
31
+ status: 'active',
32
+ name: 'PracticaMapping',
33
+ title: 'Mapeo de prácticas por cobertura, edad y sexo',
34
+ meta: {
35
+ tag: [{ system: constants_1.BILLING_CODES_TAG_SYSTEM, code: constants_1.PRACTICA_MAPPING_TAG_CODE }]
36
+ },
37
+ group: [
38
+ {
39
+ source: constants_1.EGES_PRACTICA_SYSTEM,
40
+ target: constants_1.EGES_PRACTICA_SYSTEM,
41
+ element: Array.from(elementsBySource.values())
42
+ }
43
+ ]
44
+ };
45
+ if (existingId) {
46
+ conceptMap.id = existingId;
47
+ }
48
+ return conceptMap;
49
+ }
50
+ /**
51
+ * Reads the mapping rules out of the práctica-mapping ConceptMap, preserving
52
+ * element/target order. Targets with a non-numeric code or an unreadable
53
+ * condition extension are skipped.
54
+ *
55
+ * @param conceptMap - the mapping registry ConceptMap (may be undefined)
56
+ * @returns the parsed rules (empty when the registry is absent or empty)
57
+ */
58
+ function readPracticaMappingRules(conceptMap) {
59
+ var _a, _b, _c;
60
+ const rules = [];
61
+ for (const group of (_a = conceptMap === null || conceptMap === void 0 ? void 0 : conceptMap.group) !== null && _a !== void 0 ? _a : []) {
62
+ if (group.source !== constants_1.EGES_PRACTICA_SYSTEM || group.target !== constants_1.EGES_PRACTICA_SYSTEM) {
63
+ continue;
64
+ }
65
+ for (const element of (_b = group.element) !== null && _b !== void 0 ? _b : []) {
66
+ const sourcePraId = parsePraId(element.code);
67
+ if (sourcePraId === undefined) {
68
+ continue;
69
+ }
70
+ for (const target of (_c = element.target) !== null && _c !== void 0 ? _c : []) {
71
+ const targetPraId = parsePraId(target.code);
72
+ if (targetPraId === undefined) {
73
+ continue;
74
+ }
75
+ rules.push({
76
+ sourcePraId,
77
+ targetPraId,
78
+ condition: readCondition(target),
79
+ ...(target.display !== undefined ? { display: target.display } : {})
80
+ });
81
+ }
82
+ }
83
+ }
84
+ return rules;
85
+ }
86
+ // ─── Matching ────────────────────────────────────────────────────────────────
87
+ /**
88
+ * Finds the winning rule for a source práctica under the given context.
89
+ *
90
+ * Precedence among matching rules:
91
+ * 1. Most matched condition dimensions wins.
92
+ * 2. Insurance tier breaks ties: a plan-tier match beats an obra-social-tier match.
93
+ * 3. Registry order breaks remaining ties (first rule wins).
94
+ *
95
+ * @param rules - all registry rules (in registry order)
96
+ * @param praId - the source pra_id being resolved
97
+ * @param context - the patient-side facts to match against
98
+ * @returns the winning match, or undefined when no rule applies (identity)
99
+ */
100
+ function matchPracticaMapping(rules, praId, context) {
101
+ let winner;
102
+ for (const rule of rules) {
103
+ if (rule.sourcePraId !== praId) {
104
+ continue;
105
+ }
106
+ const matchedConditions = matchConditions(rule.condition, context);
107
+ if (!matchedConditions) {
108
+ continue;
109
+ }
110
+ if (!winner || beats(matchedConditions, winner.matchedConditions)) {
111
+ winner = { rule, matchedConditions };
112
+ }
113
+ }
114
+ return winner;
115
+ }
116
+ /**
117
+ * Evaluates a rule's conditions against the context.
118
+ *
119
+ * @param condition - the rule's conditions
120
+ * @param context - the patient-side facts
121
+ * @returns the matched dimensions, or undefined when any condition fails
122
+ */
123
+ function matchConditions(condition, context) {
124
+ const matched = [];
125
+ if (condition.insuranceRef !== undefined) {
126
+ if (condition.insuranceRef === context.insurancePlanRef) {
127
+ matched.push('insurance-plan');
128
+ }
129
+ else if (condition.insuranceRef === context.insuranceOrgRef) {
130
+ matched.push('insurance-org');
131
+ }
132
+ else {
133
+ return undefined;
134
+ }
135
+ }
136
+ if (condition.ageRange !== undefined) {
137
+ if (context.age === undefined || !isAgeInRange(context.age, condition.ageRange)) {
138
+ return undefined;
139
+ }
140
+ matched.push('age');
141
+ }
142
+ if (condition.sex !== undefined) {
143
+ if (condition.sex !== context.sex) {
144
+ return undefined;
145
+ }
146
+ matched.push('sex');
147
+ }
148
+ return matched;
149
+ }
150
+ /**
151
+ * Whether match `a` takes precedence over match `b`: more matched dimensions
152
+ * first, then plan tier over obra-social tier. Equal specificity keeps `b`
153
+ * (registry order).
154
+ *
155
+ * @param a - the challenger's matched dimensions
156
+ * @param b - the current winner's matched dimensions
157
+ * @returns whether `a` wins over `b`
158
+ */
159
+ function beats(a, b) {
160
+ if (a.length !== b.length) {
161
+ return a.length > b.length;
162
+ }
163
+ return a.includes('insurance-plan') && b.includes('insurance-org');
164
+ }
165
+ /**
166
+ * Computes a patient's exact age (completed years, months, and days) at the
167
+ * given date, so `ageRange` bounds in any unit compare correctly.
168
+ *
169
+ * @param birthDate - ISO date string (`YYYY-MM-DD`)
170
+ * @param at - the reference date (defaults to now)
171
+ * @returns the age, or undefined for an unparsable or future birth date
172
+ */
173
+ function computePatientAge(birthDate, at = new Date()) {
174
+ const parsed = new Date(birthDate);
175
+ if (isNaN(parsed.getTime()) || parsed.getTime() > at.getTime()) {
176
+ return undefined;
177
+ }
178
+ let months = (at.getUTCFullYear() - parsed.getUTCFullYear()) * 12 + (at.getUTCMonth() - parsed.getUTCMonth());
179
+ if (at.getUTCDate() < parsed.getUTCDate()) {
180
+ months--;
181
+ }
182
+ if (months < 0) {
183
+ months = 0;
184
+ }
185
+ const days = Math.floor((at.getTime() - parsed.getTime()) / 86400000);
186
+ return { years: Math.floor(months / 12), months, days };
187
+ }
188
+ // ─── Internal helpers ───────────────────────────────────────────────────────
189
+ /**
190
+ * Normalizes a bound Quantity's unit to years / months / days. Accepts UCUM
191
+ * codes (`a`, `mo`, `d`) plus common Spanish/English unit strings; absent or
192
+ * unknown units default to **years** (the pre-units rule format).
193
+ *
194
+ * @param quantity - a Range bound
195
+ * @param quantity.code - the bound's UCUM code, when present
196
+ * @param quantity.unit - the bound's display unit, used as fallback
197
+ * @returns the normalized age unit
198
+ */
199
+ function boundAgeUnit(quantity) {
200
+ var _a, _b;
201
+ const raw = ((_b = (_a = quantity.code) !== null && _a !== void 0 ? _a : quantity.unit) !== null && _b !== void 0 ? _b : '').toLowerCase();
202
+ if (raw === 'mo' || raw.startsWith('mes') || raw.startsWith('month')) {
203
+ return 'mo';
204
+ }
205
+ if (raw === 'd' || raw.startsWith('día') || raw.startsWith('dia') || raw.startsWith('day')) {
206
+ return 'd';
207
+ }
208
+ return 'a';
209
+ }
210
+ function ageInUnit(age, unit) {
211
+ if (unit === 'mo') {
212
+ return age.months;
213
+ }
214
+ if (unit === 'd') {
215
+ return age.days;
216
+ }
217
+ return age.years;
218
+ }
219
+ /**
220
+ * Inclusive range check with per-bound units: each bound is compared against
221
+ * the patient's completed age in that bound's own unit, so mixed ranges like
222
+ * "desde 6 meses hasta 2 años" work as written.
223
+ *
224
+ * @param age - the patient's exact age
225
+ * @param range - the rule's ageRange
226
+ * @returns whether the age satisfies both bounds
227
+ */
228
+ function isAgeInRange(age, range) {
229
+ var _a, _b;
230
+ if (((_a = range.low) === null || _a === void 0 ? void 0 : _a.value) !== undefined && ageInUnit(age, boundAgeUnit(range.low)) < range.low.value) {
231
+ return false;
232
+ }
233
+ if (((_b = range.high) === null || _b === void 0 ? void 0 : _b.value) !== undefined && ageInUnit(age, boundAgeUnit(range.high)) > range.high.value) {
234
+ return false;
235
+ }
236
+ return true;
237
+ }
238
+ function parsePraId(code) {
239
+ if (!code) {
240
+ return undefined;
241
+ }
242
+ const parsed = parseInt(code, 10);
243
+ return isNaN(parsed) ? undefined : parsed;
244
+ }
245
+ function buildTarget(rule) {
246
+ const conditionExtensions = [];
247
+ if (rule.condition.insuranceRef !== undefined) {
248
+ conditionExtensions.push({ url: 'insurance', valueReference: { reference: rule.condition.insuranceRef } });
249
+ }
250
+ if (rule.condition.ageRange !== undefined) {
251
+ conditionExtensions.push({ url: 'ageRange', valueRange: rule.condition.ageRange });
252
+ }
253
+ if (rule.condition.sex !== undefined) {
254
+ conditionExtensions.push({ url: 'sex', valueCode: rule.condition.sex });
255
+ }
256
+ const target = {
257
+ code: String(rule.targetPraId),
258
+ equivalence: 'equivalent'
259
+ };
260
+ if (rule.display !== undefined) {
261
+ target.display = rule.display;
262
+ }
263
+ if (conditionExtensions.length > 0) {
264
+ target.extension = [
265
+ {
266
+ url: constants_1.PRACTICA_MAPPING_CONDITION_EXTENSION_URL,
267
+ extension: conditionExtensions
268
+ }
269
+ ];
270
+ }
271
+ return target;
272
+ }
273
+ function readCondition(target) {
274
+ var _a, _b, _c, _d, _e, _f;
275
+ const container = (_a = target.extension) === null || _a === void 0 ? void 0 : _a.find((e) => e.url === constants_1.PRACTICA_MAPPING_CONDITION_EXTENSION_URL);
276
+ const subs = (_b = container === null || container === void 0 ? void 0 : container.extension) !== null && _b !== void 0 ? _b : [];
277
+ const insuranceRef = (_d = (_c = subs.find((e) => e.url === 'insurance')) === null || _c === void 0 ? void 0 : _c.valueReference) === null || _d === void 0 ? void 0 : _d.reference;
278
+ const ageRange = (_e = subs.find((e) => e.url === 'ageRange')) === null || _e === void 0 ? void 0 : _e.valueRange;
279
+ const sex = (_f = subs.find((e) => e.url === 'sex')) === null || _f === void 0 ? void 0 : _f.valueCode;
280
+ return {
281
+ ...(insuranceRef !== undefined ? { insuranceRef } : {}),
282
+ ...(ageRange !== undefined ? { ageRange } : {}),
283
+ ...(sex !== undefined ? { sex } : {})
284
+ };
285
+ }
286
+ //# sourceMappingURL=practica-mapping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"practica-mapping.js","sourceRoot":"","sources":["../src/practica-mapping.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ConceptMap, ConceptMapGroupElement, ConceptMapGroupElementTarget, Extension, Range } from '@medplum/fhirtypes'\nimport {\n BILLING_CODES_TAG_SYSTEM,\n EGES_PRACTICA_SYSTEM,\n PRACTICA_MAPPING_CONCEPT_MAP_URL,\n PRACTICA_MAPPING_CONDITION_EXTENSION_URL,\n PRACTICA_MAPPING_TAG_CODE\n} from './constants'\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** FHIR administrative gender codes accepted by mapping conditions. */\nexport type PracticaMappingSex = 'male' | 'female' | 'other' | 'unknown'\n\n/**\n * Conditions under which a mapping rule applies. All present conditions must\n * match (logical AND); a rule with no conditions is an unconditional override.\n */\nexport interface PracticaMappingCondition {\n /**\n * Reference to an `InsurancePlan` (plan tier) or a payer `Organization`\n * (obra social tier), e.g. `InsurancePlan/123` / `Organization/45`.\n */\n readonly insuranceRef?: string\n /**\n * Patient age range; bounds inclusive, either side may be open. Each bound\n * Quantity may carry a UCUM code (`a` years, `mo` months, `d` days) —\n * absent unit means years — and each bound is evaluated in its own unit.\n */\n readonly ageRange?: Range\n /** FHIR administrative gender. */\n readonly sex?: PracticaMappingSex\n}\n\n/** One práctica → práctica substitution rule from the mapping registry. */\nexport interface PracticaMappingRule {\n /** EGES pra_id the rule applies to. */\n readonly sourcePraId: number\n /** EGES pra_id substituted when the rule matches. */\n readonly targetPraId: number\n readonly condition: PracticaMappingCondition\n /** Optional human label for the admin editor. */\n readonly display?: string\n}\n\n/** Units accepted on `ageRange` bounds (UCUM): years, months, days. */\nexport type PracticaAgeUnit = 'a' | 'mo' | 'd'\n\n/**\n * The patient's exact age at resolution time, floored per calendar unit, so\n * `ageRange` bounds expressed in days, months, or years all compare exactly.\n */\nexport interface PatientAge {\n /** Completed calendar years. */\n readonly years: number\n /** Completed calendar months. */\n readonly months: number\n /** Completed days. */\n readonly days: number\n}\n\n/**\n * The patient-side facts a rule's conditions are matched against. Resolved\n * once per booking (see `resolvePracticaMappingContext`).\n */\nexport interface PracticaMappingContext {\n /** `InsurancePlan/{id}` reference of the patient's plan, when known. */\n readonly insurancePlanRef?: string\n /** `Organization/{id}` reference of the plan's payer, when known. */\n readonly insuranceOrgRef?: string\n /** Patient age at resolution time, when known. */\n readonly age?: PatientAge\n readonly sex?: PracticaMappingSex\n}\n\n/** Which condition dimensions a matching rule satisfied (for audit/UI). */\nexport type PracticaMappingMatchedCondition = 'insurance-plan' | 'insurance-org' | 'age' | 'sex'\n\n/** A matched rule plus the dimensions it matched on. */\nexport interface PracticaMappingMatch {\n readonly rule: PracticaMappingRule\n readonly matchedConditions: readonly PracticaMappingMatchedCondition[]\n}\n\n// ─── ConceptMap serialization ────────────────────────────────────────────────\n\n/**\n * Builds the singleton práctica-mapping ConceptMap from a list of rules.\n * Rule order is preserved (it is the final precedence tie-break).\n *\n * @param rules - the mapping rules to serialize\n * @param existingId - optional resource id to reuse when updating\n * @returns the ConceptMap resource ready to be saved\n */\nexport function buildPracticaMappingConceptMap (\n rules: readonly PracticaMappingRule[],\n existingId?: string\n): ConceptMap {\n const elementsBySource = new Map<number, ConceptMapGroupElement>()\n for (const rule of rules) {\n let element = elementsBySource.get(rule.sourcePraId)\n if (!element) {\n element = { code: String(rule.sourcePraId), target: [] }\n elementsBySource.set(rule.sourcePraId, element)\n }\n element.target?.push(buildTarget(rule))\n }\n\n const conceptMap: ConceptMap = {\n resourceType: 'ConceptMap',\n url: PRACTICA_MAPPING_CONCEPT_MAP_URL,\n status: 'active',\n name: 'PracticaMapping',\n title: 'Mapeo de prácticas por cobertura, edad y sexo',\n meta: {\n tag: [{ system: BILLING_CODES_TAG_SYSTEM, code: PRACTICA_MAPPING_TAG_CODE }]\n },\n group: [\n {\n source: EGES_PRACTICA_SYSTEM,\n target: EGES_PRACTICA_SYSTEM,\n element: Array.from(elementsBySource.values())\n }\n ]\n }\n\n if (existingId) {\n conceptMap.id = existingId\n }\n\n return conceptMap\n}\n\n/**\n * Reads the mapping rules out of the práctica-mapping ConceptMap, preserving\n * element/target order. Targets with a non-numeric code or an unreadable\n * condition extension are skipped.\n *\n * @param conceptMap - the mapping registry ConceptMap (may be undefined)\n * @returns the parsed rules (empty when the registry is absent or empty)\n */\nexport function readPracticaMappingRules (conceptMap: ConceptMap | undefined): PracticaMappingRule[] {\n const rules: PracticaMappingRule[] = []\n for (const group of conceptMap?.group ?? []) {\n if (group.source !== EGES_PRACTICA_SYSTEM || group.target !== EGES_PRACTICA_SYSTEM) {\n continue\n }\n for (const element of group.element ?? []) {\n const sourcePraId = parsePraId(element.code)\n if (sourcePraId === undefined) {\n continue\n }\n for (const target of element.target ?? []) {\n const targetPraId = parsePraId(target.code)\n if (targetPraId === undefined) {\n continue\n }\n rules.push({\n sourcePraId,\n targetPraId,\n condition: readCondition(target),\n ...(target.display !== undefined ? { display: target.display } : {})\n })\n }\n }\n }\n return rules\n}\n\n// ─── Matching ────────────────────────────────────────────────────────────────\n\n/**\n * Finds the winning rule for a source práctica under the given context.\n *\n * Precedence among matching rules:\n * 1. Most matched condition dimensions wins.\n * 2. Insurance tier breaks ties: a plan-tier match beats an obra-social-tier match.\n * 3. Registry order breaks remaining ties (first rule wins).\n *\n * @param rules - all registry rules (in registry order)\n * @param praId - the source pra_id being resolved\n * @param context - the patient-side facts to match against\n * @returns the winning match, or undefined when no rule applies (identity)\n */\nexport function matchPracticaMapping (\n rules: readonly PracticaMappingRule[],\n praId: number,\n context: PracticaMappingContext\n): PracticaMappingMatch | undefined {\n let winner: PracticaMappingMatch | undefined\n\n for (const rule of rules) {\n if (rule.sourcePraId !== praId) {\n continue\n }\n const matchedConditions = matchConditions(rule.condition, context)\n if (!matchedConditions) {\n continue\n }\n if (!winner || beats(matchedConditions, winner.matchedConditions)) {\n winner = { rule, matchedConditions }\n }\n }\n\n return winner\n}\n\n/**\n * Evaluates a rule's conditions against the context.\n *\n * @param condition - the rule's conditions\n * @param context - the patient-side facts\n * @returns the matched dimensions, or undefined when any condition fails\n */\nfunction matchConditions (\n condition: PracticaMappingCondition,\n context: PracticaMappingContext\n): PracticaMappingMatchedCondition[] | undefined {\n const matched: PracticaMappingMatchedCondition[] = []\n\n if (condition.insuranceRef !== undefined) {\n if (condition.insuranceRef === context.insurancePlanRef) {\n matched.push('insurance-plan')\n } else if (condition.insuranceRef === context.insuranceOrgRef) {\n matched.push('insurance-org')\n } else {\n return undefined\n }\n }\n\n if (condition.ageRange !== undefined) {\n if (context.age === undefined || !isAgeInRange(context.age, condition.ageRange)) {\n return undefined\n }\n matched.push('age')\n }\n\n if (condition.sex !== undefined) {\n if (condition.sex !== context.sex) {\n return undefined\n }\n matched.push('sex')\n }\n\n return matched\n}\n\n/**\n * Whether match `a` takes precedence over match `b`: more matched dimensions\n * first, then plan tier over obra-social tier. Equal specificity keeps `b`\n * (registry order).\n *\n * @param a - the challenger's matched dimensions\n * @param b - the current winner's matched dimensions\n * @returns whether `a` wins over `b`\n */\nfunction beats (\n a: readonly PracticaMappingMatchedCondition[],\n b: readonly PracticaMappingMatchedCondition[]\n): boolean {\n if (a.length !== b.length) {\n return a.length > b.length\n }\n return a.includes('insurance-plan') && b.includes('insurance-org')\n}\n\n/**\n * Computes a patient's exact age (completed years, months, and days) at the\n * given date, so `ageRange` bounds in any unit compare correctly.\n *\n * @param birthDate - ISO date string (`YYYY-MM-DD`)\n * @param at - the reference date (defaults to now)\n * @returns the age, or undefined for an unparsable or future birth date\n */\nexport function computePatientAge (birthDate: string, at: Date = new Date()): PatientAge | undefined {\n const parsed = new Date(birthDate)\n if (isNaN(parsed.getTime()) || parsed.getTime() > at.getTime()) {\n return undefined\n }\n let months = (at.getUTCFullYear() - parsed.getUTCFullYear()) * 12 + (at.getUTCMonth() - parsed.getUTCMonth())\n if (at.getUTCDate() < parsed.getUTCDate()) {\n months--\n }\n if (months < 0) {\n months = 0\n }\n const days = Math.floor((at.getTime() - parsed.getTime()) / 86_400_000)\n return { years: Math.floor(months / 12), months, days }\n}\n\n// ─── Internal helpers ───────────────────────────────────────────────────────\n\n/**\n * Normalizes a bound Quantity's unit to years / months / days. Accepts UCUM\n * codes (`a`, `mo`, `d`) plus common Spanish/English unit strings; absent or\n * unknown units default to **years** (the pre-units rule format).\n *\n * @param quantity - a Range bound\n * @param quantity.code - the bound's UCUM code, when present\n * @param quantity.unit - the bound's display unit, used as fallback\n * @returns the normalized age unit\n */\nfunction boundAgeUnit (quantity: { code?: string, unit?: string }): PracticaAgeUnit {\n const raw = (quantity.code ?? quantity.unit ?? '').toLowerCase()\n if (raw === 'mo' || raw.startsWith('mes') || raw.startsWith('month')) {\n return 'mo'\n }\n if (raw === 'd' || raw.startsWith('día') || raw.startsWith('dia') || raw.startsWith('day')) {\n return 'd'\n }\n return 'a'\n}\n\nfunction ageInUnit (age: PatientAge, unit: PracticaAgeUnit): number {\n if (unit === 'mo') {\n return age.months\n }\n if (unit === 'd') {\n return age.days\n }\n return age.years\n}\n\n/**\n * Inclusive range check with per-bound units: each bound is compared against\n * the patient's completed age in that bound's own unit, so mixed ranges like\n * \"desde 6 meses hasta 2 años\" work as written.\n *\n * @param age - the patient's exact age\n * @param range - the rule's ageRange\n * @returns whether the age satisfies both bounds\n */\nfunction isAgeInRange (age: PatientAge, range: Range): boolean {\n if (range.low?.value !== undefined && ageInUnit(age, boundAgeUnit(range.low)) < range.low.value) {\n return false\n }\n if (range.high?.value !== undefined && ageInUnit(age, boundAgeUnit(range.high)) > range.high.value) {\n return false\n }\n return true\n}\n\nfunction parsePraId (code: string | undefined): number | undefined {\n if (!code) {\n return undefined\n }\n const parsed = parseInt(code, 10)\n return isNaN(parsed) ? undefined : parsed\n}\n\nfunction buildTarget (rule: PracticaMappingRule): ConceptMapGroupElementTarget {\n const conditionExtensions: Extension[] = []\n if (rule.condition.insuranceRef !== undefined) {\n conditionExtensions.push({ url: 'insurance', valueReference: { reference: rule.condition.insuranceRef } })\n }\n if (rule.condition.ageRange !== undefined) {\n conditionExtensions.push({ url: 'ageRange', valueRange: rule.condition.ageRange })\n }\n if (rule.condition.sex !== undefined) {\n conditionExtensions.push({ url: 'sex', valueCode: rule.condition.sex })\n }\n\n const target: ConceptMapGroupElementTarget = {\n code: String(rule.targetPraId),\n equivalence: 'equivalent'\n }\n if (rule.display !== undefined) {\n target.display = rule.display\n }\n if (conditionExtensions.length > 0) {\n target.extension = [\n {\n url: PRACTICA_MAPPING_CONDITION_EXTENSION_URL,\n extension: conditionExtensions\n }\n ]\n }\n return target\n}\n\nfunction readCondition (target: ConceptMapGroupElementTarget): PracticaMappingCondition {\n const container = target.extension?.find((e) => e.url === PRACTICA_MAPPING_CONDITION_EXTENSION_URL)\n const subs = container?.extension ?? []\n const insuranceRef = subs.find((e) => e.url === 'insurance')?.valueReference?.reference\n const ageRange = subs.find((e) => e.url === 'ageRange')?.valueRange\n const sex = subs.find((e) => e.url === 'sex')?.valueCode as PracticaMappingSex | undefined\n return {\n ...(insuranceRef !== undefined ? { insuranceRef } : {}),\n ...(ageRange !== undefined ? { ageRange } : {}),\n ...(sex !== undefined ? { sex } : {})\n }\n}\n"]}