integration administrator guide

Upload: kennedy-ngoseywe

Post on 07-Apr-2018

227 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/4/2019 Integration Administrator Guide

    1/16

    PatientOS

    PatientOSIntegration

    Administrator Guide

    Version 1.0

  • 8/4/2019 Integration Administrator Guide

    2/16

    Integration Last printed 4/18/2008 1:53:00 AM

    Administrator Guide Version 1.0

    Page 1 of 16

    Revision HistoryDate Version Description Author

    04/17/2008 1.0 Initial for version 0.70 Greg Caulton

  • 8/4/2019 Integration Administrator Guide

    3/16

    Integration Last printed 4/18/2008 1:53:00 AM

    Administrator Guide Version 1.0

    Page 2 of 16

    Contents1. OVERVIEW........................................................................................................................................................................

    1.1 DEFAULT SETTINGS ............................................................................................ ERROR!BOOKMARK NOT DEFINE1.2 DEFINITIONS ................................................................................................................................................................. 2. SYSTEM SETTINGS ........................................................................................ERROR! BOOKMARK NOT DEFINED

    2.1 SETTINGS TOOL .................................................................................................. ERROR!BOOKMARK NOT DEFINE2.2 CHANGING A SETTING ........................................................................................ ERROR!BOOKMARK NOT DEFINE2.3 ADDING A SETTING............................................................................................. ERROR!BOOKMARK NOT DEFINE

    3. BATCH JOBS ....................................................................................................ERROR! BOOKMARK NOT DEFINED3.1 ADDING BATCH JOBS.......................................................................................... ERROR!BOOKMARK NOT DEFINE3.2 SCHEDULING BATCH JOBS.................................................................................. ERROR!BOOKMARK NOT DEFINE

    4. SYSTEM IDENTIFIERS ..................................................................................ERROR! BOOKMARK NOT DEFINED4.1 IDENTIFIER SOURCE TOOL.................................................................................. ERROR!BOOKMARK NOT DEFINE4.2 ADDING AN IDENTFIER SOURCE ......................................................................... ERROR!BOOKMARK NOT DEFINE

    5. PATIENT PORTAL ..........................................................................................ERROR! BOOKMARK NOT DEFINED5.1 LOGIN.................................................................................................................. ERROR!BOOKMARK NOT DEFINE

  • 8/4/2019 Integration Administrator Guide

    4/16

    Integration Last printed 4/18/2008 1:53:00 AM

    Administrator Guide Version 1.0

    Page 3 of 16

    Integration Administrator Guide1. Overview

    1.1 Integration

    There are a number of inbound and outbound interfaces for PatientOS using Mirth for the majority of the integrationpoints. The list is not limited to:

    a) Standard HL7 Interfaces.a. ADT Inboundb. ADT Outboundc. Lab Results Inboundd. Lab Orders Outbound

    b) XML or any other format supporting by Mirtha. XML Forms/Clinical Results Inboundb. XML Clinical

    c) Web developmenta. Patient Portal running within the JBoss container

    d) Batch processinga. Scheduled scripts which can directly reference the EJB services

    e) JDBCa. Direct SQL (not recommended except for read only access)

    1.2 Definitions

    POS Refers to the PatientOS software as a system.

  • 8/4/2019 Integration Administrator Guide

    5/16

    Integration Last printed 4/18/2008 1:53:00 AM

    Administrator Guide Version 1.0

    Page 4 of 16

    2. XML Forms/Clinical Results Inbound

    2.1 Overview

    Mirth is an enterprise class integration engine with which PatientOS integrates. For inbound forms the basic flow is

    i) Mirth receives the XML file (from filesystem, JDBC, or port, etc)ii) Mirth maps the XML content into the PatientOS XML format for Recordsiii) Mirth inserts the XML into the interface_messages tableiv) PatientOS interface controller (running as a JBoss service) picks up the filev) The appropriate Converter is called to map the XML to the PatientOS FormRecordModelvi) The model is stored writing to the records and record_details (if populated).

    2.2 Mirth Setup

    2.2.1 Start Mirth

    To setup mirth start Mirth using Start Program Files PatientOSversion Interface Engine

    Figure 1 Starting Mirth

    For a production implementation Mirth would be installed as a service.

    2.2.2 Start Mirth Manager

    To setup the interface channels start the Mirth Manager using Start Program Files PatientOSversion Interface

    Manager. Login with

    admin/admin

    Figure 2 admin/admin

  • 8/4/2019 Integration Administrator Guide

    6/16

    Integration Last printed 4/18/2008 1:53:00 AM

    Administrator Guide Version 1.0

    Page 5 of 16

    2.2.3 Channels

    Select the channels tab and view the existing channels (if the channels were not included download from

    http://www.patientos.org/documentation. Download the file oru_xml_file_pos_db.xml. The file name indicates it is a

    results file reading XML from a file and posting it into the PatientOS database.

    Select the channel ORU XML File POS DB and Edit Channel to edit the properties.

    Figure 3 Channels

    The first tab defines that XML is being read and this channel will auto start.

    Figure 4 Summary tab

  • 8/4/2019 Integration Administrator Guide

    7/16

    Integration Last printed 4/18/2008 1:53:00 AM

    Administrator Guide Version 1.0

    Page 6 of 16

    2.2.4 XML Inbound Directory

    Clicking on the Source tab will show which directory is being read to find the XML content and the file name formatrequired to process.

    Note that the directory is defined as a relative path. It is relative from where the interface engine started (interfaces.bat or

    interfaces.sh). On windows this path would be

    C:\Program Files\PatientOS\\server\interfaces\bin

    Figure 5 Source tab

    In the figure above you can see that the channel will search for xml files in the directory

    C:\Program Files\PatientOS\\server\interfaces\activity\oru_xml_in

    every second.

  • 8/4/2019 Integration Administrator Guide

    8/16

    Integration Last printed 4/18/2008 1:53:00 AM

    Administrator Guide Version 1.0

    Page 7 of 16

    2.2.5 Destination

    On the destinations tab you can see the SQL used to insert into the PatientOS interface_messages table.

    Take careful note of the URL and ensure the correct database is being accessed. In this case qapos is shown though thedefault should be demopos with the correct username and password.

    Figure 6 Destination tab

    Click on the Edit Transformer link to open the Transformer. Paste your XML into the top right frame and the XML elemen

    will be parsed and displayed in a tree below. It helps if your XML is populated with sample data.

    Figure 7 Transformer incoming

  • 8/4/2019 Integration Administrator Guide

    9/16

    Integration Last printed 4/18/2008 1:53:00 AM

    Administrator Guide Version 1.0

    Page 8 of 16

    2.2.6 Transformer

    PatientOS is setup with Javascript to map the incoming XML elements to the PatientOS XML elements.

    The Outgoing tab serves to display a template XML which is populated by the Javascript. For this reason we want as little

    data as possible (most is not needed).

    However in order to see all the fields you might like to populate you can paste into the frame the RecordTransaction.xml file

    from http://www.patientos.org/documentation

    When have finished mapping replace the contents with the original XML You may need to tailor the XML (for example we

    will add RecordDetailModel rows.

    Figure 8 Outgoing data tab

    The goal is to populate

    a) Enough of the PatientModel to match the patient name and MRN (matching is a large topic) unless you have thepatient_id from the patients table.

    b) A single FormModel to reflect the formc) As many RecordModel has you have fields on this virtual form.d) As many RecordDetailModel if you have details for a specific Record.

    The concept of Record and RecordDetail is that the Record value is the significant value e.g. height, weight, lab results etc

    where as the RecordDetail are child details e.g. Clothing the patient had on when weighed or comments on the lab result.

    The script is written in Javascript and obviously you need some programming skills to understand the nuances of iterating

    through the XML elements and building up the target XML which is this tmp structure.

  • 8/4/2019 Integration Administrator Guide

    10/16

    Integration Last printed 4/18/2008 1:53:00 AM

    Administrator Guide Version 1.0

    Page 9 of 16

    2.2.7 Example Mapping

    We will work with this sample XML

    4

    300

    motion

    2008-01-18T00:00:00.000+01:00

    2008-01-18T00:15:00.000+01:00

    89,22,0,0,0,0,0,0,0,2,22,24,4,12,99,140,120,94,2,0,0,0,4,5,32,4,0,0,0,0,0,0,0,0,0,0,32,12,1,0,

    3,0,0,0,2,5,0,0,0,0,1,4,9,10,4,0,0,0,0

    commaSeparatedValues and sensorType are real:)!

    hammed motion

    minutes

    The patientId is actually the MRN and so in the javascript we first create the MRN mapping by dragging the XML patientID

    over to the javascript page. If you have setup a facility other than the default you would enter the reference key (your facilit

    name uppercase with spaces removed).

    Figure 9 Drag patientid to be MRN

    2.2.8 Records

    On version 1.6 of Mith one way of creating the many iterations of RecordModel is to have the first defined in the template

    and then copy it each time to add to the XML. This section of Javascript will likely change to an easier to perform this in

    later version of Mirth.

    But essentially we know there are 8 records needed so we loop 8 times and within the loop duplicate the first RecordModel,

    map the values and where possible set common values outside each if statement. Not great but it works

  • 8/4/2019 Integration Administrator Guide

    11/16

    Integration Last printed 4/18/2008 1:53:00 AM

    Administrator Guide Version 1.0

    Page 10 of 16

    You must setup an Identifier Source (login to PatientOS as admin/admin and select Identifier Sources) specific to where this

    incoming data is coming from. PatientOS supports multiple interfaces and the source is a unique identifier for all external

    identifiers.

    In this example Porcupine Sensor was used as the identifier source.

    Figure 10 Create identifier source

    2.2.9 Javascript

    Ideally all the record_items have been created in PatientOS. The display must be unique in the database in order to reduce

    confusion with multiple items with the same name (it is possible to have dups but not recommended).

    The short display is typically used on controls, reports etc. The display being the formal name.

    The interface will add these items on the fly (writes to the record_items and record_item_details tables). Ideally preload

    using a reference spreadsheet, then import the record items.

    Note dates must be formatted YYYYMMDD and mapped to the date component or YYYYMMDDHHMMSS and mapped the date/time format. Rather than parsing we will hard code it to get started with testing

    // map the MRN to match the patient

    tmp['PatientModel']['IdentifierModel']['sourceRef']['idvalue'] = "DEFAULTFACILITY";

    tmp['PatientModel']['IdentifierModel']['idvalue'] =

    msg['ns1:patientId'].toString();

    for (i=0; i

  • 8/4/2019 Integration Administrator Guide

    12/16

    Integration Last printed 4/18/2008 1:53:00 AM

    Administrator Guide Version 1.0

    Page 11 of 16

    tmp['RecordModel'][i]['dataTypeRef']['id'] = 56990; // DOUBLE

    tmp['RecordModel'][i]['valueDouble'] = msg['ns1:measureFrequency'].toString();

    } else if (i==1) { // sensor type

    tmp['RecordModel'][i]=tmp['RecordModel'][i-i]; // create xml element

    tmp['RecordModel'][i]['recordItemRef']['idvalue'] = "MOTIONSENSORTYPE";

    tmp['RecordModel'][i]['recordItemRef']['display'] = "Motion Sensor Type";tmp['RecordModel'][i]['dataTypeRef']['id'] = 79128; // STRING

    tmp['RecordModel'][i]['valueString'] = msg['ns1:sensorType'].toString();

    } else if (i==2) { // timestart

    tmp['RecordModel'][i]=tmp['RecordModel'][i-i]; // create xml element

    tmp['RecordModel'][i]['recordItemRef']['idvalue'] = "MOTIONTIMESTART";

    tmp['RecordModel'][i]['recordItemRef']['display'] = "Motion Time Start";

    tmp['RecordModel'][i]['dataTypeRef']['id'] = 56992; // DATE

    tmp['RecordModel'][i]['valueDate']['datetime'] = startTime;

    } else if (i==3) { // timestop

    tmp['RecordModel'][i]=tmp['RecordModel'][i-i]; // create xml element

    tmp['RecordModel'][i]['recordItemRef']['idvalue'] = "MOTIONTIMESTOP";

    tmp['RecordModel'][i]['recordItemRef']['display'] = "Motion Time Stop";

    tmp['RecordModel'][i]['dataTypeRef']['id'] = 56992; // DATE

    tmp['RecordModel'][i]['valueDate']['datetime'] = stopTime;

    } else if (i==4) { // commaseparatedvalues

    tmp['RecordModel'][i]=tmp['RecordModel'][i-i]; // create xml element

    tmp['RecordModel'][i]['recordItemRef']['idvalue'] = "MOTIONHAMMEDMOTION";

    tmp['RecordModel'][i]['recordItemRef']['display'] = "Motion Hammed Motion";

    tmp['RecordModel'][i]['dataTypeRef']['id'] = 79128; // STRING

    tmp['RecordModel'][i]['valueString'] =

    msg['ns1:commaSeparatedValues'].toString();

    } else if (i==5) { // comment

    tmp['RecordModel'][i]=tmp['RecordModel'][i-i]; // create xml element

    tmp['RecordModel'][i]['recordItemRef']['idvalue'] = "MOTIONCOMMENT";

    tmp['RecordModel'][i]['recordItemRef']['display'] = "Motion Comment";tmp['RecordModel'][i]['dataTypeRef']['id'] = 79128; // STRING

    tmp['RecordModel'][i]['valueString'] = msg['ns1:comment'].toString();

    } else if (i==6) { // dataunit

    tmp['RecordModel'][i]=tmp['RecordModel'][i-i]; // create xml element

    tmp['RecordModel'][i]['recordItemRef']['idvalue'] = "MOTIONDATAUNIT";

    tmp['RecordModel'][i]['recordItemRef']['display'] = "Motion Data Unit";

    tmp['RecordModel'][i]['dataTypeRef']['id'] = 79128; // STRING

    tmp['RecordModel'][i]['valueString'] = msg['ns1:dataUnit'].toString();

    } else if (i==7) { // intervalunit

    tmp['RecordModel'][i]=tmp['RecordModel'][i-i]; // create xml element

    tmp['RecordModel'][i]['recordItemRef']['idvalue'] = "MOTIONINTERVALUNIT";

    tmp['RecordModel'][i]['recordItemRef']['display'] = "Motion Interval Unit";tmp['RecordModel'][i]['dataTypeRef']['id'] = 79128; // STRING

    tmp['RecordModel'][i]['valueString'] = msg['ns1:intervalUnit'].toString();

    }

    // Common

    tmp['RecordModel'][i]['recordDt']['datetime'] = startTime;

    tmp['RecordModel'][i]['recordItemRef']['identifierSource'] = "PORCUPINESENSOR";

    }

  • 8/4/2019 Integration Administrator Guide

    13/16

    Integration Last printed 4/18/2008 1:53:00 AM

    Administrator Guide Version 1.0

    Page 12 of 16

    2.2.10 Deploy

    Make sure the Outgoing Data script is

    After saving the transformer changes the channel is deployed

    Figure 11 Deploy changes

    Now drop a copy of your xml file into the oru_xml_in directory identified earlier. The channel will remove the file and any

    errors will be written to the log.

    On the dashboard we can see an error occurred:

    Figure 12 Dashboard

    Selecting Events will show the log, selecting the first entry and scrolling down the exception log we find the error relates to

    the ns1 prefix used in the XML

    Figure 13 Event log for errors

  • 8/4/2019 Integration Administrator Guide

    14/16

    Integration Last printed 4/18/2008 1:53:00 AM

    Administrator Guide Version 1.0

    Page 13 of 16

    After attempting some javascript tricks to remove or build the namespace the event log stopped filling with error messages.

    Instead by right clicking on the channel in the dashboard you can select View Messages

    You can select the message which errored and view the different states the message went through before and after the

    transformating Javascript. On the error tab we see the namespace is still an issue.

    Figure 14 Message view for the big picture

    To resolve the issue on the Summary tab we deselected Strip namespace from messages and as show above the message

    was transformed and sent i.e. written to the interface_messages table.

  • 8/4/2019 Integration Administrator Guide

    15/16

    Integration Last printed 4/18/2008 1:53:00 AM

    Administrator Guide Version 1.0

    Page 14 of 16

    2.3 PatientOS Processing

    We can find our interface message in the interface_messages table

    Figure 15 Interface messages table

    Logging into PatientOS as admin/admin and opening the Interface Manager shows that the ResultTransaction processing ha

    already started but has not processed anything yet.

    But we posted a RecordTransaction so that is why it was not picked up yet. This will be included in the next version but I

    can add one (using SQL to assign the poll script). Restarting the server and this interface processor will start.

  • 8/4/2019 Integration Administrator Guide

    16/16

    Integration Last printed 4/18/2008 1:53:00 AM

    Administrator Guide Version 1.0

    Page 15 of 16

    2.3.1 Errors

    A snippet of the error message is written to the interface_messages table (select * from interface_messages) but currently yo

    need to have JBoss running in console mode so you can see the exact error.

    e.g. This error shows the MRN was not passed and confirm in Mirth on the messages tab.

    23:38:01,125 WARN [JDBCExceptionReporter] SQL Error: 0, SQLState: 42883

    23:38:01,125 ERROR [JDBCExceptionReporter] ERROR: operator does not exist:

    character varying = bytea

    23:38:01,125 ERROR [Log] data.common.BaseData.sqlQuery:select p.patient_id from

    identifiers i, patient_identifier pi, patients p where i.id

    value = :idvalue and i.source_ref_id = :identifierSourceRefId and i.identifier_id

    = pi.identifier_id and pi.patient_id = p.patient_id and

    p.active_ind = 1 idvalue = null identifierSourceRefId = 1000447(sqlQuery-

    query)

    23:38:01,125 ERROR [Log] org.hibernate.exception.SQLGrammarException could not

    execute query...

    After fixing the mapping in Mirth (namespaces were causing problems again now removed from the XML) the message

    gets this error in the interface_messages table:

    com.patientis.model.clinical.FormModel.validateDataModel(FormModel.java:55)

    JBoss showed the desired exception

    00:05:38,078 ERROR [Log] com.patientis.model.clinical.NoRecordsInFormException null...

    The validation failed for the FormModel due to all records being discarded likely to each each FormRecordModel being

    rejected due to failed validation.

    Checking the FormRecordModel the patient id is required and not populated in this version so an upgrade is required to

    fix that issue.