查找

記事
· 2025年9月26日 2m read

Git Pre-commit Hook for Health Connect Cloud

Hi,

Just thought I'd share quite a handy hook that has helped me out when developing on Health Connect Cloud with VS Code and GitBash. When developing on Health Connect Cloud, if changes are made directly on the server such as routing rules or component deployments, they aren't automatically included in source control, therefore you must export from the server into your local files and push to your remote repo. I'm sure there are easier methods to deal with that which I'm in the process of testing, but as a quick solution I thought it would be handy have a pre-commit hook which triggers a reminder in GitBash - see below.

This reminder can be tweaked to mention routing rules and anything you think needs to be considered for export.

The hook code:

#!/bin/bash
# Git pre-commit hook - gentle reminder for Production.cls
targetFile="src/HCC/Connect/Production.cls"
# Check if Production.cls is already staged
staged=$(git diff --cached --name-only | grep "$targetFile")

# If Production.cls is not staged, show a gentle reminder
if [ -z "$staged" ]; then
    echo ""
    echo "💡 Gentle reminder: Have you made any changes to the Production class on the server?"
    echo ""
    echo "   If YES: Export and add $targetFile to this commit"
    echo "   If NO:  Continue with: git commit --no-verify"
    echo ""
    echo "   (This reminder appears on every commit - use --no-verify to skip)"
    echo ""
    exit 1
fi
# Production.cls is staged, proceed normally
exit 0

I hope this is useful for anyone developing with Health Connect Cloud.

 

Jordan

1 Comment
ディスカッション (1)2
続けるにはログインするか新規登録を行ってください
お知らせ
· 2025年9月26日

[Video] Leading with Empathy: The Human Side of Customer Centricity

Hi Community,

We're excited to share the new video in the "Rarified Air" series on our InterSystems Developers YouTube:

⏯ Leading with Empathy: The Human Side of Customer Centricity

This episode explores what it truly means to build a customer-centric organization. The conversation traces a journey from early hands-on experience in support to leading innovation, showing how empathy, curiosity, and genuine care form the foundation of great customer relationships. The discussion highlights how technology, especially AI, can enhance, rather than replace, human connection. Real-world examples, from healthcare to Disney’s “magical” service model, illustrate how understanding people’s needs leads to better outcomes. Ultimately, the episode reminds us that true customer centricity begins with staying human, leading by example, and making an impact through every interaction.

Presenters: 
🗣 @John Paladino, Vice President of Client Services, InterSystems
🗣 @Alex MacLeod, Director of Healthcare Solution Support, InterSystems

Enjoy watching, and subscribe for more videos! 👍

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください
記事
· 2025年9月26日 2m read

HealthCare, cuidando de sua saúde!

Vamos lá... “Com saúde não se brinca. (português brasileiro)”, “Better safe than sorry. (inglês)”, “Mieux vaut prévenir que guérir. (francês)”, “Todo tiene solución, menos la muerte. (espanhol)”, este último é pesado (forte), não?

O que estes ditados (e poderíamos ter inúmeros outros e em ainda mais línguas) nos dizem? A importância de cuidar da saúde. E isto não é algo novo, talvez as ferramentas sejam, ou apenas melhorem com o passar dos anos. Uma coisa é certa, a ideia de nos cuidarmos e assim prevenirmos alguns males, existe há muito tempo e com certeza já ouvimos isto de bisavós, avós, pais... E agora passamos para nossos filhos, tudo bem que em muitas destas vezes, é apenas um conhecimento empírico.

Guardadas as devidas proporções, este aprendizado ou formas de cuidado, formam um conjunto de informações que podemos chamar de HealthCare (termo em inglês). É o tratamento de doenças, cuidados preventivos e paliativos, diagnósticos que, quando todos reunidos, formam um grande sistema de apoio a todos que possuam acesso a estas informações.

Uma vez que sabemos ou conhecemos como fazer, onde a InterSystems entra nesta história? Bom, com bagagem e estruturas invejáveis, consegue unir e entregar estes dados de forma única, facilitando assim o acesso às informações e consequente tomada de decisões (talvez um ponto que é crucial para o sucesso).

Com usuários no mundo inteiro, muitos deles formadores de opinião, líderes de setores (saúde e mesmo de tecnologia de informação voltada para esta área) consegue realizar uma entrega muito precisa e segura. Aqui um dado histórico para representar esta informação: “Globalmente, mais de um bilhão de registros de saúde são gerenciados por soluções construídas com base na tecnologia InterSystems.” – Fonte: Site InterSystems.

