@fuego-systems/core 0.1.14 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants.d.ts +24 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +28 -2
- package/dist/constants.js.map +1 -1
- package/dist/plan-definition-group.d.ts +64 -1
- package/dist/plan-definition-group.d.ts.map +1 -1
- package/dist/plan-definition-group.js +133 -6
- package/dist/plan-definition-group.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -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// ─── Types ───────────────────────────────────────────────────────────────────\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\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\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 if (subActions.length > 0) {\n action.action = subActions\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 const isMandatory = sub.requiredBehavior === 'must'\n const isOn = isSelected && (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) { 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)\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 }\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":";;;AAkIA,0CAIC;AAUD,gDAMC;AAQD,gDASC;AAQD,kDAEC;AAQD,gGAEC;AAaD,gDAqEC;AAsDD,wDAoCC;AAWD,4DA+BC;AAaD,sDAwBC;AA+CD,kEAgBC;AAaD,sEAeC;AAhhBD,2CAA8H;AAE9H;;;;;;;;GAQG;AACU,QAAA,kCAAkC,GAAG,kBAAkB,CAAA;AAEpE;;;;;GAKG;AACH,MAAM,kBAAkB,GAAG,mDAAmD,CAAA;AAC9E,MAAM,eAAe,GAAG,QAAQ,CAAA;AAChC,MAAM,kBAAkB,GAAG,QAAQ,CAAA;AAoGnC,gFAAgF;AAEhF;;;;;GAKG;AACH,SAAgB,eAAe,CAAE,EAAkB;;IACjD,OAAO,CAAC,MAAA,MAAA,EAAE,CAAC,IAAI,0CAAE,MAAM,mCAAI,EAAE,CAAC,CAAC,IAAI,CACjC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,0BAAc,IAAI,CAAC,CAAC,IAAI,KAAK,kCAAsB,CACxE,CAAA;AACH,CAAC;AAED,gFAAgF;AAEhF;;;;;GAKG;AACH,SAAgB,kBAAkB,CAAE,EAAkB;;IACpD,OAAO,CAAC,MAAA,EAAE,CAAC,MAAM,mCAAI,EAAE,CAAC;SACrB,MAAM,CAAC,CAAC,CAAC,EAA+D,EAAE,CACzE,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAC/B;SACA,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAA;AACzD,CAAC;AAED;;;;;GAKG;AACH,SAAgB,kBAAkB,CAAE,EAAkB;;IACpD,MAAM,MAAM,GAAG,CAAC,MAAA,EAAE,CAAC,MAAM,mCAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAA;IAChE,IAAI,CAAC,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,mBAAmB,CAAA,EAAE,CAAC;QAAC,OAAO,SAAS,CAAA;IAAC,CAAC;IACtD,OAAO;QACL,GAAG,EAAE,MAAM,CAAC,mBAAmB;QAC/B,OAAO,EAAE,MAAA,MAAM,CAAC,KAAK,mCAAI,EAAE;QAC3B,IAAI,EAAE,oBAAoB,CAAC,MAAM,CAAC;QAClC,QAAQ,EAAE,MAAM,CAAC,cAAc;KAChC,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAgB,mBAAmB,CAAE,EAAkB;IACrD,OAAO,kBAAkB,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;AAC3D,CAAC;AAED;;;;;GAKG;AACH,SAAgB,0CAA0C,CAAE,EAAkB;;IAC5E,OAAO,MAAA,MAAA,MAAA,EAAE,CAAC,SAAS,0CAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,+CAAmC,CAAC,0CAAE,cAAc,0CAAE,SAAS,CAAA;AAC5G,CAAC;AAED,gFAAgF;AAEhF;;;;;;;;GAQG;AACH,SAAgB,kBAAkB,CAChC,KAAa,EACb,OAA4C,EAC5C,UAAmB,EACnB,WAAoB;IAEpB,MAAM,OAAO,GAA2B,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;;QACxD,MAAM,UAAU,GAAG,CAAC,MAAA,CAAC,CAAC,MAAM,mCAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAChD,WAAW,CACT,KAAK,CAAC,EAAE,EACR,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,GAAG,EACT,KAAK,CAAC,IAAI,EACV,KAAK,CAAC,QAAQ,EACd,KAAK,CAAC,QAAQ,EACd,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,SAAS,CAChB,CACF,CAAA;QAED,MAAM,MAAM,GAAG,WAAW,CACxB,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAC9B,CAAC,CAAC,OAAO,EACT,CAAC,CAAC,GAAG,EACL,CAAC,CAAC,IAAI,EACN,CAAC,CAAC,QAAQ,EACV,CAAC,CAAC,QAAQ,EACV,CAAC,CAAC,KAAK,CACR,CAAA;QAED,uDAAuD;QACvD,MAAM,CAAC,iBAAiB,GAAG,aAAa,CAAA;QAExC,MAAM,aAAa,GAAG,gCAAgC,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAA;QACjF,MAAM,YAAY,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,UAAU,CAAA;QAEhF,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,CAAC,MAAM,GAAG,YAAY,CAAA;YAC5B,mEAAmE;YACnE,MAAM,CAAC,gBAAgB,GAAG,eAAe,CAAA;QAC3C,CAAC;QAED,OAAO,MAAM,CAAA;IACf,CAAC,CAAC,CAAA;IAEF,MAAM,EAAE,GAAmB;QACzB,YAAY,EAAE,gBAAgB;QAC9B,MAAM,EAAE,QAAQ;QAChB,KAAK;QACL,IAAI,EAAE;YACJ,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,0BAAc,EAAE,IAAI,EAAE,kCAAsB,EAAE,CAAC;SACnE;QACD,MAAM,EAAE,OAAO;KAChB,CAAA;IAED,IAAI,WAAW,EAAE,CAAC;QAChB,EAAE,CAAC,SAAS,GAAG;YACb;gBACE,GAAG,EAAE,+CAAmC;gBACxC,cAAc,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE;aAC3C;SACF,CAAA;IACH,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,EAAE,CAAC,EAAE,GAAG,UAAU,CAAA;IACpB,CAAC;IAED,OAAO,EAAE,CAAA;AACX,CAAC;AAoCD;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAgB,sBAAsB,CACpC,EAAkB,EAClB,SAA4B;;IAE5B,MAAM,OAAO,GAAG,MAAA,EAAE,CAAC,MAAM,mCAAI,EAAE,CAAA;IAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,QAAQ,CAAC,CAAA;IAC9D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,WAAW,SAAS,CAAC,QAAQ,8CAA8C,CAAC,CAAA;IAC9F,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;IAE5C,OAAO;QACL,GAAG,EAAE;QACL,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;;YACxB,MAAM,UAAU,GAAG,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,QAAQ,CAAA;YAC9C,MAAM,UAAU,GAAG,CAAC,MAAA,CAAC,CAAC,MAAM,mCAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;;gBAC9C,oEAAoE;gBACpE,mEAAmE;gBACnE,mDAAmD;gBACnD,MAAM,eAAe,GAAG,GAAG,CAAC,EAAE,KAAK,0CAAkC,CAAA;gBACrE,MAAM,WAAW,GAAG,GAAG,CAAC,gBAAgB,KAAK,MAAM,CAAA;gBACnD,MAAM,IAAI,GAAG,UAAU,IAAI,CAAC,eAAe,IAAI,CAAC,WAAW,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAA,GAAG,CAAC,EAAE,mCAAI,EAAE,CAAC,CAAC,CAAA;gBAC1F,OAAO;oBACL,GAAG,GAAG;oBACN,gBAAgB,EAAE,IAAI,CAAC,CAAC,CAAC,KAAc,CAAC,CAAC,CAAC,IAAa;iBACxD,CAAA;YACH,CAAC,CAAC,CAAA;YAEF,OAAO;gBACL,GAAG,CAAC;gBACJ,gBAAgB,EAAE,UAAU,CAAC,CAAC,CAAC,KAAc,CAAC,CAAC,CAAC,IAAa;gBAC7D,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC5C,CAAA;QACH,CAAC,CAAC;KACH,CAAA;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,wBAAwB,CACtC,EAAkB,EAClB,SAA4B;;IAE5B,MAAM,OAAO,GAAG,MAAA,EAAE,CAAC,MAAM,mCAAI,EAAE,CAAA;IAC/B,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,QAAQ,CAAC,CAAA;IACjE,IAAI,CAAC,CAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,mBAAmB,CAAA,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,WAAW,SAAS,CAAC,QAAQ,8CAA8C,CAAC,CAAA;IAC9F,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;IAC5C,MAAM,cAAc,GAA6B,CAAC,MAAA,QAAQ,CAAC,MAAM,mCAAI,EAAE,CAAC;SACrE,MAAM,CAAC,CAAC,GAAG,EAA6E,EAAE;QACzF,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC;YAAC,OAAO,KAAK,CAAA;QAAC,CAAC;QACzD,MAAM,WAAW,GAAG,GAAG,CAAC,gBAAgB,KAAK,MAAM,CAAA;QACnD,OAAO,WAAW,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAC5C,CAAC,CAAC;SACD,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACb,WAAW,EAAE,GAAG,CAAC,mBAAmB;QACpC,WAAW,EAAE,oBAAoB,CAAC,GAAG,CAAC;QACtC,QAAQ,EAAE,GAAG,CAAC,cAAc;KAC7B,CAAC,CAAC,CAAA;IAEL,OAAO;QACL,IAAI,EAAE;YACJ,WAAW,EAAE,QAAQ,CAAC,mBAAmB;YACzC,WAAW,EAAE,oBAAoB,CAAC,QAAQ,CAAC;YAC3C,QAAQ,EAAE,QAAQ,CAAC,cAAc;SAClC;QACD,MAAM,EAAE,cAAc;KACvB,CAAA;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,qBAAqB,CAAE,EAAkB;;IACvD,MAAM,OAAO,GAAG,MAAA,EAAE,CAAC,MAAM,mCAAI,EAAE,CAAA;IAE/B,qDAAqD;IACrD,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,KAAK,KAAK,CAAC,CAAA;IACpE,IAAI,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,EAAE,EAAE,CAAC;QACnB,MAAM,QAAQ,GAAG,CAAC,MAAA,UAAU,CAAC,MAAM,mCAAI,EAAE,CAAC;aACvC,MAAM,CAAC,CAAC,GAAG,EAAgD,EAAE;YAC5D,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,EAAE,KAAK,0CAAkC,EAAE,CAAC;gBAAC,OAAO,KAAK,CAAA;YAAC,CAAC;YAC9E,IAAI,GAAG,CAAC,gBAAgB,KAAK,MAAM,EAAE,CAAC;gBAAC,OAAO,IAAI,CAAA;YAAC,CAAC;YACpD,OAAO,GAAG,CAAC,gBAAgB,KAAK,KAAK,CAAA;QACvC,CAAC,CAAC;aACD,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACvB,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAA;IAC9C,CAAC;IAED,8DAA8D;IAC9D,MAAM,aAAa,GAAG,MAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,mCAAI,OAAO,CAAC,CAAC,CAAC,CAAA;IAC3E,MAAM,iBAAiB,GAAG,CAAC,MAAA,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAE,MAAM,mCAAI,EAAE,CAAC;SACpD,MAAM,CAAC,CAAC,GAAG,EAAgD,EAAE,CAC5D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,gBAAgB,KAAK,MAAM,CACnD;SACA,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACvB,OAAO,EAAE,QAAQ,EAAE,MAAA,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAE,EAAE,mCAAI,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE,CAAA;AAC3E,CAAC;AAED,+EAA+E;AAE/E,SAAS,oBAAoB,CAAE,MAA4B;;IACzD,MAAM,MAAM,GAAG,CAAC,MAAA,MAAM,CAAC,IAAI,mCAAI,EAAE,CAAC;SAC/B,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,WAAC,OAAA,MAAA,EAAE,CAAC,MAAM,mCAAI,EAAE,CAAA,EAAA,CAAC;SAChC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,+BAAmB,CAAC,CAAA;IAChD,OAAO,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,mCAAI,EAAE,CAAA;AAC3B,CAAC;AAED,SAAS,cAAc,CAAE,KAAyB;IAChD,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;QAAC,OAAO,IAAI,CAAA;IAAC,CAAC;IACpC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAAC,OAAO,KAAK,CAAA;IAAC,CAAC;IACpC,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,SAAS,iBAAiB,CAAE,CAAyD,EAAE,SAAkB;;IACvG,MAAM,UAAU,GAAG,CAAC,MAAA,CAAC,CAAC,MAAM,mCAAI,EAAE,CAAC;SAChC,MAAM,CAAC,CAAC,GAAG,EAAiE,EAAE,CAC7E,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,GAAG,CAAC,EAAE,KAAK,0CAAkC,CAClF;SACA,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAA;IAE9C,OAAO;QACL,QAAQ,EAAE,MAAA,CAAC,CAAC,EAAE,mCAAI,EAAE;QACpB,SAAS;QACT,KAAK,EAAE,MAAA,MAAA,CAAC,CAAC,cAAc,mCAAI,CAAC,CAAC,KAAK,mCAAI,EAAE;QACxC,QAAQ,EAAE,MAAA,CAAC,CAAC,WAAW,mCAAI,EAAE;QAC7B,WAAW,EAAE,CAAC,CAAC,mBAAmB;QAClC,eAAe,EAAE,MAAA,CAAC,CAAC,KAAK,mCAAI,EAAE;QAC9B,YAAY,EAAE,oBAAoB,CAAC,CAAC,CAAC;QACrC,QAAQ,EAAE,CAAC,CAAC,cAAc;QAC1B,UAAU,EAAE,cAAc,CAAC,CAAC,CAAC,gBAAgB,CAAC;QAC9C,SAAS,EAAE,CAAC,CAAC,gBAAgB,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QAC3D,MAAM,EAAE,UAAU;QAClB,uBAAuB,EAAE,2BAA2B,CAAC,CAAC,CAAC;KACxD,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,2BAA2B,CACzC,aAAmC;;IAEnC,MAAM,KAAK,GAAG,CAAC,MAAA,aAAa,CAAC,MAAM,mCAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,0CAAkC,CAAC,CAAA;IACvG,MAAM,MAAM,GAA6B,EAAE,CAAA;IAC3C,KAAK,MAAM,GAAG,IAAI,MAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,MAAM,mCAAI,EAAE,EAAE,CAAC;QACtC,IAAI,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC;YAAC,SAAQ;QAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,4BAA4B,CAAC,GAAG,CAAC,CAAA;QAChD,IAAI,CAAC,MAAM,EAAE,CAAC;YAAC,SAAQ;QAAC,CAAC;QACzB,MAAM,CAAC,IAAI,CACT,GAAG,CAAC,KAAK,KAAK,SAAS;YACrB,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,mBAAmB,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,KAAK,EAAE;YAC9D,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,mBAAmB,EAAE,MAAM,EAAE,CAC7C,CAAA;IACH,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,6BAA6B,CAC3C,WAA8B,EAC9B,aAA+C;IAE/C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAA;IACrC,IAAI,aAAa,EAAE,CAAC;QAClB,KAAK,MAAM,QAAQ,IAAI,2BAA2B,CAAC,aAAa,CAAC,EAAE,CAAC;YAClE,IAAI,QAAQ,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;gBAC9B,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;YAC5B,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;AAC7B,CAAC;AAED;;;;;GAKG;AACH,SAAS,4BAA4B,CACnC,GAAyB;;IAEzB,MAAM,IAAI,GAAG,MAAA,CAAC,MAAA,MAAA,GAAG,CAAC,IAAI,0CAAE,MAAM,mCAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,kBAAkB,CAAC,0CAAE,IAAI,CAAA;IACxF,IAAI,IAAI,KAAK,eAAe,EAAE,CAAC;QAAC,OAAO,KAAK,CAAA;IAAC,CAAC;IAC9C,IAAI,IAAI,KAAK,kBAAkB,EAAE,CAAC;QAAC,OAAO,QAAQ,CAAA;IAAC,CAAC;IACpD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,gCAAgC,CACvC,SAAwD;IAExD,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzC,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,OAAO;QACL,EAAE,EAAE,0CAAkC;QACtC,KAAK,EAAE,kDAAkD;QACzD,iBAAiB,EAAE,KAAK;QACxB,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAC1B,MAAM,GAAG,GAAyB;gBAChC,mBAAmB,EAAE,CAAC,CAAC,GAAG;gBAC1B,IAAI,EAAE;oBACJ,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,kBAAkB,EAAE,CAAC;iBAC1G;aACF,CAAA;YACD,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;gBACd,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,OAAO,CAAA;YACvB,CAAC;YACD,OAAO,GAAG,CAAA;QACZ,CAAC,CAAC;KACH,CAAA;AACH,CAAC;AAED,SAAS,WAAW,CAClB,EAAU,EACV,KAAa,EACb,GAAW,EACX,IAAY,EACZ,QAAmB,EACnB,QAAiB,EACjB,aAAsB,EACtB,SAAmB;IAEnB,MAAM,MAAM,GAAyB;QACnC,EAAE;QACF,KAAK;QACL,mBAAmB,EAAE,GAAG;KACzB,CAAA;IACD,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,CAAC,IAAI,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,+BAAmB,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAA;IACrE,CAAC;IACD,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,CAAC,cAAc,GAAG,QAAQ,CAAA;IAClC,CAAC;IACD,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,CAAC,WAAW,GAAG,QAAQ,CAAA;IAC/B,CAAC;IACD,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,CAAC,cAAc,GAAG,aAAa,CAAA;IACvC,CAAC;IACD,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,CAAC,gBAAgB,GAAG,MAAM,CAAA;IAClC,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC","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"]}
|