/******************************************************************************

#  $RCSfile: hl7_boom.sc,v $

#******************************************************************************

#     This is a component of Axon, the Real-Time HL7 Interface System

#     developed at the University of Washington Academic Medical Centers

#     by the HL7 Interface Team.

#

#  Author: J. Martin, from Boom Specs by T. Rozmyn et al...

#

#  Purpose: Container for functions used to support hl7_boom processing.

#

#           Functions:

#           ---------

#           msg_list_t * hl7_boom(msg_list_t *);

#             int          get_BOOM_person_no(msg_list_t *);

#             int          get_BOOM_pat_id();

#               msg_list_t * create_BOOM_list(msg_list_t *);

#

#******************************************************************************

#

#  $Source: /homes/hit/interfac/packages/rtif/common/src/RCS/hl7_boom.sc,v $

#

#******************************************************************************

#  $Log: hl7_boom.sc,v $

# Revision 1.6  2000/06/08  03:13:27  martinj

# added calls to get_bb_times

#

# Revision 1.5  2000/03/14  02:06:20  jalex

# added call to comma_del_remove to delete current patient

# from list of pat_no's to boom.

#

# Revision 1.4  2000/03/07  18:40:33  interfac

# *** empty log message ***

#

# Revision 1.1  2000/01/05  18:42:10  feattest

# Initial revision

#

# Revision 1.3  1999/11/09  16:53:54  jalex

# *** empty log message ***

#

# Revision 1.2  1999/11/02  00:44:07  jalex

# added functionality to create ZP2 and populate it when

# a non-patient person update (in NK1) occurs

#

# Revision 1.1  1999/10/18  17:21:36  martinj

# Initial revision

#

#******************************************************************************/

 

static char rcsid[] = "$Id: hl7_boom.sc,v 1.6 2000/06/08 03:13:27 martinj Exp $";

 

EXEC SQL INCLUDE SQLCA;

 

#include <stdio.h>

#include <sys/types.h>                        

#include <errno.h>

#include <strings.h>

#include <ctype.h>

#include "event.h"

#include "hl7_snd.h"

#include "error_stdout.h"

#include "safe_strcat.h"

#include "del_seg.h"

 

char *strPersonList;           /* list of person_no's  */

char *strPatIDList;            /* list of pat id's     */

 

/* set in get_BOOM_person_no                     */

char *strPID_patient_id[64];   

 

char        errmsg[128];

extern int     verbose_level;

 

extern evn_desc_t          *pEvn;

 

/* objects for hl7_getset                       */

extern spec_t EVN_event_code;

extern spec_t EVN_timestamp;

extern spec_t EVN_operator_id;

 

extern spec_t MSA_ack_code;

extern spec_t MSA_control_id;

extern spec_t MSH_send_app;

extern spec_t MSH_send_facility;

extern spec_t MSH_dest_app;   

extern spec_t MSH_dest_facility;

extern spec_t MSH_msg_timestamp;

extern spec_t MSH_msg_type;   

extern spec_t MSH_msg_event;

extern spec_t MSH_sequence_id;

extern spec_t MSH_hl7_version;

 

extern spec_t PID_set_id;    

extern spec_t PID_patient_id;

extern spec_t PID_alt_pat_id;

extern spec_t PID_alt_id_type;

extern spec_t PID_name_last;

extern spec_t PID_name_first;

extern spec_t PID_name_middle;

extern spec_t PID_name_suffix;

extern spec_t PID_ssn;

      

extern spec_t ZVN_upd_by; 

extern spec_t ZVN_upd_area;

extern spec_t ZVN_screen_id;

extern spec_t ZVN_netsec_updby;

 

/* objects to support BOOM person_no rules               */

extern spec_t ZP2_person_no;

spec_t ZN2_person_no    = { "ZN2",  3, 0, 0 };

spec_t NK1_set_id = { "NK1",  1, 0, 0 };

spec_t GT1_guar_no      = { "GT1",  2, 0, 0 };

spec_t ZI2_person_no    = { "ZI2", 33, 0, 0 };

extern spec_t ZMG_merge_type;

 

 

/*****************************************************************************

* function:    get_BOOM_person_no

* args:        msg_list_t *

* returns:     int (0=failure, 1=found a person_no/pat_id, 2=perform no Booming)

* usage info:

*

* accepts a msg_list_t pointer to a discrete event and

* extracts all the person_no's from the message using extraction

* rules given in boom_process.doc (T. Rozmyn).  Each person_no is

* concated into a string, suitable for input into Jay Alexander's

* process_bb.comma_del_sort_u function.

*

* HISTORY:

* --------

* Programmer:

* Date:

* Mod:

*

* Programmer:  J. Alexander

* Date:            16-Nov-1999

* Mod:             got rid of A28/A31 ZN2_person_no hack.

*            now using validate_syntax / hl7_set_by_grp.

*

* Programmer:  Jeff Martin

* Date:        28-Oct-1999

* Mod:         implemented v2.1 person_no rules.

*

* Programmer:  Jeff Martin

* Date:            18-Oct-1999

* Mod:             started.

*

******************************************************************************/

int

get_BOOM_person_no(msg_list_t *REGlist)

