From 8c8229b0b3515fe1486a5b8bb3ad6746e0a24cb5 Mon Sep 17 00:00:00 2001 From: Patrick LaRocque <41444457+plarocque4@users.noreply.github.com> Date: Fri, 16 May 2025 17:54:02 -0400 Subject: [PATCH 1/6] update vite to 5.4.19 (#171) * update vite to 5.4.19 * fix prettier error --- frontend/package.json | 2 +- src/server.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index b5b2e34..cc21783 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -31,6 +31,6 @@ "globals": "^15.9.0", "typescript": "^5.5.3", "typescript-eslint": "^8.0.1", - "vite": "^5.4.1" + "vite": "^5.4.19" } } diff --git a/src/server.ts b/src/server.ts index ff5fd52..b5ad26b 100644 --- a/src/server.ts +++ b/src/server.ts @@ -18,7 +18,6 @@ import bodyParserXml from 'body-parser-xml'; const logger = container.get('application'); - const initialize = (config: any) => { //const logLevel = _.get(config, 'logging.level'); return new REMSServer(config.fhirServerConfig) From b4ba2ed3fd0e268d98610c936dd4b1c62bfe8204 Mon Sep 17 00:00:00 2001 From: Sahil Malhotra <88040167+smalho01@users.noreply.github.com> Date: Tue, 20 May 2025 13:29:12 -0400 Subject: [PATCH 2/6] vite config updates (#172) * vite config updates * single quote --- frontend/vite.config.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 5aa4da6..ca9ba31 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -8,6 +8,9 @@ export default defineConfig({ // depending on your application, base can also be "/" base: '', plugins: [react()], + preview: { + allowedHosts: ['.mitre.org', '.us-east-1.elb.amazonaws.com'], + }, define: { 'process.env': process.env }, From e2e5e924a58d6a6dc76dd981c2fc53c257269541 Mon Sep 17 00:00:00 2001 From: Sahil Malhotra <88040167+smalho01@users.noreply.github.com> Date: Fri, 13 Jun 2025 12:27:27 -0400 Subject: [PATCH 3/6] auth number to case number migration (#174) * update rems admin to work with auth number to case number migration * remove case number from output params * put back case number - handle in pims * formatting * run prettier * run eslint * update ci/cd * remove all instances of auth number * fix tests? * test dependency --- .github/workflows/ci-workflow.yml | 22 ++++++++++++++++--- .github/workflows/docker-cd-dev.yml | 1 + .github/workflows/docker-cd.yml | 1 + .github/workflows/docker-ci.yml | 1 + .github/workflows/docker-tag-cd.yml | 3 ++- README.md | 2 +- .../src/views/DataViews/CaseCollection.tsx | 3 --- frontend/vite.config.ts | 2 +- src/fhir/guidanceResponseUtilities.ts | 6 ++--- src/fhir/models.ts | 2 -- src/lib/etasu.ts | 14 +++--------- src/services/guidanceresponse.service.ts | 12 +++++----- test/server.test.ts | 18 +++++++-------- 13 files changed, 47 insertions(+), 40 deletions(-) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index fe97a70..c7d51a3 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -7,18 +7,22 @@ jobs: name: Check tsc, lint, and prettier runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - name: Checkout Repository uses: actions/checkout@v3 with: submodules: true - node-version: '14.x' + clean: true + + - uses: actions/setup-node@v1 + with: + node-version: "18.x" - run: npm install - run: npm run lint - run: npm run prettier env: CI: true + test: name: Test on node ${{ matrix.node-version }} and ${{ matrix.os }} runs-on: ${{ matrix.os }} @@ -29,12 +33,24 @@ jobs: steps: - uses: actions/checkout@v1 + - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} + + - name: Install OpenSSL 1.1 on Ubuntu + if: matrix.os == 'ubuntu-latest' + run: | + sudo apt-get update + sudo apt-get install -y libssl1.1 || { + # Fallback for newer Ubuntu versions + wget http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2_amd64.deb + sudo dpkg -i libssl1.1_1.1.1f-1ubuntu2_amd64.deb + } + - run: npm install - run: git submodule update --init - run: npm test env: - CI: true + CI: true \ No newline at end of file diff --git a/.github/workflows/docker-cd-dev.yml b/.github/workflows/docker-cd-dev.yml index 809f164..fe2bb5e 100644 --- a/.github/workflows/docker-cd-dev.yml +++ b/.github/workflows/docker-cd-dev.yml @@ -14,6 +14,7 @@ jobs: uses: actions/checkout@v3 with: submodules: true + clean: true - name: Setup Docker Buildx uses: docker/setup-buildx-action@v2 diff --git a/.github/workflows/docker-cd.yml b/.github/workflows/docker-cd.yml index 78a22ed..858a0c1 100644 --- a/.github/workflows/docker-cd.yml +++ b/.github/workflows/docker-cd.yml @@ -14,6 +14,7 @@ jobs: uses: actions/checkout@v3 with: submodules: true + clean: true - name: Setup Docker Buildx uses: docker/setup-buildx-action@v2 diff --git a/.github/workflows/docker-ci.yml b/.github/workflows/docker-ci.yml index 5edae1d..36f1abe 100644 --- a/.github/workflows/docker-ci.yml +++ b/.github/workflows/docker-ci.yml @@ -15,6 +15,7 @@ jobs: uses: actions/checkout@v3 with: submodules: true + clean: true - name: Test Server Docker image Builds run: docker build . \ No newline at end of file diff --git a/.github/workflows/docker-tag-cd.yml b/.github/workflows/docker-tag-cd.yml index 0287fe9..e565595 100644 --- a/.github/workflows/docker-tag-cd.yml +++ b/.github/workflows/docker-tag-cd.yml @@ -14,7 +14,8 @@ jobs: uses: actions/checkout@v3 with: submodules: true - + clean: true + - name: Setup Docker Buildx uses: docker/setup-buildx-action@v2 diff --git a/README.md b/README.md index 84cdb6b..777d9ad 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ The FHIR server built into the REMS Admin can be queried for the questionnaire p - Input requires a parameter containing the following: - `patient` - Patient FHIR Resource, must include `medication` with `patient` - `medication` - Medication or MedicationRequest FHIR Resource, must include `patient` with `medication` - - `authNumber` - String containing the REMS Authorization Number, may be sent without `patient` or `medication` + - `caseNumber` - String containing the REMS Case Number, may be sent without `patient` or `medication` - Returns a GuidanceResponse within a Parameter with the status - Contains Nested GuidanceResponse resources for each ETASU requirement with their status - `/4_0_0/Questionnaire/\/$questionnaire-package` - The endpoint for the FHIR Operation used for retrieving the Questionnaire package for a given form diff --git a/frontend/src/views/DataViews/CaseCollection.tsx b/frontend/src/views/DataViews/CaseCollection.tsx index 0c7e496..5589d5b 100644 --- a/frontend/src/views/DataViews/CaseCollection.tsx +++ b/frontend/src/views/DataViews/CaseCollection.tsx @@ -21,7 +21,6 @@ import FormPopup from '../FormPopup'; export type RemsCase = { case_number?: string; - auth_number?: string; patientFirstName?: string; patientLastName?: string; patientDOB?: string; @@ -162,7 +161,6 @@ const CaseCollection = (props: { refresh: boolean }) => { Patient DOB Status Dispense Status - Authorization Number Met Requirements Delete @@ -180,7 +178,6 @@ const CaseCollection = (props: { refresh: boolean }) => { {row.patientDOB} {row.status} {row.dispenseStatus} - {row.auth_number} {metReq} ( const remsCaseCollectionSchema = new Schema({ case_number: { type: String }, - auth_number: { type: String }, status: { type: String }, dispenseStatus: { type: String }, drugName: { type: String }, diff --git a/src/lib/etasu.ts b/src/lib/etasu.ts index 8922b5b..e66ac42 100644 --- a/src/lib/etasu.ts +++ b/src/lib/etasu.ts @@ -33,11 +33,6 @@ router.get('/met/:caseId', async (req: Request, res: Response) => { res.send(await remsCaseCollection.findOne({ case_number: req.params.caseId })); }); -router.get('/met/auth/:authNumber', async (req: Request, res: Response) => { - console.log('get etasu by authnumber: ' + req.params.authNumber); - res.send(await remsCaseCollection.findOne({ auth_number: req.params.authNumber })); -}); - export const getCaseInfo = async ( remsCaseSearchDict: FilterQuery, medicationSearchDict: FilterQuery @@ -45,7 +40,7 @@ export const getCaseInfo = async ( RemsCase, | 'status' | 'drugName' - | 'auth_number' + | 'case_number' | 'drugCode' | 'patientFirstName' | 'patientLastName' @@ -66,7 +61,7 @@ export const getCaseInfo = async ( RemsCase, | 'status' | 'drugName' - | 'auth_number' + | 'case_number' | 'drugCode' | 'patientFirstName' | 'patientLastName' @@ -75,7 +70,7 @@ export const getCaseInfo = async ( > = { status: 'Approved', drugName: drug?.name, - auth_number: remsCaseSearchDict.auth_number || '', + case_number: remsCaseSearchDict.case_number || '', drugCode: drug?.code, patientFirstName: remsCaseSearchDict.patientFirstName || '', patientLastName: remsCaseSearchDict.patientLastName || '', @@ -230,7 +225,6 @@ const createMetRequirementAndNewCase = async ( const remsRequest: Pick< RemsCase, | 'case_number' - | 'auth_number' | 'status' | 'dispenseStatus' | 'drugName' @@ -241,7 +235,6 @@ const createMetRequirementAndNewCase = async ( | 'metRequirements' > = { case_number: case_number, - auth_number: '', status: remsRequestCompletedStatus, dispenseStatus: dispenseStatusDefault, drugName: drug?.name, @@ -390,7 +383,6 @@ const createMetRequirementAndUpdateCase = async ( if (!foundUncompleted && remsRequestToUpdate?.status === 'Pending') { remsRequestToUpdate.status = 'Approved'; - remsRequestToUpdate.auth_number = uid(); await remsRequestToUpdate.save(); } } diff --git a/src/services/guidanceresponse.service.ts b/src/services/guidanceresponse.service.ts index de37ed9..c2739e5 100644 --- a/src/services/guidanceresponse.service.ts +++ b/src/services/guidanceresponse.service.ts @@ -58,7 +58,7 @@ module.exports.remsEtasu = async (args: any, context: any, logger: any) => { const parameters: Parameters = args?.resource; let patient: Patient | undefined; let medication: Medication | MedicationRequest | undefined; - let authNumber: string | undefined; + let caseNumber: string | undefined; parameters?.parameter?.forEach(param => { if (param?.name === 'patient' && param?.resource?.resourceType === 'Patient') { @@ -69,15 +69,15 @@ module.exports.remsEtasu = async (args: any, context: any, logger: any) => { param.resource?.resourceType === 'MedicationRequest') ) { medication = param.resource; - } else if (param?.name === 'authNumber') { - authNumber = param.valueString; + } else if (param?.name === 'caseNumber') { + caseNumber = param.valueString; } }); let etasu: Pick< RemsCase, | 'drugName' - | 'auth_number' + | 'case_number' | 'status' | 'drugCode' | 'patientFirstName' @@ -86,9 +86,9 @@ module.exports.remsEtasu = async (args: any, context: any, logger: any) => { | 'metRequirements' > | null; - if (authNumber) { + if (caseNumber) { const remsCaseSearchDict = { - auth_number: authNumber + case_number: caseNumber }; const medicationSearchDict = {}; diff --git a/test/server.test.ts b/test/server.test.ts index 8b57a17..f96340e 100644 --- a/test/server.test.ts +++ b/test/server.test.ts @@ -25,7 +25,7 @@ describe('REMSServer class', () => { const set = sinon.spy(server.app, 'set'); const use = sinon.spy(server.app, 'use'); - server.configureMiddleware(); + server.configureMiddleware({}); expect(set.callCount).to.equal(6); expect(set.getCall(4).args[0]).to.equal('showStackError'); expect(set.getCall(4).args[1]).to.be.true; @@ -87,20 +87,20 @@ describe('REMSServer class', () => { }); it('should be able to prepopulate data without error', async () => { - expect(await metRequirementsCollection.count({})).to.equal(0); - expect(await medicationCollection.count({})).to.equal(0); + expect(await metRequirementsCollection.countDocuments({})).to.equal(0); + expect(await medicationCollection.countDocuments({})).to.equal(0); await FhirUtilities.populateDB(); - expect(await metRequirementsCollection.count({})).to.not.equal(0); - expect(await medicationCollection.count({})).to.not.equal(0); + expect(await metRequirementsCollection.countDocuments({})).to.not.equal(0); + expect(await medicationCollection.countDocuments({})).to.not.equal(0); await FhirUtilities.populateDB(); }); it('should be able to load artifacts from filesystem', async () => { - expect(await LibraryModel.count({})).to.equal(0); - expect(await QuestionnaireModel.count({})).to.equal(0); + expect(await LibraryModel.countDocuments({})).to.equal(0); + expect(await QuestionnaireModel.countDocuments({})).to.equal(0); await FhirUtilities.loadResources('./test/fixtures/cds-library'); - expect(await LibraryModel.count({})).to.not.equal(0); - expect(await QuestionnaireModel.count({})).to.not.equal(0); + expect(await LibraryModel.countDocuments({})).to.not.equal(0); + expect(await QuestionnaireModel.countDocuments({})).to.not.equal(0); await FhirUtilities.loadResources('./test/fixtures/cds-library'); }); }); From 5eafbb3ff77846082db268d6b5619f9c120a641d Mon Sep 17 00:00:00 2001 From: Sahil Malhotra Date: Mon, 16 Jun 2025 13:21:14 -0400 Subject: [PATCH 4/6] update vite config --- frontend/vite.config.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 12f4f80..693052e 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -17,6 +17,7 @@ export default defineConfig({ server: { port: parseInt(process.env.FRONTEND_PORT!), open: false, - host: true + host: true, + allowedHosts: ['.mitre.org', '.us-east-1.elb.amazonaws.com'] } }); From a46c44321f1b60704b16d3dd21c61874873dcaa2 Mon Sep 17 00:00:00 2001 From: Sahil Malhotra Date: Mon, 16 Jun 2025 13:24:21 -0400 Subject: [PATCH 5/6] fix ci --- .github/workflows/docker-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-ci.yml b/.github/workflows/docker-ci.yml index 36f1abe..f428b65 100644 --- a/.github/workflows/docker-ci.yml +++ b/.github/workflows/docker-ci.yml @@ -15,7 +15,7 @@ jobs: uses: actions/checkout@v3 with: submodules: true - clean: true + clean: true - name: Test Server Docker image Builds run: docker build . \ No newline at end of file From 3e9fda49c6c3e0c126989edf9a77bc2fd366acc9 Mon Sep 17 00:00:00 2001 From: Sahil Malhotra <88040167+smalho01@users.noreply.github.com> Date: Mon, 16 Jun 2025 14:32:02 -0400 Subject: [PATCH 6/6] Submit-etasu-refactor (#175) * change rems etasu url * run linting * endpoint path fix * return 201 status code * 201 status code --- src/config.ts | 10 +- src/lib/etasu.ts | 233 +++++++++--------- src/services/questionnaireresponse.service.ts | 18 ++ 3 files changed, 137 insertions(+), 124 deletions(-) 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; + } +};