diff --git a/src/config.ts b/src/config.ts index 58745c6..de555c5 100644 --- a/src/config.ts +++ b/src/config.ts @@ -112,7 +112,15 @@ export default { }, questionnaireresponse: { service: './src/services/questionnaireresponse.service.ts', - versions: [fhirConstants.VERSIONS['4_0_0']] + versions: [fhirConstants.VERSIONS['4_0_0']], + operation: [ + { + name: 'submit', + route: '/$submit', + method: 'POST', + reference: 'http://hl7.org/fhir/OperationDefinition/QuestionnaireResponse-submit' + } + ] }, valueset: { service: './src/services/valueset.service.ts', diff --git a/src/lib/etasu.ts b/src/lib/etasu.ts index e66ac42..63ef37b 100644 --- a/src/lib/etasu.ts +++ b/src/lib/etasu.ts @@ -207,7 +207,6 @@ const createMetRequirementAndNewCase = async ( drug: Medication, requirement: Requirement, questionnaireResponse: QuestionnaireResponse, - res: Response, reqStakeholderReference: string, practitionerReference: string, pharmacistReference: string, @@ -257,11 +256,9 @@ const createMetRequirementAndNewCase = async ( }; if (!(await createAndPushMetRequirements(metReq, remsRequest))) { - res.status(200); - message = 'ERROR: failed to create new met requirement for form initial to case'; + message = 'ERROR: failed to create new met requirement and initial case'; console.log(message); - res.send(message); - return res; + throw new Error(message); } // iterate through all other requirements again to create corresponding false metRequirements / assign to existing @@ -307,7 +304,7 @@ const createMetRequirementAndNewCase = async ( remsRequestCompletedStatus = 'Pending'; if (!(await createAndPushMetRequirements(newMetReq, remsRequest))) { - message = 'ERROR: failed to create new met requirement for form initial to case'; + message = 'ERROR: failed to create new met requirement for form and initial case'; console.log(message); } } @@ -316,17 +313,16 @@ const createMetRequirementAndNewCase = async ( remsRequest.status = remsRequestCompletedStatus; const returnedRemsRequestDoc = await remsCaseCollection.create(remsRequest); - res.status(201); - res.send(returnedRemsRequestDoc); - return res; + return { + returnedRemsRequestDoc + }; }; const createMetRequirementAndUpdateCase = async ( drug: Medication, requirement: Requirement, questionnaireResponse: QuestionnaireResponse, - res: Response, reqStakeholderReference: string ) => { let returnedMetReqDoc; @@ -403,9 +399,9 @@ const createMetRequirementAndUpdateCase = async ( returnedMetReqDoc = await createMetRequirements(newMetReq); } - res.status(201); - res.send(returnedMetReqDoc); - return res; + return { + returnedMetReqDoc + }; }; const createMetRequirementAndUpdateCaseNotRequiredToDispense = async ( @@ -413,7 +409,6 @@ const createMetRequirementAndUpdateCaseNotRequiredToDispense = async ( drug: Medication, requirement: Requirement, questionnaireResponse: QuestionnaireResponse, - res: Response, reqStakeholderReference: string ) => { // Find the specific case associated with an individual patient for the patient status form @@ -473,120 +468,17 @@ const createMetRequirementAndUpdateCaseNotRequiredToDispense = async ( console.log(message); } - res.status(201); if (returnRemsRequest) { - res.send(remsRequestToUpdate); + return { + remsRequestToUpdate + }; } else { - res.send(message); + return { + message + }; } - return res; }; -router.post('/met', async (req: Request, res: Response) => { - try { - const requestBody = req.body as Bundle; - - // extract params and questionnaire response identifier - const params = getResource( - requestBody, - (requestBody.entry?.[0]?.resource as MessageHeader)?.focus?.[0]?.reference || '' - ) as Parameters; - const questionnaireResponse = getQuestionnaireResponse(requestBody) as QuestionnaireResponse; - const questionnaireStringArray = questionnaireResponse?.questionnaire?.split('/'); - const requirementId = questionnaireStringArray?.[questionnaireStringArray.length - 1]; - - // stakeholder and medication references - let prescriptionReference = ''; - let practitionerReference = ''; - let pharmacistReference = ''; - let patientReference = ''; - for (const param of params.parameter || []) { - if (param.name === 'prescription') { - prescriptionReference = param.valueReference?.reference || ''; - } else if (param.name === 'prescriber') { - practitionerReference = param.valueReference?.reference || ''; - } else if (param.name === 'pharmacy') { - pharmacistReference = param.valueReference?.reference || ''; - } else if (param.name === 'source-patient') { - patientReference = param.valueReference?.reference || ''; - } - } - - // obtain drug information from database - const prescription = getResource(requestBody, prescriptionReference) as MedicationRequest; - const medicationCode = getDrugCodeFromMedicationRequest(prescription) as Coding; - const prescriptionSystem = medicationCode?.system; - const prescriptionCode = medicationCode?.code; - const patient = getResource(requestBody, patientReference) as Patient; - - const drug = await medicationCollection - .findOne({ - code: prescriptionCode, - codeSystem: prescriptionSystem - }) - .exec(); - // iterate through each requirement of the drug - if (drug) { - for (const requirement of drug.requirements) { - // figure out which stakeholder the req corresponds to - const stakeholder = requirement.stakeholderType; - const stakeholderReference = - stakeholder === 'prescriber' - ? practitionerReference - : stakeholder === 'pharmacist' - ? pharmacistReference - : patientReference; - - // if the requirement is the one submitted continue - if (requirement.resourceId === requirementId) { - // if the req submitted is a patient enrollment form and requires creating a new case - if (requirement.createNewCase) { - await createMetRequirementAndNewCase( - patient, - drug, - requirement, - questionnaireResponse, - res, - stakeholderReference, - practitionerReference, - pharmacistReference, - patientReference - ); - - return; - } else { - // If it's not the patient status requirement - if (requirement.requiredToDispense) { - await createMetRequirementAndUpdateCase( - drug, - requirement, - questionnaireResponse, - res, - stakeholderReference - ); - return; - } else { - await createMetRequirementAndUpdateCaseNotRequiredToDispense( - patient, - drug, - requirement, - questionnaireResponse, - res, - stakeholderReference - ); - return; - } - } - break; - } - } - } - } catch (error) { - console.log(error); - throw error; - } -}); - const getResource = (bundle: Bundle, resourceReference: string) => { const temp = resourceReference.split('/'); const _resourceType = temp[0]; @@ -618,4 +510,99 @@ const getQuestionnaireResponse = (bundle: Bundle) => { return null; }; +export const processQuestionnaireResponseSubmission = async (requestBody: Bundle): Promise => { + // extract params and questionnaire response identifier + const params = getResource( + requestBody, + (requestBody.entry?.[0]?.resource as MessageHeader)?.focus?.[0]?.reference || '' + ) as Parameters; + const questionnaireResponse = getQuestionnaireResponse(requestBody) as QuestionnaireResponse; + const questionnaireStringArray = questionnaireResponse?.questionnaire?.split('/'); + const requirementId = questionnaireStringArray?.[questionnaireStringArray.length - 1]; + + // stakeholder and medication references + let prescriptionReference = ''; + let practitionerReference = ''; + let pharmacistReference = ''; + let patientReference = ''; + for (const param of params.parameter || []) { + if (param.name === 'prescription') { + prescriptionReference = param.valueReference?.reference || ''; + } else if (param.name === 'prescriber') { + practitionerReference = param.valueReference?.reference || ''; + } else if (param.name === 'pharmacy') { + pharmacistReference = param.valueReference?.reference || ''; + } else if (param.name === 'source-patient') { + patientReference = param.valueReference?.reference || ''; + } + } + + // obtain drug information from database + const prescription = getResource(requestBody, prescriptionReference) as MedicationRequest; + const medicationCode = getDrugCodeFromMedicationRequest(prescription) as Coding; + const prescriptionSystem = medicationCode?.system; + const prescriptionCode = medicationCode?.code; + const patient = getResource(requestBody, patientReference) as Patient; + + const drug = await medicationCollection + .findOne({ + code: prescriptionCode, + codeSystem: prescriptionSystem + }) + .exec(); + + // iterate through each requirement of the drug + if (drug) { + for (const requirement of drug.requirements) { + // figure out which stakeholder the req corresponds to + const stakeholder = requirement.stakeholderType; + const stakeholderReference = + stakeholder === 'prescriber' + ? practitionerReference + : stakeholder === 'pharmacist' + ? pharmacistReference + : patientReference; + + // if the requirement is the one submitted continue + if (requirement.resourceId === requirementId) { + // if the req submitted is a patient enrollment form and requires creating a new case + if (requirement.createNewCase) { + return await createMetRequirementAndNewCase( + patient, + drug, + requirement, + questionnaireResponse, + stakeholderReference, + practitionerReference, + pharmacistReference, + patientReference + ); + } else { + // If it's not the patient status requirement + if (requirement.requiredToDispense) { + return await createMetRequirementAndUpdateCase( + drug, + requirement, + questionnaireResponse, + stakeholderReference + ); + } else { + return await createMetRequirementAndUpdateCaseNotRequiredToDispense( + patient, + drug, + requirement, + questionnaireResponse, + stakeholderReference + ); + } + } + } + } + } + + throw new Error('No matching requirement found for the submitted questionnaire'); +}; + +export { getResource, getQuestionnaireResponse }; + export default router; diff --git a/src/services/questionnaireresponse.service.ts b/src/services/questionnaireresponse.service.ts index 9d20d46..a50632e 100644 --- a/src/services/questionnaireresponse.service.ts +++ b/src/services/questionnaireresponse.service.ts @@ -1,5 +1,7 @@ import { FhirUtilities } from '../fhir/utilities'; import QuestionnaireResponseModel from '../lib/schemas/resources/QuestionnaireResponse'; +import { Bundle } from 'fhir/r4'; +import { processQuestionnaireResponseSubmission } from '../lib/etasu'; module.exports.searchById = async (args: any) => { const { id } = args; @@ -13,3 +15,19 @@ module.exports.create = async (args: any, req: any) => { const { base_version } = args; return await FhirUtilities.store(resource, QuestionnaireResponseModel, base_version); }; + +module.exports.submit = async (args: any, context: any, logger: any) => { + logger.info('Running QuestionnaireResponse $submit operation'); + + try { + const requestBody = args?.resource as Bundle; + const response = await processQuestionnaireResponseSubmission(requestBody); + context.req.res.status(201); + return { + response + }; + } catch (error) { + logger.error('Error in QuestionnaireResponse $submit operation:', error); + throw error; + } +};