Jeffrey Drumm · Feb 25, 2020 go to post

Did you get an actual compilation error, or just an error indicator in the expression editor?

In my case, the dialog box shows the expression indicated an error, but it doesn't cause a compilation problem.

I don't have any sample messages to test with at the moment, so I'm not sure it will actually work ...

Jeffrey Drumm · Feb 25, 2020 go to post

It appears as though the answer is no. I would think that the Private property keyword would be the most intuitive way to do this, but it does not appear to have any effect in the DTL editor.

Jeffrey Drumm · Feb 25, 2020 go to post

Hi Barry, your syntax is close but not quite right:

I don't have a message class handy that has an Observation property defined as %ListOfDataTypes, so I get an error indicator in the rule editor (which I've tried, poorly, to edit out).

Jeffrey Drumm · Feb 25, 2020 go to post

The functionality described here is pretty specific to Ensemble/HealthConnect. While I can't answer definitively, I'm fairly certain that Epic does not store queued/processed HL7 messages using the same object format and class names (i.e. SQL table names) as Ensemble.

Jeffrey Drumm · Feb 20, 2020 go to post

What version of Caché or IRIS are you using? on IRIS 2019.1, the menu returns immediately after the "No matching records found" message.

Jeffrey Drumm · Feb 19, 2020 go to post

I set up a test scenario based on your criteria. I created a service, HL7 router process and 3 operations:

Service: HL7 MLLP, target HL7 Router, AckMode=Application

Process: HL7 Router, ForceSyncSend: True, ReplyCodeActions: E=F

Target Operation 1: HL7 File Out

Target Operation 2: Custom Operation that returns an HL7 NAK, sets IsError to 1, logs an error code of 5001 with text "Forced NAK", ReplyCodeActions: E=F

Target Operation 3: HL7 File Out

Observations:

  1. Message arrives in router process
  2. Routes to Operation 1, completes successfully
  3. Routes to Operation 2, receives error
  4. Router responds to Service with Error; shuts down ... no message delivered to Operation 3
  5. Service returns NAK to sending application
  6. Message remains queued for Router

Isn't this what you would want to happen?

Jeffrey Drumm · Feb 12, 2020 go to post

While I haven't tried it, I'm fairly confident that this would be handled via ReplyCodeActions in the router.

Jeffrey Drumm · Feb 12, 2020 go to post

Once the ACK is received by the Router, it's forwarded as a Request object to the ResponseTargetConfigName list, so at that point it's just like any other message. No need for BPLs in this specific instance.

Jeffrey Drumm · Feb 12, 2020 go to post

Yes Neerav, that will avoid it, but at the possible expense of both performance and robustness. If one process called from the routing rule doesn't complete, nothing else does either.

In a BPL you have more granular control over sync/async works.

Jeffrey Drumm · Feb 12, 2020 go to post

If the order of the A02s is not important, you can simply  create a routing rule with two Send actions for the same target; the first Send is configured with a DTL that creates an A02 for the first transfer, and the second a DTL for the second transfer.

Many receiving systems will have an issue with this, though, as both patients temporarily end up in the same bed. While it might be fun for the patient, the transfers may be rejected. In some cases you may need to perform 3 transfers: Transfer patient 1 to a dummy bed, transfer patient 2 to patient 1's prior location, transfer patient 1 to patient 2's prior location. In this scenario, it would probably be prudent to use a BPL to enforce synchronous behavior, guaranteeing that the transfers happen in a specific order.

Jeffrey Drumm · Feb 11, 2020 go to post

^%SYS is mapped from IRISSYS, so it should only need to be modified int he %SYS namespace, right?

Does IRIS need to be restarted after this change? It doesn't seem to be having an effect. I'll be trying the ^EnsPortal  change shortly and will report back.

Jeffrey Drumm · Feb 11, 2020 go to post

Seems to work fine if you route the ACK to another Business Process. For the router handling messages from an inbound service:

Response comes in from TestTCPOut; the received ACK is sent to the original service and forwarded to a BP called AckWrangler. That BP runs a routing rule that optionally transforms the ACK and passes it off to another operation called AckTarget:

Jeffrey Drumm · Feb 10, 2020 go to post

What do you have set for the Response From and Response Target Config Names fields in the router's configuration? I'm thinking the former should be the operation from which you're receiving the response, and the latter should be the router itself.

Jeffrey Drumm · Feb 7, 2020 go to post

As a general rule, I'd suggest using the StartsWith() function in the DTL wizard when comparing date fields. In your case, the Birthdate field very likely does not include a Time component at a resolution of seconds. If it did, though, you could run into many combinations where the date value from CurrentDateTIme() would match.

