From bf055d6a274f2cefd403f3faf9a0072245fe28ae Mon Sep 17 00:00:00 2001 From: KeeyanGhoreshi Date: Thu, 1 Feb 2024 15:24:57 -0500 Subject: [PATCH 1/4] make task on questionnaires --- src/cards/Card.ts | 4 +- src/hooks/hookResources.ts | 89 +++++++++++++++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 4 deletions(-) diff --git a/src/cards/Card.ts b/src/cards/Card.ts index c79b9103..f269ae3d 100644 --- a/src/cards/Card.ts +++ b/src/cards/Card.ts @@ -5,12 +5,12 @@ interface Source { url: URL; icon?: URL; } -interface Action { +export interface Action { type: string; description: string; resource?: Resource | string; } -interface Suggestion { +export interface Suggestion { label: string; uuid?: string; actions: Action[]; diff --git a/src/hooks/hookResources.ts b/src/hooks/hookResources.ts index ff7588f6..b4513661 100644 --- a/src/hooks/hookResources.ts +++ b/src/hooks/hookResources.ts @@ -1,5 +1,13 @@ -import { MedicationRequest, Coding, FhirResource, Identifier } from 'fhir/r4'; -import Card, { Link } from '../cards/Card'; +import { + MedicationRequest, + Coding, + FhirResource, + Identifier, + Task, + Questionnaire, + Patient +} from 'fhir/r4'; +import Card, { Link, Suggestion, Action } from '../cards/Card'; import { HookPrefetch, OrderSignPrefetch, @@ -17,6 +25,16 @@ type HandleCallback = ( contextRequest: FhirResource | undefined, patient: FhirResource | undefined ) => Promise; + +interface Requirement { + name: string; + description: string; + stakeholderType: string; + createNewCase: boolean; + resourceId: string; + requiredToDispense: boolean; + appContext?: string; +} export interface CardRule { links: Link[]; summary?: string; @@ -364,6 +382,9 @@ export async function handleCardOrder( card.addLink( createSmartLink(requirement.name, requirement.appContext, contextRequest) ); + if (patient && patient.resourceType === 'Patient') { + createQuestionnaireSuggestion(card, requirement, patient); + } smartLinkCount++; } } @@ -463,3 +484,67 @@ export function handleHook( res.json(buildErrorCard('Unknown Error')); } } + +export function createQuestionnaireSuggestion( + card: Card, + requirement: Requirement, + patient: Patient +) { + if (requirement.appContext && requirement.appContext.includes('=')) { + const qArr = requirement.appContext.split('='); // break up into parts + let qUrl = null; + for (let i = 0; i < qArr.length; i++) { + if (qArr[i].toLowerCase() === 'questionnaire') { + if (i + 1 < qArr.length) { + // not at end of array + qUrl = qArr[i + 1]; + } + } + } + if (qUrl) { + const action: Action = { + type: 'create', + description: `Create task for "completion of ${requirement.name} Questionnaire`, + resource: createQuestionnaireCompletionTask(requirement.name, qUrl, patient) + }; + const suggestion: Suggestion = { + label: `Add "Completion of ${requirement.name} Questionnaire" to task list`, + actions: [action] + }; + card.addSuggestion(suggestion); + } + } +} +export function createQuestionnaireCompletionTask( + questionnaireTitle: string, + questionnaireUrl: string, + patient: Patient +) { + const taskResource: Task = { + resourceType: 'Task', + status: 'ready', + intent: 'order', + code: { + coding: [ + { + system: 'http://hl7.org/fhir/uv/sdc/CodeSystem/temp', + code: 'complete-questionnaire' + } + ] + }, + description: `Complete ${questionnaireTitle} Questionnaire`, + for: { + reference: `${patient.resourceType}/${patient.id}` + }, + authoredOn: `${Date.now().toLocaleString()}`, + input: [ + { + type: { + text: 'questionnaire' + }, + valueCanonical: `${questionnaireUrl}` + } + ] + }; + return taskResource; +} From 5cd71012c52359540053cca58f15ae503ca72f94 Mon Sep 17 00:00:00 2001 From: KeeyanGhoreshi Date: Thu, 1 Feb 2024 15:34:36 -0500 Subject: [PATCH 2/4] fix hook issue --- src/hooks/hookResources.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hooks/hookResources.ts b/src/hooks/hookResources.ts index b4513661..4f7eee81 100644 --- a/src/hooks/hookResources.ts +++ b/src/hooks/hookResources.ts @@ -442,14 +442,14 @@ export async function handleCard( // verify ids if ( patient?.id && - patient.id.replace('Patient/', '') !== context.patientId.replace('Patient/', '') + patient.id.replace('Patient/', '') !== context.patientId?.replace('Patient/', '') ) { res.json(buildErrorCard('Context patientId does not match prefetch Patient ID')); return; } if ( practitioner?.id && - practitioner.id.replace('Practitioner/', '') !== context.userId.replace('Practitioner/', '') + practitioner.id.replace('Practitioner/', '') !== context.userId?.replace('Practitioner/', '') ) { res.json(buildErrorCard('Context userId does not match prefetch Practitioner ID')); return; From 8887cfa29b5d0307ba57394c82639c31dfeba976 Mon Sep 17 00:00:00 2001 From: KeeyanGhoreshi Date: Mon, 5 Feb 2024 16:09:36 -0500 Subject: [PATCH 3/4] fix date --- src/hooks/hookResources.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks/hookResources.ts b/src/hooks/hookResources.ts index 4f7eee81..adf6479f 100644 --- a/src/hooks/hookResources.ts +++ b/src/hooks/hookResources.ts @@ -536,7 +536,7 @@ export function createQuestionnaireCompletionTask( for: { reference: `${patient.resourceType}/${patient.id}` }, - authoredOn: `${Date.now().toLocaleString()}`, + authoredOn: `${new Date(Date.now()).toISOString()}`, input: [ { type: { From a4cafb552fe082e7ff3a012628d3ba3c5f08381c Mon Sep 17 00:00:00 2001 From: KeeyanGhoreshi Date: Thu, 8 Feb 2024 14:30:38 -0500 Subject: [PATCH 4/4] cover other link cases --- src/hooks/hookResources.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/hooks/hookResources.ts b/src/hooks/hookResources.ts index adf6479f..2bea88c7 100644 --- a/src/hooks/hookResources.ts +++ b/src/hooks/hookResources.ts @@ -393,6 +393,9 @@ export async function handleCardOrder( card.addLink( createSmartLink(requirement.name, requirement.appContext, contextRequest) ); + if (patient && patient.resourceType === 'Patient') { + createQuestionnaireSuggestion(card, requirement, patient); + } smartLinkCount++; } } else { @@ -401,6 +404,9 @@ export async function handleCardOrder( card.addLink( createSmartLink(requirement.name, requirement.appContext, contextRequest) ); + if (patient && patient.resourceType === 'Patient') { + createQuestionnaireSuggestion(card, requirement, patient); + } smartLinkCount++; } }