TMGSEQL1B ;TMG/kst/Interface with a generic PMS ;03/25/06 ;;1.0;TMG-LIB;**1**;01/09/06 ;"TMG DEMOGRAPHICS IMPORT FUNCTIONS ;"Custom import routines for Clinica Adelante ;"Kevin Toppenberg MD ;"GNU General Public License (GPL) applies ;"6-12-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) ;"$$InvalPtName(FName,LName) ;"$$GetDFN(PtInfo) ;"======================================================================= ;"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 PMS 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 PMS 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 ;" *** F2Name Won't be used in this alteration of the code... ;" 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 ;" *** F2Path Won't be used in this alteration of the code... ;" 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","PMSIMPORT","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","PMSIMPORT","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. ;" *** Note: G2Ref won't be used in this alteration of the code. ;" 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() ;" *** Note: This won't be used by this alteration of the code. ;" 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. ;" This parser is written to handle the dataformat as put out by the PMS ;" at the Clinica Adelante, with Matthew King, MD and Benjamin Guldborg ;"Input: OneLine -- One line from CVS demographics file. (Format as per ProcessPt) ;" Format is as follows, *** all on one line (comma delimited) ;" Note: Only a few of these fields are used... cde could be modified for use later ;" This would be done by putting data field into Array("SOME NAME")=value ;" Then modify UpdateDB to put data into VistA ;" 01-PatientProfileId ;" 02-PatientId ;" 03-Inactive ;" 04-Prefix ;" 05-First ;" 06-Middle ;" 07-Last ;" 08-Suffix ;" 09-Address1 ;" 10-Address2 ;" 11-City ;" 12-State ;" 13-Zip ;" 14-Country ;" 15-Phone1 ;" 16-Phone1Type ;" 17-Phone2 ;" 18-Phone2Type ;" 19-County ;" 20-EMailAddress ;" 21-EmpStat ;" 22-EmpStatusDate ;" 23-EmpOccup ;" 24-EduStat ;" 25-SchoolName ;" 26-SSN ;" 27-Birthdate ;" 28-DeathDate ;" 29-Sex ;" 30-Race ;" 31-MaritalStat ;" 32-GuarantorId ;" 33-GarPrefix ;" 34-GarFirst ;" 35-GarMiddle ;" 36-GarLast ;" 37-GarSuffix ;" 38-GarAddress1 ;" 39-GarAddress2 ;" 40-GarCity ;" 41-GarState ;" 42-GarZip ;" 43-GarCountry ;" 44-GarPhone1 ;" 45-GarPhoneType1 ;" 46-GarPhone2 ;" 47-GarPhoneType2 ;" 48-GarEmail ;" 49-GarSSN ;" 50-GarBirthDate ;" 51-GarSex ;" 52-GarRealation ;" 53-FinancialClass ;" 54-MedicalRecordNumber ;" 55-PCPDoctor ;" 56-PCFacility ;" ;" ---- Below is the original data fields from Sequel PMS (FYI)--- ;" 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 ;" 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") ;" Array("LAST NAME") ;" Array("FIRST NAME") ;" Array("MIDDLE NAME") <--- NEW ;" Array("NAME SUFFIX") <--- NEW ;" Array("NAME PREFIX") <--- NEW ;" Array("PMS ACCOUNT NUM") ;" Array("ADDRESS1") ;" Array("ADDRESS2") ;" Array("ADDRESS3") ;" Array("STATE") ;" Array("RESP LAST NAME") ;" Array("RESP FIRST NAME") ;" Array("CITY") ;" Array("PROVIDER") ;" Array("ZIP CODE") ;" Array("DOB") ;" Array("PHONE NUM") ;" Array("SEX") ;" Array("SSNUM")=Social security number ;" Array("FULL NAME")=FIRSTNAME MIDDLENAME LASTNAME SUFFIX(DOB) ;" Array("FULL NAME2")=LASTNAME,FIRSTNAME MIDDLE SUFFIX (DOB) ;" Array("FULL NAME3")=LASTNAME,FIRSTNAME MIDDLE SUFFIX ;"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")="ADELANTE" ;"hard code for only 1 site set Array("LAST NAME")=$$Trim^TMGSTUTL($piece(OneLine,",",7)) set Array("FIRST NAME")=$$Trim^TMGSTUTL($piece(OneLine,",",5)) set Array("MIDDLE NAME")=$$Trim^TMGSTUTL($piece(OneLine,",",6)) set Array("NAME SUFFIX")=$$Trim^TMGSTUTL($piece(OneLine,",",6)) ;"I'm not sure what to do with prefix yet -- not used. set Array("NAME PREFIX")=$$Trim^TMGSTUTL($piece(OneLine,",",6)) set Array("PMS ACCOUNT NUM")=$piece(OneLine,",",2) set Array("ADDRESS1")=$piece(OneLine,",",9) set Array("ADDRESS2")=$piece(OneLine,",",10) if Array("ADDRESS2")="Same As Above" set Array("ADDRESS2")="" set Array("STATE")=$piece(OneLine,",",12) set Array("RESP LAST NAME")=$piece(OneLine,",",36) set Array("RESP FIRST NAME")=$piece(OneLine,",",34) set Array("CITY")=$$Trim^TMGSTUTL($piece(OneLine,",",11),"""") set Array("PROVIDER")="" set Array("ZIP CODE")=$piece(OneLine,",",13) new DOB set DOB=$piece(OneLine,",",27) 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,",",15) set Array("SEX")=$piece(OneLine,"^",29) new tMName set tMName=$get(Array("MIDDLE NAME")) if tMName'="" set tMName=" "_tMName ;"add space only if middle name provided new tSuffix set tSuffix=$get(Array("NAME SUFFIX")) if tSuffix'="" set tSuffix=" "_tSuffix ;"add space only if suffix provided set Array("FULL NAME")=Array("FIRST NAME")_tMName_" "_Array("LAST NAME")_tSuffix_" ("_Array("DOB")_")" set Array("FULL NAME2")=Array("LAST NAME")_","_Array("FIRST NAME")_tMName_tSuffix_" ("_Array("DOB")_")" set Array("FULL NAME3")=Array("LAST NAME")_","_Array("FIRST NAME")_tMName_tSuffix ;"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) ;" VistA address allows for: ;" .111 -- address line 1 ;" .112 -- address line 2 ;" .113 -- address line 3 ;" BUT, each line must be 3-35 characters ;" PMS might not match this ;" SO, I need to divide the line if not 3-35 new value set value=$get(Array("ADDRESS1")) if $length(value)'<35 do . new s1,s2 . do NiceSplit^TMGSTUTL(value,35,.s1,.s2,3) . set Array("ADDRESS1")=s1 . if $get(Array("ADDRESS2"))'="" set s2=s2_"; "_$get(Array("ADDRESS2")) . set Array("ADDRESS2")=s2 set value=$get(Array("ADDRESS2")) if $length(value)'<35 do . do NiceSplit^TMGSTUTL(value,35,.s1,.s2,3) . set Array("ADDRESS2")=s1 . if s2'="" set Array("ADDRESS3")=$extract(s2,1,35) ;"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 SSNum set SSNum=$$Trim^TMGSTUTL($piece(OneLine,",",26)) if +SSNum'=SSNum set SSNum="" ;"remove alpha answers such as 'UNKNOWN' 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 PLDone 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,DFN set Entry(.01)=$$FormatName^TMGMISC($get(Array("FULL NAME3"))) set Entry(.03)=$get(PtInfo("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 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("FULL NAME3") ----> field .01 ;" PtInfo("SEX") ----> field .02 ;" PtInfo("DOB") ----> field .03 ;" PtInfo("SSNUM") ----> field .09 ;" 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 ;" 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 new Fields ;"Store names indexes of import data to compare with set Fields(22701)="PMS ACCOUNT NUM" set Fields(.01)="FULL NAME3" set Fields(.02)="SEX" set Fields(.03)="DOB" set Fields(.09)="SSNUM" 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" ;"This will be fields to get from VistA for comparison ;"For every number there should be a matched entry above. set Fields="22701;.01;.02;.03;.09;.111;.112;.113;.115;.114;.1112;.131;.1041" set Name=$get(PtInfo("FULL NAME3")) 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) ;"Add patient to database (register) if appropriate 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 from database for comparison 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 do . . . . set UpdateNeeded=1 . . . . 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 UpdateNeeded=1 . . . . 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)_"PMS#="_PtInfo(field)_" vs. VistA#="_TMGARRAY(2,IENS,index) . . . set abort=1,result=0 . . else if index=.03 do ;"compare internal values of DOBs, not external values . . . new %DT set %DT="P" ;"past dates A . . . new ddate1,date2 . . . set X=value do ^%DT set date1=Y;"get internal form of date, store in date1 . . . set X=$get(TMGARRAY(2,IENS,index)) . . . do ^%DT set date2=Y;"get internal form of date, store in date2 . . . if date1'=date2 set NewInfo(.03)=value ;"dates do differ, so update Vist . . . set UpdateNeeded=1 . . else do . . . 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