Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
233 changes: 110 additions & 123 deletions src/lib/etasu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,6 @@
drug: Medication,
requirement: Requirement,
questionnaireResponse: QuestionnaireResponse,
res: Response,
reqStakeholderReference: string,
practitionerReference: string,
pharmacistReference: string,
Expand Down Expand Up @@ -257,11 +256,9 @@
};

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
Expand Down Expand Up @@ -307,7 +304,7 @@
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);
}
}
Expand All @@ -316,17 +313,16 @@

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;
Expand Down Expand Up @@ -370,7 +366,7 @@
// _id comparison would not work for some reason
if (req4?.requirementName === matchedMetReq.requirementName) {
metReqArray[i].completed = true;
req4!.completed = true;

Check warning on line 369 in src/lib/etasu.ts

View workflow job for this annotation

GitHub Actions / Check tsc, lint, and prettier

Forbidden non-null assertion

Check warning on line 369 in src/lib/etasu.ts

View workflow job for this annotation

GitHub Actions / Check tsc, lint, and prettier

Forbidden non-null assertion
await remsCaseCollection.updateOne(
{ _id: remsRequestToUpdate?._id },
{ $set: { metRequirements: metReqArray } }
Expand Down Expand Up @@ -403,17 +399,16 @@
returnedMetReqDoc = await createMetRequirements(newMetReq);
}

res.status(201);
res.send(returnedMetReqDoc);
return res;
return {
returnedMetReqDoc
};
};

const createMetRequirementAndUpdateCaseNotRequiredToDispense = async (
patient: Patient,
drug: Medication,
requirement: Requirement,
questionnaireResponse: QuestionnaireResponse,
res: Response,
reqStakeholderReference: string
) => {
// Find the specific case associated with an individual patient for the patient status form
Expand Down Expand Up @@ -473,120 +468,17 @@
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];
Expand Down Expand Up @@ -618,4 +510,99 @@
return null;
};

export const processQuestionnaireResponseSubmission = async (requestBody: Bundle): Promise<any> => {
// 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;
18 changes: 18 additions & 0 deletions src/services/questionnaireresponse.service.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;
}
};
Loading