Skip to content

Commit 722c78a

Browse files
authored
Merge pull request #52 from mcode/dev
Dev
2 parents da6b6d1 + 2ad26c1 commit 722c78a

11 files changed

Lines changed: 374 additions & 39 deletions

File tree

.env

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ VITE_CLIENT = app-login
1717
VITE_SCOPE_ID = intermediary
1818
REMS_ADMIN_HOOK_PATH=http://localhost:8090/cds-services/rems-
1919
REMS_ADMIN_FHIR_PATH=http://localhost:8090/4_0_0
20+
REMS_ADMIN_NCPDP_PATH=http://localhost:8090/4_0_0
2021
FRONTEND_PORT = 9080
2122
BACKEND_API_BASE = http://localhost:3003
2223
EHR_URL = http://localhost:8080/test-ehr/r4
@@ -26,3 +27,4 @@ DIRECTORY_SPL_PATH = /drugs/spl.zip
2627
SPL_ZIP_FILE_NAME=TESTDATA_rems_document_and_rems_indexing_spl_files.zip
2728
NCPDP_SCRIPT_FORWARD_URL=http://localhost:5051/ncpdp/script
2829

30+

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,13 @@ Following are a list of modifiable paths:
121121
| EHR_URL | `http://localhost:8080/test-ehr/r4` | URL for the EHR System |
122122
| DIRECTORY_SERVICE_URL | http://localhost:3323 | The url for the directory server |
123123
| SPL_ZIP_FILE_NAME | TESTDATA_rems_document_and_rems_indexing_spl_files.zip | The file name of the spl zip expected to be downloaded |
124+
| SMART_ENDPOINT | `http://localhost:4040/launch` | Launch URL of associated SMART app. |
125+
| FRONTEND_VITE_AUTH | `http://localhost:8180` | Frontend-specific authentication server URL for Keycloak. |
126+
| VITE_SCOPE_ID | `intermediary` | Scope identifier for authentication. |
127+
| DIRECTORY_API_PATH | `/drug/ndc.json` | API path for querying the directory service. |
128+
| DIRECTORY_SPL_PATH | `/drugs/spl.zip` | Path for downloading SPL zip files from directory service. |
129+
| NCPDP_SCRIPT_FORWARD_URL | `http://localhost:5051/ncpdp/script` | URL for forwarding NCPDP Script messages to pharmacy system. |
130+
124131

125132
# Data Rights
126133

