Newbie question

  • Creator
    Topic
  • #55133
    Chris Plummer
    Participant

    I have a question on the best way to fix a problem. We are sending ORM messages to a vendor and they would like us to reformat the ODS segments as below

    From ODS|D||83282^DTY: DIET SUPPLEMENT^DTY~Glucerna~~~

    To     ODS|S||83282^DTY: DIET SUPPLEMENT^DTY~Glucerna~~~

    Basically they want to change the second segment from a D to a S but only if the fourth segment has the code 83282. My question is would this best be handled via a tcl script or a xlate? At the moment I have no xlate built for this.

    If it matters we are running version 5.7 of the engine.

    Thanks for any help you can offer

Viewing 16 reply threads
  • Author
    Replies
    • #84234
      Jim Kosloskey
      Participant

      Simple enough to do in an Xlate. Can be done either way though.

      So his depends on your shop’s philosophy regarding whether you use Xlate or Tcl primarily for message transformation.

      email: jim.kosloskey@jim-kosloskey.com 29+ years Cloverleaf, 59 years IT - old fart.

    • #84235
      Chris Plummer
      Participant

      Well I tried my hand at creating a proc, I pilfered some of the code from other procs we have. The issue seems to be that the proc is not looping through each message type. Below is my code, ignore the puts commands those where for trouble shooting. I hope it is ok to post code in this forum

      Code:


      ######################################################################
      # Name:       chg_ods_1_to_S_basedon_ods3
      # Author:     Chris Plummer
      # Purpose:    Translate ODS segment 2 from D to S based on segment 3
      # Date:       July 13, 2016

      proc chg_ods_1_to_S_basedon_ods3  { args } {
         keylget args MODE mode                      ;# Fetch mode

         set dispList {}                             ;# Nothing to return

         switch -exact — $mode {
             start {
                 # Perform special init functions
                 # N.B.: there may or may not be a MSGID key in args
             }

             run {
                 # ‘run’ mode always has a MSGID; fetch and process it
                 keylget args MSGID mh
               
                 set msg [msgget $mh]
                 set outbuf “”
                   
                 set field_sep [csubstr $msg 3 1]                    ;# HL7 field separator      
                 set sub_sep [csubstr $msg 4 1]                      ;# HL7 subfield separator  
                 set rep_sep [csubstr $msg 5 1]
                 set segmentList [split $msg r]                     ;# Get segments
                 puts “This is before the for each loop”  
                 foreach segment $segmentList {
         puts “This is in the first loop $segmentList”
                     if [cequal $segment “”] { continue }
                        puts “This is after the first if $segment”                              
                     set fieldsList [split $segment $field_sep]               ;# Just in case
                     set segtype [csubstr $segment 0 3]                  ;# Get segment name
                        puts “This is the field sep $field_sep”
              puts “this is the segtype $segtype”
                     if [cequal $segtype “ODS”] {
      puts “This is after the second if segtype $segtype”
                         set fieldsList [split $segment $field_sep]  
                         set ods_3 [split [lindex $fieldsList 3] $sub_sep]
                         set ods_1 [split [lindex $fieldsList 1] $sub_sep]
                         puts “The Patient Account is: $sub_sep”              
                                                                     
                         if {[cequal $ods_3 “83282”]}  {
                            set new_ods_1 “S”

           # might not need this
                            set new_ods_1 [join $new_ods_1 $sub_sep]

                            set fieldsList [lreplace $fieldsList 1 1 $new_ods_1]
                            set segment [join $fieldsList $field_sep]
                          }            
                      }
            puts “This is the end of msg compare before the append”
                      append outbuf ${segment}r
                         
                 } ;# end of ‘foreach’

                 # Put modified message ($newmsg) in message handle
                   
               
                      msgset $mh $outbuf
                      lappend dispList “CONTINUE $mh”
                   
             }

             time {
                 # Timer-based processing
                 # N.B.: there may or may not be a MSGID key in args
             }
             
             shutdown {
                 # Doing some clean-up work
             }
         }
         # end switch mode
         puts “end of switch mode”
         return $dispList
      }

    • #84236

      That should be handled in an XLATE in most cases. It would be a simple IF statement with a nested COPY statement.

      -- Max Drown (Infor)

    • #84237
      Chris Plummer
      Participant

      I finally figured out my problem it seems my system does not like [cequal $segtype “ODS”] I used {$segtype == “ODS”} instead and it worked better. I had one or two other similar changes to make.

      I assume handling it in a xlate would be more efficient though so I’ll work on that next.

    • #84238

      To compare strings, consider using eq and ne instead of == and !=.

      Also, note that the c-commands have been deprecated in favor of the string commands.

      -- Max Drown (Infor)

    • #84239
      Chris Plummer
      Participant

      Thanks for the info

    • #84240
      Charlie Bursell
      Participant

      Listen to what Max is telling you.  

      Also, for future reference, do not loop through all of the segments to get the segments you want.  The lsearch command is much more ergonomic.

      Also as stated the ‘C” commands are deprecated.  Use string equal, string range, string index. etc.

      As Max stated the eq or ne is preferred.  When you use == or != on a string, that string must first be converted to a number.

      Max or I either one could probably let you have some examples of code from the Cloverleaf classes if you think it would help.

      I would recommend the Infor Tcl class.  If you have ever written code in any language Tcl should be a breeze.  All you need to do is become familiar with the Cloverleaf API’s

    • #84241
      Chris Plummer
      Participant

      Thanks for the information Charlie. Do you happen to have a script using the lsearch that searches for a particular message segment? I would just like to see how it works. I’ll google the lsearch command to gather more information.

    • #84242

      Here’s the reference page: https://www.tcl.tk/man/tcl8.5/TclCmd/lsearch.htm

      An example:

      set msg [split $msg r] ;# Convert the message to a list
      set obx_segs [lsearch -all -inline -regexp $msg {^OBX} ;# Create a list of all of the OBX segments found in the message
      foreach obx $obx_segs {

      [code]set msg [split $msg r] ;# Convert the message to a list
      set obx_segs [lsearch -all -inline -regexp $msg {^OBX} ;# Create a list of all of the OBX segments found in the message
      foreach obx $obx_segs {

      -- Max Drown (Infor)

    • #84243
      Marc Pleijers
      Participant

      Hi,

      See attached tcl file with example of lsearch.

      It is made to run stand-alone without the need of any example message.

      You can run it inside the tcl interpreter (hcitcl ) using source example_lsearch.tcl

      kind regards Marc

      Marc Pleijers
      Senior Integration Consultant
      Enovation BV
      The Netherlands

    • #84244
      Charlie Bursell
      Participant

      Here are a couple of examples from my old level 3 class.  One using lsearch when you just want to look at the data and one where you want to change data.

      The things to remember are:

      If you use the -inline option lsearch returns the data else it returns the location

      If you use -all it returns *ALL* locations or data as a *LIST* else it returns the location or data at the first match.

      Be sure to treat a list properly!

    • #84245
      Chris Plummer
      Participant

      Thank you both for these examples, will dissect them.

    • #84246
      Chris Plummer
      Participant

      Thanks to your help I went from what I had to this new code which looks a lot better and works doing what was originally asked but alas they want more. If it is a supplement identified by the code 83282 (as before) they want me to copy the duration and frequency from the ORC segment section 7. I have them labeled orc_7_1 and orc_7_2. They would like these added to the end of the supplement name after the tilde. So in the example below it would be after the Glucerna~

      ODS|S||83282^DTY: DIET SUPPLEMENT^DTY~Glucerna~~~

      I’ll keep at it but while I’m getting close I have not gotten the values to go where I needed them. I can place them anywhere in the message other than the repeating area in which they need to go. I was hoping someone has done something similar and could chime in.

      Thanks again for any help you can offer.


      proc changeHL7_ORC { args } {

      [code]
      proc changeHL7_ORC { args } {

    • #84247
      Charlie Bursell
      Participant

      A bit confused about the requirement.

      “added to the end of the supplement name after the tilde”

      There are three tildes after the supplement name.  After which one?  Will the supplement name always be in the last populated iteration?

      Are each of the values placed after the supplement~ joined together or in separate iterations?  would it look like:

      ODS|S||83282^DTY: DIET SUPPLEMENT^DTY~Glucerna~orc7-1~orc_7_2 or what?

      FWIW, to understand it I cleaned up the code a bit and removed what I consider some superfluous stuff.  No message to test with so may be some fat-finger errors

      changeHL7_ORC { args } {

         keylget args MODE mode                 ;# Fetch mode

         set dispList “CONTINUE $mh”            ;# Continue message

         switch -exact — $mode {

         start {

             # Nothing speific

             return “”

         }

         run {

             keylget args MSGID mh

             set msg [msgget $mh]

             echo “this is the msg $msg”

             set fsep [string index $msg 3]  ;# Field separator (|)

             set csep [string index $msg 4]  ;# Subfield separator (^)

             set rsep [string index $msg 5]  ;# Repetition separator (~)

             # List of segments

             set seglist [split $msg r]

             # Location of ODS segment (First one only)

             set ods_loc [lsearch -regexp $seglist {^ODS}]

             # Don’t need location of ORC, just the data

             # Split into fields

             set ORC [split [lsearch -inline -regexp $seglist {^ORC}] $fsep]

             # Get ODS fields

             set ODS [split [lindex $seglist $ods_loc] $fsep]

             # ODS.1.1

             set ods_1 [lindex [split [lindex $ODS 1] $csep] 0]

             # ODS 3.1

             set ods_3 [lindex [split [lindex $ODS 3] $csep] 0]

             # ORC 7.1

             set orc_7_1 [lindex [split [lindex $ORC 7] $csep] 0]

             # ORC 7.2

             set orc_7_1 [lindex [split [lindex $ORC 7] $csep] 1]

             echo “this is orc_7_1 $orc_7_1”

             echo “this is orc_7_2 $orc_7_2”

             if {$ods_3 eq 83282} {

                 # Replace OBS.1 wit “S”

                 set ODS [lreplace $ODS 1 1 S]

                 # Put new ODS back in segment list

                 set seglist [lreplace $seglist $ods_loc $ods_loc [join $ODS $fsep]]

                 echo “this is new msg $newmsg”

                 msgset $mh [join $seglist r]

             } else {

                 # Send original message

                 echo “Nothing to do”

             }

         }

         return $dispList

      }

    • #84248
      Chris Plummer
      Participant

      Thanks Charlie and your ODS was a lot shorter than my ods_new and did the same thing. Sorry I was not more clear on the orc part but yes this is correct

      ODS|S||83282^DTY: DIET SUPPLEMENT^DTY~Glucerna~orc7-1~orc_7_2

      but instead of the tilde in between the two orc values it would be a carat

      ODS|S||83282^DTY: DIET SUPPLEMENT^DTY~Glucerna~orc7-1^orc_7_2~~

      I was off Friday so I going to try and see if I can get the message to combine like it should. I’m sure I’m just not rejoining the message correctly because of the repeating segment.

    • #84249
      Charlie Bursell
      Participant

      You still did not answer as to whether the supplement would always be the last populated iteration of ODS.3.3?

      I am making some assumptions her but here is the way I would do it:  I made a test message which may or may not be right so test it with yours

      As I suspected I had some really dumb errors in what I sent before like misspellings and setting dispList before I even set mh.  Stupid!

      Anyway see if it helps.  I have attach a simple proc with no header for you to test.  Named it after you 😀

      Good thing I get bored enough to do stuff like this.  Rainy season over here  🙁

    • #84250
      Chris Plummer
      Participant

      Thanks and now I see the reasoning for your question with your trim statement, I was trying to squeeze the values in between the repeating separators. I did not think to use trim and just append it. I’ll have some more test supplements ordered and see how it goes.

      Worse case I go back to my method, which is not as elegant and I have your code to help me out in the future; but I believe your strategy will work fine.

      Thanks once again.

Viewing 16 reply threads
  • The forum ‘Cloverleaf’ is closed to new topics and replies.

Forum Statistics

Registered Users
5,117
Forums
28
Topics
9,292
Replies
34,435
Topic Tags
286
Empty Topic Tags
10