Skip to content

Commit 1412f60

Browse files
authored
Merge pull request #53 from mcode/869-rxfill-errors
Forward RxFill message to the correct recipient based on To qualifier.
2 parents 2ad26c1 + c7d8085 commit 1412f60

4 files changed

Lines changed: 90 additions & 29 deletions

File tree

.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ REMS_ADMIN_NCPDP_PATH=http://localhost:8090/4_0_0
2121
FRONTEND_PORT = 9080
2222
BACKEND_API_BASE = http://localhost:3003
2323
EHR_URL = http://localhost:8080/test-ehr/r4
24+
EHR_BASE_URL = http://localhost:8080/test-ehr
2425
DIRECTORY_SERVICE_URL=http://localhost:3323
2526
DIRECTORY_API_PATH = /drug/ndc.json
2627
DIRECTORY_SPL_PATH = /drugs/spl.zip

src/config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export type Config = {
2525
remsAdminFhirEtasuPath: string;
2626
remsAdminNcpdpPath: string;
2727
ehrUrl: string | undefined;
28+
ehrBaseUrl: string | undefined;
2829
discoveryBaseUrl: string | undefined;
2930
discoveryApiUrl: string | undefined;
3031
discoverySplZipUrl: string | undefined;
@@ -94,6 +95,7 @@ const config: Config = {
9495
remsAdminFhirEtasuPath: env.get('REMS_ADMIN_FHIR_PATH').asString() + '/GuidanceResponse/$rems-etasu',
9596
remsAdminNcpdpPath: env.get('REMS_ADMIN_NCPDP_PATH').asString() + '/ncpdp/scripts',
9697
ehrUrl: env.get('EHR_URL').asString(),
98+
ehrBaseUrl: env.get('EHR_BASE_URL').asString(),
9799
},
98100
database: {
99101
selected: 'mongo',

src/lib/ncpdpHelpers.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,67 @@ interface NcpdpDrugInfo {
1414
description?: string;
1515
}
1616

17+
export enum Qualifier {
18+
Pharmacy = "P", // Pharmacy
19+
Clinic = "C", // Clinic
20+
Mailbox = "M", // Mailbox
21+
Prescriber = "P", // Prescriber
22+
CentralFillFacility = "CF", // Central Fill Facility
23+
MutuallyDefined = "ZZZ", // Mutually Defined
24+
Payer = "PY", // Payer
25+
DirectIDSecureEmailAddress = "DIRECT",// Direct ID secure email address
26+
REMSAdministrator="REMS", // REMS Administrator
27+
Unknown="?" // Unknown / Error
28+
}
29+
30+
/**
31+
*
32+
* Determine the to:qualifier from the NCPDP message xml
33+
*/
34+
export function getToQualifier(xmlData: string | any): Qualifier {
35+
try {
36+
let parsedXml;
37+
38+
if (typeof xmlData === 'object') {
39+
parsedXml = xmlData;
40+
} else {
41+
const parser = new XMLParser(XML_PARSER_OPTIONS);
42+
parsedXml = parser.parse(xmlData);
43+
}
44+
45+
const message = parsedXml?.Message || parsedXml?.message;
46+
if (!message) {
47+
console.log('Error: NCPDP XML missing Message')
48+
return Qualifier.Unknown;
49+
}
50+
51+
const header = message?.Header || message?.header;
52+
if (!header) {
53+
console.log('Error: NCPDP XML missing Header')
54+
return Qualifier.Unknown;
55+
}
56+
57+
const to = header?.To || header?.to;
58+
if (!to) {
59+
console.log('Error: NCPDP XML missing To')
60+
return Qualifier.Unknown;
61+
}
62+
63+
const qualifier = to['@_Qualifier'];
64+
65+
if (!qualifier) {
66+
console.log('Error: NCPDP XML missing Qualifier')
67+
return Qualifier.Unknown;
68+
}
69+
70+
return qualifier;
71+
72+
} catch (error) {
73+
console.error('Error determining NCPDP To Qualifier:', error);
74+
return Qualifier.Unknown;
75+
}
76+
}
77+
1778
/**
1879
* Determine NCPDP message type from parsed XML
1980
*/

src/server.ts

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import path from 'path';
1919
import { Connection } from './lib/schemas/Phonebook';
2020
import { EHRWhitelist, loadPhonebook } from './hooks/hookProxy';
2121
import cookieParser from 'cookie-parser';
22-
import { extractDrugFromNcpdp, ndcToCoding, getMessageType} from './lib/ncpdpHelpers';
22+
import { extractDrugFromNcpdp, ndcToCoding, getMessageType, Qualifier, getToQualifier } from './lib/ncpdpHelpers';
2323
import { getServiceConnection } from './hooks/hookProxy';
2424

2525
const logger = container.get('application');
@@ -131,14 +131,14 @@ class REMSIntermediary extends Server {
131131
return this;
132132
}
133133

134-
registerNcpdpScript({ ncpdpScriptForwardUrl, ehrUrl }: Config['general']) {
134+
registerNcpdpScript({ ncpdpScriptForwardUrl, ehrBaseUrl }: Config['general']) {
135135
console.log('Registering NCPDP SCRIPT endpoint with intelligent routing');
136136

137137
this.app.post('/ncpdp/script', async (req: any, res: any) => {
138138
try {
139139
console.log('Processing NCPDP SCRIPT message');
140140

141-
const ehrEndpoint = ehrUrl + '/script'
141+
const ehrEndpoint = ehrBaseUrl + '/ncpdp/script'
142142

143143
// Determine message type
144144
const messageType = getMessageType(req.body);
@@ -195,38 +195,35 @@ class REMSIntermediary extends Server {
195195
console.log('Processing RxFill message');
196196

197197
const drugInfo = extractDrugFromNcpdp(req.body);
198-
const promises = [];
199198

200-
// Send to EHR
201-
202-
console.log(`Sending RxFill to EHR: ${ehrEndpoint}`);
203-
promises.push(
204-
axios.post(ehrEndpoint, req.body, { headers: req.headers })
205-
.then(() => console.log('✓ RxFill sent to EHR'))
206-
.catch(err => console.error('✗ Error sending RxFill to EHR:', err.message))
207-
);
208-
199+
// grab the qualifier from the to
200+
const qualifier = getToQualifier(req.body);
209201

210-
// Send to REMS Admin if REMS drug
211-
if (drugInfo && drugInfo.ndc) {
212-
const coding = ndcToCoding(drugInfo.ndc);
213-
const serviceConnection = await getServiceConnection(coding, undefined);
214-
215-
if (serviceConnection && serviceConnection.toNcpdp) {
216-
console.log(`Sending RxFill to REMS Admin: ${serviceConnection.toNcpdp}`);
217-
console.log(` Drug: ${drugInfo.description || 'Unknown'} (${drugInfo.ndc})`);
202+
if (qualifier == Qualifier.Clinic || qualifier == Qualifier.Prescriber) {
203+
// Send to EHR
204+
console.log(`Sending RxFill to EHR: ${ehrEndpoint}`);
205+
206+
await axios.post(ehrEndpoint, req.body, { headers: req.headers })
207+
.then(() => console.log('✓ RxFill sent to EHR'))
208+
.catch(err => console.error('✗ Error sending RxFill to EHR:', err.message));
209+
210+
} else if (qualifier == Qualifier.REMSAdministrator) {
211+
// Send to REMS Admin if REMS drug
212+
if (drugInfo && drugInfo.ndc) {
213+
const coding = ndcToCoding(drugInfo.ndc);
214+
const serviceConnection = await getServiceConnection(coding, undefined);
218215

219-
promises.push(
220-
axios.post(serviceConnection.toNcpdp, req.body, { headers: req.headers })
221-
.then(() => console.log('✓ RxFill sent to REMS Admin'))
222-
.catch(err => console.error('✗ Error sending RxFill to REMS Admin:', err.message))
223-
);
216+
if (serviceConnection && serviceConnection.toNcpdp) {
217+
console.log(`Sending RxFill to REMS Admin: ${serviceConnection.toNcpdp}`);
218+
console.log(` Drug: ${drugInfo.description || 'Unknown'} (${drugInfo.ndc})`);
219+
220+
await axios.post(serviceConnection.toNcpdp, req.body, { headers: req.headers })
221+
.then(() => console.log('✓ RxFill sent to REMS Admin'))
222+
.catch(err => console.error('✗ Error sending RxFill to REMS Admin:', err.message));
223+
}
224224
}
225225
}
226226

227-
// Wait for all sends to complete
228-
await Promise.all(promises);
229-
230227
// Return success status
231228
return res.send({ status: 'success', message: 'RxFill processed' });
232229
}

0 commit comments

Comments
 (0)