diff --git a/.env b/.env index 3839cb5..39bb68e 100644 --- a/.env +++ b/.env @@ -21,6 +21,7 @@ REMS_ADMIN_NCPDP_PATH=http://localhost:8090/4_0_0 FRONTEND_PORT = 9080 BACKEND_API_BASE = http://localhost:3003 EHR_URL = http://localhost:8080/test-ehr/r4 +EHR_BASE_URL = http://localhost:8080/test-ehr DIRECTORY_SERVICE_URL=http://localhost:3323 DIRECTORY_API_PATH = /drug/ndc.json DIRECTORY_SPL_PATH = /drugs/spl.zip diff --git a/src/config.ts b/src/config.ts index 01bd30e..ad1d45e 100644 --- a/src/config.ts +++ b/src/config.ts @@ -25,6 +25,7 @@ export type Config = { remsAdminFhirEtasuPath: string; remsAdminNcpdpPath: string; ehrUrl: string | undefined; + ehrBaseUrl: string | undefined; discoveryBaseUrl: string | undefined; discoveryApiUrl: string | undefined; discoverySplZipUrl: string | undefined; @@ -94,6 +95,7 @@ const config: Config = { remsAdminFhirEtasuPath: env.get('REMS_ADMIN_FHIR_PATH').asString() + '/GuidanceResponse/$rems-etasu', remsAdminNcpdpPath: env.get('REMS_ADMIN_NCPDP_PATH').asString() + '/ncpdp/scripts', ehrUrl: env.get('EHR_URL').asString(), + ehrBaseUrl: env.get('EHR_BASE_URL').asString(), }, database: { selected: 'mongo', diff --git a/src/lib/ncpdpHelpers.ts b/src/lib/ncpdpHelpers.ts index 0244651..7ec9107 100644 --- a/src/lib/ncpdpHelpers.ts +++ b/src/lib/ncpdpHelpers.ts @@ -14,6 +14,67 @@ interface NcpdpDrugInfo { description?: string; } +export enum Qualifier { + Pharmacy = "P", // Pharmacy + Clinic = "C", // Clinic + Mailbox = "M", // Mailbox + Prescriber = "P", // Prescriber + CentralFillFacility = "CF", // Central Fill Facility + MutuallyDefined = "ZZZ", // Mutually Defined + Payer = "PY", // Payer + DirectIDSecureEmailAddress = "DIRECT",// Direct ID secure email address + REMSAdministrator="REMS", // REMS Administrator + Unknown="?" // Unknown / Error +} + +/** + * + * Determine the to:qualifier from the NCPDP message xml + */ +export function getToQualifier(xmlData: string | any): Qualifier { + try { + let parsedXml; + + if (typeof xmlData === 'object') { + parsedXml = xmlData; + } else { + const parser = new XMLParser(XML_PARSER_OPTIONS); + parsedXml = parser.parse(xmlData); + } + + const message = parsedXml?.Message || parsedXml?.message; + if (!message) { + console.log('Error: NCPDP XML missing Message') + return Qualifier.Unknown; + } + + const header = message?.Header || message?.header; + if (!header) { + console.log('Error: NCPDP XML missing Header') + return Qualifier.Unknown; + } + + const to = header?.To || header?.to; + if (!to) { + console.log('Error: NCPDP XML missing To') + return Qualifier.Unknown; + } + + const qualifier = to['@_Qualifier']; + + if (!qualifier) { + console.log('Error: NCPDP XML missing Qualifier') + return Qualifier.Unknown; + } + + return qualifier; + + } catch (error) { + console.error('Error determining NCPDP To Qualifier:', error); + return Qualifier.Unknown; + } +} + /** * Determine NCPDP message type from parsed XML */ diff --git a/src/server.ts b/src/server.ts index a204af0..65b33a0 100644 --- a/src/server.ts +++ b/src/server.ts @@ -19,7 +19,7 @@ import path from 'path'; import { Connection } from './lib/schemas/Phonebook'; import { EHRWhitelist, loadPhonebook } from './hooks/hookProxy'; import cookieParser from 'cookie-parser'; -import { extractDrugFromNcpdp, ndcToCoding, getMessageType} from './lib/ncpdpHelpers'; +import { extractDrugFromNcpdp, ndcToCoding, getMessageType, Qualifier, getToQualifier } from './lib/ncpdpHelpers'; import { getServiceConnection } from './hooks/hookProxy'; const logger = container.get('application'); @@ -131,14 +131,14 @@ class REMSIntermediary extends Server { return this; } - registerNcpdpScript({ ncpdpScriptForwardUrl, ehrUrl }: Config['general']) { + registerNcpdpScript({ ncpdpScriptForwardUrl, ehrBaseUrl }: Config['general']) { console.log('Registering NCPDP SCRIPT endpoint with intelligent routing'); this.app.post('/ncpdp/script', async (req: any, res: any) => { try { console.log('Processing NCPDP SCRIPT message'); - const ehrEndpoint = ehrUrl + '/script' + const ehrEndpoint = ehrBaseUrl + '/ncpdp/script' // Determine message type const messageType = getMessageType(req.body); @@ -195,38 +195,35 @@ class REMSIntermediary extends Server { console.log('Processing RxFill message'); const drugInfo = extractDrugFromNcpdp(req.body); - const promises = []; - // Send to EHR - - console.log(`Sending RxFill to EHR: ${ehrEndpoint}`); - promises.push( - axios.post(ehrEndpoint, req.body, { headers: req.headers }) - .then(() => console.log('✓ RxFill sent to EHR')) - .catch(err => console.error('✗ Error sending RxFill to EHR:', err.message)) - ); - + // grab the qualifier from the to + const qualifier = getToQualifier(req.body); - // Send to REMS Admin if REMS drug - if (drugInfo && drugInfo.ndc) { - const coding = ndcToCoding(drugInfo.ndc); - const serviceConnection = await getServiceConnection(coding, undefined); - - if (serviceConnection && serviceConnection.toNcpdp) { - console.log(`Sending RxFill to REMS Admin: ${serviceConnection.toNcpdp}`); - console.log(` Drug: ${drugInfo.description || 'Unknown'} (${drugInfo.ndc})`); + if (qualifier == Qualifier.Clinic || qualifier == Qualifier.Prescriber) { + // Send to EHR + console.log(`Sending RxFill to EHR: ${ehrEndpoint}`); + + await axios.post(ehrEndpoint, req.body, { headers: req.headers }) + .then(() => console.log('✓ RxFill sent to EHR')) + .catch(err => console.error('✗ Error sending RxFill to EHR:', err.message)); + + } else if (qualifier == Qualifier.REMSAdministrator) { + // Send to REMS Admin if REMS drug + if (drugInfo && drugInfo.ndc) { + const coding = ndcToCoding(drugInfo.ndc); + const serviceConnection = await getServiceConnection(coding, undefined); - promises.push( - axios.post(serviceConnection.toNcpdp, req.body, { headers: req.headers }) - .then(() => console.log('✓ RxFill sent to REMS Admin')) - .catch(err => console.error('✗ Error sending RxFill to REMS Admin:', err.message)) - ); + if (serviceConnection && serviceConnection.toNcpdp) { + console.log(`Sending RxFill to REMS Admin: ${serviceConnection.toNcpdp}`); + console.log(` Drug: ${drugInfo.description || 'Unknown'} (${drugInfo.ndc})`); + + await axios.post(serviceConnection.toNcpdp, req.body, { headers: req.headers }) + .then(() => console.log('✓ RxFill sent to REMS Admin')) + .catch(err => console.error('✗ Error sending RxFill to REMS Admin:', err.message)); + } } } - // Wait for all sends to complete - await Promise.all(promises); - // Return success status return res.send({ status: 'success', message: 'RxFill processed' }); }