Mirth: Making sure that dev/test code doesn’t get into LIVE (Is this lazy, or just accommodating reality?)

In a perfect world database connections and other things that must be changed when you migrate code between environments are neatly stored in one place where they can be easily changed.

With Mirth you can do this using global maps,  however when you do that,  they are exposed to anyone who has appropriate access to Connect.

I get around this by declaring variables at the top of the filters or transformers where I make database calls.

One of the things with my position is that I wear many hats and am the organization’s ‘go to’ for a great many things.  This means that interruptions are frequent.

This means that I when I’m doing something like preparing an interface to move from TEST to PRODUCTION that I can miss things.

Some of you might scoff,  but that is the reality of my world,  and almost 50 years on this planet has taught me that reality is often very far from ideal,   so you plan for reality.

I’m working on a project where I reach out to a couple of databases to pull data that isn’t included in the HL7 message.

Some of the transformations are complex,  and things were complicated by very tight deadlines,  and a situation where the spec “needed clarification”.  (as in I built my end to spec but they wanted a change).

Those of you familiar with this reality thing will know that this often leads to kludged together solutions.

After spending several hours making sure that our iPeople Echo downloads were moving the correct data from our test environment and copying/altering stored procedures and SQL functions I finally got to combing through my Mirth interface to make the changes there.

To give you an idea of the complexity,  I have 13 transformers in my source connector.

I realized that when I moved this to Live that there were too many potential failure points and wanted to prevent them.

So I added this code to my source filter:


var channelName = ChannelUtil.getDeployedChannelName(channelId);

if (channelName.indexOf('LIVE') > -1) {

logger.error('******************** CHECK ' + channelName + ' FOR DEV/TEST SETTINGS! ****************');
 return false;
 
}

return true;

/* Changes for Live
-remove anonymizer
-change db settings in source PID, PV1, OBR and ZDR
-change db settings in destination MR PID transformer

*/

Hey look…a checklist of sorts!

My thinking is that if I forgot to make this very basic change that I’ll look and wonder why all my messages are being filtered!

But then I got to thinking of how many times I’ve been interrupted today and what would happen if I missed a single change…

So I wrote this:

function envcheck(sql,strTest,strLive) {

 var channelName = ChannelUtil.getDeployedChannelName(channelId);

 if (channelName.indexOf('LIVE') > -1) {

 logger.error(channelName + ' **** CHANGE SQL STATEMENT FOR LIVE ' + sql);

 sql = sql.replace(strTest,strLive);
 
 }

 return sql;
 
 
}



Advertisements

MEDITECH and iPeople Echo: Providing near real time patient census data

Anyone whose worked with the Meditech Magic Hospital Information System knows that sometimes it can be a challenge to pull useful and timely statistical data from it.

Late last year, the Huron-Perth Healthcare Alliance implemented the iPeople Connect product which includes Echo an application that allows us to build our own SQL Server based data-repository,  specifying what data we want from our Meditech system,  and how frequently to update it.

What this does is allows us to provide our client base with a broad range of reports and reporting tools instead of the text based reports generated by Meditech’s NPR report writer.

One of the very first requests we received was to provide near real-time patient census data.

The project, dubbed Atlas,  asked for the following data elements:

  • Location
  • Bed Count
  • Patient Count
  • Empty Beds
  • Occupancy Rate
  • Isolation Patients
  • Pending DC dates prior to current date
  • Pending DC dates on current day
  • ALC patient counts

Anyone who has ever faced pulling data from Meditech knows that it be difficult figuring out where the data is stored.

With the help of iPeople Scout,  an application that allows us to search the Meditech Dictionaries,  and view joins,  we found that the best Meditech source table was ADM.ADMStatsInLocation.   This table gave us the bed census data for each location, as of the midnight run on any given date.

While all this seems straight forward,  there was a complication in how to define a bed.

I know what you’re thinking,  “a bed is something that you sleep in, or on…and its where hospitals keep patients!”.    You’d be correct,  except that our organization may have several entries for the same physical bed in the Meditech dictionary.    The reason for this is that some beds may be either acute,  or chronic.  It all depends on what type of patient gets admitted.

My preference is that data elements be identified programmatically.    After spending several hours running test queries,  trying to ensure that our virtual bed count matched our physical bed count I realized that this was impossible.   The reason is that those pesky humans might get in there and create a bed that wouldn’t fit the existing naming convention.

I opted instead to use an associative array within the PHP script that contained the official bed counts for each facility and location.

The next, and most difficult challenge to solve, was how to identify ALC patients.

For those unfamiliar with the term,  ALC means (Alternative Level of Care).   This term refers to patients occupying acute beds,  who are ready for discharge,  but do not have a place to go.   They still require care (long term facility,  chronic or palliative etc),  but there are no beds for them to go to.

When I first reviewed the specifications,  I figured this would be a flag,  perhaps a custom query somewhere within ADM.   I was somewhat mortified to learn that the only way to identify an ALC patient was through ALC orders.

This was complicated by the fact that a patient who has been in hospital for some time,  could be designated ALC several times through their stay.

Within the organization we have several ALC order types in our OE.ORD dictionary.

  • Identify:  indicates that the patient is an ALC patient
  • Change:  changes the order
  • Discontinue:  discontinues the order,  however the patient remains in that bed, and
  • Discharge:  the patient is discharged

It took several days to work this out,  and it was only with the assistance of our Nursing Informatics team,  as well as input from Bed Management that I managed to figure it out at all.

In order to identify,  and add a patient to the ALC tally,   while compiling the information,   I query OE.ORD for each in patient,   looking for any ALC orders for their current visit.

I pull the data sorted in descending order by order date and time.

This is the logic I use:

If the query gets no results,  then patient is not now,  nor has ever been an ALC patient.   I then set the ALC flag within the XML node for this patient to “no”.

If there are results,  I check to see if the last result is a discontinue or discharge.   If it is,  this indicates that the patient was an ALC patient.   I set the ALC attribute to “expired” for these patients.

The only option left at this point is that the patient is an alc patient.   I increment the appropriate counters,  and set the ALC flag to “yes”,  which is used for display and functionality as the user can pull up a patient’s entire ALC order history in this case.

Other data types,  such as Isolation and Pending Discharge are determined by checking custom query fields which are exported into the SQL Server database.

All this information is formatted into an XML document by a PHP script.   In order to save time on processing,  the script is run every 10 minutes by a cron job,  and the results written to a file on the web server.

When a user accesses the Atlas home page,   it is this file that is accessed,  saving the user a long wait each time they go looking for data.

There is functionality that checks the age of the data,  and,  if it is older than 10 minutes,  the user be flagged, and notified to call IT to report a problem.

The front end is a simple web page,  with JQuery/javascript programming that will take the XML document and dynamically create tables using Document Object Model traversal methods.

The user has the ability, via checkboxes, to limit which sites within the organization they want to see.

Upon page load,  each site is collapsed.   The user can view or hide site specific locations by clicking on the desired site.

The screenshot below shows the Stratford General Hospital locations expanded.

censusbigscreenshot

Other functionality includes the ability to view a list of patients in each location.   The list only uses account numbers,  reducing the risk of a privacy breach.

Within the individual patient list,  the user can view a history of ALC orders for patients that have them.

They can also view a list of patients for whom there is a pending discharge.

Managers and other stakeholders receive a static copy of this report via email every morning at 7am.

The iPeople DR,   combined with the ability to use modern programming languages has allowed us to improve patient flow, and service delivery to our patients.