@fuego-systems/core 0.1.6 → 0.1.7
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 +12 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +14 -1
- package/dist/constants.js.map +1 -1
- package/dist/plan-definition-group.d.ts +74 -0
- package/dist/plan-definition-group.d.ts.map +1 -1
- package/dist/plan-definition-group.js +116 -0
- package/dist/plan-definition-group.js.map +1 -1
- package/dist/scheduling/appointment.d.ts.map +1 -1
- package/dist/scheduling/appointment.js +7 -0
- package/dist/scheduling/appointment.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/dist/constants.d.ts
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
export declare const FHIR_BASE = "https://www.cdrossi.com/fhir";
|
|
2
2
|
export declare const EGES_SYSTEM_BASE = "https://www.cdrossi.com/eges";
|
|
3
|
+
export declare const EGES_PACIENTE_SYSTEM = "https://www.cdrossi.com/eges/paciente";
|
|
4
|
+
export declare const EGES_DOCUMENTO_SYSTEM = "https://www.cdrossi.com/eges/documentos";
|
|
5
|
+
export declare const EGES_SUCURSAL_SYSTEM = "https://www.cdrossi.com/eges/sucursal";
|
|
6
|
+
export declare const EGES_MEDICO_SYSTEM = "https://www.cdrossi.com/eges/medico";
|
|
7
|
+
export declare const EGES_MEDICO_ASOCIACION_SYSTEM = "https://www.cdrossi.com/eges/medico-asociacion";
|
|
8
|
+
export declare const EGES_EQUIPO_SYSTEM = "https://www.cdrossi.com/eges/equipo";
|
|
9
|
+
export declare const EGES_TURNO_SYSTEM = "https://www.cdrossi.com/eges/turno";
|
|
10
|
+
export declare const EGES_PRACTICA_SYSTEM = "https://www.cdrossi.com/eges/practica";
|
|
11
|
+
export declare const EGES_PRESTACION_SYSTEM = "https://www.cdrossi.com/eges/prestacion";
|
|
12
|
+
export declare const RENAPER_BASE = "https://www.argentina.gob.ar/interior/renaper";
|
|
13
|
+
export declare const MATRICULA_NACIONAL_SYSTEM = "https://www.argentina.gob.ar/interior/renaper/matricula-nacional";
|
|
14
|
+
export declare const MATRICULA_PROVINCIAL_SYSTEM = "https://www.argentina.gob.ar/interior/renaper/matricula-provincial";
|
|
3
15
|
export declare const SCHEDULING_PARAMETERS_EXTENSION_URL = "http://medplum.com/fhir/StructureDefinition/scheduling-parameters";
|
|
4
16
|
export declare const REQUIRES_PRACTITIONER_EXTENSION_URL = "https://www.cdrossi.com/fhir/requires-practitioner";
|
|
5
17
|
export declare const SERVICE_TYPE_SYSTEM = "https://www.cdrossi.com/fhir/service-type";
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,iCAAiC,CAAA;AACvD,eAAO,MAAM,gBAAgB,iCAAiC,CAAA;AAE9D,eAAO,MAAM,mCAAmC,sEAAsE,CAAA;AACtH,eAAO,MAAM,mCAAmC,uDAAuC,CAAA;AACvF,eAAO,MAAM,mBAAmB,8CAA8B,CAAA;AAE9D,eAAO,MAAM,wBAAwB,8DAA8C,CAAA;AACnF,eAAO,MAAM,gCAAgC,cAAc,CAAA;AAG3D,eAAO,MAAM,mBAAmB,uCAAuB,CAAA;AACvD,eAAO,MAAM,yBAAyB,6CAA6B,CAAA;AACnE,eAAO,MAAM,0BAA0B,8CAA8B,CAAA;AACrE,eAAO,MAAM,8BAA8B,8BAAsC,CAAA;AACjF,eAAO,MAAM,yBAAyB,yBAAiC,CAAA;AACvE,eAAO,MAAM,wBAAwB,wBAAgC,CAAA;AACrE,eAAO,MAAM,sBAAsB,sBAA8B,CAAA;AACjE,eAAO,MAAM,yBAAyB,yBAAiC,CAAA;AACvE,eAAO,MAAM,6BAA6B,6BAAqC,CAAA;AAE/E,eAAO,MAAM,sBAAsB,mDAAmD,CAAA;AACtF,eAAO,MAAM,gCAAgC,+BAA+B,CAAA;AAC5E,eAAO,MAAM,4BAA4B,yDAAyD,CAAA;AAClG,eAAO,MAAM,6BAA6B,0DAA0D,CAAA;AAIpG,oDAAoD;AACpD,eAAO,MAAM,cAAc,iEAAiD,CAAA;AAE5E,iGAAiG;AACjG,eAAO,MAAM,sBAAsB,mBAAmB,CAAA;AAItD,yGAAyG;AACzG,eAAO,MAAM,oBAAoB,0DAA0C,CAAA;AAE3E,yEAAyE;AACzE,eAAO,MAAM,uBAAuB,6DAA6C,CAAA;AAEjF,oEAAoE;AACpE,eAAO,MAAM,iBAAiB,uDAAuC,CAAA;AAErE,wGAAwG;AACxG,eAAO,MAAM,yBAAyB,iEAAiD,CAAA;AAEvF,mGAAmG;AACnG,eAAO,MAAM,wBAAwB,gEAAgD,CAAA;AAErF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,+BAA+B,uEAAuD,CAAA;AAInG,6EAA6E;AAC7E,eAAO,MAAM,yBAAyB,qDAAqC,CAAA;AAE3E,wCAAwC;AACxC,eAAO,MAAM,eAAe,4DAA4D,CAAA;AAExF,iDAAiD;AACjD,eAAO,MAAM,iBAAiB,QAAQ,CAAA;AAEtC,uEAAuE;AACvE,eAAO,MAAM,kBAAkB,SAAS,CAAA;AAIxC,6EAA6E;AAC7E,eAAO,MAAM,gCAAgC,4DAA4C,CAAA;AAIzF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,sCAAsB,CAAA;AAE3D;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,kBAAkB,CAAA;AAErD;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,6EAA6D,CAAA;AAErG;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,yDAAyC,CAAA;AAEtF;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,6DAA6D,CAAA;AACpG,eAAO,MAAM,wBAAwB,SAAS,CAAA"}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"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"}
|
package/dist/constants.js
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.BILLING_CID_CONTEXT_SYSTEM = exports.BILLING_CID_PD_IDENTIFIER_SYSTEM = exports.BILLING_CODES_ORG_EXTENSION = exports.BILLING_CODES_TAG_CODE = exports.BILLING_CODES_TAG_SYSTEM = exports.INSURANCE_PLAN_IDENTIFIER_SYSTEM = exports.ORG_TYPE_PROV_CODE = exports.ORG_TYPE_PAY_CODE = exports.ORG_TYPE_SYSTEM = exports.INSURER_IDENTIFIER_SYSTEM = exports.HS_SEARCH_ALIASES_EXTENSION_URL = exports.HS_BILLING_EXTENSION_URL = exports.HS_PROTOCOL_EXTENSION_URL = exports.SPECIALITY_SYSTEM = exports.SERVICE_CATEGORY_SYSTEM = exports.SERVICE_CODES_SYSTEM = exports.PD_TYPE_PROTOCOL_GROUP = exports.PD_TYPE_SYSTEM = exports.HL7_IMPORT_TASK_OUTPUT_SYSTEM = exports.HL7_IMPORT_TASK_INPUT_SYSTEM = exports.HL7_IMPORT_APPOINTMENT_TASK_CODE = exports.HL7_IMPORT_TASK_SYSTEM = exports.MIGRATE_APPOINTMENT_TASK_CODE = exports.MIGRATE_SERVICE_TASK_CODE = exports.MIGRATE_SITE_TASK_CODE = exports.MIGRATE_DEVICE_TASK_CODE = exports.MIGRATE_PATIENT_TASK_CODE = exports.MIGRATE_PRACTITIONER_TASK_CODE = exports.MIGRATE_TASK_OUTPUT_SYSTEM = exports.MIGRATE_TASK_INPUT_SYSTEM = exports.MIGRATE_TASK_SYSTEM = exports.PRACTITIONER_ROLE_REFERRING_CODE = exports.PRACTITIONER_ROLE_SYSTEM = exports.SERVICE_TYPE_SYSTEM = exports.REQUIRES_PRACTITIONER_EXTENSION_URL = exports.SCHEDULING_PARAMETERS_EXTENSION_URL = exports.MATRICULA_PROVINCIAL_SYSTEM = exports.MATRICULA_NACIONAL_SYSTEM = exports.RENAPER_BASE = exports.EGES_PRESTACION_SYSTEM = exports.EGES_PRACTICA_SYSTEM = exports.EGES_TURNO_SYSTEM = exports.EGES_EQUIPO_SYSTEM = exports.EGES_MEDICO_ASOCIACION_SYSTEM = exports.EGES_MEDICO_SYSTEM = exports.EGES_SUCURSAL_SYSTEM = exports.EGES_DOCUMENTO_SYSTEM = exports.EGES_PACIENTE_SYSTEM = exports.EGES_SYSTEM_BASE = exports.FHIR_BASE = void 0;
|
|
4
|
+
exports.BILLING_CID_CONTEXT_CODE = void 0;
|
|
4
5
|
exports.FHIR_BASE = 'https://www.cdrossi.com/fhir';
|
|
5
6
|
exports.EGES_SYSTEM_BASE = 'https://www.cdrossi.com/eges';
|
|
7
|
+
exports.EGES_PACIENTE_SYSTEM = `${exports.EGES_SYSTEM_BASE}/paciente`;
|
|
8
|
+
exports.EGES_DOCUMENTO_SYSTEM = `${exports.EGES_SYSTEM_BASE}/documentos`;
|
|
9
|
+
exports.EGES_SUCURSAL_SYSTEM = `${exports.EGES_SYSTEM_BASE}/sucursal`;
|
|
10
|
+
exports.EGES_MEDICO_SYSTEM = `${exports.EGES_SYSTEM_BASE}/medico`;
|
|
11
|
+
exports.EGES_MEDICO_ASOCIACION_SYSTEM = `${exports.EGES_SYSTEM_BASE}/medico-asociacion`;
|
|
12
|
+
exports.EGES_EQUIPO_SYSTEM = `${exports.EGES_SYSTEM_BASE}/equipo`;
|
|
13
|
+
exports.EGES_TURNO_SYSTEM = `${exports.EGES_SYSTEM_BASE}/turno`;
|
|
14
|
+
exports.EGES_PRACTICA_SYSTEM = `${exports.EGES_SYSTEM_BASE}/practica`;
|
|
15
|
+
exports.EGES_PRESTACION_SYSTEM = `${exports.EGES_SYSTEM_BASE}/prestacion`;
|
|
16
|
+
exports.RENAPER_BASE = 'https://www.argentina.gob.ar/interior/renaper';
|
|
17
|
+
exports.MATRICULA_NACIONAL_SYSTEM = `${exports.RENAPER_BASE}/matricula-nacional`;
|
|
18
|
+
exports.MATRICULA_PROVINCIAL_SYSTEM = `${exports.RENAPER_BASE}/matricula-provincial`;
|
|
6
19
|
exports.SCHEDULING_PARAMETERS_EXTENSION_URL = 'http://medplum.com/fhir/StructureDefinition/scheduling-parameters';
|
|
7
20
|
exports.REQUIRES_PRACTITIONER_EXTENSION_URL = `${exports.FHIR_BASE}/requires-practitioner`;
|
|
8
21
|
exports.SERVICE_TYPE_SYSTEM = `${exports.FHIR_BASE}/service-type`;
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"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","sourcesContent":["export const FHIR_BASE = 'https://www.cdrossi.com/fhir'\nexport const EGES_SYSTEM_BASE = 'https://www.cdrossi.com/eges'\n\nexport const EGES_PACIENTE_SYSTEM = `${EGES_SYSTEM_BASE}/paciente`\nexport const EGES_DOCUMENTO_SYSTEM = `${EGES_SYSTEM_BASE}/documentos`\nexport const EGES_SUCURSAL_SYSTEM = `${EGES_SYSTEM_BASE}/sucursal`\nexport const EGES_MEDICO_SYSTEM = `${EGES_SYSTEM_BASE}/medico`\nexport const EGES_MEDICO_ASOCIACION_SYSTEM = `${EGES_SYSTEM_BASE}/medico-asociacion`\nexport const EGES_EQUIPO_SYSTEM = `${EGES_SYSTEM_BASE}/equipo`\nexport const EGES_TURNO_SYSTEM = `${EGES_SYSTEM_BASE}/turno`\nexport const EGES_PRACTICA_SYSTEM = `${EGES_SYSTEM_BASE}/practica`\nexport const EGES_PRESTACION_SYSTEM = `${EGES_SYSTEM_BASE}/prestacion`\nexport const RENAPER_BASE = 'https://www.argentina.gob.ar/interior/renaper'\nexport const MATRICULA_NACIONAL_SYSTEM = `${RENAPER_BASE}/matricula-nacional`\nexport const MATRICULA_PROVINCIAL_SYSTEM = `${RENAPER_BASE}/matricula-provincial`\n\nexport const SCHEDULING_PARAMETERS_EXTENSION_URL = 'http://medplum.com/fhir/StructureDefinition/scheduling-parameters'\nexport const REQUIRES_PRACTITIONER_EXTENSION_URL = `${FHIR_BASE}/requires-practitioner`\nexport const SERVICE_TYPE_SYSTEM = `${FHIR_BASE}/service-type`\n\nexport const PRACTITIONER_ROLE_SYSTEM = `${FHIR_BASE}/CodeSystem/practitioner-role`\nexport const PRACTITIONER_ROLE_REFERRING_CODE = 'referring'\n\nconst MIGRATE_TASK_BASE = 'eges-migrate'\nexport const MIGRATE_TASK_SYSTEM = `${FHIR_BASE}/tasks`\nexport const MIGRATE_TASK_INPUT_SYSTEM = `${FHIR_BASE}/task-inputs`\nexport const MIGRATE_TASK_OUTPUT_SYSTEM = `${FHIR_BASE}/task-outputs`\nexport const MIGRATE_PRACTITIONER_TASK_CODE = `${MIGRATE_TASK_BASE}-practitioner`\nexport const MIGRATE_PATIENT_TASK_CODE = `${MIGRATE_TASK_BASE}-patient`\nexport const MIGRATE_DEVICE_TASK_CODE = `${MIGRATE_TASK_BASE}-device`\nexport const MIGRATE_SITE_TASK_CODE = `${MIGRATE_TASK_BASE}-site`\nexport const MIGRATE_SERVICE_TASK_CODE = `${MIGRATE_TASK_BASE}-service`\nexport const MIGRATE_APPOINTMENT_TASK_CODE = `${MIGRATE_TASK_BASE}-appointment`\n\nexport const HL7_IMPORT_TASK_SYSTEM = 'http://example.org/CodeSystem/hl7-import-tasks'\nexport const HL7_IMPORT_APPOINTMENT_TASK_CODE = 'import-orm-o01-appointment'\nexport const HL7_IMPORT_TASK_INPUT_SYSTEM = 'http://example.org/CodeSystem/hl7-import-task-inputs'\nexport const HL7_IMPORT_TASK_OUTPUT_SYSTEM = 'http://example.org/CodeSystem/hl7-import-task-outputs'\n\n// ─── PlanDefinition type ─────────────────────────────────────────────────────\n\n/** Coding system for custom PlanDefinition types */\nexport const PD_TYPE_SYSTEM = `${FHIR_BASE}/CodeSystem/plan-definition-type`\n\n/** Type code that marks a PlanDefinition as a protocol-group (wrapping multiple concrete PDs) */\nexport const PD_TYPE_PROTOCOL_GROUP = 'protocol-group'\n\n// ─── HealthcareService model ──────────────────────────────────────────────────\n\n/** Identifier system for service codes on HealthcareService (mirrors the ServiceCodes CodeSystem URL) */\nexport const SERVICE_CODES_SYSTEM = `${FHIR_BASE}/CodeSystem/service-codes`\n\n/** Coding system for service categories on HealthcareService.category */\nexport const SERVICE_CATEGORY_SYSTEM = `${FHIR_BASE}/CodeSystem/service-category`\n\n/** Coding system for specialities on HealthcareService.specialty */\nexport const SPECIALITY_SYSTEM = `${FHIR_BASE}/CodeSystem/speciality`\n\n/** Extension URL for the mandatory PlanDefinition (clinical protocol) reference on HealthcareService */\nexport const HS_PROTOCOL_EXTENSION_URL = `${FHIR_BASE}/StructureDefinition/hs-protocol`\n\n/** Extension URL for the optional ChargeItemDefinition (billing) reference on HealthcareService */\nexport const HS_BILLING_EXTENSION_URL = `${FHIR_BASE}/StructureDefinition/hs-billing`\n\n/**\n * Extension URL for additional search aliases on HealthcareService.\n *\n * Stored as multiple same-URL extensions, each with a `valueString`.\n * These are indexed at weight 1.2 by the search indexer.\n * Using an extension instead of HealthcareService.alias[] because the local\n * FHIR profile does not permit the standard alias field.\n *\n * @example\n * { url: HS_SEARCH_ALIASES_EXTENSION_URL, valueString: \"placa de tórax\" }\n */\nexport const HS_SEARCH_ALIASES_EXTENSION_URL = `${FHIR_BASE}/StructureDefinition/hs-search-aliases`\n\n// ─── Organization (payer / insurance company) ─────────────────────────────────\n\n/** Identifier system for insurance company (payer) Organization resources */\nexport const INSURER_IDENTIFIER_SYSTEM = `${FHIR_BASE}/CodeSystem/insurers`\n\n/** HL7 organization-type code system */\nexport const ORG_TYPE_SYSTEM = 'http://terminology.hl7.org/CodeSystem/organization-type'\n\n/** organization-type code for payer/insurance */\nexport const ORG_TYPE_PAY_CODE = 'pay'\n\n/** organization-type code for healthcare provider (the main clinic) */\nexport const ORG_TYPE_PROV_CODE = 'prov'\n\n// ─── InsurancePlan ────────────────────────────────────────────────────────────\n\n/** Identifier system for InsurancePlan resources (specific plan products) */\nexport const INSURANCE_PLAN_IDENTIFIER_SYSTEM = `${FHIR_BASE}/CodeSystem/insurance-plans`\n\n// ─── Billing CodeSystem discovery tag ────────────────────────────────────────\n\n/**\n * Tag system applied to every billing-codes CodeSystem resource,\n * enabling dynamic discovery via `CodeSystem?_tag=<system>|<code>`.\n */\nexport const BILLING_CODES_TAG_SYSTEM = `${FHIR_BASE}/tags`\n\n/**\n * Tag code that marks a CodeSystem as a billing codes system.\n * Every billing CodeSystem must carry:\n * meta.tag = [{ system: BILLING_CODES_TAG_SYSTEM, code: BILLING_CODES_TAG_CODE }]\n */\nexport const BILLING_CODES_TAG_CODE = 'billing-codes'\n\n/**\n * Extension URL stored on a billing CodeSystem to record which billing\n * Organization (obra social) owns / uses this billing code system.\n *\n * Value type: Reference (Organization)\n *\n * Example:\n * extension: [{ url: BILLING_CODES_ORG_EXTENSION, valueReference: { reference: 'Organization/123' } }]\n */\nexport const BILLING_CODES_ORG_EXTENSION = `${FHIR_BASE}/extensions/billing-code-system-organization`\n\n/**\n * Identifier system used to tag every billing ChargeItemDefinition with the ID\n * of the PlanDefinition it belongs to, enabling reliable search via\n * `ChargeItemDefinition?identifier=<system>|<planDefinitionId>`.\n * (The FHIR R4 `instance` search parameter is not supported by Medplum.)\n */\nexport const BILLING_CID_PD_IDENTIFIER_SYSTEM = `${FHIR_BASE}/billing/plan-definition`\n\n/**\n * Usage-context type system used to scope a ChargeItemDefinition to a specific InsurancePlan.\n * useContext.code.system = BILLING_CID_CONTEXT_SYSTEM\n * useContext.code.code = BILLING_CID_CONTEXT_CODE\n * useContext.valueReference → InsurancePlan\n */\nexport const BILLING_CID_CONTEXT_SYSTEM = 'http://terminology.hl7.org/CodeSystem/usage-context-type'\nexport const BILLING_CID_CONTEXT_CODE = 'user'\n"]}
|
|
@@ -11,6 +11,12 @@ export interface ProtocolActionInfo {
|
|
|
11
11
|
readonly protocolDisplay: string;
|
|
12
12
|
readonly protocolCode: string;
|
|
13
13
|
readonly duration?: Duration;
|
|
14
|
+
/**
|
|
15
|
+
* Whether this action is pre-selected in a **configured** protocol-group.
|
|
16
|
+
* Set by {@link configureProtocolGroup} via FHIR `precheckBehavior`.
|
|
17
|
+
* `undefined` means the PD has not been configured (use `isDefault` as fallback).
|
|
18
|
+
*/
|
|
19
|
+
readonly prechecked?: boolean;
|
|
14
20
|
/** Optional sub-actions (addons) with `any` selection behavior. */
|
|
15
21
|
readonly addons: readonly ProtocolActionInfo[];
|
|
16
22
|
}
|
|
@@ -72,4 +78,72 @@ export declare function getProtocolVariants(pd: PlanDefinition): ProtocolActionI
|
|
|
72
78
|
* @returns the constructed protocol-group PlanDefinition
|
|
73
79
|
*/
|
|
74
80
|
export declare function buildProtocolGroup(title: string, entries: readonly ProtocolGroupActionEntry[], existingId?: string): PlanDefinition;
|
|
81
|
+
/**
|
|
82
|
+
* A user's selection within a protocol-group PlanDefinition.
|
|
83
|
+
*
|
|
84
|
+
* Represents the patient's choices when configuring a HealthcareService:
|
|
85
|
+
* one main action (from the `exactly-one` selection) plus zero or more
|
|
86
|
+
* addon sub-actions.
|
|
87
|
+
*/
|
|
88
|
+
export interface ProtocolSelection {
|
|
89
|
+
/** The `action.id` of the chosen top-level action. */
|
|
90
|
+
readonly actionId: string;
|
|
91
|
+
/** The `action.id`s of toggled-on addon sub-actions within the selected action. */
|
|
92
|
+
readonly addonIds: readonly string[];
|
|
93
|
+
}
|
|
94
|
+
/** Resolved booking parameters for a single protocol action. */
|
|
95
|
+
export interface ResolvedProtocolAction {
|
|
96
|
+
/** The `definitionCanonical` reference to the order-set PlanDefinition. */
|
|
97
|
+
readonly protocolRef: string;
|
|
98
|
+
/** The service-type code for slot searching / billing. */
|
|
99
|
+
readonly serviceType: string;
|
|
100
|
+
/** Estimated duration for this action. */
|
|
101
|
+
readonly duration?: Duration;
|
|
102
|
+
}
|
|
103
|
+
/** Fully resolved booking parameters produced by {@link resolveProtocolSelection}. */
|
|
104
|
+
export interface ResolvedProtocol {
|
|
105
|
+
/** Resolved main action. */
|
|
106
|
+
readonly main: ResolvedProtocolAction;
|
|
107
|
+
/** Resolved addon actions (empty when none selected). */
|
|
108
|
+
readonly addons: readonly ResolvedProtocolAction[];
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Returns a **configured** copy of a protocol-group PlanDefinition by stamping
|
|
112
|
+
* `precheckBehavior` on every action according to the given selection.
|
|
113
|
+
*
|
|
114
|
+
* - The selected top-level action gets `precheckBehavior: "yes"`, all others `"no"`.
|
|
115
|
+
* - Within the selected action, each addon sub-action is stamped according to
|
|
116
|
+
* whether its id appears in `selection.addonIds`.
|
|
117
|
+
* - Unselected top-level actions have all their sub-actions stamped as `"no"`.
|
|
118
|
+
*
|
|
119
|
+
* The returned PD is a shallow copy — the original is never mutated.
|
|
120
|
+
*
|
|
121
|
+
* @param pd - a protocol-group PlanDefinition
|
|
122
|
+
* @param selection - the user's action + addon selection
|
|
123
|
+
* @returns a new PlanDefinition with `precheckBehavior` set on every action
|
|
124
|
+
* @throws if the selected `actionId` is not found in the PD
|
|
125
|
+
*/
|
|
126
|
+
export declare function configureProtocolGroup(pd: PlanDefinition, selection: ProtocolSelection): PlanDefinition;
|
|
127
|
+
/**
|
|
128
|
+
* Resolves a protocol-group PlanDefinition + selection into concrete booking
|
|
129
|
+
* parameters (service-type codes, definitionCanonical references, durations).
|
|
130
|
+
*
|
|
131
|
+
* @param pd - a protocol-group PlanDefinition
|
|
132
|
+
* @param selection - the user's action + addon selection
|
|
133
|
+
* @returns the resolved main + addon protocol references and codes
|
|
134
|
+
* @throws if the selected `actionId` is not found in the PD
|
|
135
|
+
*/
|
|
136
|
+
export declare function resolveProtocolSelection(pd: PlanDefinition, selection: ProtocolSelection): ResolvedProtocol;
|
|
137
|
+
/**
|
|
138
|
+
* Reads the current selection from a **configured** protocol-group PlanDefinition
|
|
139
|
+
* (one whose actions have been stamped with `precheckBehavior` via
|
|
140
|
+
* {@link configureProtocolGroup}).
|
|
141
|
+
*
|
|
142
|
+
* Falls back to `id === "default"` with no addons if no action has
|
|
143
|
+
* `precheckBehavior: "yes"`.
|
|
144
|
+
*
|
|
145
|
+
* @param pd - a (possibly configured) protocol-group PlanDefinition
|
|
146
|
+
* @returns the selection encoded in the PD, or the default selection
|
|
147
|
+
*/
|
|
148
|
+
export declare function readProtocolSelection(pd: PlanDefinition): ProtocolSelection;
|
|
75
149
|
//# sourceMappingURL=plan-definition-group.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan-definition-group.d.ts","sourceRoot":"","sources":["../src/plan-definition-group.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAwB,MAAM,oBAAoB,CAAA;AAKxF,oEAAoE;AACpE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,kDAAkD;IAClD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAA;IAC5B,mEAAmE;IACnE,QAAQ,CAAC,MAAM,EAAE,SAAS,kBAAkB,EAAE,CAAA;CAC/C;AAED,sDAAsD;AACtD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAA;IAC5B,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,wBAAwB,EAAE,CAAA;CACtD;AAID,0DAA0D;AAC1D,MAAM,MAAM,mBAAmB,GAAG,kBAAkB,CAAA;AAEpD,0DAA0D;AAC1D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAA;CAC7B;AAID;;;;;GAKG;AACH,wBAAgB,eAAe,CAAE,EAAE,EAAE,cAAc,GAAG,OAAO,CAI5D;AAID;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAE,EAAE,EAAE,cAAc,GAAG,kBAAkB,EAAE,CAM5E;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAE,EAAE,EAAE,cAAc,GAAG,mBAAmB,GAAG,SAAS,CASvF;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAE,EAAE,EAAE,cAAc,GAAG,kBAAkB,EAAE,CAE7E;AAID;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,SAAS,wBAAwB,EAAE,EAC5C,UAAU,CAAC,EAAE,MAAM,GAClB,cAAc,CAmDhB"}
|
|
1
|
+
{"version":3,"file":"plan-definition-group.d.ts","sourceRoot":"","sources":["../src/plan-definition-group.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,9 @@ exports.getProtocolActions = getProtocolActions;
|
|
|
5
5
|
exports.getDefaultProtocol = getDefaultProtocol;
|
|
6
6
|
exports.getProtocolVariants = getProtocolVariants;
|
|
7
7
|
exports.buildProtocolGroup = buildProtocolGroup;
|
|
8
|
+
exports.configureProtocolGroup = configureProtocolGroup;
|
|
9
|
+
exports.resolveProtocolSelection = resolveProtocolSelection;
|
|
10
|
+
exports.readProtocolSelection = readProtocolSelection;
|
|
8
11
|
const constants_1 = require("./constants");
|
|
9
12
|
// ─── Detection ───────────────────────────────────────────────────────────────
|
|
10
13
|
/**
|
|
@@ -95,6 +98,109 @@ function buildProtocolGroup(title, entries, existingId) {
|
|
|
95
98
|
}
|
|
96
99
|
return pd;
|
|
97
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Returns a **configured** copy of a protocol-group PlanDefinition by stamping
|
|
103
|
+
* `precheckBehavior` on every action according to the given selection.
|
|
104
|
+
*
|
|
105
|
+
* - The selected top-level action gets `precheckBehavior: "yes"`, all others `"no"`.
|
|
106
|
+
* - Within the selected action, each addon sub-action is stamped according to
|
|
107
|
+
* whether its id appears in `selection.addonIds`.
|
|
108
|
+
* - Unselected top-level actions have all their sub-actions stamped as `"no"`.
|
|
109
|
+
*
|
|
110
|
+
* The returned PD is a shallow copy — the original is never mutated.
|
|
111
|
+
*
|
|
112
|
+
* @param pd - a protocol-group PlanDefinition
|
|
113
|
+
* @param selection - the user's action + addon selection
|
|
114
|
+
* @returns a new PlanDefinition with `precheckBehavior` set on every action
|
|
115
|
+
* @throws if the selected `actionId` is not found in the PD
|
|
116
|
+
*/
|
|
117
|
+
function configureProtocolGroup(pd, selection) {
|
|
118
|
+
var _a;
|
|
119
|
+
const actions = (_a = pd.action) !== null && _a !== void 0 ? _a : [];
|
|
120
|
+
const found = actions.some((a) => a.id === selection.actionId);
|
|
121
|
+
if (!found) {
|
|
122
|
+
throw new Error(`Action "${selection.actionId}" not found in protocol-group PlanDefinition`);
|
|
123
|
+
}
|
|
124
|
+
const addonSet = new Set(selection.addonIds);
|
|
125
|
+
return {
|
|
126
|
+
...pd,
|
|
127
|
+
action: actions.map((a) => {
|
|
128
|
+
var _a;
|
|
129
|
+
const isSelected = a.id === selection.actionId;
|
|
130
|
+
const subActions = ((_a = a.action) !== null && _a !== void 0 ? _a : []).map((sub) => {
|
|
131
|
+
var _a;
|
|
132
|
+
return ({
|
|
133
|
+
...sub,
|
|
134
|
+
precheckBehavior: (isSelected && addonSet.has((_a = sub.id) !== null && _a !== void 0 ? _a : '')) ? 'yes' : 'no'
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
return {
|
|
138
|
+
...a,
|
|
139
|
+
precheckBehavior: isSelected ? 'yes' : 'no',
|
|
140
|
+
...(a.action ? { action: subActions } : {})
|
|
141
|
+
};
|
|
142
|
+
})
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Resolves a protocol-group PlanDefinition + selection into concrete booking
|
|
147
|
+
* parameters (service-type codes, definitionCanonical references, durations).
|
|
148
|
+
*
|
|
149
|
+
* @param pd - a protocol-group PlanDefinition
|
|
150
|
+
* @param selection - the user's action + addon selection
|
|
151
|
+
* @returns the resolved main + addon protocol references and codes
|
|
152
|
+
* @throws if the selected `actionId` is not found in the PD
|
|
153
|
+
*/
|
|
154
|
+
function resolveProtocolSelection(pd, selection) {
|
|
155
|
+
var _a, _b;
|
|
156
|
+
const actions = (_a = pd.action) !== null && _a !== void 0 ? _a : [];
|
|
157
|
+
const selected = actions.find((a) => a.id === selection.actionId);
|
|
158
|
+
if (!(selected === null || selected === void 0 ? void 0 : selected.definitionCanonical)) {
|
|
159
|
+
throw new Error(`Action "${selection.actionId}" not found in protocol-group PlanDefinition`);
|
|
160
|
+
}
|
|
161
|
+
const addonSet = new Set(selection.addonIds);
|
|
162
|
+
const resolvedAddons = ((_b = selected.action) !== null && _b !== void 0 ? _b : [])
|
|
163
|
+
.filter((sub) => { var _a; return Boolean(sub.id) && addonSet.has((_a = sub.id) !== null && _a !== void 0 ? _a : '') && Boolean(sub.definitionCanonical); })
|
|
164
|
+
.map((sub) => ({
|
|
165
|
+
protocolRef: sub.definitionCanonical,
|
|
166
|
+
serviceType: getActionServiceCode(sub),
|
|
167
|
+
duration: sub.timingDuration
|
|
168
|
+
}));
|
|
169
|
+
return {
|
|
170
|
+
main: {
|
|
171
|
+
protocolRef: selected.definitionCanonical,
|
|
172
|
+
serviceType: getActionServiceCode(selected),
|
|
173
|
+
duration: selected.timingDuration
|
|
174
|
+
},
|
|
175
|
+
addons: resolvedAddons
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Reads the current selection from a **configured** protocol-group PlanDefinition
|
|
180
|
+
* (one whose actions have been stamped with `precheckBehavior` via
|
|
181
|
+
* {@link configureProtocolGroup}).
|
|
182
|
+
*
|
|
183
|
+
* Falls back to `id === "default"` with no addons if no action has
|
|
184
|
+
* `precheckBehavior: "yes"`.
|
|
185
|
+
*
|
|
186
|
+
* @param pd - a (possibly configured) protocol-group PlanDefinition
|
|
187
|
+
* @returns the selection encoded in the PD, or the default selection
|
|
188
|
+
*/
|
|
189
|
+
function readProtocolSelection(pd) {
|
|
190
|
+
var _a, _b, _c, _d;
|
|
191
|
+
const actions = (_a = pd.action) !== null && _a !== void 0 ? _a : [];
|
|
192
|
+
// Look for an action explicitly marked as prechecked
|
|
193
|
+
const prechecked = actions.find((a) => a.precheckBehavior === 'yes');
|
|
194
|
+
if (prechecked === null || prechecked === void 0 ? void 0 : prechecked.id) {
|
|
195
|
+
const addonIds = ((_b = prechecked.action) !== null && _b !== void 0 ? _b : [])
|
|
196
|
+
.filter((sub) => sub.precheckBehavior === 'yes' && Boolean(sub.id))
|
|
197
|
+
.map((sub) => sub.id);
|
|
198
|
+
return { actionId: prechecked.id, addonIds };
|
|
199
|
+
}
|
|
200
|
+
// Fallback: default action, no addons
|
|
201
|
+
const defaultAction = (_c = actions.find((a) => a.id === 'default')) !== null && _c !== void 0 ? _c : actions[0];
|
|
202
|
+
return { actionId: (_d = defaultAction === null || defaultAction === void 0 ? void 0 : defaultAction.id) !== null && _d !== void 0 ? _d : '', addonIds: [] };
|
|
203
|
+
}
|
|
98
204
|
// ─── Internal helpers ───────────────────────────────────────────────────────
|
|
99
205
|
function getActionServiceCode(action) {
|
|
100
206
|
var _a, _b;
|
|
@@ -103,6 +209,15 @@ function getActionServiceCode(action) {
|
|
|
103
209
|
.find((c) => c.system === constants_1.SERVICE_TYPE_SYSTEM);
|
|
104
210
|
return (_b = coding === null || coding === void 0 ? void 0 : coding.code) !== null && _b !== void 0 ? _b : '';
|
|
105
211
|
}
|
|
212
|
+
function precheckToBool(value) {
|
|
213
|
+
if (value === 'yes') {
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
if (value === 'no') {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
106
221
|
function extractActionInfo(a, isDefault) {
|
|
107
222
|
var _a, _b, _c, _d, _e, _f;
|
|
108
223
|
const subActions = ((_a = a.action) !== null && _a !== void 0 ? _a : [])
|
|
@@ -117,6 +232,7 @@ function extractActionInfo(a, isDefault) {
|
|
|
117
232
|
protocolDisplay: (_f = a.title) !== null && _f !== void 0 ? _f : '',
|
|
118
233
|
protocolCode: getActionServiceCode(a),
|
|
119
234
|
duration: a.timingDuration,
|
|
235
|
+
prechecked: precheckToBool(a.precheckBehavior),
|
|
120
236
|
addons: subActions
|
|
121
237
|
};
|
|
122
238
|
}
|
|
@@ -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_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 /** 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 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 /** 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// ─── 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 * @returns the constructed protocol-group PlanDefinition\n */\nexport function buildProtocolGroup (\n title: string,\n entries: readonly ProtocolGroupActionEntry[],\n existingId?: string\n): PlanDefinition {\n const actions: PlanDefinitionAction[] = entries.map((e) => {\n const subActions = (e.addons ?? []).map((addon) =>\n buildAction(\n crypto.randomUUID(),\n addon.display,\n addon.ref,\n addon.code,\n addon.duration,\n addon.question,\n addon.label\n )\n )\n\n const action = buildAction(\n e.isDefault ? 'default' : crypto.randomUUID(),\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 (existingId) {\n pd.id = existingId\n }\n\n return pd\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 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 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): 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 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 { 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 /** 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 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 /** 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// ─── 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 * @returns the constructed protocol-group PlanDefinition\n */\nexport function buildProtocolGroup (\n title: string,\n entries: readonly ProtocolGroupActionEntry[],\n existingId?: string\n): PlanDefinition {\n const actions: PlanDefinitionAction[] = entries.map((e) => {\n const subActions = (e.addons ?? []).map((addon) =>\n buildAction(\n crypto.randomUUID(),\n addon.display,\n addon.ref,\n addon.code,\n addon.duration,\n addon.question,\n addon.label\n )\n )\n\n const action = buildAction(\n e.isDefault ? 'default' : crypto.randomUUID(),\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 (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`.\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 ...sub,\n precheckBehavior: (isSelected && addonSet.has(sub.id ?? '')) ? 'yes' as const : 'no' as const\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 Boolean(sub.id) && addonSet.has(sub.id ?? '') && Boolean(sub.definitionCanonical)\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 no addons if no action has\n * `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 sub.precheckBehavior === 'yes' && Boolean(sub.id)\n )\n .map((sub) => sub.id)\n return { actionId: prechecked.id, addonIds }\n }\n\n // Fallback: default action, no addons\n const defaultAction = actions.find((a) => a.id === 'default') ?? actions[0]\n return { actionId: defaultAction?.id ?? '', addonIds: [] }\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 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): 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 return action\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appointment.d.ts","sourceRoot":"","sources":["../../src/scheduling/appointment.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8C,aAAa,EAAE,MAAM,eAAe,CAAA;AACzF,OAAO,EACL,WAAW,EAEX,MAAM,EAIN,OAAO,EACP,SAAS,EAET,IAAI,EACL,MAAM,oBAAoB,CAAA;AAI3B,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,IAAI,EAAE,CAAA;IACb,gBAAgB,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAA;CACtC;AAED,wBAAsB,eAAe,CAAE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAO9H;AAED,MAAM,WAAW,wBAAwB;IACvC,oBAAoB,CAAC,EAAE,SAAS,CAAC,WAAW,CAAC,CAAA;IAC7C,KAAK,CAAC,EAAE,IAAI,EAAE,CAAA;IACd,gBAAgB,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAA;CACtC;AAED,wBAAsB,eAAe,CAAE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAsI9H;AAED,wBAAsB,iBAAiB,CAAE,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,SAAS,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"appointment.d.ts","sourceRoot":"","sources":["../../src/scheduling/appointment.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8C,aAAa,EAAE,MAAM,eAAe,CAAA;AACzF,OAAO,EACL,WAAW,EAEX,MAAM,EAIN,OAAO,EACP,SAAS,EAET,IAAI,EACL,MAAM,oBAAoB,CAAA;AAI3B,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,IAAI,EAAE,CAAA;IACb,gBAAgB,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAA;CACtC;AAED,wBAAsB,eAAe,CAAE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAO9H;AAED,MAAM,WAAW,wBAAwB;IACvC,oBAAoB,CAAC,EAAE,SAAS,CAAC,WAAW,CAAC,CAAA;IAC7C,KAAK,CAAC,EAAE,IAAI,EAAE,CAAA;IACd,gBAAgB,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAA;CACtC;AAED,wBAAsB,eAAe,CAAE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAsI9H;AAED,wBAAsB,iBAAiB,CAAE,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,SAAS,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAwE3I"}
|
|
@@ -158,6 +158,13 @@ async function cancelAppointment(medplum, appointmentReference) {
|
|
|
158
158
|
{ name: 'path', valueString: '/status' },
|
|
159
159
|
{ name: 'value', valueString: JSON.stringify('cancelled') }
|
|
160
160
|
]
|
|
161
|
+
}, {
|
|
162
|
+
name: 'operation',
|
|
163
|
+
part: [
|
|
164
|
+
{ name: 'op', valueCode: 'replace' },
|
|
165
|
+
{ name: 'path', valueString: '/slot' },
|
|
166
|
+
{ name: 'value', valueString: JSON.stringify([]) }
|
|
167
|
+
]
|
|
161
168
|
}]
|
|
162
169
|
}
|
|
163
170
|
}]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appointment.js","sourceRoot":"","sources":["../../src/scheduling/appointment.ts"],"names":[],"mappings":"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","sourcesContent":["import { generateId, getReferenceString, isResource, MedplumClient } from '@medplum/core'\nimport {\n Appointment,\n AppointmentParticipant,\n Bundle,\n BundleEntry,\n BundleEntryResponse,\n Parameters,\n Patient,\n Reference,\n Resource,\n Slot\n} from '@medplum/fhirtypes'\nimport { formatISO } from 'date-fns'\nimport { isResourceReference } from './slot'\n\nexport interface HoldAppointmentArguments {\n slots: Slot[]\n patientReference?: Reference<Patient>\n}\n\nexport async function holdAppointment (medplum: MedplumClient, options: HoldAppointmentArguments): Promise<Bundle<Appointment>> {\n return createAppointment(\n medplum,\n options.slots,\n 'pending',\n 'busy-tentative',\n options.patientReference)\n}\n\nexport interface BookAppointmentArguments {\n appointmentReference?: Reference<Appointment>\n slots?: Slot[]\n patientReference?: Reference<Patient>\n}\n\nexport async function bookAppointment (medplum: MedplumClient, options: BookAppointmentArguments): Promise<Bundle<Appointment>> {\n const { appointmentReference, slots, patientReference } = options\n\n if (appointmentReference) {\n const appointment = await medplum.readReference(appointmentReference)\n\n if (appointment.status !== 'pending') {\n throw new Error('Expected pending appointment')\n }\n\n if (!appointment.slot) {\n throw new Error('Slots missing on pending appointment')\n }\n\n const appointmentSlots = await medplum.searchResources('Slot', {\n _id: appointment.slot.map(slot => getReferenceString(slot)).join(','),\n status: 'busy-tentative'\n })\n\n if (appointmentSlots.length !== appointment.slot.length) {\n throw new Error('Reserved slots not found for pending appointment')\n }\n\n const appoinmentParameters: Parameters = {\n resourceType: 'Parameters',\n parameter: [{\n name: 'operation',\n part: [\n { name: 'op', valueCode: 'test' },\n { name: 'path', valueString: '/meta/versionId' },\n { name: 'value', valueString: JSON.stringify(appointment.meta?.versionId) }\n ]\n }, {\n name: 'operation',\n part: [\n { name: 'op', valueCode: 'replace' },\n { name: 'path', valueString: '/status' },\n { name: 'value', valueString: JSON.stringify('booked') }\n ]\n }]\n }\n\n if (patientReference) {\n if (appointment.participant.some(participant => participant.actor && isResourceReference('Patient', participant.actor))) {\n throw new Error('Appointment already has a patient participant')\n }\n\n // Validate patient reference\n await medplum.readReference(patientReference)\n\n appoinmentParameters.parameter?.push({\n name: 'operation',\n part: [\n { name: 'op', valueCode: 'add' },\n { name: 'path', valueString: '/participant/-' },\n {\n name: 'value',\n valueString: JSON.stringify({\n actor: patientReference,\n required: 'required',\n status: 'needs-action'\n } as AppointmentParticipant)\n }\n ]\n })\n }\n\n const transaction: Bundle = {\n resourceType: 'Bundle',\n type: 'transaction',\n entry: [{\n request: {\n method: 'PATCH',\n url: getReferenceString(appointment) as string\n },\n resource: appoinmentParameters\n }]\n }\n\n for (const slot of appointmentSlots) {\n transaction.entry?.push({\n request: {\n method: 'PATCH',\n url: getReferenceString(slot)\n },\n resource: {\n resourceType: 'Parameters',\n parameter: [{\n name: 'operation',\n part: [\n { name: 'op', valueCode: 'test' },\n { name: 'path', valueString: '/meta/versionId' },\n { name: 'value', valueString: JSON.stringify(slot.meta?.versionId) }\n ]\n }, {\n name: 'operation',\n part: [\n { name: 'op', valueCode: 'replace' },\n { name: 'path', valueString: '/status' },\n { name: 'value', valueString: JSON.stringify('busy') }\n ]\n }]\n }\n })\n }\n\n const result = await medplum.executeBatch(transaction)\n const ok = result.entry?.every(entry => entry.response?.outcome?.id === 'ok')\n\n if (ok) {\n return {\n resourceType: 'Bundle',\n type: 'searchset',\n entry: [findAppointmentBundleEntry(result)]\n }\n } else {\n return {\n resourceType: 'Bundle',\n type: 'searchset',\n entry: [{\n response: conflictResponse('Appointment update conflict')\n }]\n }\n }\n } else if (slots) {\n return createAppointment(\n medplum,\n slots,\n 'booked',\n 'busy',\n patientReference)\n }\n\n throw new Error('Appointment or slots not provided')\n}\n\nexport async function cancelAppointment (medplum: MedplumClient, appointmentReference: Reference<Appointment>): Promise<Bundle<Appointment>> {\n const appointment = await medplum.readReference(appointmentReference)\n\n if (appointment.status !== 'booked' && appointment.status !== 'pending') {\n throw new Error('Unexpected appointment status')\n }\n\n const transaction: Bundle = {\n resourceType: 'Bundle',\n type: 'transaction',\n entry: [{\n request: {\n method: 'PATCH',\n url: getReferenceString(appointmentReference) as string\n },\n resource: {\n resourceType: 'Parameters',\n parameter: [{\n name: 'operation',\n part: [\n { name: 'op', valueCode: 'test' },\n { name: 'path', valueString: '/meta/versionId' },\n { name: 'value', valueString: JSON.stringify(appointment.meta?.versionId) }\n ]\n }, {\n name: 'operation',\n part: [\n { name: 'op', valueCode: 'replace' },\n { name: 'path', valueString: '/status' },\n { name: 'value', valueString: JSON.stringify('cancelled') }\n ]\n }]\n }\n }]\n }\n\n if (appointment.slot) {\n for (const slot of appointment.slot) {\n transaction.entry?.push({\n request: {\n method: 'DELETE',\n url: getReferenceString(slot) as string\n }\n })\n }\n }\n\n const result = await medplum.executeBatch(transaction)\n const ok = result.entry?.every(entry => entry.response?.outcome?.id === 'ok')\n\n if (ok) {\n return {\n resourceType: 'Bundle',\n type: 'searchset',\n entry: [findAppointmentBundleEntry(result)]\n }\n } else {\n return {\n resourceType: 'Bundle',\n type: 'searchset',\n entry: [{\n response: conflictResponse('Appointment update conflict')\n }]\n }\n }\n}\n\nasync function createAppointment (\n medplum: MedplumClient,\n slots: Slot[],\n appoinmentStatus: Appointment['status'],\n slotStatus: Slot['status'],\n patientReference?: Reference<Patient>): Promise<Bundle<Appointment>> {\n const [first, ...rest] = slots\n\n for (const slot of rest) {\n if (first.start !== slot.start || first.end !== slot.end) {\n throw new Error('Slot dates do not match')\n }\n }\n\n const schedules = await medplum.searchResources('Schedule', {\n _id: slots.map(slot => getReferenceString(slot.schedule)).join(','),\n active: true\n })\n\n for (const slot of slots) {\n if (!schedules.some(schedule => getReferenceString(schedule) === getReferenceString(slot.schedule))) {\n throw new Error('Active schedule for slot not found')\n }\n }\n\n if (patientReference) {\n // Validate patient reference\n await medplum.readReference(patientReference)\n }\n\n const transaction: Bundle = {\n resourceType: 'Bundle',\n type: 'transaction',\n entry: []\n }\n\n for (const slot of slots) {\n const parameters = new URLSearchParams()\n\n parameters.set('schedule', getReferenceString(slot.schedule) as string)\n parameters.set('status', 'busy,busy-unavailable,busy-tentative')\n parameters.set('start', 'lt' + formatISO(slot.end))\n parameters.set('end', 'gt' + formatISO(slot.start))\n\n slot.id = generateId()\n\n transaction.entry?.push({\n fullUrl: 'urn:uuid:' + slot.id,\n request: {\n method: 'POST',\n url: 'Slot',\n ifNoneExist: parameters.toString()\n },\n resource: {\n resourceType: 'Slot',\n status: slotStatus,\n start: slot.start,\n end: slot.end,\n schedule: slot.schedule\n }\n })\n }\n\n const participants = new Map<string, AppointmentParticipant>()\n\n if (patientReference) {\n participants.set(getReferenceString(patientReference) as string, {\n actor: patientReference,\n required: 'required',\n status: 'needs-action'\n })\n }\n\n for (const schedule of schedules) {\n for (const actor of schedule.actor) {\n participants.set(getReferenceString(actor) as string, {\n actor,\n required: 'required',\n status: isResourceReference('Device', actor) || isResourceReference('Location', actor) ? 'accepted' : 'needs-action'\n })\n }\n }\n\n transaction.entry?.push({\n request: {\n method: 'POST',\n url: 'Appointment'\n },\n resource: {\n resourceType: 'Appointment',\n status: appoinmentStatus,\n start: first.start,\n end: first.end,\n participant: Array.from(participants.values()),\n slot: slots.map(slot => {\n return { reference: 'urn:uuid:' + slot.id }\n })\n }\n })\n\n const result = await medplum.executeBatch(transaction)\n const created = result.entry?.filter(entry => entry.response?.outcome?.id === 'created')\n\n if (created?.length !== slots.length + 1) {\n // Not all resources were created. Using ifNoneExists does not fail the transaction,\n // it returns an existing resource if it matches the parameters.\n // Try to delete all created resources by best effort.\n if (created?.length) {\n await medplum.executeBatch({\n resourceType: 'Bundle',\n type: 'batch',\n entry: created.map(entry => {\n return {\n request: {\n method: 'DELETE',\n url: getReferenceString(entry.resource as Resource) as string\n }\n }\n })\n })\n }\n\n return {\n resourceType: 'Bundle',\n type: 'searchset',\n entry: [{\n response: conflictResponse('Requested time slots not available'),\n resource: {\n resourceType: 'Appointment',\n status: 'cancelled',\n participant: []\n }\n }]\n }\n } else {\n return {\n resourceType: 'Bundle',\n type: 'searchset',\n entry: [findAppointmentBundleEntry(result)]\n }\n }\n}\n\nfunction findAppointmentBundleEntry (bundle: Bundle): BundleEntry<Appointment> {\n const appointmentEntry = bundle.entry?.find((entry): entry is BundleEntry<Appointment> => isResource(entry.resource, 'Appointment'))\n\n if (!appointmentEntry) {\n throw new Error('Bundle does not contain appointment')\n }\n\n return appointmentEntry\n}\n\nfunction conflictResponse (message: string): BundleEntryResponse {\n return {\n outcome: {\n resourceType: 'OperationOutcome',\n issue: [{\n severity: 'error',\n code: 'conflict',\n diagnostics: message\n }]\n },\n status: '409'\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"appointment.js","sourceRoot":"","sources":["../../src/scheduling/appointment.ts"],"names":[],"mappings":"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","sourcesContent":["import { generateId, getReferenceString, isResource, MedplumClient } from '@medplum/core'\nimport {\n Appointment,\n AppointmentParticipant,\n Bundle,\n BundleEntry,\n BundleEntryResponse,\n Parameters,\n Patient,\n Reference,\n Resource,\n Slot\n} from '@medplum/fhirtypes'\nimport { formatISO } from 'date-fns'\nimport { isResourceReference } from './slot'\n\nexport interface HoldAppointmentArguments {\n slots: Slot[]\n patientReference?: Reference<Patient>\n}\n\nexport async function holdAppointment (medplum: MedplumClient, options: HoldAppointmentArguments): Promise<Bundle<Appointment>> {\n return createAppointment(\n medplum,\n options.slots,\n 'pending',\n 'busy-tentative',\n options.patientReference)\n}\n\nexport interface BookAppointmentArguments {\n appointmentReference?: Reference<Appointment>\n slots?: Slot[]\n patientReference?: Reference<Patient>\n}\n\nexport async function bookAppointment (medplum: MedplumClient, options: BookAppointmentArguments): Promise<Bundle<Appointment>> {\n const { appointmentReference, slots, patientReference } = options\n\n if (appointmentReference) {\n const appointment = await medplum.readReference(appointmentReference)\n\n if (appointment.status !== 'pending') {\n throw new Error('Expected pending appointment')\n }\n\n if (!appointment.slot) {\n throw new Error('Slots missing on pending appointment')\n }\n\n const appointmentSlots = await medplum.searchResources('Slot', {\n _id: appointment.slot.map(slot => getReferenceString(slot)).join(','),\n status: 'busy-tentative'\n })\n\n if (appointmentSlots.length !== appointment.slot.length) {\n throw new Error('Reserved slots not found for pending appointment')\n }\n\n const appoinmentParameters: Parameters = {\n resourceType: 'Parameters',\n parameter: [{\n name: 'operation',\n part: [\n { name: 'op', valueCode: 'test' },\n { name: 'path', valueString: '/meta/versionId' },\n { name: 'value', valueString: JSON.stringify(appointment.meta?.versionId) }\n ]\n }, {\n name: 'operation',\n part: [\n { name: 'op', valueCode: 'replace' },\n { name: 'path', valueString: '/status' },\n { name: 'value', valueString: JSON.stringify('booked') }\n ]\n }]\n }\n\n if (patientReference) {\n if (appointment.participant.some(participant => participant.actor && isResourceReference('Patient', participant.actor))) {\n throw new Error('Appointment already has a patient participant')\n }\n\n // Validate patient reference\n await medplum.readReference(patientReference)\n\n appoinmentParameters.parameter?.push({\n name: 'operation',\n part: [\n { name: 'op', valueCode: 'add' },\n { name: 'path', valueString: '/participant/-' },\n {\n name: 'value',\n valueString: JSON.stringify({\n actor: patientReference,\n required: 'required',\n status: 'needs-action'\n } as AppointmentParticipant)\n }\n ]\n })\n }\n\n const transaction: Bundle = {\n resourceType: 'Bundle',\n type: 'transaction',\n entry: [{\n request: {\n method: 'PATCH',\n url: getReferenceString(appointment) as string\n },\n resource: appoinmentParameters\n }]\n }\n\n for (const slot of appointmentSlots) {\n transaction.entry?.push({\n request: {\n method: 'PATCH',\n url: getReferenceString(slot)\n },\n resource: {\n resourceType: 'Parameters',\n parameter: [{\n name: 'operation',\n part: [\n { name: 'op', valueCode: 'test' },\n { name: 'path', valueString: '/meta/versionId' },\n { name: 'value', valueString: JSON.stringify(slot.meta?.versionId) }\n ]\n }, {\n name: 'operation',\n part: [\n { name: 'op', valueCode: 'replace' },\n { name: 'path', valueString: '/status' },\n { name: 'value', valueString: JSON.stringify('busy') }\n ]\n }]\n }\n })\n }\n\n const result = await medplum.executeBatch(transaction)\n const ok = result.entry?.every(entry => entry.response?.outcome?.id === 'ok')\n\n if (ok) {\n return {\n resourceType: 'Bundle',\n type: 'searchset',\n entry: [findAppointmentBundleEntry(result)]\n }\n } else {\n return {\n resourceType: 'Bundle',\n type: 'searchset',\n entry: [{\n response: conflictResponse('Appointment update conflict')\n }]\n }\n }\n } else if (slots) {\n return createAppointment(\n medplum,\n slots,\n 'booked',\n 'busy',\n patientReference)\n }\n\n throw new Error('Appointment or slots not provided')\n}\n\nexport async function cancelAppointment (medplum: MedplumClient, appointmentReference: Reference<Appointment>): Promise<Bundle<Appointment>> {\n const appointment = await medplum.readReference(appointmentReference)\n\n if (appointment.status !== 'booked' && appointment.status !== 'pending') {\n throw new Error('Unexpected appointment status')\n }\n\n const transaction: Bundle = {\n resourceType: 'Bundle',\n type: 'transaction',\n entry: [{\n request: {\n method: 'PATCH',\n url: getReferenceString(appointmentReference) as string\n },\n resource: {\n resourceType: 'Parameters',\n parameter: [{\n name: 'operation',\n part: [\n { name: 'op', valueCode: 'test' },\n { name: 'path', valueString: '/meta/versionId' },\n { name: 'value', valueString: JSON.stringify(appointment.meta?.versionId) }\n ]\n }, {\n name: 'operation',\n part: [\n { name: 'op', valueCode: 'replace' },\n { name: 'path', valueString: '/status' },\n { name: 'value', valueString: JSON.stringify('cancelled') }\n ]\n }, {\n name: 'operation',\n part: [\n { name: 'op', valueCode: 'replace' },\n { name: 'path', valueString: '/slot' },\n { name: 'value', valueString: JSON.stringify([]) }\n ]\n }]\n }\n }]\n }\n\n if (appointment.slot) {\n for (const slot of appointment.slot) {\n transaction.entry?.push({\n request: {\n method: 'DELETE',\n url: getReferenceString(slot) as string\n }\n })\n }\n }\n\n const result = await medplum.executeBatch(transaction)\n const ok = result.entry?.every(entry => entry.response?.outcome?.id === 'ok')\n\n if (ok) {\n return {\n resourceType: 'Bundle',\n type: 'searchset',\n entry: [findAppointmentBundleEntry(result)]\n }\n } else {\n return {\n resourceType: 'Bundle',\n type: 'searchset',\n entry: [{\n response: conflictResponse('Appointment update conflict')\n }]\n }\n }\n}\n\nasync function createAppointment (\n medplum: MedplumClient,\n slots: Slot[],\n appoinmentStatus: Appointment['status'],\n slotStatus: Slot['status'],\n patientReference?: Reference<Patient>): Promise<Bundle<Appointment>> {\n const [first, ...rest] = slots\n\n for (const slot of rest) {\n if (first.start !== slot.start || first.end !== slot.end) {\n throw new Error('Slot dates do not match')\n }\n }\n\n const schedules = await medplum.searchResources('Schedule', {\n _id: slots.map(slot => getReferenceString(slot.schedule)).join(','),\n active: true\n })\n\n for (const slot of slots) {\n if (!schedules.some(schedule => getReferenceString(schedule) === getReferenceString(slot.schedule))) {\n throw new Error('Active schedule for slot not found')\n }\n }\n\n if (patientReference) {\n // Validate patient reference\n await medplum.readReference(patientReference)\n }\n\n const transaction: Bundle = {\n resourceType: 'Bundle',\n type: 'transaction',\n entry: []\n }\n\n for (const slot of slots) {\n const parameters = new URLSearchParams()\n\n parameters.set('schedule', getReferenceString(slot.schedule) as string)\n parameters.set('status', 'busy,busy-unavailable,busy-tentative')\n parameters.set('start', 'lt' + formatISO(slot.end))\n parameters.set('end', 'gt' + formatISO(slot.start))\n\n slot.id = generateId()\n\n transaction.entry?.push({\n fullUrl: 'urn:uuid:' + slot.id,\n request: {\n method: 'POST',\n url: 'Slot',\n ifNoneExist: parameters.toString()\n },\n resource: {\n resourceType: 'Slot',\n status: slotStatus,\n start: slot.start,\n end: slot.end,\n schedule: slot.schedule\n }\n })\n }\n\n const participants = new Map<string, AppointmentParticipant>()\n\n if (patientReference) {\n participants.set(getReferenceString(patientReference) as string, {\n actor: patientReference,\n required: 'required',\n status: 'needs-action'\n })\n }\n\n for (const schedule of schedules) {\n for (const actor of schedule.actor) {\n participants.set(getReferenceString(actor) as string, {\n actor,\n required: 'required',\n status: isResourceReference('Device', actor) || isResourceReference('Location', actor) ? 'accepted' : 'needs-action'\n })\n }\n }\n\n transaction.entry?.push({\n request: {\n method: 'POST',\n url: 'Appointment'\n },\n resource: {\n resourceType: 'Appointment',\n status: appoinmentStatus,\n start: first.start,\n end: first.end,\n participant: Array.from(participants.values()),\n slot: slots.map(slot => {\n return { reference: 'urn:uuid:' + slot.id }\n })\n }\n })\n\n const result = await medplum.executeBatch(transaction)\n const created = result.entry?.filter(entry => entry.response?.outcome?.id === 'created')\n\n if (created?.length !== slots.length + 1) {\n // Not all resources were created. Using ifNoneExists does not fail the transaction,\n // it returns an existing resource if it matches the parameters.\n // Try to delete all created resources by best effort.\n if (created?.length) {\n await medplum.executeBatch({\n resourceType: 'Bundle',\n type: 'batch',\n entry: created.map(entry => {\n return {\n request: {\n method: 'DELETE',\n url: getReferenceString(entry.resource as Resource) as string\n }\n }\n })\n })\n }\n\n return {\n resourceType: 'Bundle',\n type: 'searchset',\n entry: [{\n response: conflictResponse('Requested time slots not available'),\n resource: {\n resourceType: 'Appointment',\n status: 'cancelled',\n participant: []\n }\n }]\n }\n } else {\n return {\n resourceType: 'Bundle',\n type: 'searchset',\n entry: [findAppointmentBundleEntry(result)]\n }\n }\n}\n\nfunction findAppointmentBundleEntry (bundle: Bundle): BundleEntry<Appointment> {\n const appointmentEntry = bundle.entry?.find((entry): entry is BundleEntry<Appointment> => isResource(entry.resource, 'Appointment'))\n\n if (!appointmentEntry) {\n throw new Error('Bundle does not contain appointment')\n }\n\n return appointmentEntry\n}\n\nfunction conflictResponse (message: string): BundleEntryResponse {\n return {\n outcome: {\n resourceType: 'OperationOutcome',\n issue: [{\n severity: 'error',\n code: 'conflict',\n diagnostics: message\n }]\n },\n status: '409'\n }\n}\n"]}
|