1- /* NCPDP SCRIPT v2017071 Support */
1+ /* NCPDP SCRIPT v2017071 Support - Enhanced for Full REMS Compliance */
22import { XMLBuilder } from 'fast-xml-parser' ;
33import { v4 as uuidv4 } from 'uuid' ;
44
@@ -12,6 +12,9 @@ const XML_BUILDER_OPTIONS = {
1212 oneListGroup : 'true'
1313} ;
1414
15+ /**
16+ * Build base NCPDP message structure
17+ */
1518function buildMessage ( inputMessage , body ) {
1619 const { Message } = inputMessage ;
1720 const { Header, Body } = Message ;
@@ -33,8 +36,10 @@ function buildMessage(inputMessage, body) {
3336 }
3437 } ,
3538 {
36- Message :
37- 'NewRx Request Received For: ' + Body . NewRx . MedicationPrescribed . DrugDescription
39+ MessageID : Header . MessageID
40+ } ,
41+ {
42+ Message : 'NewRx Request Received For: ' + Body . NewRx . MedicationPrescribed . DrugDescription
3843 } ,
3944 { RelatesToMessageID : Header . MessageID } ,
4045 { SentTime : time . toISOString ( ) } ,
@@ -49,12 +54,15 @@ function buildMessage(inputMessage, body) {
4954 return message ;
5055}
5156
57+ /**
58+ * Build NCPDP Status message (success response)
59+ */
5260export function buildRxStatus ( newRxMessageConvertedToJSON ) {
5361 const body = [
5462 {
5563 Status : [
5664 {
57- Code : '000' // Placeholder: This is dependent on individual pharmacy
65+ Code : '000'
5866 }
5967 ]
6068 }
@@ -64,13 +72,16 @@ export function buildRxStatus(newRxMessageConvertedToJSON) {
6472 return builder . build ( rxStatus ) ;
6573}
6674
75+ /**
76+ * Build NCPDP Error message
77+ */
6778export function buildRxError ( newRxMessageConvertedToJSON , errorMessage ) {
6879 const body = [
6980 {
7081 Error : [
7182 {
72- Code : 900 , // Transaction was rejected
73- DescriptionCode : 1000 , // Unable to identify based on information submitted
83+ Code : 900 ,
84+ DescriptionCode : 1000 ,
7485 Description : errorMessage
7586 }
7687 ]
@@ -81,13 +92,56 @@ export function buildRxError(newRxMessageConvertedToJSON, errorMessage) {
8192 return builder . build ( rxStatus ) ;
8293}
8394
95+ /**
96+ * Build NCPDP RxFill message
97+ * Per NCPDP spec: Sent when medication is dispensed/picked up
98+ * Must be sent to both EHR and REMS Admin for REMS drugs
99+ */
84100export const buildRxFill = newRx => {
85101 const { Message } = JSON . parse ( newRx . serializedJSON ) ;
86102 const { Header, Body } = Message ;
87- console . log ( 'Message' , Message ) ;
103+ console . log ( 'Building RxFill per NCPDP SCRIPT' ) ;
88104 const time = new Date ( ) ;
105+
106+ // Extract medication data from NewRx
107+ const medicationPrescribed = Body . NewRx . MedicationPrescribed ;
108+ const drugCoded = medicationPrescribed . DrugCoded ;
109+
110+ const medicationDispensed = {
111+ DrugDescription : medicationPrescribed . DrugDescription ,
112+ DrugCoded : {
113+ ProductCode : drugCoded . ProductCode ? {
114+ Code : drugCoded . ProductCode . Code ,
115+ Qualifier : drugCoded . ProductCode . Qualifier
116+ } : undefined ,
117+ Strength : drugCoded . Strength ? {
118+ StrengthValue : drugCoded . Strength . StrengthValue ,
119+ StrengthForm : drugCoded . Strength . StrengthForm ,
120+ StrengthUnitOfMeasure : drugCoded . Strength . StrengthUnitOfMeasure
121+ } : undefined
122+ } ,
123+ Quantity : {
124+ Value : medicationPrescribed . Quantity . Value ,
125+ CodeListQualifier : medicationPrescribed . Quantity . CodeListQualifier || '87' ,
126+ QuantityUnitOfMeasure : medicationPrescribed . Quantity . QuantityUnitOfMeasure
127+ } ,
128+ DaysSupply : medicationPrescribed . DaysSupply ,
129+ WrittenDate : medicationPrescribed . WrittenDate ,
130+ Substitutions : medicationPrescribed . Substitutions ?. Substitutions ||
131+ medicationPrescribed . Substitutions || '0' ,
132+ NumberOfRefills : medicationPrescribed . Refills ?. Quantity ||
133+ medicationPrescribed . NumberOfRefills || 0 ,
134+ Sig : medicationPrescribed . Sig
135+ } ;
136+
89137 const message = {
90138 Message : {
139+ '@@DatatypesVersion' : '20170715' ,
140+ '@@TransportVersion' : '20170715' ,
141+ '@@TransactionDomain' : 'SCRIPT' ,
142+ '@@TransactionVersion' : '20170715' ,
143+ '@@StructuresVersion' : '20170715' ,
144+ '@@ECLVersion' : '20170715' ,
91145 Header : [
92146 {
93147 To : {
@@ -104,6 +158,7 @@ export const buildRxFill = newRx => {
104158 { MessageID : uuidv4 ( ) } ,
105159 { RelatesToMessageID : Header . MessageID } ,
106160 { SentTime : time . toISOString ( ) } ,
161+ { RxReferenceNumber : Header . MessageID } ,
107162 { PrescriberOrderNumber : Header . PrescriberOrderNumber }
108163 ] ,
109164 Body : [
@@ -117,16 +172,16 @@ export const buildRxFill = newRx => {
117172 Patient : Body . NewRx . Patient ,
118173 Pharmacy : {
119174 Identification : {
120- NCPDPID : MOCK_VALUE ,
175+ NCPDPID : Header . To . _ || MOCK_VALUE ,
121176 NPI : MOCK_VALUE
122177 } ,
123- BusinessName : Header . To . _ ,
178+ BusinessName : Header . To . _ || 'Pharmacy' ,
124179 Address : {
125180 AddressLine1 : MOCK_VALUE ,
126181 City : MOCK_VALUE ,
127182 StateProvince : MOCK_VALUE ,
128183 PostalCode : MOCK_VALUE ,
129- Country : MOCK_VALUE
184+ CountryCode : 'US'
130185 } ,
131186 CommunicationNumbers : {
132187 PrimaryTelephone : {
@@ -135,12 +190,194 @@ export const buildRxFill = newRx => {
135190 }
136191 } ,
137192 Prescriber : Body . NewRx . Prescriber ,
193+ MedicationDispensed : medicationDispensed
194+ }
195+ }
196+ ]
197+ }
198+ } ;
199+ const builder = new XMLBuilder ( XML_BUILDER_OPTIONS ) ;
200+ return builder . build ( message ) ;
201+ } ;
202+
203+ /**
204+ * Build NCPDP REMSInitiationRequest
205+ */
206+ export const buildREMSInitiationRequest = newRx => {
207+ const { Message } = JSON . parse ( newRx . serializedJSON ) ;
208+ const { Header, Body } = Message ;
209+ const time = new Date ( ) ;
210+
211+ // Extract NDC from medication (prioritize NDC, fallback to other codes)
212+ const drugCoded = Body . NewRx . MedicationPrescribed . DrugCoded ;
213+ const ndcCode =
214+ drugCoded ?. NDC || drugCoded ?. ProductCode ?. Code ;
215+ const humanPatient = Body . NewRx . Patient . HumanPatient ;
216+ const patient = {
217+ HumanPatient : {
218+ Identification : { } ,
219+ Names : humanPatient . Names ,
220+ GenderAndSex : humanPatient . GenderAndSex ,
221+ DateOfBirth : humanPatient . DateOfBirth ,
222+ Address : humanPatient . Address
223+ }
224+ } ;
225+
226+ const message = {
227+ Message : {
228+ '@@DatatypesVersion' : '2024011' ,
229+ '@@TransportVersion' : '2024011' ,
230+ '@@TransactionDomain' : 'SCRIPT' ,
231+ '@@TransactionVersion' : '2024011' ,
232+ '@@StructuresVersion' : '2024011' ,
233+ '@@ECLVersion' : '2024011' ,
234+ Header : [
235+ {
236+ To : {
237+ '#text' : ndcCode ,
238+ '@@Qualifier' : 'ZZZ'
239+ }
240+ } ,
241+ {
242+ From : {
243+ '#text' : Header . To . _ || 'PIMS Pharmacy' ,
244+ '@@Qualifier' : 'REMS'
245+ }
246+ } ,
247+ { MessageID : uuidv4 ( ) } ,
248+ { SentTime : time . toISOString ( ) } ,
249+ {
250+ Security : {
251+ Sender : {
252+ SecondaryIdentification : 'PASSWORDR'
253+ }
254+ }
255+ } ,
256+ {
257+ SenderSoftware : {
258+ SenderSoftwareDeveloper : 'PIMS' ,
259+ SenderSoftwareProduct : 'PharmacySystem' ,
260+ SenderSoftwareVersionRelease : '1'
261+ }
262+ } ,
263+ { TestMessage : 'false' }
264+ ] ,
265+ Body : [
266+ {
267+ REMSInitiationRequest : {
268+ REMSReferenceID : uuidv4 ( ) . replace ( / - / g, '' ) . substring ( 0 , 25 ) ,
269+ Patient : patient ,
270+ Pharmacy : {
271+ Identification : {
272+ NCPDPID : Header . To . _ || MOCK_VALUE ,
273+ NPI : MOCK_VALUE
274+ } ,
275+ BusinessName : Header . To . _ || 'PIMS Pharmacy' ,
276+ CommunicationNumbers : {
277+ PrimaryTelephone : {
278+ Number : MOCK_VALUE
279+ }
280+ }
281+ } ,
282+ Prescriber : Body . NewRx . Prescriber ,
138283 MedicationPrescribed : Body . NewRx . MedicationPrescribed
139284 }
140285 }
141286 ]
142287 }
143288 } ;
289+
144290 const builder = new XMLBuilder ( XML_BUILDER_OPTIONS ) ;
145291 return builder . build ( message ) ;
146292} ;
293+
294+ /**
295+ * Build NCPDP REMSRequest
296+ */
297+ export const buildREMSRequest = ( newRx , caseNumber ) => {
298+ const { Message } = JSON . parse ( newRx . serializedJSON ) ;
299+ const { Header, Body } = Message ;
300+ const time = new Date ( ) ;
301+ const deadlineDate = new Date ( ) ;
302+ deadlineDate . setDate ( deadlineDate . getDate ( ) + 7 ) ;
303+
304+ // Extract NDC from medication
305+ const drugCoded = Body . NewRx . MedicationPrescribed . DrugCoded ;
306+ const ndcCode =
307+ drugCoded ?. NDC || drugCoded ?. ProductCode ?. Code || '66215050130' ;
308+
309+ const message = {
310+ Message : {
311+ '@@DatatypesVersion' : '2024011' ,
312+ '@@TransportVersion' : '2024011' ,
313+ '@@TransactionDomain' : 'SCRIPT' ,
314+ '@@TransactionVersion' : '2024011' ,
315+ '@@StructuresVersion' : '2024011' ,
316+ '@@ECLVersion' : '2024011' ,
317+ Header : [
318+ {
319+ To : {
320+ '#text' : ndcCode ,
321+ '@@Qualifier' : 'ZZZ'
322+ }
323+ } ,
324+ {
325+ From : {
326+ '#text' : Header . To . _ || 'PIMS Pharmacy' ,
327+ '@@Qualifier' : 'REMS'
328+ }
329+ } ,
330+ { MessageID : uuidv4 ( ) } ,
331+ { SentTime : time . toISOString ( ) } ,
332+ {
333+ Security : {
334+ Sender : {
335+ SecondaryIdentification : 'PASSWORD'
336+ }
337+ }
338+ } ,
339+ {
340+ SenderSoftware : {
341+ SenderSoftwareDeveloper : 'PIMS' ,
342+ SenderSoftwareProduct : 'PharmacySystem' ,
343+ SenderSoftwareVersionRelease : '1'
344+ }
345+ } ,
346+ { TestMessage : 'false' }
347+ ] ,
348+ Body : [
349+ {
350+ REMSRequest : {
351+ REMSReferenceID : uuidv4 ( ) . replace ( / - / g, '' ) . substring ( 0 , 25 ) ,
352+ Patient : Body . NewRx . Patient ,
353+ Pharmacy : {
354+ Identification : {
355+ NCPDPID : Header . To . _ || MOCK_VALUE ,
356+ NPI : MOCK_VALUE
357+ } ,
358+ BusinessName : Header . To . _ || 'PIMS Pharmacy' ,
359+ CommunicationNumbers : {
360+ PrimaryTelephone : {
361+ Number : MOCK_VALUE
362+ }
363+ }
364+ } ,
365+ Prescriber : Body . NewRx . Prescriber ,
366+ MedicationPrescribed : Body . NewRx . MedicationPrescribed ,
367+ Request : {
368+ SolicitedModel : {
369+ REMSCaseID : caseNumber ,
370+ DeadlineForReply : {
371+ Date : deadlineDate . toISOString ( ) . split ( 'T' ) [ 0 ]
372+ }
373+ }
374+ }
375+ }
376+ }
377+ ]
378+ }
379+ } ;
380+
381+ const builder = new XMLBuilder ( XML_BUILDER_OPTIONS ) ;
382+ return builder . build ( message ) ;
383+ } ;
0 commit comments