<strong>Test</strong>: Retrieve Old data
Contents
So I added ‘dbfill’ to the filter routine and added a new routine called dbfill with this code:
function dbfill.CompareMessage(Data) local Out = hl7.parse{vmd='CVISOutbound.vmd', data=Data} end
And then tweaked the main routine to call this code:
local Out = Msg:S() dbfill.CompareMessage(Out) queue.push{data=Out}
That told me my first problem with the new mapping code. It was missing the message type! Oops.
Easy enough to solve with two additional lines of script (on lines 23 and 24) in the MapMSH function:
Then I altered the dbfill routine to:
function dbfill.LoadMessage(Base, Msg) local FileName = 'D:temp'..Base ..Msg.MSH[10]..'.txt' trace(FileName) local F = io.open(FileName, "r") return F:read("*a") end function dbfill.CompareMessage(Data) local Out = hl7.parse{vmd='CVISOutbound.vmd', data=Data} local Orig = dbfill.LoadMessage('orig', Out) return hl7.parse{vmd='CVISOutbound.vmd', data=Orig} end
This is where the real power of the Translator shows through because we are returning a parsed node tree from the loading routine we can open up parallel dialogs for the original message and the new output message and compare them along side each other. This screen shot shows exactly that with the left hand side showing the new tree and the right hand side the original output:
It’s easy to see the gaps that we have to fill in the new interface. I went through and added in the missing MSH fields:
function MapMSH(MSH, T) MSH[9][1]='ORU' MSH[9][2]='R01' MSH[3][1] = 'NHCCVIS' MSH[4][1] = 'NHC' MSH[5][1] = 'PCS' MSH[6][1] = 'EMR' MSH[12] = '2.3' MSH[10] = T.MSHMessageControlID MSH[7] = os.date('%Y%M%d%H%m') MSH[11][1] = 'T' return MSH end
I went through the script putting in the mappings. Some observations:
- Having very regularly named source data made it quite easy see if data was set as a constant or came from the database.
- Deep auto-completion was very helpful in locating source data in the database table to map it.
To give an example see:
You can see in the above I was searching for the key phrase “219” in order to find the OBXObservationIdentifierText219 value.
Doing things this way makes for a very efficient work flow. It took me about 1/2 hour to flesh out the rest of the mappings. My script looked like this now:
require 'dateparse' require 'node' require 'dbfill' local conn = db.connect{ api=db.SQLITE, name='test', live=true } local function trace(a,b,c,d,) return end function main(Data) local R = conn:query{ live=true, sql="SELECT * FROM NHCCVISREPORT WHERE MESSAGE_ID = "..Data } local Msg = hl7.message{vmd='CVISOutbound.vmd', name='NHCCVIS'} MapMSH(Msg.MSH, R[1]) MapPID(Msg.PID, R[1]) MapPV1(Msg.PV1, R[1]) MapOBR(Msg.OBR, R[1]) MapOBX(Msg.OBX, R[1]) trace(Msg) local Out = Msg:S() dbfill.CompareMessage(Out) queue.push{data=Out} end function MapMSH(MSH, T) MSH[9][1]='ORU' MSH[9][2]='R01' MSH[3][1] = 'NHCCVIS' MSH[4][1] = 'NHC' MSH[5][1] = 'PCS' MSH[6][1] = 'EMR' MSH[12] = '2.3' MSH[10] = T.MSHMessageControlID MSH[7] = os.date('%Y%M%d%H%m') MSH[11][1] = 'T' return MSH end function node.HD(N) return os.date('%Y%m%d', dateparse.parse(N:S())) end function node.HT(N) return os.date('%Y%m%d%H%M', dateparse.parse(N:S())) end function MapPID(PID, T) PID[2][1] = T.PIDPatientIDExternalIDID PID[2][3] = '11' PID[2][4][1] = 'EMI Primary' PID[3][1] = T.PIDPatientIDInternalIDID PID[3][2] = T.PIDPatientIDInternalIDCheckDigit PID[3][3] = '11' PID[3][4][1] = 'MRN' PID[5][1] = T.PIDPatientNameFamilyName PID[5][2] = T.PIDPatientNameGivenName PID[7] = T.PIDDateTimeofBirth:HD() PID[8] = T.PIDSex PID[18][1] = T.PIDPatientAccountNumberID PID[18][4][1] = "Visit" return PID end function MapPV1(PV1, T) PV1[2] = 'OUTPATIENT' PV1[3][1] = 'NHCCVIS Assign' PV1[3][4][1] = 'NHC' PV1[18] = 'NA' PV1[19][1] = T.PVVisitNumberID PV1[19][4][1] = 'Visit' PV1[44] = T.PVAdmitDateTime:HT() end function MapOBR(OBR, T) OBR[2][2] = 'PCS' OBR[3][1] = T.OBRFillerOrderNumberEntityIdentifier OBR[3][2] = 'NHCCVIS' OBR[4][1] = T.OBRUniversalServiceIDIdentifier OBR[4][2] = T.OBRUniversalServiceIDText OBR[4][3] = 'NHCCVIS' OBR[7] = T.OBRObservationDateTime:HT() OBR[18] = T.OBRPlacerField OBR[25] = 'F' OBR[27][6] = 'ROUTINE' return OBR end function MapOBX(OBX, T) OBX[1][1] = '1' OBX[1][2] = 'FT' OBX[1][3][1] = T.OBXObservationIdentifierIdentifier OBX[1][3][3] = 'NHCCVIS' OBX[1][5][1] = T.OBXObservationValue OBX[1][11] = 'F' OBX[2][1] = '2' OBX[2][2] = 'RP' OBX[2][3][1] = T.OBXObservationIdentifierIdentifier1 OBX[2][11] = 'F' OBX[3][1] = '3' OBX[3][2] = 'FT' OBX[3][3][1] = T.OBXObservationIdentifierIdentifier2 OBX[3][3][2] = T.OBXObservationIdentifierText2 OBX[3][3][3] = 'NHCCVIS' OBX[3][5][1] = T.OBXObservationValue2 OBX[3][11] = 'F' end
This screen shot shows the changes as we can see inside the editor, you can really see the power of having integrated version control in the Translator:
Next Step?
At this point our equivalent mapping is fairly complete. What is required now is to use the power of the Translator to programmatically identify the last few remaining differences between the old implementation of the interface and the new one.