TMGSEQL1 ;TMG/kst/Interface with SequelSystems PMS ;03/25/06
         ;;1.0;TMG-LIB;**1**;01/09/06
 
 ;"TMG SEQUEL IMPORT FUNCTIONS
 ;"Kevin Toppenberg MD
 ;"GNU General Public License (GPL) applies
 ;"1-9-2006
 
 
 ;"=======================================================================
 ;" API -- Public Functions.
 ;"=======================================================================
 ;"ASKIMPORT
 ;"RUNNOW  provide an entry point for running import NOW.  This will delete prior alerts
 ;"AUTOIN  ;"entry point for scheduled task
 ;"QUIETIN
 
 ;"$$IMPORTFILE(FilePath,FileName,F2Name,ErrArray,ChgLog,PrgCallback,F2Path,DelFiles,UserID)
 ;"$$IMPORTGLOBAL(GRef,G2Ref,ErrArray,ChgLog,PrgCallback,UserID)
 
 ;"=======================================================================
 ;"PRIVATE API FUNCTIONS
 ;"=======================================================================
 ;"$$ProcessPt(OneLine,ErrArray,ChgLog,SSNArray,DUZ)
 ;"$$ParseLine(OneLine,Array,SSNArray)
 ;"UpdateDB(PtInfo,AutoRegister,ErrArray,ChgLog)
 ;"$$InactivePt(PMSAcctNum,SSNArray)
 ;"$$InvalidProvider(SequelProvider)
 ;"$$InvalPtName(FName,LName)
 
 
 ;"=======================================================================
 ;"DEPENDENCIES
 ;"TMGIOUTL
 ;"TMGMISC
 ;"=======================================================================
 ;"=======================================================================
 
 
 
 ;"=======================================================================
 ;"      Below are three custom files that are used by the TMGSEQL* code
 ;"=======================================================================
 
 
 ;"File: 22706 TMG DEMOGRAPHICS IMPORT ERRORS                           Branch: 1
 ;"REF  NODE;PIECE     FLD NUM  FIELD NAME
 ;"===============================================================================
 ;"  1  0;1                .01  ACCOUNT NUMBER                           [RNJ9,0]
 ;"  2  4;1                .02  CREATION DATE                                 [D]
 ;"  3  4;2                .03  PATIENT NAME                                  [F]
 ;"  4  0;2                  1  MESSAGE                                       [F]
 ;"     2;0                  2  IMPORT DATA                       <-WP [22706.02]
 ;"  5   -0;1              .01   -IMPORT DATA                                 [W]
 ;"     3;0                  3  DIERR MESSAGE                     <-WP [22706.03]
 ;"  6   -0;1              .01   -DIERR MESSAGE                               [W]
 ;"  7  4;3                  4  ALERT IEN                                 [NJ9,0]
 ;" <> <> <>
 ;"  A.) FILE NAME:------------- TMG DEMOGRAPHICS IMPORT ERRORS
 ;"                                                F.) FILE ACCESS:
 ;"  B.) FILE NUMBER:----------- 22706                  DD______ @
 ;"                                                     Read____ @
 ;"  C.) NUM OF FLDS:----------- 9                      Write___ @
 ;"                                                     Delete__ @
 ;"  D.) DATA GLOBAL:----------- ^TMG(22706,            Laygo___ @
 ;"
 ;"  E.) TOTAL GLOBAL ENTRIES:-- 76                G.) PRINTING STATUS:-- Off
 ;"================================================================================
 
 
 
 ;"File: 22707 TMG NAME SEX                                              Branch: 1
 ;"REF  NODE;PIECE     FLD NUM  FIELD NAME
 ;"===============================================================================
 ;"  1  0;1                .01  FIRST NAME                                   [RF]
 ;"  2  0;2                  1  SEX                                           [S]
 ;"<> <> <>
 ;"  A.) FILE NAME:------------- TMG NAME SEX
 ;"                                                F.) FILE ACCESS:
 ;"  B.) FILE NUMBER:----------- 22707                  DD______ @
 ;"                                                     Read____ @
 ;"  C.) NUM OF FLDS:----------- 2                      Write___ @
 ;"                                                     Delete__ @
 ;"  D.) DATA GLOBAL:----------- ^TMG(22707,            Laygo___ @
 ;"
 ;"  E.) TOTAL GLOBAL ENTRIES:-- 698               G.) PRINTING STATUS:-- Off
 ;"================================================================================
 
 
 
 ;"File: 22711 TMG UPLOAD SETTINGS                                       Branch: 1
 ;"REF  NODE;PIECE     FLD NUM  FIELD NAME
 ;"===============================================================================
 ;"  1  0;1                .01  NAME                                        [RFX]
 ;"  2  0;2                  1  DEBUG SHOW                               [NJ1,0X]
 ;"  3  1;1                1.1  DEBUG OUTPUT FILE                             [F]
 ;"  4  2;1               1.15  DEBUG OUTPUT PATH                             [F]
 ;"  5  1;2                1.2  DEBUG CUMULATIVE                          [NJ1,0]
 ;"  6  3;1                  2  IMPORT DATAFILE NAME                          [F]
 ;"  7  5;1                2.1  IMPORT DATAFILE 2 NAME                        [F]
 ;"  8  4;1                2.5  IMPORT DATAFILE PATH                          [F]
 ;"  9  6;1                  3  ALERT RECIPIENT                   <-Pntr  [P200']
 ;" 10  6;2                  4  LAST IMPORT DATE                              [D]
 ;" 11  6;3                  5  DELETE DATAFILE AFTER IMPORT?                 [S]
 ;" 12  6;4                  6  PICK GENDER FROM NAME?                        [S]
 ;" 13  6;5                  7  IMPORT FREQUENCY (IN HOURS)               [NJ4,0]
 ;" <> <> <>
 ;"  A.) FILE NAME:------------- TMG UPLOAD SETTINGS
 ;"                                                F.) FILE ACCESS:
 ;"  B.) FILE NUMBER:----------- 22711                  DD______ @
 ;"                                                     Read____ @
 ;"  C.) NUM OF FLDS:----------- 12                     Write___ @
 ;"                                                     Delete__ @
 ;"  D.) DATA GLOBAL:----------- ^TMG(22711,            Laygo___ @
 ;"
 ;"  E.) TOTAL GLOBAL ENTRIES:-- 1                 G.) PRINTING STATUS:-- Off
 ;"================================================================================
 
 
 
 