frontend/src/views/DataViews/Connections.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export type Connection = {
2626
code?: string;
2727
to?: string;
2828
toEtasu?: string;
29+
toNcpdp?: string;
2930
system?: string;
3031
from?: Array<String>;
3132
_id: string;
@@ -35,7 +36,7 @@ const Connections = () => {
3536
const [allData, setAllData] = useState<Connection[]>([]);
3637
const [isLoading, setIsLoading] = useState(true);
3738
const [openEdit, setOpenEdit] = useState(false);
38-
const [connection, setConnection] = useState<Connection | null>({code: '', to: '', toEtasu: '', from: [''], system: '', _id: ''});
39+
const [connection, setConnection] = useState<Connection | null>({code: '', to: '', toEtasu: '', toNcpdp: '', from: [''], system: '', _id: ''});
3940
const [addNew, setAddNew] = useState(false);
4041
const [title, setTitle] = useState('Edit Connection');
4142

@@ -99,7 +100,7 @@ const Connections = () => {
99100
}
100101

101102
const registerClient = () => {
102-
setConnection({code: '', to: '', toEtasu: '', from: [''], system: '', _id: ''});
103+
setConnection({code: '', to: '', toEtasu: '', toNcpdp: '', from: [''], system: '', _id: ''});
103104
setAddNew(true);
104105
setTitle('Register Client');
105106
setOpenEdit(true);
@@ -179,6 +180,7 @@ const Connections = () => {
179180
<TableCell align="left">Code</TableCell>
180181
<TableCell align="left">To</TableCell>
181182
<TableCell align="left">Etasu</TableCell>
183+
<TableCell align="left">NCPDP</TableCell>
182184
<TableCell align="left">From</TableCell>
183185
<TableCell align="left">System</TableCell>
184186
<TableCell align="left">Actions</TableCell>
@@ -191,6 +193,7 @@ const Connections = () => {
191193
<TableCell align="left" className='btn-group'>{row.code}</TableCell>
192194
<TableCell align="left" className='btn-group'>{row.to}</TableCell>
193195
<TableCell align="left" className='btn-group'>{row.toEtasu}</TableCell>
196+
<TableCell align="left" className='btn-group'>{row.toNcpdp}</TableCell>
194197
<TableCell align="left" className='btn-group'>{row.from}</TableCell>
195198
<TableCell align="left" className='btn-group'>{row.system}</TableCell>
196199
<TableCell align="left" className='btn-group'>

frontend/src/views/DataViews/EditPopup.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,24 @@ const EditPopup = (props) => {
155155
variant="standard"
156156
/>
157157
</div>
158+
<div className='section'>
159+
<DialogContentText id="alert-dialog-description" style={{width: '220px'}}>
160+
REMS NCPDP Endpoint:
161+
</DialogContentText>
162+
<TextField
163+
autoFocus
164+
fullWidth
165+
margin="dense"
166+
id="toNcpdp"
167+
name="toNcpdp"
168+
type="string"
169+
value={updatedConnection?.toNcpdp}
170+
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
171+
setUpdatedConnection((prevState: any) => ({...prevState, toNcpdp: event.target.value}));
172+
}}
173+
variant="standard"
174+
/>
175+
</div>
158176
<div className='section'>
159177
<DialogContentText id="alert-dialog-description" style={{width: '140px'}}>
160178
From (optional):

public/connections.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ <h1>Connections</h1>
5656
<td class="highlight"><input type="text" value="${connection.code}" data-id="${connection._id}" data-field="code"></td>
5757
<td><input type="text" value="${connection.to}" data-id="${connection._id}" data-field="to"></td>
5858
<td><input type="text" value="${connection.toEtasu}" data-id="${connection._id}" data-field="toEtasu"></td>
59+
<td><input type="text" value="${connection.toNcpdp}" data-id="${connection._id}" data-field="toNcpdp"></td>
5960
<td><input type="text" value="${connection.from.join(', ')}" data-id="${connection._id}" data-field="from"></td>
6061
<td><input type="text" value="${connection.system}" data-id="${connection._id}" data-field="system"></td>
6162
<td>
@@ -71,14 +72,15 @@ <h1>Connections</h1>
7172
const codeInput = document.querySelector(`input[data-id="${id}"][data-field="code"]`);
7273
const toInput = document.querySelector(`input[data-id="${id}"][data-field="to"]`);
7374
const toEtasuInput = document.querySelector(`input[data-id="${id}"][data-field="toEtasu"]`);
74-
75+
const toNcpdpInput = document.querySelector(`input[data-id="${id}"][data-field="toNcpdp"]`);
7576
const fromInput = document.querySelector(`input[data-id="${id}"][data-field="from"]`);
7677
const systemInput = document.querySelector(`input[data-id="${id}"][data-field="system"]`);
7778

7879
const updatedConnection = {
7980
code: codeInput.value,
8081
to: toInput.value,
8182
toEtasu: toEtasuInput.value,
83+
toNcpdp: toNcpdpInput.value,
8284
from: fromInput.value.split(',').map(item => item.trim()),
8385
system: systemInput.value
8486
};

src/config.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export type Config = {
2323
general: {
2424
remsAdminHookPath: string | undefined;
2525
remsAdminFhirEtasuPath: string;
26+
remsAdminNcpdpPath: string;
2627
ehrUrl: string | undefined;
2728
discoveryBaseUrl: string | undefined;
2829
discoveryApiUrl: string | undefined;
@@ -90,9 +91,9 @@ const config: Config = {
9091
remsAdminHookPath: env.get('REMS_ADMIN_HOOK_PATH').asString(),
9192
splZipFileName: env.get('SPL_ZIP_FILE_NAME').asString() || 'TESTDATA_rems_document_and_rems_indexing_spl_files.zip',
9293
ncpdpScriptForwardUrl: env.get('NCPDP_SCRIPT_FORWARD_URL').asString() || 'http://localhost:5051/ncpdp/script',
93-
remsAdminFhirEtasuPath:
94-
env.get('REMS_ADMIN_FHIR_PATH').asString() + '/GuidanceResponse/$rems-etasu',
95-
ehrUrl: env.get('EHR_URL').asString(),
94+
remsAdminFhirEtasuPath: env.get('REMS_ADMIN_FHIR_PATH').asString() + '/GuidanceResponse/$rems-etasu',
95+
remsAdminNcpdpPath: env.get('REMS_ADMIN_NCPDP_PATH').asString() + '/ncpdp/scripts',
96+
ehrUrl: env.get('EHR_URL').asString(),
9697
},
9798
database: {
9899
selected: 'mongo',

src/hooks/hookProxy.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ interface DrugInfo {
3535
const REMSAdminWhitelist = {
3636
standardRemsAdmin: config?.general?.remsAdminHookPath,
3737
standardRemsAdminEtasu: config?.general?.remsAdminFhirEtasuPath,
38+
standardRemsAdminNcpdp: config?.general?.remsAdminNcpdpPath,
3839
discoveryUrlBase: config?.general?.discoveryBaseUrl,
3940
discoveryApiEndpoint: config?.general?.discoveryApiUrl,
4041
discoverySplZipEndpoint: config?.general?.discoverySplZipUrl,
@@ -407,15 +408,17 @@ async function saveOrUpdateEntry(entryToSave: any, model: any): Promise<{ action
407408

408409
if (existingEntry) {
409410
const hasChanges = existingEntry.to !== entryToSave.to ||
410-
existingEntry.toEtasu !== entryToSave.toEtasu;
411+
existingEntry.toEtasu !== entryToSave.toEtasu ||
412+
existingEntry.toNcpdp !== entryToSave.toNcpdp;
411413

412414
if (hasChanges) {
413415
await model.updateOne(
414416
{ code: entryToSave.code, system: entryToSave.system },
415417
{
416418
$set: {
417419
to: entryToSave.to,
418-
toEtasu: entryToSave.toEtasu
420+
toEtasu: entryToSave.toEtasu,
421+
toNcpdp: entryToSave.toNcpdp
419422
}
420423
}
421424
);
@@ -624,13 +627,19 @@ function createDrugEntry(drug: DrugInfo, cdsEndpoint?: string, fhirBaseUrl?: str
624627
? finalFhirBaseUrl + '4_0_0/GuidanceResponse/$rems-etasu'
625628
: finalFhirBaseUrl + '/4_0_0/GuidanceResponse/$rems-etasu';
626629

630+
// Add NCPDP endpoint
631+
const ncpdpUrl = finalFhirBaseUrl.endsWith('/')
632+
? finalFhirBaseUrl + 'ncpdp/script'
633+
: finalFhirBaseUrl + '/ncpdp/script';
634+
627635
return {
628636
code: code,
629637
system: system,
630638
brand_name: drug.brandName,
631639
generic_name: drug.genericName,
632640
to: cdsUrl,
633641
toEtasu: etasuUrl,
642+
toNcpdp: ncpdpUrl,
634643
from: [EHRWhitelist.any]
635644
};
636645
}
@@ -678,12 +687,26 @@ async function processPhonebookEntries(splDrugs: any[]): Promise<{ drugs: any[],
678687
? apiResult.rems_fhir_base_url + '4_0_0/GuidanceResponse/$rems-etasu'
679688
: apiResult.rems_fhir_base_url + '/4_0_0/GuidanceResponse/$rems-etasu';
680689

690+
entryToSave.toNcpdp = apiResult.rems_fhir_base_url.endsWith('/')
691+
? apiResult.rems_fhir_base_url + 'ncpdp/script'
692+
: apiResult.rems_fhir_base_url + '/ncpdp/script';
693+
681694
phonebookApiCount++;
682695
} else {
683696
console.log(` ⚙️ PHONEBOOK DEFAULT USED: ${entry.brand_name} (${entry.code})`);
684697
console.log(` 🔗 Using fallback endpoints`);
685698
entryToSave.to = REMSAdminWhitelist.standardRemsAdmin;
686699
entryToSave.toEtasu = REMSAdminWhitelist.standardRemsAdminEtasu;
700+
entryToSave.toNcpdp = REMSAdminWhitelist.standardRemsAdminNcpdp;
701+
702+
// Add default NCPDP endpoint if we have a base URL
703+
if (REMSAdminWhitelist.standardRemsAdminEtasu) {
704+
const baseUrl = REMSAdminWhitelist.standardRemsAdminEtasu.split('/4_0_0')[0];
705+
entryToSave.toNcpdp = baseUrl.endsWith('/')
706+
? baseUrl + 'ncpdp/script'
707+
: baseUrl + '/ncpdp/script';
708+
}
709+
687710
phonebookDefaultCount++;
688711
}
689712

@@ -803,6 +826,7 @@ export async function getServiceConnection(coding: Coding, requester: string | u
803826
const connectionModel = Connection;
804827
if (coding.system && coding.code) {
805828
const connection = await connectionModel.findOne({ code: coding.code, system: coding.system });
829+
console.log(connection)
806830
if (!connection) {
807831
return undefined;
808832
}

src/hooks/hookResources.ts

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -95,22 +95,22 @@ export async function handleHook(
9595

9696
if (contextRequest && contextRequest.resourceType === 'MedicationRequest') {
9797

98-
const forwardData = (hook: Hook, url: string) => {
98+
const forwardData = async (hook: Hook, url: string) => {
9999
// remove the auth token before any forwarding occurs
100100
delete hook.fhirAuthorization;
101101
const options = {
102102
method: 'POST',
103103
data: hook,
104104
timeout: 5000,
105105
};
106-
const response = axios(url, options);
107-
response.then(e => {
108-
res.json(e.data);
109-
})
110-
.catch(err => {
106+
107+
try {
108+
const response = await axios(url, options);
109+
res.json(response.data);
110+
} catch (err) {
111111
console.log(err);
112112
res.json({ cards: [] }); // Return fallback response
113-
});
113+
}
114114
};
115115

116116
let drugCodes = getDrugCodesFromMedicationRequest(contextRequest);
@@ -128,14 +128,14 @@ export async function handleHook(
128128
const url = serviceConnection.to + hook.hook;
129129
console.log('rems-admin hook url: ' + url);
130130
if (hook.fhirAuthorization && hook.fhirServer && hook.fhirAuthorization.access_token) {
131-
hydrate(getFhirResource, hookPrefetch, hook).then(hydratedPrefetch => {
131+
hydrate(getFhirResource, hookPrefetch, hook).then(async hydratedPrefetch => {
132132
if (hydratedPrefetch) {
133133
hook.prefetch = hydratedPrefetch;
134134
}
135-
forwardData(hook, url);
135+
await forwardData(hook, url);
136136
});
137137
} else {
138-
forwardData(hook, url);
138+
await forwardData(hook, url);
139139
}
140140

141141
found = true;
@@ -226,23 +226,31 @@ export async function handleHook(
226226
res.json({ cards: [] });
227227
return;
228228
}
229-
uniqueUrls.forEach((url: string) => {
229+
uniqueUrls.forEach(async (url: string) => {
230230
// remove the auth token before any forwarding occurs
231231
delete hook.fhirAuthorization;
232+
232233
const options = {
233234
method: 'POST',
234235
data: hook
235236
};
236-
const response = axios(url, options);
237-
response.then(e => {
238-
cards = [...cards, ...e.data.cards];
237+
238+
try {
239+
const response = await axios(url, options);
240+
cards = [...cards, ...response.data.cards];
239241

240242
urlCount--;
241243
if (urlCount <= 0) {
242244
// return the final list of cards
243245
res.json({ cards });
244246
}
245-
});
247+
} catch (error) {
248+
console.error('Error calling REMS Admin:', error);
249+
urlCount--;
250+
if (urlCount <= 0) {
251+
res.json({ cards });
252+
}
253+
}
246254
});
247255
}
248256
});
@@ -253,4 +261,4 @@ export async function handleHook(
253261
res.json(createErrorCard('No MedicationRequests in ' + hookType + ' hook'));
254262
}
255263
}
256-
}
264+
}

0 commit comments

Comments
 (0)