Mas, como a InterSystems consegue atender “todo mundo”? Ora, com suporte para FHIR (Fast Healthcare Interoperability Resource utilizado para troca de informações), HL7 V2 (Health Level Seven linguagem padrão para o compartilhamento e integração de informações eletrônicas de saúde), IHE (Integrating the Healthcare Enterprise, que é uma iniciativa internacional que visa melhorar a interoperabilidade de sistemas na saúde, com colaboração entre profissionais de saúde e fabricantes de tecnologia para a definição e utilização de padrões de comunicação bem como outros protocolos globais de informação de saúde e formatos de mensagens, permitindo a integração e interoperabilidade de todas estas aplicações para a área da saúde).

Com amplas possibilidades para a gestão de todos estes dados e informações, consagra-se neste mundo tão importante para o desenvolvimento humano de forma segura e eficaz.        

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください
記事
· 2025年9月26日 3m read

HealthCare, prenez soin de votre santé !

Allons-y… "Com saúde não se brinca." (portugais brésilien), "Better safe than sorry" (anglais), "Mieux vaut prévenir que guérir" (français), "Todo tiene solución, menos la muerte." (espagnol), ce dernier terme est lourd de sens, n'est-ce pas ?

Que nous disent ces dictons (et nous pourrions en avoir d'innombrables autres dans encore plus de langues) ? L'importance de prendre soin de sa santé. Et ce n'est pas nouveau ; peut-être que les outils évoluent, ou s'améliorent simplement, au fil des ans. Une chose est sûre : l'idée de prendre soin de soi et ainsi de prévenir certaines maladies existe depuis longtemps, et nous l'avons certainement entendue de la bouche de nos arrière-grands-parents, grands-parents, parents… Et maintenant, nous la transmettons à nos enfants. Certes, dans bien des cas, il ne s'agit que de connaissances empiriques.

Dans les proportions nécessaires, cet apprentissage ou ces formes de soins forment un ensemble d'informations que nous pouvons appeler HealthCare (terme anglais). Le traitement des maladies, les soins préventifs et palliatifs, ainsi que les diagnostics, constituent un puissant système de soutien pour tous ceux qui ont accès à ces informations.

Une fois que nous saurons comment procéder, quelle est la place d'InterSystems dans ce contexte ? Grâce à son expertise et à son infrastructure enviables, InterSystems peut fédérer et diffuser ces données de manière unique, facilitant ainsi l'accès à l'information et la prise de décision (un point crucial pour la réussite).

Avec des utilisateurs dans le monde entier, dont beaucoup sont des leaders d'opinion et des leaders du secteur (de la santé, et même des soins axés sur les technologies de l'information), InterSystems peut fournir des données extrêmement précises et sécurisées. Voici quelques données historiques pour illustrer cela : "À l'échelle mondiale, plus d'un milliard de dossiers médicaux sont gérés par des solutions basées sur la technologie InterSystems." – Source : site web d'InterSystems.

Mais comment InterSystems parvient-il à servir "tout le monde" ? Avec la prise en charge de FHIR (Fast Healthcare Interoperability Resource, utilisée pour l'échange d'informations), HL7 V2 (Health Level Seven, langage standard pour le partage et l'intégration des informations de santé électroniques) et IHE (Integrating the Healthcare Enterprise, initiative internationale visant à améliorer l'interopérabilité des systèmes de santé, grâce à la collaboration entre professionnels de santé et fabricants de technologies pour définir et utiliser des normes de communication, ainsi que d'autres protocoles et formats de messagerie d'information médicale mondiaux, permettant l'intégration et l'interopérabilité de toutes ces applications de santé).

Grâce à ses capacités étendues de gestion de toutes ces données et informations, il s'impose de manière sûre et efficace dans ce monde si important pour le développement humain.

                                                                                                   

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください
記事
· 2025年9月26日 19m read

A Configurable Template for Automated Splitting of HL7 Repeating Segments

Introduction

HL7 messages often contain multiple repeating segments such as NTE, AL1, OBX, ZTX, DG1, and others. These segments sometimes require individual processing and routing to different downstream systems. This technical paper introduces a configurable template designed to automate the splitting of these repeating HL7 segments, improving message handling and integration efficiency.

This template offers flexibility by allowing users to either send the message as-is with the required logic applied or split the message based on customizable settings defined within the business process configuration. Importantly, this approach supports reuse across various use cases and HL7 schemas.