ASKIMPORT
        ;"Purpose: To ask user for filename and then import data.
        ;"Input: None
        ;"Output: Database is updated with data from file.
        ;"Result: None
 
        new DiscardName
        new DefPath set DefPath="/tmp/"
        new DefFName set DefFName="demographics.csv"
        new DefF2Name set DefF2Name="demographics2.csv"
        new FPath,FName,F2Name
        new ErrArray,ChLog
        new result
 
        new PrgsFn set PrgsFn="do ProgressBar^TMGUSRIF(TMGCUR,""Progress"",1,TMGMAX,,TMGSTART)"
        set PrgsFn=PrgsFn_" read *TMGkeyin:0 set:(TMGkeyin=27) TMGABORT=1"
 
        set DiscardName=$$GetFName^TMGIOUTL("Please enter file to import.",.DefPath,.DefFName,,.FPath,.FName)
        if DiscardName="" goto AIDone
 
        set DiscardName=$$GetFName^TMGIOUTL("Please enter 2nd file to import.",.DefPath,.DefF2Name,,.FPath,.F2Name)
        if DiscardName="" goto AIDone
 
        set result=$$IMPORTFILE(FPath,FName,F2Name,.ErrArray,.ChLog,PrgsFn)
 
AIDone
    quit
 
 
RUNNOW
        ;"Purpose: To provide an entry point for running import NOW.  This will delete prior alerts
        ;"Input: none.  Settings stored in File 22711 are used
        ;"Output: None.  Progress shown to console.  The database should be updated
        ;"Results: none
 
        write !!,"Import Sequel Demographics Now...",!
 
        new FName,F2Name,FPath
        new result
        new ErrArray,ChLog
        new DelFiles
        new UserID
 
        set FName=$$GET1^DIQ(22711,"1,","IMPORT DATAFILE NAME")
        set F2Name=$$GET1^DIQ(22711,"1,","IMPORT DATAFILE 2 NAME")
        set FPath=$$GET1^DIQ(22711,"1,","IMPORT DATAFILE PATH")
        set DelFiles=+$$GET1^DIQ(22711,"1,","DELETE DATAFILE AFTER IMPORT?","I")
        set UserID=$$GET1^DIQ(22711,"1,","ALERT RECIPIENT","I")
 
        new PrgsFn set PrgsFn="do ProgressBar^TMGUSRIF(TMGCUR,""Progress"",1,TMGMAX,,TMGSTART)"
        set PrgsFn=PrgsFn_" read *TMGkeyin:0 set:(TMGkeyin=27) TMGABORT=1"
 
        set result=$$IMPORTFILE(FPath,FName,F2Name,,,PrgsFn,,DelFiles,UserID)
 
        quit
 
 
AUTOIN
        ;"Purpose: To provide an entry point for a scheduled task.  This will delete prior alerts
        ;"Input: none.  Settings stored in File 22711 are used
        ;"Output: None.  There should be no console output.  The database should be updated
        ;"Results: none
 
        new InitTime set InitTime=$H
 
        new UserID set UserID=$$GET1^DIQ(22711,"1,","ALERT RECIPIENT","I")
 
        do  ;"clear out 'next run task number'
        . new TMGFDA,TMGMSG
        . set TMGFDA(22711,"1,",8)="@"  ;"#4 = TASK FOR NEXT RUN
        . do FILE^DIE("E","TMGFDA","TMGMSG")  ;" note: ignores TMGMSG or errors.
 
        new temp set temp=$$QuietClear^TMGSEQL3(UserID)  ;"clear prior alerts & errors
        do QUIETIN  ;" do import
 
        ;"Here I schedule the next task to run again.
        new HrInterval set HrInterval=$$GET1^DIQ(22711,"1,","IMPORT FREQUENCY (IN HOURS)","I")
        if +HrInterval>0 do
        . new time set time=$$HADD^XLFDT(InitTime,0,HrInterval,0)
        . new task set task=$$Schedule^TMGSEQL3(time,"AUTOIN^TMGSEQL1","Import of demographic data from Sequel billing system.")
        . ;"store 'next run task number'
        . set TMGFDA(22711,"1,",8)="`"_task  ;"#4 = TASK FOR NEXT RUN
        . do FILE^DIE("E","TMGFDA","TMGMSG")  ;" note: ignores TMGMSG or errors.
 
        quit
 
 