{

 

hl7_union_t *vs_result, *msgReg; /* message in hl7_get format              */

char    *c, *sub_c;              /* generic string pointers for hl7_get    */

char    evn_code[4];             /* evn_code from REG event                */

int     handledEvent = 0;        /* set if event code is BOOM eligible     */

int     shutdownEnable = 1;      /* used to further gate return(0)         */

 

segment_t    *pSeg_t;

 

char         *strWorking[MAX_HL7_MESSAGE_SIZE];

 

extern evn_desc_t  *pEvn;

evn_desc_t         *pTrav;

char               evn_grammar[1025];

 

/***** code section **************************************************/

evn_grammar[0]=(char)'\0';

 

if( verbose_level >= 100)

    log_bb_times("get_BOOM_person_no: start");

 

 

/* convert message to storage format  */

if((msgReg =  (hl7_union_t *)str2mesg(REGlist->msg)) == NULL) {

     sprintf(errmsg,

             "REG event %d failed str2msg",

             REGlist->seq_no );

     error_notify(__FILE__, __LINE__,errmsg, NOTIFY_FATAL);

     return(0);

}

 

/* get the REG event code     */

c = (char *) hl7_get(msgReg, &EVN_event_code, 1, 0, NULL, 0, 0);

if (c == NULL) {

  sprintf(errmsg,

         "BOOM can't get EVENT CODE for REG event %d",

          REGlist->seq_no );

  error_notify(__FILE__, __LINE__,errmsg, NOTIFY_FATAL);

  freemesg(msgReg);

  return(0);

}

strcpy(evn_code, c);

 

sprintf(errmsg,

      "BOOM got event code %s.",evn_code);

error_notify(__FILE__, __LINE__,errmsg, NOTIFY_UPDATE);

 

for(pTrav = pEvn; pTrav; pTrav = pTrav->next){

  if(!strcmp(pTrav->event_code, evn_code)) break;

}

if(!pTrav) {

  sprintf(errmsg, "No HL7 grammar defined for message %s", evn_code);

  error_notify(__FILE__, __LINE__, errmsg, NOTIFY_FATAL);

  freemesg(msgReg);

  return(0);

} else {

  safe_strcat(evn_grammar, pTrav->event_desc,1025);

  if(safe_strcat_err) {

    freemesg(msgReg);

    return(0);

  }

  if(strlen(evn_grammar) == 0) {

    sprintf(errmsg, "No message grammar defined for event %s",

            evn_code);

    error_notify(__FILE__, __LINE__, errmsg, NOTIFY_FATAL);

    freemesg(msgReg);

    return(0);

  } else {

    hl7_union_t *vs_result;

 

    vs_result = (hl7_union_t*)validate_syntax(evn_grammar, msgReg);

    if(!vs_result) {

      sprintf(errmsg, "Message failed syntax validation");

      error_notify(__FILE__, __LINE__, errmsg, NOTIFY_SERIOUS);

      printmesg(msgReg);

      sprintf(errmsg, "Validate_syntax:  Error: syntax must match %s",

              evn_grammar);

      error_notify(__FILE__, __LINE__, errmsg, NOTIFY_FATAL);

      freemesg(msgReg);

      return(0);

      }

    msgReg = vs_result;

  }

}

evn_grammar[0]=(char)'\0';

 

sprintf(errmsg,

      "Finished validate_syntax.");

error_notify(__FILE__, __LINE__,errmsg, NOTIFY_UPDATE);

 

/* allocate some storage for strPersonList      */

strPersonList = (char *) calloc(512, sizeof(char));

if(strPersonList == NULL) {

        error_notify(__FILE__, __LINE__,

                 "Can't calloc for strPersonList",

                 NOTIFY_FATAL);

        freemesg(msgReg);

        return NULL;

       }

 

/* implement BOOM person_no rules.  See boom_process.doc */

if (strcmp(evn_code,"A04") == 0) {

    handledEvent = 1;

    c = (char *) hl7_get(msgReg, &ZP2_person_no, 1, 0, NULL, 0, 0);

    if (c != NULL) {

       if (verbose_level >= 10000)

           printf("\t\t\tgot A04 ZP2_person_no: %s\n",c);

       strcat(strPersonList, c);

       strcat(strPersonList,",");

    }

 

} /* A04        */

 

if (strcmp(evn_code,"A08") == 0) {

    handledEvent = 1;

    c = (char *) hl7_get(msgReg, &ZP2_person_no, 1, 0, NULL, 0, 0);

    if (c != NULL) {

      if (verbose_level >= 10000)        

            printf("\t\t\tgot A08 ZP2_person_no: %s\n",c);

        strcat(strPersonList, c);

        strcat(strPersonList,",");

    }

 

    c = (char *) hl7_get(msgReg, &ZN2_person_no, 1, 0, NULL, 0, 0);

    /* strWorking is a hack at a big stump in the

       field I've decided to plow around     */

    sprintf(strWorking,"%s",c?c:"<null>");   

 

    if (c != NULL)  {

        sub_c = (char *) hl7_get(msgReg, &NK1_set_id, 1, 0, NULL, 0, 0);

        if (sub_c != NULL ) {

            if ( strcmp(sub_c,"PTN")==0 || strcmp(sub_c,"LNOK")==0 ) {

                if (verbose_level >= 10000)

                    printf("\t\t\tgot A08 ZN2_person_no: %s\n",strWorking);

            strcat(strPersonList, strWorking);

            strcat(strPersonList,",");