For example, Contains() would return true on the 19th or 20th of February 2020 against "20200220200219" ... February 20th 2020 at 8:02:19pm. This would certainly be a rare occurrence, but not impossible.

Jeffrey Drumm · Feb 6, 2020 go to post

A few of questions:

  1. Can we assume that the tracking information will be received asynchronously, after the PO?
  2. Will there be only one tracking file per PO, or will there be a distinct file per line item in the PO?
  3. Can the tracking file name be somehow derived from data found in the PO, or must the file(s) be scanned/parsed to determine its related PO?
Jeffrey Drumm · Jan 29, 2020 go to post

I get the same result using your suggested method, Brendan.

I'm not technically a customer; I work for a Services Partner of ISC. I am a DC Moderator though (if that carries any weight) so it would be nice to keep abreast of the new stuff laugh

Jeffrey Drumm · Jan 16, 2020 go to post

Thanks for the response, fellow Jeffrey!

The tables I'm currently working with are tiny, literally no more than a couple dozenmessage header and body records. The query in the IRIS SQL shell (and management portal SQL facility) returns results immediately.

I think we have some sort of obscure bug here. This is with IRIS for Health CE 2019.1 running on Ubuntu (not a docker image), and the client is Windows 10 using IRIS ADO.NET support. Same result when using the ODBC drivers, though.

I think you're right on reaching out to WRC ... thanks again.

Jeffrey Drumm · Jan 14, 2020 go to post

I should also point out (after doing some additional experimentation) that this method works for individual fields as well:

Again, I should mention that what you see in the DTL Test facility does not represent what will happen in the transformation. I believe this is an artifact of the way the Windows clipboard handles EOL characters in a cut/paste operation.

Jeffrey Drumm · Jan 14, 2020 go to post

I'm pretty sure you don't want a newline character anywhere in the target OBX segments, so this should do the trick:

Unfortunately, this does not appear to do the right thing in the DTL Test tool. You can verify it works at the Caché/IRIS prompt, though:

You can, of course, also verify that it works by calling it from a routing rule laugh

Jeffrey Drumm · Jan 11, 2020 go to post

The fact that the DB1 and OBX segments are shown in the color black is an indicator that your HL7 schema does not match the message's actual structure. Unless you correct that in the schema (which may require creating a custom schema) you won't be able to reference the OBX (or DB1) segments in your routing rule using the standard conventions.

Jeffrey Drumm · Jan 9, 2020 go to post

I've added a query to the HICG.HL7 class that lets you leverage Ensemble's HL7 Search Tables to select messages by the fields specified for indexing. The new version is available on the HL7 Spy website.

An example, using the default search table to select messages by PatientID/MRN:

-- region 8 - message rows by SearchTable

SELECT
    tbl.BodyId,
    msg.TimeCreated,
    msg.Name,
    msg.DocType,
    HICG.GetMsg(msg.Id) As Message
    FROM
        HICG.TblSrch('EnsLib.HL7.SearchTable','PatientID','4444') tbl
    INNER JOIN
        EnsLib_HL7.Message msg
    ON
        tbl.BodyId = msg.Id
-- endregion
Jeffrey Drumm · Jan 9, 2020 go to post

From COS -  $SYSTEM.Version.GetVersion()

From SQL - SELECT $ZVERSION

Not a .NET guy, sorry!

Jeffrey Drumm · Jan 6, 2020 go to post

This works in a client also ...

SELECT head.ID As HeadId, body.ID As BodyId, body.Name as BodyName
FROM Ens.MessageHeader head
INNER JOIN EnsLib_HL7.Message body
ON head.MessageBodyId = body.%ID
WHERE head.ID > 0 AND head.MessageBodyClassName = 'EnsLib.HL7.Message' AND body.Name = 'ADT_A04'


There's something fundamental here I'm missing.

Jeffrey Drumm · Jan 6, 2020 go to post

So to clarify ... the class method isn't so much a stored procedure as a custom function. It should return an HL7 message as a  string, which will be represented as a column in the result set generated by a SELECT. So technically, the SQLCODE I'm getting back is correct for what I'm doing, which is calling a function against a column value in the query. If the function fails, the query fails, and the reason for the query failure is the function failure. That's how it's coming back to ADO/ODBC when I force a failure, and the reason I asked the question in the first place is that sometimes I'm just not too smart :D

Jeffrey Drumm · Jan 5, 2020 go to post

Hi Robert,

Thanks. I understand what's happening now ... and very much appreciate your research and input!

Jeffrey Drumm · Jan 4, 2020 go to post

I had tried PublicList as well. See my comment on Eduard's answer ... I think it may not be possible to set the "top level" error code returned from the SELECT (which is what I was hoping to do).