QUIETIN
        ;"Purpose: To import data based on settings, with no user interaction (in or out)
        ;"Input: none.  Settings stored in File 22711 are used
        ;"Output: None.  There should be no console output.  The database should be updated
        ;"Results: none
 
        new FName,F2Name,FPath
        new result
        new ErrArray,ChLog
        new DelFiles
        new UserID
 
        set FName=$$GET1^DIQ(22711,"1,","IMPORT DATAFILE NAME")
        set F2Name=$$GET1^DIQ(22711,"1,","IMPORT DATAFILE 2 NAME")
        set FPath=$$GET1^DIQ(22711,"1,","IMPORT DATAFILE PATH")
        set DelFiles=+$$GET1^DIQ(22711,"1,","DELETE DATAFILE AFTER IMPORT?","I")
        set UserID=$$GET1^DIQ(22711,"1,","ALERT RECIPIENT","I")
 
        set result=$$IMPORTFILE(FPath,FName,F2Name,,,,,DelFiles,UserID)
 
        quit
 
 
IMPORTFILE(FilePath,FileName,F2Name,ErrArray,ChgLog,PrgCallback,F2Path,DelFiles,UserID)
        ;"Purpose: To import data from file specified.
        ;"Input:   FilePath: Path of file to input.
        ;"         FileName: The Name of file of file to input.
        ;"              Note: This is written to import a specific file
        ;"                      created by SequelMed Systems, filled with
        ;"                      patient demographics, in CVS format
        ;"              Note: This file will be DELETED if DelFiles=1
        ;"         F2Name : the name of the second demographics file in input
        ;"              The reason for 2 files is because Sequel doesn't report the SSN in the
        ;"              primary demographics report.  So a second report must be used, and these
        ;"              two files are merged to provide complete patient demographics.
        ;"              Note: This file will be DELETED if DelFiles=1
        ;"         ErrArray: PASS BY REFERENCE.  Array to receive failed data lines.
        ;"         ChgLog: PASS BY REFERENCE.  An array to receive record of changes made to database
        ;"         PrgCallback: OPTIONAL -- if supplied, then M code contained in this string
        ;"              will be xecuted periodically, to allow display of a progress bar etc.
        ;"              Note: the following variables with global scope will be declared and
        ;"                      available for use: TMGCUR (current count), TMGMAX (max count),
        ;"                      TMGSTART (the start time
        ;"                      External function can signal a request an abort by setting TMGABORT=1
        ;"         F2Path: OPTIONAL -- path of 2nd demographics file.  Default=FilePath
        ;"         DelFiles: OPTIONAL -- if 1, then source files (FileName and F2Name) are deleted after import
        ;"         UserID : OPTIONAL -- user to receive alerts regarding errors.  Default is current user (DUZ)
        ;"Note: I have learned that SequelMed billing system exports ALL patients in the primary
        ;"      export file, including one that have been marked inactive do to invalid data etc.
        ;"      Thus, while the second file (F2Name) has limited info, it contains the list of
        ;"      ACTIVE patients.  So if a name is not included in the 2nd file, then its info will
        ;"      be ignored in the 1st file.
        ;"Output: Database is updated with data from file.
        ;"Result: 1 successful completion, 0=error
 
        new GRef,GRef1
        new G2Ref,G2Ref1
        new result
 
        set F2Path=$get(F2Path,FilePath)
 
        set GRef=$name(^TMP("TMG","SEQUELIMPORT","DATA",1,$J))   ;"I use this to process array
        set GRef1=$name(@GRef@(1))                   ;"I use this to load file
        kill @GRef
        set result=$$FTG^%ZISH(FilePath,FileName,GRef1,6)  ;"load file into a global
        if result=0 goto IFDONE
 
        set G2Ref=$name(^TMP("TMG","SEQUELIMPORT","DATA",2,$J))   ;"I use this to process array
        set G2Ref1=$name(@G2Ref@(1))                   ;"I use this to load file
        kill @G2Ref
        set result=$$FTG^%ZISH(F2Path,F2Name,G2Ref1,6)  ;"load file into a global
        if result=0 goto IFDONE
 
        set UserID=$get(UserID,+$get(DUZ))
 
        set result=$$IMPORTGLOBAL(GRef,G2Ref,.ErrArray,.ChLog,.PrgCallback,UserID)
 
        ;"Note: @GRef, @G2Ref killed at end of $$IMPORTGLOBAL()
 
        do  ;"record the current time as the time of last import
        . do NOW^%DTC
        . new TMGFDA,TMGMSG
        . set TMGFDA(22711,"1,",4)=%  ;"#4 = LAST IMPORT DATE
        . do FILE^DIE("E","TMGFDA","TMGMSG")  ;" note: ignores TMGMSG or errors.
 
        if $get(DelFiles)=1 do
        . ;"Notice: After I implemented this, I realized that I have a permissions problem
        . ;"  at my site... the uploaded files belong to the uploaded user, and deletion by
        . ;"  this user is being blocked.  I'll leave in for now...
        . new temp
        . set temp=$$DelFile^TMGIOUTL(FilePath_FileName)
        . set temp=$$DelFile^TMGIOUTL(F2Path_F2Name)
 
IFDONE
        quit result
 