Please note that you may need to update or modify a few lines of code depending on your HL7 schema or any custom schema you use. The source message must conform to your message schema.

Key configurable parameters include:

  • Message type selection
  • Identification of repeating segments
  • Segment group definitions
  • Unique identifier settings

Highlights:

  • The source message can contain multiple repeating segments such as NTE, AL1, OBX, etc.
  • You can send the entire message without splitting it, applying only your logic, to downstream systems.
  • Alternatively, you can split the message according to your instructions and send the segments separately to one or multiple downstream systems as needed.

This process is designed to split any repeating HL7 message segment and route it to the chosen downstream systems.  It functions as a reusable template, requiring little to no code modification to adapt to your specific needs.

The process provides dynamic configuration settings within the business process setup, allowing users to customize message splitting as needed. The main settings are detailed in Table 1 below:

Table 1: Process Settings – Configurations

SN

Setting Name

Short Description

Example

1.

MessageType 

HL7 message type used for splitting.

ADT^A01, ORU^01, DFT^P03 etc

2.

MultipleSegmentName

Repeating segment(s) in the HL7 message to be split individually. Specify the segment name that needs to be sent individually

NTE, OBX, ZTX, RXP, etc.

3.

IsRepeating

Confirms if the segment in #2 repeats. Only "Y" is currently supported (default is "Y").

Y or N

4.

SegmentRepeatingGrp

Indicates if the segment is part of a group (e.g., RXCgrp()). Nested groups like PIDgrp().NTE() are not supported here.

RXCgrp(), PIDgrp(),

 

5.

MultipleSegGrpPath

If #4 is "Y", define the path to the group. Can be selected from a list

Note: You can edit or update this according to your requirements by changing the code.
Be careful, it depends on your message schema. If you have a custom schema, please update it accordingly.

PIDgrp() → NTE(), PIDgrp() → OBX()
Select DropDownList: PIDgrp, MRGgrp, PRG1grp, IN1grp, ORCgrp(1).OBRuniongrp, PIDgrpgrp(1).ORCgrp(1).OBXgrp

6.

SegmentNameForUniqueID

Segment name to be used for generating a unique message identifier.

MHS or FT1grp

7.

SegmentDetails

Full segment path for inserting the value. Use the segment name if it's the same.

MSH,

FT1grp(1).FT1

8.

SegmentFieldNo

Field number where the unique value should be inserted. Use the instance number.

 

10 = (MSH:10 – Control id)

 2 = ( FT1grp(1).FT1.2 – Financial transaction id) 

9.

SeperationUniqueID 

Separator for the unique value (e.g., ".", "#", "-"). Appends a unique number to the field value.

., #, -, etc

For example, such as XXXXX.1, XXXXX.2, etc.

 

Usage Instructions

  1. Copy the provided code and create a new business process in the HealthConnect Management Portal using the code class.
  2. Navigate to Process → Settings, then select TargetConfigurations.

  1. Choose the operations and target systems where you want to send the message.
  2. Configure all settings as specified in the table above according to your requirements and apply the changes.
  3. Restart your process to activate the new configuration.

TESTING:

Screenshot 1: Management Portal showing sending the entire source HL7 message and sending repeating segments to three different systems.

Select à Process à Setting and complete all the configuration according to your requirements.

Screenshot 2.a: Process settings configuration screen.

If you need more information about any configuration, simply click the title for detailed explanations.

Screenshot 2.b: Supporting information screen.

Examples of Source and Target Messages:

Screenshot 3: Source message containing 5 repeating ZTX segments.

Screenshot 4.a: Target system configuration sending the source message as-is and splitting the ZTX segments individually to operations.

Screenshot 4.b: Target system sending the source message as-is and splitting only the last ZTX segment to operations.

Another example where only split messages are sent, without sending the original full message first:

Screenshot 5: Source message with two ZTX segments split into two separate messages, each containing one ZTX segment.

Screenshot 6: Source Message

Screenshot 7.a: Target message containing the first ZTX  segment.

Screenshot 7.b: Target message containing the second ZTX segment.

Additional Example with Different Configurations

In this example, the source message contains multiple repeating NTE segments, where each NTE segment is part of the group path: PIDgrpgrp().ORCgrp().OBXgrp.

The process is configured to split and send each NTE segment individually to the target system. The resulting target messages are shown below:

  • Screenshot 10.a – First NTE segment
  • Screenshot 10.b – Second NTE segment
  • Screenshot 10.c– Third NTE segment

Screenshot 8: Process Configurations

