From 71885295a4a24ec4a8a69a474d86a7e2fd78ae16 Mon Sep 17 00:00:00 2001 From: Ariel Virgulto Date: Fri, 23 Aug 2024 09:56:49 -0400 Subject: [PATCH 01/10] Update endpoint to be a common ncpdp endpoint that calls rxfill --- package.json | 4 +++- src/fhir/models.ts | 2 ++ src/lib/etasu.ts | 3 +++ src/lib/rxfill.ts | 40 ++++++++++++++++++++++++++++++++++++++++ src/server.ts | 19 +++++++++++++++++++ 5 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/lib/rxfill.ts diff --git a/package.json b/package.json index 82aee2b..b15462c 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,8 @@ "@types/fhir": "^0.0.35", "@types/glob": "^8.1.0", "axios": "^1.2.1", - "body-parser": "^1.19.0", + "body-parser": "^1.20.2", + "body-parser-xml": "^2.0.5", "conventional-changelog-cli": "^2.0.34", "cors": "^2.8.5", "dotenv": "^16.3.1", @@ -50,6 +51,7 @@ "winston-daily-rotate-file": "^4.2.1" }, "devDependencies": { + "@types/body-parser-xml": "^2.0.5", "@types/chai": "^4.3.4", "@types/cors": "^2.8.12", "@types/express": "^4.17.14", diff --git a/src/fhir/models.ts b/src/fhir/models.ts index 566f5e2..c5615be 100644 --- a/src/fhir/models.ts +++ b/src/fhir/models.ts @@ -34,6 +34,7 @@ export interface RemsCase extends Document { case_number: string; auth_number: string; status: string; + dispenseStatus: string; drugName: string; drugCode: string; patientFirstName: string; @@ -91,6 +92,7 @@ const remsCaseCollectionSchema = new Schema({ case_number: { type: String }, auth_number: { type: String }, status: { type: String }, + dispenseStatus: { type: String }, drugName: { type: String }, patientFirstName: { type: String }, patientLastName: { type: String }, diff --git a/src/lib/etasu.ts b/src/lib/etasu.ts index a397c2a..a65f57d 100644 --- a/src/lib/etasu.ts +++ b/src/lib/etasu.ts @@ -226,11 +226,13 @@ const createMetRequirementAndNewCase = async ( // create new rems request and add the created metReq to it let remsRequestCompletedStatus = 'Approved'; + const dispenseStatusDefault = 'Pending'; const remsRequest: Pick< RemsCase, | 'case_number' | 'auth_number' | 'status' + | 'dispenseStatus' | 'drugName' | 'drugCode' | 'patientFirstName' @@ -241,6 +243,7 @@ const createMetRequirementAndNewCase = async ( case_number: case_number, auth_number: '', status: remsRequestCompletedStatus, + dispenseStatus: dispenseStatusDefault, drugName: drug?.name, drugCode: drug?.code, patientFirstName: patientFirstName, diff --git a/src/lib/rxfill.ts b/src/lib/rxfill.ts new file mode 100644 index 0000000..26fa2f1 --- /dev/null +++ b/src/lib/rxfill.ts @@ -0,0 +1,40 @@ +import { Router, Response, Request } from 'express'; +import { remsCaseCollection } from '../fhir/models'; +const router = Router(); + +router.post('/ncpdp', async (req: Request, res: Response) => { + try { + const requestBody = req.body; + if (requestBody.message?.body?.rxfill) { + // call to handle rxfill + handleRxFill(requestBody); + } else { + // do nothing for now + } + } catch (error) { + console.log(error); + throw error; + } +}); + +const handleRxFill = async (bundle: any) => { + const rxfill = bundle.message?.body?.rxfill; + + const fillStatus = rxfill?.fillstatus?.dispensed?.note; + const patient = rxfill?.patient; + const code = rxfill?.medicationprescribed?.drugcoded?.drugdbcode?.code; + + await remsCaseCollection.findOneAndUpdate( + { + patientFirstName: patient?.humanpatient?.name?.firstname, + patientLastName: patient?.humanpatient?.name?.lastname, + patientDOB: patient?.humanpatient?.dateofbirth?.date, + drugCode: code + }, + { dispenseStatus: fillStatus }, + { new: true } + ); + return fillStatus; +}; + +export default router; diff --git a/src/server.ts b/src/server.ts index b9c816f..55d33d3 100644 --- a/src/server.ts +++ b/src/server.ts @@ -9,9 +9,11 @@ import patientViewService from './hooks/rems.patientview'; import encounterStartService from './hooks/rems.encounterstart'; import { Server } from '@projecttacoma/node-fhir-server-core'; import Etasu from './lib/etasu'; +import Ncpdp from './lib/rxfill'; import env from 'env-var'; import https from 'https'; import fs from 'fs'; +import bodyParserXml from 'body-parser-xml'; const logger = container.get('application'); @@ -26,6 +28,7 @@ const initialize = (config: any) => { .setProfileRoutes() .registerCdsHooks(config.server) .configureEtasuEndpoints() + .configureNCPDPEndpoints() .setErrorRoutes(); }; @@ -116,6 +119,22 @@ class REMSServer extends Server { return this; } + configureNCPDPEndpoints() { + bodyParserXml(bodyParser); + this.app.use( + bodyParser.xml({ + limit: '1MB', + xmlParseOptions: { + normalize: true, + normalizeTags: true, + explicitArray: false + } + }) + ); + this.app.use('/', Ncpdp); + return this; + } + /** * @method listen * @description Start listening on the configured port From 7e58213d3537749ea2e655f5bc377e43030401c2 Mon Sep 17 00:00:00 2001 From: Ariel Virgulto Date: Fri, 23 Aug 2024 10:07:57 -0400 Subject: [PATCH 02/10] update lint --- src/lib/rxfill.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/rxfill.ts b/src/lib/rxfill.ts index 26fa2f1..68b18dd 100644 --- a/src/lib/rxfill.ts +++ b/src/lib/rxfill.ts @@ -1,8 +1,8 @@ -import { Router, Response, Request } from 'express'; +import { Router, Request } from 'express'; import { remsCaseCollection } from '../fhir/models'; const router = Router(); -router.post('/ncpdp', async (req: Request, res: Response) => { +router.post('/ncpdp', async (req: Request) => { try { const requestBody = req.body; if (requestBody.message?.body?.rxfill) { From 1afca17c7aeeb591c41c05bb68b54f7d4b211b2d Mon Sep 17 00:00:00 2001 From: Sahil Malhotra Date: Tue, 3 Sep 2024 15:54:47 -0400 Subject: [PATCH 03/10] update submodules --- src/rems-cds-hooks | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rems-cds-hooks b/src/rems-cds-hooks index 8458dc2..8a51ac5 160000 --- a/src/rems-cds-hooks +++ b/src/rems-cds-hooks @@ -1 +1 @@ -Subproject commit 8458dc2a9199d2be3eb4ad6c98bdff4247266c1f +Subproject commit 8a51ac5c6837549e43a30c4f886c0bfd2aeae50d From aee014cefaf88e1119cabf0b9b76b3e7141d4da6 Mon Sep 17 00:00:00 2001 From: Sahil Malhotra Date: Tue, 3 Sep 2024 15:58:22 -0400 Subject: [PATCH 04/10] point submodule to dev --- src/rems-cds-hooks | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rems-cds-hooks b/src/rems-cds-hooks index 8a51ac5..7f8c04a 160000 --- a/src/rems-cds-hooks +++ b/src/rems-cds-hooks @@ -1 +1 @@ -Subproject commit 8a51ac5c6837549e43a30c4f886c0bfd2aeae50d +Subproject commit 7f8c04aab290c81b2f38476ab70c757925346100 From 502a640e37368104639ef51628a7774e84334d54 Mon Sep 17 00:00:00 2001 From: Sahil Malhotra Date: Tue, 3 Sep 2024 16:08:41 -0400 Subject: [PATCH 05/10] point submodule to main --- src/rems-cds-hooks | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rems-cds-hooks b/src/rems-cds-hooks index 7f8c04a..8a51ac5 160000 --- a/src/rems-cds-hooks +++ b/src/rems-cds-hooks @@ -1 +1 @@ -Subproject commit 7f8c04aab290c81b2f38476ab70c757925346100 +Subproject commit 8a51ac5c6837549e43a30c4f886c0bfd2aeae50d From 4e2b0f34a2af36903b70d2275a3a1e3a55c31a07 Mon Sep 17 00:00:00 2001 From: Sahil Malhotra Date: Tue, 3 Sep 2024 16:12:17 -0400 Subject: [PATCH 06/10] revert cds hooks --- src/rems-cds-hooks | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rems-cds-hooks b/src/rems-cds-hooks index 8a51ac5..8458dc2 160000 --- a/src/rems-cds-hooks +++ b/src/rems-cds-hooks @@ -1 +1 @@ -Subproject commit 8a51ac5c6837549e43a30c4f886c0bfd2aeae50d +Subproject commit 8458dc2a9199d2be3eb4ad6c98bdff4247266c1f From 3ba48098be561581fb2082105caa3dd16af4e3bb Mon Sep 17 00:00:00 2001 From: Sahil Malhotra Date: Tue, 3 Sep 2024 16:14:32 -0400 Subject: [PATCH 07/10] point cds hooks to main --- src/rems-cds-hooks | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rems-cds-hooks b/src/rems-cds-hooks index 8458dc2..8a51ac5 160000 --- a/src/rems-cds-hooks +++ b/src/rems-cds-hooks @@ -1 +1 @@ -Subproject commit 8458dc2a9199d2be3eb4ad6c98bdff4247266c1f +Subproject commit 8a51ac5c6837549e43a30c4f886c0bfd2aeae50d From 95f7720857fd215e0d4ca0fa89e260f6a515ae05 Mon Sep 17 00:00:00 2001 From: Ariel Virgulto Date: Fri, 6 Sep 2024 11:11:40 -0400 Subject: [PATCH 08/10] Update location of file and api url --- src/ncpdp/script.ts | 40 ++++++++++++++++++++++++++++++++++++++++ src/server.ts | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 src/ncpdp/script.ts diff --git a/src/ncpdp/script.ts b/src/ncpdp/script.ts new file mode 100644 index 0000000..df4c210 --- /dev/null +++ b/src/ncpdp/script.ts @@ -0,0 +1,40 @@ +import { Router, Request } from 'express'; +import { remsCaseCollection } from '../fhir/models'; +const router = Router(); + +router.post('/ncpdp/script', async (req: Request) => { + try { + const requestBody = req.body; + if (requestBody.message?.body?.rxfill) { + // call to handle rxfill + handleRxFill(requestBody); + } else { + // do nothing for now + } + } catch (error) { + console.log(error); + throw error; + } +}); + +const handleRxFill = async (bundle: any) => { + const rxfill = bundle.message?.body?.rxfill; + + const fillStatus = rxfill?.fillstatus?.dispensed?.note; + const patient = rxfill?.patient; + const code = rxfill?.medicationprescribed?.drugcoded?.drugdbcode?.code; + + await remsCaseCollection.findOneAndUpdate( + { + patientFirstName: patient?.humanpatient?.name?.firstname, + patientLastName: patient?.humanpatient?.name?.lastname, + patientDOB: patient?.humanpatient?.dateofbirth?.date, + drugCode: code + }, + { dispenseStatus: fillStatus }, + { new: true } + ); + return fillStatus; +}; + +export default router; diff --git a/src/server.ts b/src/server.ts index 55d33d3..a2e2f8f 100644 --- a/src/server.ts +++ b/src/server.ts @@ -9,7 +9,7 @@ import patientViewService from './hooks/rems.patientview'; import encounterStartService from './hooks/rems.encounterstart'; import { Server } from '@projecttacoma/node-fhir-server-core'; import Etasu from './lib/etasu'; -import Ncpdp from './lib/rxfill'; +import Ncpdp from './ncpdp/script'; import env from 'env-var'; import https from 'https'; import fs from 'fs'; From f703ce86ff5be23cbda1fc09b14c790defad6203 Mon Sep 17 00:00:00 2001 From: Ariel Virgulto Date: Fri, 6 Sep 2024 11:19:57 -0400 Subject: [PATCH 09/10] Remove rxfill page since its renamed --- src/lib/rxfill.ts | 40 ---------------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 src/lib/rxfill.ts diff --git a/src/lib/rxfill.ts b/src/lib/rxfill.ts deleted file mode 100644 index 68b18dd..0000000 --- a/src/lib/rxfill.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Router, Request } from 'express'; -import { remsCaseCollection } from '../fhir/models'; -const router = Router(); - -router.post('/ncpdp', async (req: Request) => { - try { - const requestBody = req.body; - if (requestBody.message?.body?.rxfill) { - // call to handle rxfill - handleRxFill(requestBody); - } else { - // do nothing for now - } - } catch (error) { - console.log(error); - throw error; - } -}); - -const handleRxFill = async (bundle: any) => { - const rxfill = bundle.message?.body?.rxfill; - - const fillStatus = rxfill?.fillstatus?.dispensed?.note; - const patient = rxfill?.patient; - const code = rxfill?.medicationprescribed?.drugcoded?.drugdbcode?.code; - - await remsCaseCollection.findOneAndUpdate( - { - patientFirstName: patient?.humanpatient?.name?.firstname, - patientLastName: patient?.humanpatient?.name?.lastname, - patientDOB: patient?.humanpatient?.dateofbirth?.date, - drugCode: code - }, - { dispenseStatus: fillStatus }, - { new: true } - ); - return fillStatus; -}; - -export default router; From 3d42530f8838fa32b489737babd3e98de7546e59 Mon Sep 17 00:00:00 2001 From: Ariel Virgulto Date: Fri, 6 Sep 2024 11:55:31 -0400 Subject: [PATCH 10/10] remove import that wasn't compiling --- src/hooks/hookResources.ts | 16 ++++++---------- src/hooks/rems.encounterstart.ts | 8 ++------ src/hooks/rems.orderselect.ts | 8 ++------ src/hooks/rems.ordersign.ts | 8 ++------ src/hooks/rems.patientview.ts | 8 ++------ 5 files changed, 14 insertions(+), 34 deletions(-) diff --git a/src/hooks/hookResources.ts b/src/hooks/hookResources.ts index 89aa268..4d435a4 100644 --- a/src/hooks/hookResources.ts +++ b/src/hooks/hookResources.ts @@ -9,11 +9,7 @@ import { BundleEntry } from 'fhir/r4'; import Card, { Link, Suggestion, Action } from '../cards/Card'; -import { - HookPrefetch, - TypedRequestBody, - TypedResponseBody -} from '../rems-cds-hooks/resources/HookTypes'; +import { HookPrefetch, TypedRequestBody } from '../rems-cds-hooks/resources/HookTypes'; import config from '../config'; import { RemsCase, @@ -28,7 +24,7 @@ import { ServicePrefetch } from '../rems-cds-hooks/resources/CdsService'; import { hydrate } from '../rems-cds-hooks/prefetch/PrefetchHydrator'; type HandleCallback = ( - res: TypedResponseBody, + res: any, hydratedPrefetch: HookPrefetch | undefined, contextRequest: FhirResource | undefined, patient: FhirResource | undefined @@ -360,7 +356,7 @@ const getErrorCard = ( // handles order-sign and order-select currently export const handleCardOrder = async ( - res: TypedResponseBody, + res: any, hydratedPrefetch: HookPrefetch | undefined, contextRequest: FhirResource | undefined, resource: FhirResource | undefined @@ -485,7 +481,7 @@ const getSuggestions = ( // make sure code here is applicable to all supported hooks. export async function handleCard( req: TypedRequestBody, - res: TypedResponseBody, + res: any, hydratedPrefetch: HookPrefetch, contextRequest: FhirResource | undefined, callback: HandleCallback @@ -517,7 +513,7 @@ export async function handleCard( // handles all hooks, any supported hook should pass through this function export function handleHook( req: TypedRequestBody, - res: TypedResponseBody, + res: any, hookPrefetch: ServicePrefetch, contextRequest: FhirResource | undefined, callback: HandleCallback @@ -732,7 +728,7 @@ const getSuggestionOrEmptyArray = // handles patient-view and encounter-start currently export const handleCardEncounter = async ( - res: TypedResponseBody, + res: any, hookPrefetch: HookPrefetch | undefined, _contextRequest: FhirResource | undefined, resource: FhirResource | undefined diff --git a/src/hooks/rems.encounterstart.ts b/src/hooks/rems.encounterstart.ts index 8b56250..ca11070 100644 --- a/src/hooks/rems.encounterstart.ts +++ b/src/hooks/rems.encounterstart.ts @@ -1,8 +1,4 @@ -import { - EncounterStartHook, - SupportedHooks, - TypedResponseBody -} from '../rems-cds-hooks/resources/HookTypes'; +import { EncounterStartHook, SupportedHooks } from '../rems-cds-hooks/resources/HookTypes'; import { ServicePrefetch, CdsService } from '../rems-cds-hooks/resources/CdsService'; import { handleCardEncounter, handleHook } from './hookResources'; @@ -24,7 +20,7 @@ const definition: CdsService = { prefetch: hookPrefetch }; -const handler = (req: TypedRequestBody, res: TypedResponseBody) => { +const handler = (req: TypedRequestBody, res: any) => { console.log('REMS encounter-start hook'); const contextRequest = undefined; handleHook(req, res, hookPrefetch, contextRequest, handleCardEncounter); diff --git a/src/hooks/rems.orderselect.ts b/src/hooks/rems.orderselect.ts index 6ba60e9..b3b2c63 100644 --- a/src/hooks/rems.orderselect.ts +++ b/src/hooks/rems.orderselect.ts @@ -1,8 +1,4 @@ -import { - SupportedHooks, - TypedResponseBody, - OrderSelectHook -} from '../rems-cds-hooks/resources/HookTypes'; +import { SupportedHooks, OrderSelectHook } from '../rems-cds-hooks/resources/HookTypes'; import { ServicePrefetch, CdsService } from '../rems-cds-hooks/resources/CdsService'; import { handleCardOrder, handleHook } from './hookResources'; @@ -22,7 +18,7 @@ const definition: CdsService = { prefetch: hookPrefetch }; -const handler = (req: TypedRequestBody, res: TypedResponseBody) => { +const handler = (req: TypedRequestBody, res: any) => { console.log('REMS order-select hook'); const context = req.body.context; const selection = context.selections?.[0]; diff --git a/src/hooks/rems.ordersign.ts b/src/hooks/rems.ordersign.ts index d15798a..3e0fedc 100644 --- a/src/hooks/rems.ordersign.ts +++ b/src/hooks/rems.ordersign.ts @@ -1,8 +1,4 @@ -import { - OrderSignHook, - SupportedHooks, - TypedResponseBody -} from '../rems-cds-hooks/resources/HookTypes'; +import { OrderSignHook, SupportedHooks } from '../rems-cds-hooks/resources/HookTypes'; import { ServicePrefetch, CdsService } from '../rems-cds-hooks/resources/CdsService'; import { handleCardOrder, handleHook } from './hookResources'; @@ -22,7 +18,7 @@ const definition: CdsService = { prefetch: hookPrefetch }; -const handler = (req: TypedRequestBody, res: TypedResponseBody) => { +const handler = (req: TypedRequestBody, res: any) => { console.log('REMS order-sign hook'); const contextRequest = req.body.context.draftOrders?.entry?.[0]?.resource; handleHook(req, res, hookPrefetch, contextRequest, handleCardOrder); diff --git a/src/hooks/rems.patientview.ts b/src/hooks/rems.patientview.ts index a3e9a6d..007e3ee 100644 --- a/src/hooks/rems.patientview.ts +++ b/src/hooks/rems.patientview.ts @@ -1,8 +1,4 @@ -import { - PatientViewHook, - SupportedHooks, - TypedResponseBody -} from '../rems-cds-hooks/resources/HookTypes'; +import { PatientViewHook, SupportedHooks } from '../rems-cds-hooks/resources/HookTypes'; import { ServicePrefetch, CdsService } from '../rems-cds-hooks/resources/CdsService'; import { handleCardEncounter, handleHook } from './hookResources'; @@ -24,7 +20,7 @@ const definition: CdsService = { prefetch: hookPrefetch }; -const handler = (req: TypedRequestBody, res: TypedResponseBody) => { +const handler = (req: TypedRequestBody, res: any) => { console.log('REMS patient-view hook'); const contextRequest = undefined; handleHook(req, res, hookPrefetch, contextRequest, handleCardEncounter);