IMPORTGLOBAL(GRef,G2Ref,ErrArray,ChLog,PrgCallback,UserID)
        ;"Purpose: To import data from global specified.
        ;"Input:   GRef -- the NAME of array holding the data to import (1st file)
        ;"              Format: @GRef@(1)=OneLine
        ;"                      @GRef@(2)=OneLine .. etc.
        ;"              Note: This is written to import a specific file
        ;"                      created by SequelMed Systems, filled with
        ;"                      patient demographics, in CVS format
        ;"              Note: Array will be KILLED at the end of this function.
        ;"         G2Ref -- the NAME of array holding the data to import (2nd file)
        ;"              Note: Array will be KILLED at the end of this function.
        ;"         ErrArray: PASS BY REFERENCE.  Array to receive failed data lines.
        ;"         ChgLog: PASS BY REFERENCE.  An array to receive record of changes made to database
        ;"         PrgCallback: OPTIONAL -- if supplied, then M code contained in this string
        ;"              will be xecuted periodically, to allow display of a progress bar etc.
        ;"              Note: the following variables with global scope will be declared and
        ;"                      available for use: TMGCUR (current count), TMGMAX (max count),
        ;"                      TMGSTART (the start time
        ;"                      External function can signal a request an abort by setting TMGABORT=1
        ;"         UserID : OPTIONAL -- user to receive alerts regarding errors.  Default is current user (DUZ)
        ;"Output: Database is updated with data from file.
        ;"Result: 1 successful completion, 0=error
 
        new TMGInvalid ;"Will be used as a globally-scoped variable in the module
        new result set result=1
        new delay set delay=0
        new TMGCUR,TMGMAX,TMGSTART,TMGABORT ;"avail for PrgCallback function
        set TMGABORT=0
        set TMGMAX=+$order(@GRef@(""),-1)
        set TMGSTART=$H  ;"store starting time.
        set UserID=$get(UserID,+$get(DUZ))
 
        new SSNArray
        do XtractSSNum(G2Ref,.SSNArray)
 
        set TMGCUR=$order(@GRef@(""))
        if TMGCUR'="" for  do  quit:(TMGCUR="")!(TMGABORT=1)
        . new OneLine
        . set OneLine=$get(@GRef@(TMGCUR))
        . set result=$$ProcessPt(OneLine,.ErrArray,.ChgLog,.SSNArray,UserID)
        . set delay=delay+1
        . if (delay>30),$get(PrgCallback)'="" do  ;"update progress bar every 30 cycles
        . . new $etrap set $etrap="write ""(Invalid M Code!.  Error Trapped.)"" set $etrap="""",$ecode="""""
        . . xecute PrgCallback  ;"call the specified progress code.
        . . set delay=0
        . set TMGCUR=$order(@GRef@(TMGCUR))
 
        kill @GRef
        kill @G2Ref
        quit result
 
 
 
ProcessPt(OneLine,ErrArray,ChgLog,SSNArray,DUZ,InputFn)
        ;"Purpose: To process one line from patient demographics file.
        ;"Input: OneLine-- One line from CVS demographics file.
        ;"      Format is as follows, *** all on one line (comma delimited)
                ;"      01- patient_seq_num,
                ;"      02- facility_short_name,
                ;"      03- pat_last_name,
                ;"      04- pat_first_name,
                ;"      05- pat_account_num,
                ;"      06- pat_address,
                ;"      07- state,
                ;"      08- resp_last_name,
                ;"      09- resp_first_name,
                ;"      10- facility_seq_num,
                ;"      11- register_date,
                ;"      12- location_name,
                ;"      13- city,
                ;"      14- provider_short_name,
                ;"      15- zipcode,
                ;"      16- class_name,
                ;"      17- pat_dob,
                ;"      18- ref_prov_short_name,
                ;"      19- pat_tel_num,
                ;"      20- last_visit_days,
                ;"      21- name,
                ;"      22- description
                ;"      ADDENDUM:
                ;"        sometimes SEX will be appended to line.  Format:
                ;"              previous data^MALE or previous data^FEMALE
                ;"        sometimes SSN will be appended to line.  Format:
                ;"              previous data^(sex)^SSNUM
        ;"    ErrArray: PASS BY REFERENCE.  Array to receive failed data lines.
        ;"    ChgLog: PASS BY REFERENCE.  An array to receive record of changes made to database
        ;"    SSNArray: OPTIONAL -- PASS BY REFERENCE.  An array with social security numbers,
        ;"              as created by XtractSSNum()
        ;"    DUZ: The user who will recieve alerts of errors
        ;"    InputFn:  OPTIONAL-- the name of a function to turn parse on csv line
        ;"              default value is "ParseLine"
        ;"              e.g. "MyFn" or "MyFn^MyRoutine".  Must take same params as ParseLine
        ;"              This will allow this code to be used on a variety of .csv files, with
        ;"              different data-formats--each one with its own parser funtion.
        ;"Output: Data is put into database, if it is not there already.
        ;"Result: 1=OK To continue; 0=abort or bad data
 
        new XFn
        new PtInfo,OneErrArray
        new result set result=1
        new AutoRegister set AutoRegister=1
        set InputFn=$get(InputFn,"ParseLine")
 
        set XFn="set result=$$"_InputFn_"(.OneLine,.PtInfo,.SSNArray)"
        xecute XFn       ;"old -- set result=$$ParseLine(.OneLine,.PtInfo,.SSNArray)
        if result'>0 goto PPtDone
        if $get(PtInfo("FACILITY"))="SAMPLE" goto PPtDone
 
        if $$UpdateDB(.PtInfo,AutoRegister,.OneErrArray,.ChgLog)=0 do
        . new count set count=+$get(ErrArray)+1
        . set ErrArray=count
        . set ErrArray(count)=OneLine
        . merge ErrArray(count,"INFO")=OneErrArray
        . ;"------
        . do AlertError^TMGSEQL2(OneLine,.PtInfo,.OneErrArray,DUZ)
 