Screenshot 9: Source message

Screenshot 10.a: Target message – First NTE segment

Screenshot 10.b: Target message – Second NTE segment

Screenshot 10.c: Target message – Third NTE segment

CODE

/// This process reads the HL7 messages from the source, splits the messages according 
/// to the given segment, and forwards them to the specified router/system. 
/// For example, if the message has multiple OBX, NTE, or ZTX segments,each message will 
/// include only one of the given segments. Additionally, if required, it will make the 
/// message unique by adding the serial number to the given segment's field.
/// <br>
///  This is a template that can be reused without modification in the code or with minimal modification based on the requirements. 
/// <br/> 
/// <br><b>Author: Sanjib Pandey</b>
/// Version:1.0
/// Date : 25/09/2025
/// <br>
Class SANJIB.Process.SegmentSplitAndSendMessage Extends Ens.BusinessProcess [ ClassType = persistent ]
{

/// The descriptions of the datasets:
/// <ul>
/// <li>Message Type - Type of HL7 Message </li>
/// <li>Multiple Segment Names - Segment Name. </li>
/// <li>Is Repeating - Defines whether the segment given above is repeating or not.</li>
/// <li>Segment Repeating Group - Defines whether the segment is part of a repeating group or not, e.g., RXCgrp(), and not part of multiple or nested groups.</li>
/// <li>Multiple Segment Group Path - define and give the path if segment is multiple group eg PIDgrp->OBX()</li>
/// <li>Segment Name for Unique ID - Specifies the segment for the message's unique ID eg. MSH, FT1.</li>
/// <li>Segment Details - Specifies the segment path details with the field name for the message's unique ID, e.g., MSH, FT1grp(1).FT1.</li>
/// <li>Segment Field No - Specifies the field name where the unique ID should be placed.</li>
/// </ul>
/// Provide the message type, e.g., ADT^A01, DFT^P03.
Property MessageType As %String(MAXLEN = 10);
/// Specify the segment name that needs to be sent individually (e.g., ZTX, RXP, etc.)
Property MultipleSegmentName As %String(MAXLEN = 20);
/// Are the selected multiple segments (MulSegmentName) repeating or not? [Y, N], e.g., OBX(), ZTX(), NTE(). 
/// Note: Currently, only the "Y" part is implemented. By default, it is set to "Y".
Property IsRepeating As %String(VALUELIST = ",Y,N") [ InitialExpression = "Y", Required ];
/// Define if this segment is part of any other group [Y, N]. It should be something like "RXCgrp()",
/// but not part of multiple or nested groups, e.g., PIDgrp()-NTE().
Property SegmentRepeatingGrp As %String(VALUELIST = ",Y,N") [ InitialExpression = "N", Required ];
/// Define and provide the path if a segment has come from nested groups.</li>
/// Define the segment path if a repeating segment consists of another repeating group segment, 
/// e.g., PIDgrp() → NTE(), PIDgrp() → OBX(), PIDgrp() → AL1(). 
/// Currently, this might be suitable for Merge or Move Message e.g. A38, A40, A41, A42, A45 etc and other types of message. 
/// PIDgrpgrp(1)->ORCgrp(1)->OBXgrp(1), ORCgrp(1).OBRuniongrp.NTE() 
/// <br>
/// Note: The following is included but some of them has not been tested yet; it will be included in the new version (working on):
/// <ul>
/// <li>PIDgrpgrp(1)->ORCgrp(1)->OBXgrp(1)->any repeating group segment</li>
/// <li>ORCgrp(1).OBRuniongrp.any repeating group segment </li>
/// <li>RGSgrp(1).AISgrp(1).any repeating group segment?</li>
/// <li>RGSgrp(1).AIGgrp(1).any repeating group segment?</li>
/// <li>RGSgrp(1).AILgrp(1).any repeating group segment?</li>
/// </ul>
/// Multiple Segment Group Path - define and give the path if segment is multiple group eg PIDgrp->OBX()
/// PIDgrp(1).ORCgrp(1).OBXgrp(1).NTE() = PIDgrp(1).ORCgrp(1).OBXgrp (the last segment doesn't need to be mentioned (1)).
Property MultipleSegGrpPath As %String(VALUELIST = ",NA,PIDgrp,MRGgrp,PRG1grp,IN1grp,ORCgrp(1).OBRuniongrp,PIDgrpgrp(1).ORCgrp(1).OBXgrp,The following requires more testing — do not select or use in production!,ORCgrp(1).OBRuniongrp.OBXgrp,RGSgrp(1).AILgrp,RGSgrp(1).AIGgrp,RGSgrp(1).AISgrp") [ InitialExpression = "NA", Required ];
/// To make the message unique, please specify which segment and field you want to use, e.g., MHS or FT1.
Property SegmentNameForUniqueID As %String(MAXLEN = 5);
/// Provide the full segment path to insert the value. If it is the same as the segment name, use the same name here, e.g., MSH, FT1grp(1).FT1.
Property SegmentDetails As %String(MAXLEN = 50);
/// Which field do you want to put the unique number in? For example, MSH:10 (control ID) 
/// or FT1.2 (financial transaction ID). You are required to specify the field 
/// instance number. If you want to use the existing MSH control ID field, enter 10.
Property SegmentFieldNo As %String(MAXLEN = 2);
/// Separation of the unique value: For example, if you want to use MSH:10, 
/// the existing value of MSH:10 will be used, and an additional unique number will be 
/// automatically added by the program, such as XXXXX.1, XXXXX.2, etc.
Property SeperationUniqueID As %String(MAXLEN = 2);
/// Target Configuration Name
Property TargetConfigurations As Ens.DataType.ConfigName(MAXLEN = 100) [ Required ];
Parameter SETTINGS = "MessageType,MultipleSegmentName,IsRepeating,SegmentRepeatingGrp,MultipleSegGrpPath,SegmentNameForUniqueID,SegmentDetails,SegmentFieldNo,SeperationUniqueID,TargetConfigurations:Basic:selector?multiSelect=1&context={Ens.ContextSearch/ProductionItems?targets=1&productionName=@productionId}";
Method OnRequest(pRequest As EnsLib.HL7.Message, Output pResponse As Ens.Response) As %Status
{
 /* ----------------------------------------------------------------------------------------------
   Note: You can access user-defined data directly from the management portal settings. However, 
   for business requirements, you may need to manipulate or further check the data. In such cases,
   it’s better to assign the data to a local variable. For example, while you can select multiple 
   target configurations in the portal, some business logic may require sending the message to a 
   specific operation, router, or process. All of this can be controlled here.
   ...............................................................................................	*/
   S tSC = $$$OK
   //Let's clear the memory variable and get all user-defined datasets
   S (msgType,mulSeg,isRepeat,segRepGrp,mulSegGrpPath,segNameUID,segFieldNo,sepUID,tgtConfig)=""
   S msgType =..MessageType
   S mulSeg=..MultipleSegmentName
   S isRepeat=..IsRepeating
   S segRepGrp=..SegmentRepeatingGrp
   S mulSegGrpPath=..MultipleSegGrpPath
   S segNameUID=..SegmentNameForUniqueID
   S segDetail=..SegmentDetails
   S segFieldNo=..SegmentFieldNo
   S sepUID=..SeperationUniqueID
   S tgtConfig=..TargetConfigurations
   K messageType S messageType=pRequest.GetValueAt("MSH:9")
   K cpyMsg S cpyMsg = pRequest.%New()
   S cpyMsg =pRequest.%ConstructClone()
   S (segIdx,totSegment)=0
   Try
   { 
      #dim totSegment=pRequest.SegCount
      F i=1:1:totSegment
      {
         K segName S segName = pRequest.GetSegmentAt(i).Name
         I (segName = mulSeg)
          {
            S segIdx=i
            /*-----------------------------------------------------------------------------------
              Note:
               The following line of code is only required if you want to send the original message to another downstream system or perform interface transformation. Otherwise, it is not needed and can be deleted or commented out:
               [S tSC=..ProcessMessage(pRequest,tgtConfig)]
               This line is included here for testing purposes only.. 
            ------------------------------------------------------------------------------------*/
            //S tSC=..ProcessMessage(pRequest,tgtConfig) 
            Q
         }
      }
      //checking necessry datasets
      I ((msgType="" ) || (mulSeg="")||(isRepeat="")|| (segRepGrp=""))
      {
         S tSC=$system.Status.Error(5001,"Empty fields. Please check the MessageType, MultipleSegmentName, IsRepeating, SegmentRepeatingGrp,multipleSegGrpPath in the Process Settings at the Management Portal.")
      }
      elseif messageType=msgType
      {
         I ((isRepeat= "Y") && (segRepGrp="N")&& (mulSegGrpPath="NA") && (segIdx >0))  
         {	
            S tSC=..ProcessMessageFromNoRepeatGroup(cpyMsg,msgType,mulSeg,isRepeat,segRepGrp,segNameUID,segDetail,segFieldNo,sepUID,segIdx,tgtConfig)
         }
         elseif ((isRepeat= "Y") && (segRepGrp="Y") && (mulSegGrpPath="NA") && (segIdx >0))
         {
            S tSC=..ProcessMessageFromRepeatingGroup(cpyMsg,msgType,mulSeg,isRepeat,segRepGrp,segNameUID,segDetail,segFieldNo,sepUID,segIdx,tgtConfig)
         }
         elseif ((isRepeat = "Y") && (mulSegGrpPath '="") && (segIdx >0))
         {
            S tSC=..ProcessMessageFromRepeatingGroupPath(cpyMsg,msgType,mulSeg,isRepeat,segRepGrp,mulSegGrpPath,segNameUID,segDetail,segFieldNo,sepUID,segIdx,tgtConfig)
         }
         else
         {
            S tSC=..ProcessMessage(pRequest,tgtConfig)	
         }
      }
   }
   catch ErException
   {
      S tSC=ErException.AsStatus()
      $$$TRACE("Exception :"_tSC)	
   }
   Q tSC
}

/// The following method splits, processes, and sends the message only from the given repeating segment.
Method ProcessMessageFromNoRepeatGroup(ByRef mRequest As EnsLib.HL7.Message, msgType As %String, mulSeg As %String, isRepeat As %String, segRepGrp As %String, segNameUID As %String, segDetail As %String, segFieldNo As %Integer, sepUID As %String, segIdx As %Integer, tgtConfig As %String) As %Status
{
   S tSC = $$$OK
   Try
   {
      K totSeg 
      #dim totSeg = mRequest.SegCount
      //prepare dataset
      S dataSets=..GetDataSets(mRequest,segNameUID,segDetail,segFieldNo)
      K flag S msgUID=$P(dataSets,":",1)
      K flag S flag=$P(dataSets,":",2)
      I sepUID="" S sepUID="-"
      K totRepSeg S totRepSeg=mRequest.GetValueAt(mulSeg_"(*)")
      I (totRepSeg >1)
      {
         F j=1:1:totRepSeg
         {
            K newMsg S newMsg=##class(EnsLib.HL7.Message).%New()
            S newMsg.DocType=mRequest.DocType
            I ((segNameUID="MSH") && (flag="G"))
            {
               D newMsg.SetSegmentAt(mRequest.FindSegment("MSH"),1)
               D newMsg.SetValueAt(msgUID_sepUID_j,"MSH:"_segFieldNo)
            }
            else
            {
               D newMsg.SetSegmentAt(mRequest.FindSegment("MSH"),1)
            }
            F k=1:1:totSeg
            {
               K segName S segName = mRequest.GetSegmentAt(k).Name
               I (segName '= "MSH") && (segName '= mulSeg) 
               {
                  K getSegment S getSegment=mRequest.FindSegment(segName,,.sc)
                  I $ISOBJECT(getSegment)
                  {
                     I ((segName=segNameUID) && (flag ="G"))
                        {
                           D newMsg.AppendSegment(getSegment)
                           D newMsg.SetValueAt(msgUID_sepUID_j,segDetail_":"_segFieldNo) 
                        }
                        else
                        {
                           D newMsg.AppendSegment(getSegment)
                        }
                  }
                  else
                  {
                     s tSC=$system.Status.Error(5001,"Not found "_segName_"Segment")
                  }
               }
            }
            S addSeg=mRequest.GetSegmentAt(mulSeg_"("_j_")")
            D newMsg.InsertSegmentAt(addSeg,segIdx)
            $$$QuitOnError(..ProcessMessage(newMsg,tgtConfig))
            K addSeg
         }
      }
      else
      {
         S tSC=..ProcessMessage(mRequest,tgtConfig)
      }
   }
   catch ErException
   {
      S tSC=ErException.AsStatus()
      $$$TRACE("Exception :"_tSC)	
   }
   Q tSC
}

/// The following method splits, processes, and sends the message only from the given repeating group segment.
Method ProcessMessageFromRepeatingGroup(ByRef pRequest As EnsLib.HL7.Message, msgType As %String, mulSeg As %String, isRepeat As %String, segRepGrp As %String, segNameUID As %String, segDetail As %String, segFieldNo As %Integer, sepUID As %String, segIdx As %Integer, tgtConfig As %String) As %Status
{
   S tSC = $$$OK
   Try
   {
      K totSeg 
      #dim totSeg = pRequest.SegCount
      S dataSets=..GetDataSets(pRequest,segNameUID,segDetail,segFieldNo)
      K flag S msgUID=$P(dataSets,":",1)
      K flag S flag=$P(dataSets,":",2)
      I sepUID="" S sepUID="-"
      K totRepSeg S totRepSeg=pRequest.GetValueAt(mulSeg_"grp(*)")
      I (totRepSeg >1)
      {
         F j=1:1:totRepSeg
         {
            K newMsg S newMsg=##class(EnsLib.HL7.Message).%New()
            S newMsg.DocType=pRequest.DocType
            I ((segNameUID="MSH") && (flag="G"))
            {
               D newMsg.SetSegmentAt(pRequest.FindSegment("MSH"),1)
               D newMsg.SetValueAt(msgUID_sepUID_j,"MSH:"_segFieldNo)
            }
            else
            {
               D newMsg.SetSegmentAt(pRequest.FindSegment("MSH"),1)
            }
            F k=1:1:totSeg
            {
               K segName S segName = pRequest.GetSegmentAt(k).Name
               I (segName '= "MSH") && (segName '= mulSeg) 
               {
                  K getSegment S getSegment=pRequest.FindSegment(segName,,.sc)
                  I $ISOBJECT(getSegment)
                  {
                     I ((segName=segNameUID) && (flag ="G"))
                        {
                           D newMsg.AppendSegment(getSegment)
                           D newMsg.SetValueAt(msgUID_sepUID_j,segDetail_":"_segFieldNo) 
                        }
                        else
                        {
                           D newMsg.AppendSegment(getSegment)
                        }
                  }
                  else
                  {
                     S tSC=$system.Status.Error(5001,"Not found "_segName_"Segment")
                  }
               }
            }
            S addSeg=pRequest.GetSegmentAt(mulSeg_"grp("_j_")."_mulSeg)
            D newMsg.InsertSegmentAt(addSeg,segIdx)
            $$$QuitOnError(..ProcessMessage(newMsg,tgtConfig))	
            K addSeg 
         }
      }
      else
      {
         S tSC=..ProcessMessage(pRequest,tgtConfig)	
      }
   }
   catch ErException
   {
      S tSC=ErException.AsStatus()
      $$$TRACE("Exception :"_tSC)	
   }
   Q tSC
}

/// The following method splits, processes, and sends the message only from the specified group segments, e.g., PIDgrp().NTE(), ORCgrp(1).OBRuniongrp.NTE(), etc.
Method ProcessMessageFromRepeatingGroupPath(ByRef pRequest As EnsLib.HL7.Message, msgType As %String, mulSeg As %String, isRepeat As %String, segRepGrp As %String, mulSegGrpPath As %String, segNameUID As %String, segDetail As %String, segFieldNo As %Integer, sepUID As %String, segIdx As %Integer, tgtConfig As %String) As %Status
{
   // This method is not fully completed yet, it's still a work in progress. 
   // But whatever existing features are here are working.
   S tSC = $$$OK
   Try
   {   
      K totSeg 
      #dim totSeg = pRequest.SegCount
      S dataSets=..GetDataSets(pRequest,segNameUID,segDetail,segFieldNo)
      K flag S msgUID=$P(dataSets,":",1)
      K flag S flag=$P(dataSets,":",2)
      I sepUID="" S sepUID="-"
      S mulSegPathType=0
      I mulSegGrpPath="ORCgrp(1).OBRuniongrp"
      {
         S totRepSeg=pRequest.GetValueAt(mulSegGrpPath_"."_mulSeg_"(*)")
         S mulSegPathType=1
      }
      else
      {
         S totRepSeg=pRequest.GetValueAt(mulSegGrpPath_"(1)."_mulSeg_"(*)")
         S mulSegPathType=2
      }
      I (totRepSeg >1)
      {
         F j=1:1:totRepSeg
         {
            K newMsg S newMsg=##class(EnsLib.HL7.Message).%New()
            S newMsg.DocType=pRequest.DocType
            I ((segNameUID="MSH") && (flag="G"))
            {
               D newMsg.SetSegmentAt(pRequest.FindSegment("MSH"),1)
               D newMsg.SetValueAt(msgUID_sepUID_j,"MSH:"_segFieldNo)
            }
            else
            {
               D newMsg.SetSegmentAt(pRequest.FindSegment("MSH"),1)
            }
            F k=1:1:totSeg
            {
               K segName S segName = pRequest.GetSegmentAt(k).Name
               I (segName '= "MSH") && (segName '= mulSeg) 
               {
                  K getSegment S getSegment=pRequest.FindSegment(segName,,.sc)
                  I $ISOBJECT(getSegment)
                  {
                     I ((segName=segNameUID) && (flag ="G"))
                     {
                        D newMsg.AppendSegment(getSegment)
                        D newMsg.SetValueAt(msgUID_sepUID_j,segDetail_":"_segFieldNo) 
                     }
                     else
                     {
                        D newMsg.AppendSegment(getSegment)
                     }
                  }
                  else
                  {
                     s tSC=$system.Status.Error(5001,"Not found "_segName_"Segment")
                  }
               }
            }
            I mulSegPathType=1
            {
               S addSeg=pRequest.GetSegmentAt(mulSegGrpPath_"."_mulSeg_"("_j_")")
            }
            I mulSegPathType=2
            {
               S addSeg=pRequest.GetSegmentAt(mulSegGrpPath_"(1)."_mulSeg_"("_j_")")
            }
            D newMsg.InsertSegmentAt(addSeg,segIdx)
            $$$QuitOnError(..ProcessMessage(newMsg,tgtConfig))	
            K addSeg
         }
      }
      else
      {
         S tSC=..ProcessMessage(pRequest,tgtConfig)		
      }
   }
   catch ErException
   {
      S tSC=ErException.AsStatus()
      $$$TRACE("Exception :"_tSC)	
   }
   Q tSC
}

/// The following method retrieves the existing source message ID from the given location to create a new unique message ID for the new message (repeating segment).
Method GetDataSets(ByRef pRequest As EnsLib.HL7.Message, segNameUID As %String, segDetail As %String, segFieldNo As %Integer, pOutput As %Integer = 0, flag As %String = "R") As %Status
{
   S tSC=$$$OK
   Try
   {
      I $ISOBJECT(pRequest)
      {
         K msgUID
         I (segNameUID '="" && segDetail '= "" && segFieldNo '="")
         {
            S msgUID = pRequest.GetValueAt(segDetail_":"_segFieldNo)
            I (msgUID =""){S msgUID=0}
            S flag="G"
            S pOutput=msgUID
         }
      }
      else
      {
         S tSC=$system.Status.Error(5001,"Not a valid HL7 message!")
      }
   }
   catch Exception
   {
      S tSC=Exception.AsStatus()
   }
   Q pOutput_":"_flag
}

/// The following sends or processes the message to the selected target names in the management portal.
Method ProcessMessage(pMessage As EnsLib.HL7.Message, TargetList As %String) As %Status
{
   S tSC=$$$OK
   Try
   {
      I $ISOBJECT(pMessage)
      {
         For i=1:1:$L(TargetList,",") 
         {
            S tSC=..SendRequestAsync($P(TargetList,",",i),pMessage,0)	
         }
      }
   }
   catch ErException
   {
      S tSC=ErException.AsStatus()
   }
   Q tSC
}

Method OnResponse(request As Ens.Request, ByRef response As Ens.Response, callrequest As Ens.Response, callresponse As Ens.Response, pCompletionKey As %String) As %Status
{
   Quit $$$OK
}

Storage Default
{
<Data name="SegmentSplitAndSendMessageDefaultData">
<Subscript>"SegmentSplitAndSendMessage"</Subscript>
<Value name="1">
<Value>MessageType</Value>
</Value>
<Value name="2">
<Value>MultipleSegmentName</Value>
</Value>
<Value name="3">
<Value>IsRepeating</Value>
</Value>
<Value name="4">
<Value>SegmentRepeatingGrp</Value>
</Value>
<Value name="5">
<Value>MultipleSegGrpPath</Value>
</Value>
<Value name="6">
<Value>SegmentNameForUniqueID</Value>
</Value>
<Value name="7">
<Value>SegmentDetails</Value>
</Value>
<Value name="8">
<Value>SegmentFieldNo</Value>
</Value>
<Value name="9">
<Value>SeperationUniqueID</Value>
</Value>
<Value name="10">
<Value>TargetConfigurations</Value>
</Value>
</Data>
<DefaultData>SegmentSplitAndSendMessageDefaultData</DefaultData>
<Type>%Storage.Persistent</Type>
}

}

 

You can also download the code from the GitHub  

I hope this template will help streamline your HL7 message processing. If you have any questions or need further assistance, please feel free to ask.

Thank you.

3 Comments
ディスカッション (3)2
続けるにはログインするか新規登録を行ってください