PPtDone
        quit result
 
 
ParseLine(OneLine,Array,SSNArray)
        ;"Purpose: To process one line from patient demographics file.
        ;"         Also gets data into an acceptible format.
        ;"Input: OneLine -- One line from CVS demographics file. (Format as per ProcessPt)
        ;"         NOTE: if PASSED BY REFERENCE, then line may be altered such that SSN is
        ;"              added as a 3rd piece, using ^ as a delimiter. (2nd piece used elsewhere
        ;"              to store sex.
        ;"              When processing line, if SSNArray doesn't provide a SSN for patient, then
        ;"              this 3rd piece can provide the SSN
        ;"       Array -- PASS BY REFERENCE. And OUT parameter.  Any prior data killed.
        ;"       Note: uses TMGInvalid (globally scoped var defined in this module)
        ;"       SSNArray: OPTIONAL -- PASS BY REFERENCE.  An array with social security numbers,
        ;"               as created by XtractSSNum()
        ;"Output: Array is filled with Format as follows (note not all data used):
        ;"        Array("FACILITY"),  to hold 02- facility_short_name
        ;"        Array("LAST NAME"), to hold 03- pat_last_name,
        ;"        Array("FIRST NAME"), to hold 04- pat_first_name,
        ;"        Array("PMS ACCOUNT NUM"), to hold 05- pat_account_num,
        ;"        Array("ADDRESS1"), to hold 06- pat_address,
        ;"        Array("ADDRESS2"), to hold 06- pat_address,
        ;"        Array("ADDRESS3"), to hold 06- pat_address,
        ;"        Array("STATE"), to hold 07- state,
        ;"        Array("RESP LAST NAME"), to hold 08- resp_last_name,
        ;"        Array("RESP FIRST NAME"), to hold 09- resp_first_name,
        ;"        Array("CITY"), to hold 13- city,
        ;"        Array("PROVIDER"), to hold 14- provider_short_name,
        ;"        Array("ZIP CODE"), to hold 15- zipcode,
        ;"        Array("DOB"), to hold 17- pat_dob,
        ;"        Array("PHONE NUM"), to hold 19- pat_tel_num,
        ;"        Array("SEX"), to hold Patient sex, if provided.
        ;"        Array("SSNUM")=Social security number
        ;"        Array("FULL NAME")=FIRSTNAME LASTNAME (DOB)
        ;"        Array("FULL NAME2")=LASTNAME,FIRSTNAME (DOB)
        ;"        Array("FULL NAME3")=LASTNAME,FIRSTNAME
        ;"Result: 1=OK To continue; 0=abort or bad data; -1 skip, but don't store as error
 
        new temp
        new result set result=1
 
        set OneLine=$translate($get(OneLine),"""","'") ;"  convert " to ' to avoid fileman error
 
        kill Array
        set Array("FACILITY")=$piece(OneLine,",",2)
        set Array("LAST NAME")=$$Trim^TMGSTUTL($piece(OneLine,",",3))
        set Array("FIRST NAME")=$$Trim^TMGSTUTL($piece(OneLine,",",4))
        set Array("PMS ACCOUNT NUM")=$piece(OneLine,",",5)
        set Array("ADDRESS1")=$piece(OneLine,",",6)
        set Array("STATE")=$piece(OneLine,",",7)
        set Array("RESP LAST NAME")=$piece(OneLine,",",8)
        set Array("RESP FIRST NAME")=$piece(OneLine,",",9)
        set Array("CITY")=$$Trim^TMGSTUTL($piece(OneLine,",",13),"""")
        set Array("PROVIDER")=$piece(OneLine,",",14)
        set Array("ZIP CODE")=$piece(OneLine,",",15)
        new DOB set DOB=$piece(OneLine,",",17)
        set DOB=$$Trim^TMGSTUTL(DOB)
        set DOB=$piece(DOB," ",1)  ;" '03/09/05 00:00' --> '03/09/05'
        set Array("DOB")=DOB
        set Array("PHONE NUM")=$piece(OneLine,",",19)
        set Array("SEX")=$piece(OneLine,"^",2)
 
        set Array("FULL NAME")=Array("FIRST NAME")_" "_Array("LAST NAME")_" ("_Array("DOB")_")"
        set Array("FULL NAME2")=Array("LAST NAME")_","_Array("FIRST NAME")_" ("_Array("DOB")_")"
        set Array("FULL NAME3")=Array("LAST NAME")_","_Array("FIRST NAME")
 
        ;"do a lookup on abreviattion for ALL states, convert to external format
        new DIC,X,Y
        set DIC=5 ;"STATE file
        set DIC(0)="M"
        set X=Array("STATE")
        do ^DIC
        set Array("STATE")=$piece(Y,"^",2)
 
        ;"convert Sequel format to VistA format
        if Array("PROVIDER")'="" do
        . set Array("PROVIDER")=$$ConvProvider(Array("PROVIDER"))
        if Array("PROVIDER")="SKIP" set result=0 goto PLDone
 
        ;"  VistA address allows for:
        ;"      .111 -- address line 1
        ;"      .112 -- address line 2
        ;"      .113 -- address line 3
        ;"      BUT, each line must be 3-35 characters
        ;"  Sequel puts this all on one line.
        ;"  SO, I need to divide the Sequel line if not 3-35
        new value set value=Array("ADDRESS1")
        if $length(value)'<35 do
        . new s1,s2
        . do NiceSplit^TMGSTUTL(value,35,.s1,.s2,3)
        . set Array("ADDRESS1")=s1
        . if $length(s2)'<35 do
        . . do NiceSplit^TMGSTUTL(s1,35,.s1,.s2,3)
        . . set Array("ADDRESS2")=s1  ;"<-- is this correct?
        . . if s2'="" set Array("ADDRESS3")=$extract(s2,1,35)
        . else  set Array("ADDRESS2")=s2
 
        ;"Ensure proper length of city.
        set Array("CITY")=$extract(Array("CITY"),1,15)
        if $length(Array("CITY"))=1 set Array("CITY")=Array("CITY")_" "
 
        ;"Ensure proper length of phone
        if $length(Array("PHONE NUM"))<7 kill Array("PHONE NUM")
 
        new AcctNum set AcctNum=$get(Array("PMS ACCOUNT NUM"))
        new SSNum set SSNum=$get(SSNArray(AcctNum))
        if SSNum=999999999 set SSNum=0
        if +SSNum=0 do   ;"see if 3rd ^ piece holds SSNum data
        . set SSNum=$piece(OneLine,"^",3) ;"note this won't overwrite valid data from SSNArray()
        if SSNum>0 do
        . set Array("SSNUM")=SSNum
        . set $piece(OneLine,"^",3)=SSNum
 
        if result'=0 do
        . if $$InvalPtName(Array("FIRST NAME"),Array("LAST NAME"))=1 set result=-1 quit
        . if $$InactivePt(Array("PMS ACCOUNT NUM"),.SSNArray)=1 do
xx      . . set result=-1
        . . ;"write !,"Skipping: ",Array("FULL NAME3"),!  ;"temp
 
PLDone
        quit result
 
 
ConvProvider(SequelProvider)
        ;"Purpose: To convert Sequel provider shortname to VistA file 200 name.
        ;"Input: SequelProvider
        ;"Result: VistA provider name (string), or "" if not found, or "SKIP" if not to be used
 
        new result set result=""
 
        if $$InvalidProvider(SequelProvider) set result="SKIP" goto ConPrDone
        if SequelProvider="SAMPLE" set result="SKIP" goto ConPrDone
 
 
        new TMGARRAY,TMGMSG
        do FIND^DIC(200,,".01",,SequelProvider,"*","TMG",,,"TMGARRAY","TMGMSG")
        if +TMGARRAY("DILIST",0)>0 do
        . set result=TMGARRAY("DILIST",1,1)
        else  do
        . new DIC
        . set DIC=200
        . ;"try converting name and doing quiet lookup (KTOPPEN->TOPPEN,K)
        . set X=$extract(SequelProvider,2,99)_","_$extract(SequelProvider,1)
        . do ^DIC
        . if (+Y=-1)&(1=0) do  ;"<--- FEATURE TURNED OFF.  If not found, don't ask (no longer needed)
        . . if $data(TMGInvalid(SequelProvider))'=0 quit
        . . write !,"Please help match the Sequel 'shortname' to a VistA provider name.",!
        . . write "This should have to be done only once.",!
        . . write "Enter ^ if the provider name is not valid.",!
        . . write "Please enter VistA provider name for: '",SequelProvider,"'",!
        . . set DIC(0)="AEQM"
        . . do ^DIC
        . . write !
        . if +Y>-1 do
        . . new DFN set DFN=+Y
        . . new TMGFDA set TMGFDA(200,DFN_",",22702)=SequelProvider
        . . kill TMGMSG
        . . do FILE^DIE(,"TMGFDA","TMGMSG")  ;"ignore errors
        . . set result=$piece(Y,"^",2)
        . else  do
        . . set TMGInvalid(SequelProvider)=""
ConPrDone
        quit result
 
 
InvalPtName(FName,LName)
        ;"Purpose: To determine if the Patient name is invalid (i.e. CAP TOPPENBERG, or INSURANCE INSURANCE etc.)
        ;"Input: FName,LName -- the first and last names
        ;"Result: 1 if name is invalid, 0 if OK name
 
        new result set result=0
 
        if FName="CAP" do  ;"screen out 'CAP TOPPENBERG' etc ?? entries ??
        . new DIC set DIC=200
        . set DIC(0)="M"
        . set X=LName
        . do ^DIC
        . if +Y>0 set result=1
 
        if (FName="INSURANCE")&(LName="INSURANCE") set result=1
 
        quit result
 
 
InactivePt(PMSAcctNum,SSNArray)
        ;"Purpose: to determine if patient is inactive, and should be skipped.
        ;"      This is determined by testing for existence of AccountNumber in SSNArray.
        ;"      SSNArray is created from the 2nd demographics file.  This is a list of ACTIVE patients,
        ;"      which is different from the 1st demographics file--which holds ALL patients.
        ;"Input: PMSAcctNum -- as stored in PtInfo("PMS ACCOUNT NUM")
        ;"       SSNArray: PASS BY REFERENCE.  An array with social security numbers, as created by XtractSSNum()
        ;"Result: 1 if patient is INACTIVE, and should be skipped.
        ;"        0 if OK to use
 
        new result
        set result=+$get(SSNArray(PMSAcctNum))'>0
        quit result
 
 
InvalidProvider(SequelProvider)
        ;"Purpose: To return if provider should not be used (i.e. cause data to be skipped)
        ;"Input: SequelProvider
        ;"Result: 0: OK to use provider
        ;"        1: Don't use provider
 
        new result set result=0
 
        if SequelProvider="SAMPLE" set result=1
        if SequelProvider="GREENEVILLE" set result=1
        if SequelProvider="AFOSTER" set result=1
        if SequelProvider="AFTON" set result=1
        if SequelProvider="JWRIGHT" set result=1  ;"not an active provider
        ;"These providers are leaving group, so don't import their data.
        if SequelProvider="CPERRY" set result=1
        if SequelProvider="OSWARNER" set result=1
        if SequelProvider="SGILES" set result=1
        if SequelProvider="SPENNY" set result=1
        if SequelProvider="TFULLER" set result=1
 
        quit result
 
 
UpdateDB(PtInfo,AutoRegister,ErrArray,ChgLog)
        ;"Purpose: To put that data from the PtInfo array into the database (if needed)
        ;"Input: PtInfo -- array (PASS BY REFERENCE), with the following items being used:
        ;"              PtInfo("LAST NAME"), to hold 03- pat_last_name,
        ;"              PtInfo("FIRST NAME"), to hold 04- pat_first_name,
        ;"              PtInfo("PMS ACCOUNT NUM")  ----> field 22701 (custom field)
        ;"              PtInfo("ADDRESS")             ----> field .111
        ;"              PtInfo("STATE")               ----> field .115
        ;"              PtInfo("CITY")                ----> field .114
        ;"              PtInfo("ZIP CODE")            ----> field .1112
        ;"              PtInfo("PHONE NUM")           ----> field .131
        ;"              PtInfo("PROVIDER")            ----> field .1041
        ;"              PtInfo("SSNUM")               ----> field .09
        ;"      AutoRegister: if 1, then patient will be automatically added/registered
        ;"      ErrArray -- PASS BY REFERENCE.  And OUT parameter to get back error info.
        ;"      ChgLog: PASS BY REFERENCE.  An array to receive record of changes made to database
        ;"Output: Data is put into database, if it is not there already.
        ;"Result: 1 successful completion, 0=error
 
        new Entry
        new result set result=1
        new Name,TMGDOB,DFN
        new TMGARRAY,TMGMSG
        new PriorErrorFound
        new NewInfo
        new IENS
        new index
        kill ErrArray
        new TMGDEBUG set TMGDEBUG=-1 ;"//EXTRA QUIET mode --> shut down TMGDBAPI messages
 
 
        ;"NOTE:  I need to have some method such that IF a patient is positively matched
        ;"      (i.e. via SSNUM or PMS Account number), THEN changes in spelling of name, or
        ;"      DOB on Sequel side should be reflected in VistA.  Currently, I don't this
        ;"      this happens.
 
        new Fields
        set Fields(22701)="PMS ACCOUNT NUM"
        set Fields(.111)="ADDRESS1"
        set Fields(.112)="ADDRESS2"
        set Fields(.113)="ADDRESS3"
        set Fields(.115)="STATE"
        set Fields(.114)="CITY"
        set Fields(.1112)="ZIP CODE"
        set Fields(.131)="PHONE NUM"
        set Fields(.1041)="PROVIDER"
        set Fields(.02)="SEX"
        set Fields(.09)="SSNUM"
        set Fields="22701;.111;.112;.113;.115;.114;.1112;.131;.1041;.09"
 
        set Name=$get(PtInfo("LAST NAME"))_","_$get(PtInfo("FIRST NAME"))
        set Name=$$FormatName^TMGMISC(Name)
        set TMGDOB=$get(PtInfo("DOB"))
 
        set Entry(.01)=Name
        set Entry(.03)=TMGDOB
        if $get(PtInfo("SEX"))'="" set Entry(.02)=$get(PtInfo("SEX"))
        set Entry(.09)=$get(PtInfo("SSNUM"))
 
        set DFN=$$GetDFN(.PtInfo)
 
        if (DFN=0)&($get(AutoRegister)=1) do
        . set ErrArray=-1  ;"extra quiet mode.
        . if $get(Entry(.02))="" do  ;"autopick gender if missing
        . . new AutoPick
        . . set AutoPick=$$GET1^DIQ(22711,"1,","PICK GENDER FROM NAME?","I")
        . . if AutoPick'=1 quit
        . . set Entry(.02)=$$GetSex^TMGSEQL2($get(PtInfo("FIRST NAME")))
        . ;"OK, can't find, so will add new patient.
        . set DFN=+$$AddNewPt^TMGGDFN(.Entry,.ErrArray)
        . if DFN'=0 set ChLog(Name_" "_TMGDOB,0)="ADDED PATIENT: "_Name_" "_TMGDOB
        if DFN=0 do  goto UDBDone  ;"failure
        . set result=0
        . set ErrArray(0)=$$NameError^TMGSEQL2(.ErrArray)  ;"get name if DIERR encountered.
        . if ErrArray(0)["DOB" do
        . . ;"write !,"DOB error found for: ",PtInfo("FULL NAME"),!
        . if ErrArray(0)="" do
        . . set ErrArray(0)="PATIENT NOT IN DATABASE:"  ;"if changed, also change in TMGSEQL2.m
        set IENS=DFN_","
 
        ;"use DFN(IEN in file 2) to get data into database
        do GETS^DIQ(2,IENS,Fields,"","TMGARRAY","TMGMSG")
 
        ;"check for errors.
        if $data(TMGMSG("DIERR"))'=0 do  goto UDBDone
        . set result=0
        . merge ErrArray=TMGMSG("DIERR")
        . ;"do ShowDIERR^TMGDEBUG(.TMGMSG,.PriorErrorFound)
        kill TMGMSG
 
        ;"If any data in data base differs from Array, setup NewInfo
        new UpdateNeeded set UpdateNeeded=0
        new abort set abort=0
        set index=$order(Fields(""))
        for  do  quit:(+index'>0)!(abort=1)
        . new field set field=Fields(index)
        . if $data(PtInfo(field)),$get(TMGARRAY(2,IENS,index))'=$get(PtInfo(field)) do
        . . new value set value=$get(PtInfo(field))
        . . if index=.1112 do
        . . . if +value'=0 set NewInfo(index)=value
        . . else  if (index=.09)&(+value'=0)&(+TMGARRAY(2,IENS,index)'=0) do
        . . . if TMGARRAY(2,IENS,index)["P" do  quit
        . . . . set NewInfo(index)=value
        . . . ;"we have CONFLICTING SOCIAL SECURITY NUMBERS --> PROBLEM...
        . . . set ErrArray(0)="CONFLICTING SS-NUMBERS: " ;"NOTE! if error message format is changed, also change in TMGSEQL2
        . . . set ErrArray(0)=ErrArray(0)_"Sequel#="_PtInfo(field)_" vs. VistA#="_TMGARRAY(2,IENS,index)
        . . . set abort=1,result=0
        . . else  set NewInfo(index)=value
        . . set UpdateNeeded=1
        . set index=$order(Fields(index))
 
        if (UpdateNeeded=0)!(abort=1) goto UDBDone
 
        ;"Setup FDA array for database update
        new TMGFDA
        set index=$order(NewInfo(""))
        if index'=""  do
        . for  do  quit:(+index'>0)
        . . set TMGFDA(2,IENS,index)=NewInfo(index)
        . . set index=$order(NewInfo(index))
        . ;
        . do FILE^DIE("E","TMGFDA","TMGMSG")
        . if $data(TMGMSG("DIERR"))'=0 do  ;"goto UDBDone
        . . set result=0
        . . merge ErrArray=TMGMSG("DIERR")
 
        merge ChLog($get(Name,"?")_" "_$get(TMGDOB,"?"),1)=NewInfo
 
UDBDone
        quit result
 
 
GetDFN(PtInfo)
        ;"Purpose: Serve as interface to ^TMGGDFN functions (using PtInfo as input)
        ;"Input: PtInfo, Array of PtInfo, as defined in UpdateDB, and created by ParseLine
        ;"Result: the IEN in file 2 (i.e. DFN) if found, otherwise 0 if not found.
 
        new Entry,Name,DOB,DFN
 
        set Name=$get(PtInfo("LAST NAME"))_","_$get(PtInfo("FIRST NAME"))
        set Name=$$FormatName^TMGMISC(Name)
        set DOB=$get(PtInfo("DOB"))
 
        set Entry(.01)=Name
        set Entry(.03)=DOB
        set Entry(.02)=$get(PtInfo("SEX"))
        set Entry(.09)=$get(PtInfo("SSNUM"))
        set DFN=+$$LookupPatient^TMGGDFN(.Entry)  ;"get IEN in file 2 of patient
        ;"do an extended search with increasing intensity.
        if +DFN=0 set DFN=$$ExtraLookup^TMGGDFN(.Entry,1)
        if +DFN=0 set DFN=$$ExtraLookup^TMGGDFN(.Entry,2)
        if +DFN=0 set DFN=$$ExtraLookup^TMGGDFN(.Entry,3)
 
        quit DFN
 
 
 
XtractSSNum(G2Ref,SSNArray)
        ;"Purpose: To extract info from 2nd demographics file into an array of SSNums.
        ;"Input: G2Ref - Name of global array holding 2nd demographics file
        ;"              Note: Format of each line is as follows:
        ;"                scratchNum,AccountNumber,LastName,FirstName,SSNUM ... (other data is redundant)
        ;"                i.e. SSNUM is the 5th piece
        ;"       SSNArray -- PASS BY REFERENCE.  An OUT parameter.  See format below
        ;"Output: SSNArray will be filled as follows:
        ;"              SSNArray(SequelAccountNumber)=SSNum
        ;"Result: None
        ;"Note: 3/2/06 modification:
        ;"  An entry for every SequelAccountNumber will be created.  If SSNum is invalid, it will
        ;"  be converted to 0, but an entry will still be created, i.e.
        ;"              SSNArray(SequelAccountNumber)=0
 
 
        new i
 
        set i=$order(@G2Ref@(""))
        if i'="" for  do  quit:(i="")
        . new OneLine,AcctNum,SSNum
        . set OneLine=$get(@G2Ref@(i))
        . set AcctNum=$piece(OneLine,",",2)
        . set SSNum=$$Trim^TMGSTUTL($piece(OneLine,",",5))
        . new value set value=0 ;"default value
        . if +SSNum'<999999 do   ;"force at least 6 digits --> allow 0000 11 1111
        . . if $length(SSNum)'=9 do
        . . . set SSNArray("ERRORS",AcctNum)=SSNum  ;"leaves value="" --> not used
        . . else  do
        . . . ;"set SSNArray(AcctNum)=SSNum
        . . . set value=SSNum
        . set SSNArray(AcctNum)=value
        . set i=$order(@G2Ref@(i))
 
        quit
 
 
