Changeset 422


Ignore:
Timestamp:
Mar 29, 2009, 5:48:58 PM (15 years ago)
Author:
Sam Habiel
Message:

First take on implementing paramters for RPMS...

Location:
ccr/trunk/p
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • ccr/trunk/p/C0CMED.m

    r421 r422  
    11C0CMED  ; WV/CCDCCR/GPL/SMH - CCR/CCD Medications Driver; Mar 23 2009
    2         ;;0.5;CCDCCR;;JUL 16,2008;
     2        ;;0.6;CCDCCR;;JUL 16,2008;
    33        ; Copyright 2008,2009 George Lilly, University of Minnesota and Sam Habiel.
    44        ; Licensed under the terms of the GNU General Public License.
     
    4040        ; 6. RPMS Meds are in C0CMED6. Need to create other routines for subdivisions of RPMS Meds is not known at this time.
    4141        ;
    42         ; --Prep variables     
     42        ; --Find out what system we are on...   
    4343        I $$RPMS^C0CUTIL() D RPMS QUIT
    4444        I ($$VISTA^C0CUTIL())!($$WV^C0CUTIL())!($$OV^C0CUTIL()) D VISTA QUIT
    45         ; Extraction Sections
     45        ; --Get parameters for meds
     46        N C0CMFLAG
     47        S C0CMFLAG=$$GET^C0CPARMS("MEDALL")_"^"_$$GET^C0CPARMS("MEDLIMIT")_"^"_$$GET^C0CPARMS("MEDACTIVE")_"^"_$$GET^C0CPARMS("MEDPENDING")
    4648RPMS   
    47         D EXTRACT^C0CMED6(MEDXML,DFN,MEDOUTXML) QUIT
     49        D EXTRACT^C0CMED6(MEDXML,DFN,MEDOUTXML,C0CMFLAG) QUIT
    4850VISTA   
    4951        N MEDCOUNT S MEDCOUNT=0
  • ccr/trunk/p/C0CMED6.m

    r416 r422  
    1 C0CMED6 ; WV/CCDCCR/SMH - Meds from RPMS: Outpatient Meds;01/10/09
    2  ;;0.1;CCDCCR;;JUL 16,2008;
    3  ; Copyright 2008 WorldVistA.  Licensed under the terms of the GNU
    4  ; General Public License See attached copy of the License.
    5  ;
    6  ; This program is free software; you can redistribute it and/or modify
    7  ; it under the terms of the GNU General Public License as published by
    8  ; the Free Software Foundation; either version 2 of the License, or
    9  ; (at your option) any later version.
    10  ;
    11  ; This program is distributed in the hope that it will be useful,
    12  ; but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  ; GNU General Public License for more details.
    15  ;
    16  ; You should have received a copy of the GNU General Public License along
    17  ; with this program; if not, write to the Free Software Foundation, Inc.,
    18  ; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    19  ;
    20  W "NO ENTRY FROM TOP",!
    21  Q
    22  ;
    23 EXTRACT(MINXML,DFN,OUTXML)  ; EXTRACT MEDICATIONS INTO PROVIDED XML TEMPLATE
    24  ;
    25  ; MINXML and OUTXML are passed by name so globals can be used
    26  ; MINXML will contain only the medications skeleton of the overall template
    27  ;
    28  ; MEDS is return array from RPC.
    29  ; MAP is a mapping variable map (store result) for each med
    30  ; MED is holds each array element from MEDS(J), one medicine
    31  ; J is a counter.
    32  ;
    33  ; GETRXS^BEHORXFN(ARRAYNAME,DFN,DAYS) will be the the API used.
    34  ; This API has been developed by Medsphere for IHS for getting
    35  ; Medications from RPMS. It has most of what we need.
    36  ; API written by Doug Martin when he worked for Medsphere (thanks Doug!)
    37  ; -- ARRAYNAME is passed by name (required)
    38  ; -- DFN is passed by value (required)
    39  ; -- DAYS is passed by value (optional; if not passed defaults to 365)
    40  ;
    41  ; Return:
    42  ; ~Type^PharmID^Drug^InfRate^StopDt^RefRem^TotDose^UnitDose^OrderID
    43  ; ^Status^LastFill^Chronic^Issued^Rx #^Provider^
    44  ; Status Reason^DEA Handling
    45  ;
    46  N MEDS,MEDS1,MAP
    47  D GETRXS^BEHORXFN("MEDS1",DFN,365) ; Days hard set to 365
    48  ; If MEDS1 is not defined, then no meds
    49  I '$D(MEDS1) S @OUTXML@(0)=0 QUIT
    50  I DEBUG ZWR MEDS1,MINXML
    51  N MEDCNT S MEDCNT=0 ; Med Count
    52  ; The next line is a super line. It goes through the array return
    53  ; and if the first characters are ~OP, it grabs the line.
    54  ; This means that line is for a dispensed Outpatient Med.
    55  ; That line has the metadata about the med that I need.
    56  ; The next lines, however many, are the med and the sig.
    57  ; I won't be using those because I have to get the sig parsed exactly.
    58  N J S J="" F  S J=$O(MEDS1(J)) Q:J=""  I $E(MEDS1(J),1,3)="~OP" S MEDCNT=MEDCNT+1 S MEDS(MEDCNT)=MEDS1(J)
    59  K MEDS1
    60  S MEDMAP=$NA(^TMP("C0CCCR",$J,"MEDMAP")) ; this is the variable map
    61  S @MEDMAP@(0)=0 ; Initial count of meds
    62  S MEDCNT="" ; Initialize for $Order
    63  F  S MEDCNT=$O(MEDS(MEDCNT)) Q:MEDCNT=""  D  ; for each medication in the list
    64  . I DEBUG W "MEDCNT IS ",MEDCNT,!
    65  . S MAP=$NA(^TMP("C0CCCR",$J,"MEDMAP",MEDCNT))
    66  . ; K @MAP DO NOT KILL HERE, WAS CLEARED IN C0CMED
    67  . S @MEDMAP@(0)=@MEDMAP@(0)+1 ; increment total meds in var array
    68  . I DEBUG W "MAP= ",MAP,!
    69  . S @MAP@("MEDOBJECTID")="MED"_MEDCNT ; MEDCNT FOR ID
    70  . S @MAP@("MEDISSUEDATETXT")="Issue Date"
    71  . S @MAP@("MEDISSUEDATE")=$$FMDTOUTC^C0CUTIL($P(MEDS(MEDCNT),U,13))
    72  . S @MAP@("MEDLASTFILLDATETXT")="Last Fill Date"
    73  . S @MAP@("MEDLASTFILLDATE")=$$FMDTOUTC^C0CUTIL($P(MEDS(MEDCNT),U,11))
    74  . S @MAP@("MEDRXNOTXT")="Prescription Number"
    75  . S @MAP@("MEDRXNO")=$P(MEDS(MEDCNT),U,14)
    76  . S @MAP@("MEDTYPETEXT")="Medication"
    77  . S @MAP@("MEDDETAILUNADORNED")=""  ; Leave blank, field has its uses
    78  . S @MAP@("MEDSTATUSTEXT")=$P(MEDS(MEDCNT),U,10)
    79  . ; Provider only provided in API as text, not DUZ.
    80  . ; We need to get DUZ from filman file 52 (Prescription)
    81  . ; Field 4; IEN is Piece 2 of Meds stripped of trailing characters.
    82  . ; Note that I will use RXIEN several times later
    83  . N RXIEN S RXIEN=+$P(MEDS(MEDCNT),U,2)
    84  . S @MAP@("MEDSOURCEACTORID")="ACTORPROVIDER_"_$$GET1^DIQ(52,RXIEN,4,"I")
    85  . S @MAP@("MEDPRODUCTNAMETEXT")=$P(MEDS(MEDCNT),U,3)
    86  . ; --- RxNorm Stuff
    87  . ; 176.001 is the file for Concepts; 176.003 is the file for
    88  . ; sources (i.e. for RxNorm Version)
    89  . ;
    90  . ; I use 176.001 for the Vista version of this routine (files 1-3)
    91  . ; Since IHS does not have VUID's, I will be getting RxNorm codes
    92  . ; using NDCs. My specially crafted index (sounds evil) named "NDC"
    93  . ; is in file 176.002. The file is called RxNorm NDC to VUID.
    94  . ; Except that I don't need the VUID, but it's there if I need it.
    95  . ;
    96  . ; We obviously need the NDC. That is easily obtained from the prescription.
    97  . ; Field 27 in file 52
    98  . N NDC S NDC=$$GET1^DIQ(52,RXIEN,27,"I")
    99  . ; I discovered that file 176.002 might give you two codes for the NDC
    100  . ; One for the Clinical Drug, and one for the ingredient.
    101  . ; So the plan is to get the two RxNorm codes, and then find from
    102  . ; file 176.001 which one is the Clinical Drug.
    103  . ; ... I refactored this into GETRXN
    104  . N RXNORM,SRCIEN,RXNNAME,RXNVER
    105  . I +NDC,$D(^C0CRXN) D  ; $Data is for Systems that don't have our RxNorm file yet.
    106  . . S RXNORM=$$GETRXN(NDC)
    107  . . S SRCIEN=$$FIND1^DIC(176.003,,,"RXNORM","B")
    108  . . S RXNNAME=$$GET1^DIQ(176.003,SRCIEN,6)
    109  . . S RXNVER=$$GET1^DIQ(176.003,SRCIEN,7)
    110  . ;
    111  . E  S (RXNORM,RXNNAME,RXNVER)=""
    112  . ; End if/else block
    113  . S @MAP@("MEDPRODUCTNAMECODEVALUE")=RXNORM
    114  . S @MAP@("MEDPRODUCTNAMECODINGINGSYSTEM")=RXNNAME
    115  . S @MAP@("MEDPRODUCTNAMECODEVERSION")=RXNVER
    116  . ; --- End RxNorm section
    117  . ;
    118  . ; Brand name is 52 field 6.5
    119  . S @MAP@("MEDBRANDNAMETEXT")=$$GET1^DIQ(52,RXIEN,6.5)
    120  . ;
    121  . ; Next I need Med Form (tab, cap etc), strength (250mg)
    122  . ; concentration for liquids (250mg/mL)
    123  . ; Since IHS does not have any of the new calls that
    124  . ; Vista has, I will be doing a crosswalk:
    125  . ; File 52, field 6 is Drug IEN in file 50
    126  . ; File 50, field 22 is VA Product IEN in file 50.68
    127  . ; In file 50.68, I will get the following:
    128  . ; -- 1: Dosage Form
    129  . ; -- 2: Strength
    130  . ; -- 3: Units
    131  . ; -- 8: Dispense Units
    132  . ; -- Conc is 2 concatenated with 3
    133  . ;
    134  . ; *** If Drug is not matched to NDF, then VA Product will be "" ***
    135  . ;
    136  . N MEDIEN S MEDIEN=$$GET1^DIQ(52,RXIEN,6,"I") ; Drug IEN in 50
    137  . N VAPROD S VAPROD=$$GET1^DIQ(50,MEDIEN,22,"I") ; VA Product in file 50.68
    138  . I +VAPROD D
    139  . . S @MAP@("MEDSTRENGTHVALUE")=$$GET1^DIQ(50.68,VAPROD,2)
    140  . . S @MAP@("MEDSTRENGTHUNIT")=$$GET1^DIQ(50.68,VAPROD,3)
    141  . . S @MAP@("MEDFORMTEXT")=$$GET1^DIQ(50.68,VAPROD,1)
    142  . . S @MAP@("MEDCONCVALUE")=@MAP@("MEDSTRENGTHVALUE")
    143  . . S @MAP@("MEDCONCUNIT")=@MAP@("MEDSTRENGTHUNIT")
    144  . E  D
    145  . . S @MAP@("MEDSTRENGTHVALUE")=""
    146  . . S @MAP@("MEDSTRENGTHUNIT")=""
    147  . . S @MAP@("MEDFORMTEXT")=""
    148  . . S @MAP@("MEDCONCVALUE")=""
    149  . . S @MAP@("MEDCONCUNIT")=""
    150  . ; End Strengh/Conc stuff
    151  . ;
    152  . ; Quantity is in the prescription, field 7
    153  . S @MAP@("MEDQUANTITYVALUE")=$$GET1^DIQ(52,RXIEN,7)
    154  . ; Dispense unit is in the drug file, field 14.5
    155  . S @MAP@("MEDQUANTITYUNIT")=$$GET1^DIQ(50,MEDIEN,14.5)
    156  . ;
    157  . ; --- START OF DIRECTIONS ---
    158  . ; Sig data not in any API :-(  Oh yes, you can get the whole thing, but...
    159  . ; we want the components.
    160  . ; It's in multiple 113 in the Prescription File (52)
    161  . ; #.01 DOSAGE ORDERED [1F]                   "20"
    162  . ; #1 DISPENSE UNITS PER DOSE [2N]    "1"
    163  . ; #2 UNITS [3P:50.607]                               "MG"
    164  . ; #3 NOUN [4F]                                               "TABLET"
    165  . ; #4 DURATION [5F]                                   "10D"
    166  . ; #5 CONJUNCTION [6S]                                "AND"
    167  . ; #6 ROUTE [7P:51.2]                                 "ORAL"
    168  . ; #7 SCHEDULE [8F]                                   "BID"
    169  . ; #8 VERB [9F]                                               "TAKE"
    170  . ;
    171  . ; Will use GETS^DIQ to get fields.
    172  . ; Data comes out like this:
    173  . ; SAMINS(52.0113,"1,23,",.01)=20
    174  . ; SAMINS(52.0113,"1,23,",1)=1
    175  . ; SAMINS(52.0113,"1,23,",2)="MG"
    176  . ; SAMINS(52.0113,"1,23,",3)="TABLET"
    177  . ; SAMINS(52.0113,"1,23,",4)="5D"
    178  . ; SAMINS(52.0113,"1,23,",5)="THEN"
    179  . ;
    180  . N RAWDATA
    181  . D GETS^DIQ(52,RXIEN,"113*",,"RAWDATA","DIERR")
    182  . D:$D(DIERR) ^%ZTER  ; Log if there's an error in retrieving sig field
    183  . ; none the less, continue; some parts are retrievable.
    184  . N FMSIG M FMSIG=RAWDATA(52.0113) ; Merge into subfile...
    185  . K RAWDATA
    186  . N FMSIGNUM S FMSIGNUM="" ; Sigline number in fileman.
    187  . ; FMSIGNUM gets outputted as "IEN,RXIEN,".
    188  . ; DIRCNT is the proper Sigline numer.
    189  . ; SIGDATA is the simplfied array.
    190  . F  S FMSIGNUM=$O(FMSIG(FMSIGNUM)) Q:FMSIGNUM=""  D
    191  . . N DIRCNT S DIRCNT=$P(FMSIGNUM,",")
    192  . . N SIGDATA M SIGDATA=FMSIG(FMSIGNUM)
    193  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDIRECTIONDESCRIPTIONTEXT")=""  ; This is reserved for systems not able to generate the sig in components.
    194  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDOSEINDICATOR")="1"  ; means that we are specifying it. See E2369-05.
    195  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDELIVERYMETHOD")=$G(SIGDATA(8))
    196  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDOSEVALUE")=$G(SIGDATA(.01))
    197  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDOSEUNIT")=$G(SIGDATA(2))
    198  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDRATEVALUE")=""  ; For inpatient
    199  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDRATEUNIT")=""  ; For inpatient
    200  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDVEHICLETEXT")=""  ; For inpatient
    201  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDIRECTIONROUTETEXT")=$G(SIGDATA(6))
    202  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDFREQUENCYVALUE")=$G(SIGDATA(7))
    203  . . ; Invervals... again another call.
    204  . . ; In the wisdom of the original programmers, the schedule is a free text field
    205  . . ; However, it gets translated by a call to the administration schedule file
    206  . . ; to see if that schedule exists.
    207  . . ; That's the same thing I am going to do.
    208  . . ; Search B index of 51.1 (Admin Schedule) with schedule
    209  . . ; First, remove "PRN" if it exists (don't ask, that's how the file
    210  . . ; works; I wouldn't do it that way).
    211  . . N SCHNOPRN S SCHNOPRN=$G(SIGDATA(7))
    212  . . I SCHNOPRN["PRN" S SCHNOPRN=$E(SCHNOPRN,1,$F(SCHNOPRN,"PRN")-5)
    213  . . ; Super call below:
    214  . . ; 1=File 51.1 3=Field 2 (Frequency in Minutes)
    215  . . ; 4=Packed format, Exact Match 5=Lookup Value
    216  . . ; 6=# of entries to return 7=Index 10=Return Array
    217  . . ;
    218  . . ; I do not account for the fact that two schedules can be
    219  . . ; spelled identically (ie duplicate entry). In that case,
    220  . . ; I get the first. That's just a bad pharmacy pkg maintainer.
    221  . . N C0C515
    222  . . D FIND^DIC(51.1,,"@;2","PX",SCHNOPRN,1,"B",,,"C0C515")
    223  . . N INTERVAL S INTERVAL="" ; Default
    224  . . ; If there are entries found, get it
    225  . . I +$G(C0C515("DILIST",0)) S INTERVAL=$P(C0C515("DILIST",1,0),U,2)
    226  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDINTERVALVALUE")=INTERVAL
    227  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDINTERVALUNIT")="Minute"
    228  . . ; Duration is 10M minutes, 10H hours, 10D for Days
    229  . . ; 10W for weeks, 10L for months. I smell $Select
    230  . . ; But we don't need to do that if there isn't a duration
    231  . . I +$G(SIGDATA(4)) D
    232  . . . N DURUNIT S DURUNIT=$E(SIGDATA(4),$L(SIGDATA(4))) ; get last char
    233  . . . N DURTXT S DURTXT=$S(DURUNIT="M":"Minutes",DURUNIT="H":"Hours",DURUNIT="D":"Days",DURUNIT="W":"Weeks",DURUNIT="L":"Months",1:"Days")
    234  . . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDURATIONVALUE")=+SIGDATA(4)
    235  . . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDURATIONUNIT")=DURTXT
    236  . . E  D
    237  . . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDURATIONVALUE")=""
    238  . . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDURATIONUNIT")=""
    239  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDPRNFLAG")=$G(SIGDATA(4))["PRN"
    240  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDPROBLEMOBJECTID")="" ; when avail
    241  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDPROBLEMTYPETXT")=""
    242  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDPROBLEMDESCRIPTION")=""
    243  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDPROBLEMCODEVALUE")=""
    244  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDPROBLEMCODINGSYSTEM")=""
    245  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDPROBLEMCODINGVERSION")=""
    246  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDPROBLEMSOURCEACTORID")=""
    247  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDSTOPINDICATOR")="" ; not stored
    248  . . ; Another confusing line; I am pretty bad:
    249  . . ; If there is another entry in the FMSIG array (i.e. another line
    250  . . ; in the sig), set the direction count indicator.
    251  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDIRSEQ")=""  ; Default
    252  . . S:+$O(FMSIG(FMSIGNUM)) @MAP@("M","DIRECTIONS",DIRCNT,"MEDDIRSEQ")=DIRCNT
    253  . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDMULDIRMOD")=$G(SIGDATA(5))
    254  . ;
    255  . ; --- END OF DIRECTIONS ---
    256  . ;
    257  . ; Med instructions is a WP field, thus the acrobatics
    258  . ; Notice buffer overflow protection set at 10,000 chars
    259  . ; -- 1. Med Patient Instructions
    260  . N MEDPTIN1 S MEDPTIN1=$$GET1^DIQ(52,RXIEN,115,,"MEDPTIN1")
    261  . N MEDPTIN2,J  S (MEDPTIN2,J)=""
    262  . I $L(MEDPTIN1) F  S J=$O(@MEDPTIN1@(J)) Q:J=""  Q:$L(MEDPTIN2)>10000  S MEDPTIN2=MEDPTIN2_@MEDPTIN1@(J)_" "
    263  . S @MAP@("MEDPTINSTRUCTIONS")=MEDPTIN2
    264  . K J
    265  . ; -- 2. Med Provider Instructions
    266  . N MEDPVIN1 S MEDPVIN1=$$GET1^DIQ(52,RXIEN,39,,"MEDPVIN1")
    267  . N MEDPVIN2,J S (MEDPVIN2,J)=""
    268  . I $L(MEDPVIN1) F  S J=$O(@MEDPVIN1@(J)) Q:J=""  Q:$L(MEDPVIN2)>10000  S MEDPVIN2=MEDPVIN2_@MEDPVIN1@(J)_" "
    269  . S @MAP@("MEDFULLFILLMENTINSTRUCTIONS")=MEDPVIN2
    270  . ;
    271  . ; Remaining refills
    272  . S @MAP@("MEDRFNO")=$P(MEDS(MEDCNT),U,6)
    273  . ; ------ END OF MAPPING
    274  . ;
    275  . ; ------ BEGIN XML INSERTION
    276  . N RESULT S RESULT=$NA(^TMP("C0CCCR",$J,"MAPPED"))
    277  . K @RESULT
    278  . D MAP^C0CXPATH(MINXML,MAP,RESULT)
    279  . ; D PARY^C0CXPATH(RESULT)
    280  . ; MAPPING DIRECTIONS
    281  . N MEDDIR1,DIRXML1 S DIRXML1="MEDDIR1" ; VARIABLE AND NAME VARIABLE TEMPLATE
    282  . N MEDDIR2,DIRXML2 S DIRXML2="MEDDIR2" ; VARIABLE AND NAME VARIABLE RESULT
    283  . D QUERY^C0CXPATH(MINXML,"//Medications/Medication/Directions",DIRXML1)
    284  . D REPLACE^C0CXPATH(RESULT,"","//Medications/Medication/Directions")
    285  . ; N MDZ1,MDZNA
    286  . N DIRCNT S DIRCNT=""
    287  . I +$O(@MAP@("M","DIRECTIONS",DIRCNT)) D  ; IF THERE ARE DIRCTIONS
    288  . . F DIRCNT=$O(@MAP@("M","DIRECTIONS",DIRCNT)) D  ; FOR EACH DIRECTION
    289  . . . S MDZNA=$NA(@MAP@("M","DIRECTIONS",DIRCNT))
    290  . . . D MAP^C0CXPATH(DIRXML1,MDZNA,DIRXML2)
    291  . . . D INSERT^C0CXPATH(RESULT,DIRXML2,"//Medications/Medication")
    292  . D:MEDCNT=1 CP^C0CXPATH(RESULT,OUTXML) ; First one is a copy
    293  . D:MEDCNT>1 INSINNER^C0CXPATH(OUTXML,RESULT) ; AFTER THE FIRST, INSERT INNER XML
    294  N MEDTMP,MEDI
    295  D MISSING^C0CXPATH(OUTXML,"MEDTMP") ; SEARCH XML FOR MISSING VARS
    296  I MEDTMP(0)>0 D  ; IF THERE ARE MISSING VARS - MARKED AS @@X@@
    297  . W "MEDICATION MISSING ",!
    298  . F MEDI=1:1:MEDTMP(0) W MEDTMP(MEDI),!
    299  Q
    300  ;
    301 GETRXN(NDC) ; Extrinsic Function; PUBLIC; NDC to RxNorm
    302  ;; Get RxNorm Concept Number for a Given NDC
    303  ;
    304  S NDC=$TR(NDC,"-")  ; Remove dashes
    305  N RXNORM,C0CZRXN,DIERR
    306  D FIND^DIC(176.002,,"@;.01","PX",NDC,"*","NDC",,,"C0CZRXN","DIERR")
    307  I $D(DIERR) D ^%ZTER BREAK
    308  S RXNORM(0)=+C0CZRXN("DILIST",0) ; RxNorm(0) will be # of entries
    309  N I S I=0
    310  F  S I=$O(C0CZRXN("DILIST",I)) Q:I=""  S RXNORM(I)=$P(C0CZRXN("DILIST",I,0),U,2)
    311  ; At this point, RxNorm(0) is # of entries; RxNorm(1...) are the entries
    312  ; If RxNorm(0) is 1, then we only have one entry, and that's it.
    313  I RXNORM(0)=1 QUIT RXNORM(1)  ; RETURN RXNORM(1)
    314  ; Otherwise, we need to find out which one is the semantic
    315  ; clinical drug. I built an index on 176.001 (RxNorm Concepts)
    316  ; for that purpose.
    317  I RXNORM(0)>1 D
    318  . S I=0
    319  . F  S I=$O(RXNORM(I)) Q:I=""  D  Q:$G(RXNORM)
    320  . . N RXNIEN S RXNIEN=$$FIND1^DIC(176.001,,,RXNORM(I),"SCD")
    321  . . I +$G(RXNIEN)=0 QUIT  ; try the next entry...
    322  . . E  S RXNORM=RXNORM(I) QUIT  ; We found the right code
    323  QUIT +$G(RXNORM)  ; RETURN RXNORM; if we couldn't find a clnical drug, return with 0
    324  
     1C0CMED6 ; WV/CCDCCR/SMH - Meds from RPMS: Outpatient Meds;01/10/09
     2        ;;0.1;CCDCCR;;JUL 16,2008;
     3        ; Copyright 2008 WorldVistA.  Licensed under the terms of the GNU
     4        ; General Public License See attached copy of the License.
     5        ;
     6        ; This program is free software; you can redistribute it and/or modify
     7        ; it under the terms of the GNU General Public License as published by
     8        ; the Free Software Foundation; either version 2 of the License, or
     9        ; (at your option) any later version.
     10        ;
     11        ; This program is distributed in the hope that it will be useful,
     12        ; but WITHOUT ANY WARRANTY; without even the implied warranty of
     13        ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14        ; GNU General Public License for more details.
     15        ;
     16        ; You should have received a copy of the GNU General Public License along
     17        ; with this program; if not, write to the Free Software Foundation, Inc.,
     18        ; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     19        ;
     20        W "NO ENTRY FROM TOP",!
     21        Q
     22        ;
     23EXTRACT(MINXML,DFN,OUTXML,FLAGS)         ; EXTRACT MEDICATIONS INTO PROVIDED XML TEMPLATE
     24        ;
     25        ; MINXML and OUTXML are passed by name so globals can be used
     26        ; MINXML will contain only the medications skeleton of the overall template
     27        ; FLAGS are: MEDALL(bool)^MEDLIMIT(int)^MEDACTIVE(bool)^MEDPENDING(bool)
     28        ; FLAGS are set-up in C0CMED.
     29        ;
     30        ; MEDS is return array from RPC.
     31        ; MAP is a mapping variable map (store result) for each med
     32        ; MED is holds each array element from MEDS(J), one medicine
     33        ; J is a counter.
     34        ;
     35        ; GETRXS^BEHORXFN(ARRAYNAME,DFN,DAYS) will be the the API used.
     36        ; This API has been developed by Medsphere for IHS for getting
     37        ; Medications from RPMS. It has most of what we need.
     38        ; API written by Doug Martin when he worked for Medsphere (thanks Doug!)
     39        ; -- ARRAYNAME is passed by name (required)
     40        ; -- DFN is passed by value (required)
     41        ; -- DAYS is passed by value (optional; if not passed defaults to 365)
     42        ;
     43        ; Return:
     44        ; ~Type^PharmID^Drug^InfRate^StopDt^RefRem^TotDose^UnitDose^OrderID
     45        ; ^Status^LastFill^Chronic^Issued^Rx #^Provider^
     46        ; Status Reason^DEA Handling
     47        ;
     48        N MEDS,MEDS1,MAP
     49        D GETRXS^BEHORXFN("MEDS1",DFN,$P(FLAGS,U,2)) ; 2nd piece of FLAGS is # of days to retrieve
     50        N ALL S ALL=+FLAGS
     51        N ACTIVE S ACTIVE=$P(FLAGS,U,3)
     52        N PENDING S PENDING=$P(FLAGS,U,4)
     53        ; If MEDS1 is not defined, then no meds
     54        I '$D(MEDS1) S @OUTXML@(0)=0 QUIT
     55        I DEBUG ZWR MEDS1,MINXML
     56        N MEDCNT S MEDCNT=0 ; Med Count
     57        ; The next line is a super line. It goes through the array return
     58        ; and if the first characters are ~OP, it grabs the line.
     59        ; This means that line is for a dispensed Outpatient Med.
     60        ; That line has the metadata about the med that I need.
     61        ; The next lines, however many, are the med and the sig.
     62        ; I won't be using those because I have to get the sig parsed exactly.
     63        N J S J="" F  S J=$O(MEDS1(J)) Q:J=""  I $E(MEDS1(J),1,3)="~OP" S MEDCNT=MEDCNT+1 S MEDS(MEDCNT)=MEDS1(J)
     64        K MEDS1
     65        S MEDCNT="" ; Initialize for $Order
     66        F  S MEDCNT=$O(MEDS(MEDCNT)) Q:MEDCNT=""  D  ; for each medication in the list
     67        . I 'ALL,ACTIVE,$P(MEDS(MEDCNT),U,10)'="ACTIVE" QUIT
     68        . I 'ALL,PENDING,$P(MEDS(MEDCNT),U,10)'="PENDING" QUIT
     69        . I DEBUG W "MEDCNT IS ",MEDCNT,!
     70        . S MAP=$NA(^TMP("C0CCCR",$J,"MEDMAP",MEDCNT))
     71        . ; K @MAP DO NOT KILL HERE, WAS CLEARED IN C0CMED
     72        . I DEBUG W "MAP= ",MAP,!
     73        . S @MAP@("MEDOBJECTID")="MED"_MEDCNT ; MEDCNT FOR ID
     74        . S @MAP@("MEDISSUEDATETXT")="Issue Date"
     75        . S @MAP@("MEDISSUEDATE")=$$FMDTOUTC^C0CUTIL($P(MEDS(MEDCNT),U,13))
     76        . S @MAP@("MEDLASTFILLDATETXT")="Last Fill Date"
     77        . S @MAP@("MEDLASTFILLDATE")=$$FMDTOUTC^C0CUTIL($P(MEDS(MEDCNT),U,11))
     78        . S @MAP@("MEDRXNOTXT")="Prescription Number"
     79        . S @MAP@("MEDRXNO")=$P(MEDS(MEDCNT),U,14)
     80        . S @MAP@("MEDTYPETEXT")="Medication"
     81        . S @MAP@("MEDDETAILUNADORNED")=""  ; Leave blank, field has its uses
     82        . S @MAP@("MEDSTATUSTEXT")=$P(MEDS(MEDCNT),U,10)
     83        . ; Provider only provided in API as text, not DUZ.
     84        . ; We need to get DUZ from filman file 52 (Prescription)
     85        . ; Field 4; IEN is Piece 2 of Meds stripped of trailing characters.
     86        . ; Note that I will use RXIEN several times later
     87        . N RXIEN S RXIEN=+$P(MEDS(MEDCNT),U,2)
     88        . S @MAP@("MEDSOURCEACTORID")="ACTORPROVIDER_"_$$GET1^DIQ(52,RXIEN,4,"I")
     89        . S @MAP@("MEDPRODUCTNAMETEXT")=$P(MEDS(MEDCNT),U,3)
     90        . ; --- RxNorm Stuff
     91        . ; 176.001 is the file for Concepts; 176.003 is the file for
     92        . ; sources (i.e. for RxNorm Version)
     93        . ;
     94        . ; I use 176.001 for the Vista version of this routine (files 1-3)
     95        . ; Since IHS does not have VUID's, I will be getting RxNorm codes
     96        . ; using NDCs. My specially crafted index (sounds evil) named "NDC"
     97        . ; is in file 176.002. The file is called RxNorm NDC to VUID.
     98        . ; Except that I don't need the VUID, but it's there if I need it.
     99        . ;
     100        . ; We obviously need the NDC. That is easily obtained from the prescription.
     101        . ; Field 27 in file 52
     102        . N NDC S NDC=$$GET1^DIQ(52,RXIEN,27,"I")
     103        . ; I discovered that file 176.002 might give you two codes for the NDC
     104        . ; One for the Clinical Drug, and one for the ingredient.
     105        . ; So the plan is to get the two RxNorm codes, and then find from
     106        . ; file 176.001 which one is the Clinical Drug.
     107        . ; ... I refactored this into GETRXN
     108        . N RXNORM,SRCIEN,RXNNAME,RXNVER
     109        . I +NDC,$D(^C0CRXN) D  ; $Data is for Systems that don't have our RxNorm file yet.
     110        . . S RXNORM=$$GETRXN(NDC)
     111        . . S SRCIEN=$$FIND1^DIC(176.003,,,"RXNORM","B")
     112        . . S RXNNAME=$$GET1^DIQ(176.003,SRCIEN,6)
     113        . . S RXNVER=$$GET1^DIQ(176.003,SRCIEN,7)
     114        . ;
     115        . E  S (RXNORM,RXNNAME,RXNVER)=""
     116        . ; End if/else block
     117        . S @MAP@("MEDPRODUCTNAMECODEVALUE")=RXNORM
     118        . S @MAP@("MEDPRODUCTNAMECODINGINGSYSTEM")=RXNNAME
     119        . S @MAP@("MEDPRODUCTNAMECODEVERSION")=RXNVER
     120        . ; --- End RxNorm section
     121        . ;
     122        . ; Brand name is 52 field 6.5
     123        . S @MAP@("MEDBRANDNAMETEXT")=$$GET1^DIQ(52,RXIEN,6.5)
     124        . ;
     125        . ; Next I need Med Form (tab, cap etc), strength (250mg)
     126        . ; concentration for liquids (250mg/mL)
     127        . ; Since IHS does not have any of the new calls that
     128        . ; Vista has, I will be doing a crosswalk:
     129        . ; File 52, field 6 is Drug IEN in file 50
     130        . ; File 50, field 22 is VA Product IEN in file 50.68
     131        . ; In file 50.68, I will get the following:
     132        . ; -- 1: Dosage Form
     133        . ; -- 2: Strength
     134        . ; -- 3: Units
     135        . ; -- 8: Dispense Units
     136        . ; -- Conc is 2 concatenated with 3
     137        . ;
     138        . ; *** If Drug is not matched to NDF, then VA Product will be "" ***
     139        . ;
     140        . N MEDIEN S MEDIEN=$$GET1^DIQ(52,RXIEN,6,"I") ; Drug IEN in 50
     141        . N VAPROD S VAPROD=$$GET1^DIQ(50,MEDIEN,22,"I") ; VA Product in file 50.68
     142        . I +VAPROD D
     143        . . S @MAP@("MEDSTRENGTHVALUE")=$$GET1^DIQ(50.68,VAPROD,2)
     144        . . S @MAP@("MEDSTRENGTHUNIT")=$$GET1^DIQ(50.68,VAPROD,3)
     145        . . S @MAP@("MEDFORMTEXT")=$$GET1^DIQ(50.68,VAPROD,1)
     146        . . S @MAP@("MEDCONCVALUE")=@MAP@("MEDSTRENGTHVALUE")
     147        . . S @MAP@("MEDCONCUNIT")=@MAP@("MEDSTRENGTHUNIT")
     148        . E  D
     149        . . S @MAP@("MEDSTRENGTHVALUE")=""
     150        . . S @MAP@("MEDSTRENGTHUNIT")=""
     151        . . S @MAP@("MEDFORMTEXT")=""
     152        . . S @MAP@("MEDCONCVALUE")=""
     153        . . S @MAP@("MEDCONCUNIT")=""
     154        . ; End Strengh/Conc stuff
     155        . ;
     156        . ; Quantity is in the prescription, field 7
     157        . S @MAP@("MEDQUANTITYVALUE")=$$GET1^DIQ(52,RXIEN,7)
     158        . ; Dispense unit is in the drug file, field 14.5
     159        . S @MAP@("MEDQUANTITYUNIT")=$$GET1^DIQ(50,MEDIEN,14.5)
     160        . ;
     161        . ; --- START OF DIRECTIONS ---
     162        . ; Sig data not in any API :-(  Oh yes, you can get the whole thing, but...
     163        . ; we want the components.
     164        . ; It's in multiple 113 in the Prescription File (52)
     165        . ; #.01 DOSAGE ORDERED [1F]                    "20"
     166        . ; #1 DISPENSE UNITS PER DOSE [2N]     "1"
     167        . ; #2 UNITS [3P:50.607]                                "MG"
     168        . ; #3 NOUN [4F]                                                "TABLET"
     169        . ; #4 DURATION [5F]                                    "10D"
     170        . ; #5 CONJUNCTION [6S]                                 "AND"
     171        . ; #6 ROUTE [7P:51.2]                          "ORAL"
     172        . ; #7 SCHEDULE [8F]                                    "BID"
     173        . ; #8 VERB [9F]                                                "TAKE"
     174        . ;
     175        . ; Will use GETS^DIQ to get fields.
     176        . ; Data comes out like this:
     177        . ; SAMINS(52.0113,"1,23,",.01)=20
     178        . ; SAMINS(52.0113,"1,23,",1)=1
     179        . ; SAMINS(52.0113,"1,23,",2)="MG"
     180        . ; SAMINS(52.0113,"1,23,",3)="TABLET"
     181        . ; SAMINS(52.0113,"1,23,",4)="5D"
     182        . ; SAMINS(52.0113,"1,23,",5)="THEN"
     183        . ;
     184        . N RAWDATA
     185        . D GETS^DIQ(52,RXIEN,"113*",,"RAWDATA","DIERR")
     186        . D:$D(DIERR) ^%ZTER  ; Log if there's an error in retrieving sig field
     187        . ; none the less, continue; some parts are retrievable.
     188        . N FMSIG M FMSIG=RAWDATA(52.0113) ; Merge into subfile...
     189        . K RAWDATA
     190        . N FMSIGNUM S FMSIGNUM="" ; Sigline number in fileman.
     191        . ; FMSIGNUM gets outputted as "IEN,RXIEN,".
     192        . ; DIRCNT is the proper Sigline numer.
     193        . ; SIGDATA is the simplfied array.
     194        . F  S FMSIGNUM=$O(FMSIG(FMSIGNUM)) Q:FMSIGNUM=""  D
     195        . . N DIRCNT S DIRCNT=$P(FMSIGNUM,",")
     196        . . N SIGDATA M SIGDATA=FMSIG(FMSIGNUM)
     197        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDIRECTIONDESCRIPTIONTEXT")=""  ; This is reserved for systems not able to generate the sig in components.
     198        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDOSEINDICATOR")="1"  ; means that we are specifying it. See E2369-05.
     199        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDELIVERYMETHOD")=$G(SIGDATA(8))
     200        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDOSEVALUE")=$G(SIGDATA(.01))
     201        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDOSEUNIT")=$G(SIGDATA(2))
     202        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDRATEVALUE")=""  ; For inpatient
     203        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDRATEUNIT")=""  ; For inpatient
     204        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDVEHICLETEXT")=""  ; For inpatient
     205        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDIRECTIONROUTETEXT")=$G(SIGDATA(6))
     206        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDFREQUENCYVALUE")=$G(SIGDATA(7))
     207        . . ; Invervals... again another call.
     208        . . ; In the wisdom of the original programmers, the schedule is a free text field
     209        . . ; However, it gets translated by a call to the administration schedule file
     210        . . ; to see if that schedule exists.
     211        . . ; That's the same thing I am going to do.
     212        . . ; Search B index of 51.1 (Admin Schedule) with schedule
     213        . . ; First, remove "PRN" if it exists (don't ask, that's how the file
     214        . . ; works; I wouldn't do it that way).
     215        . . N SCHNOPRN S SCHNOPRN=$G(SIGDATA(7))
     216        . . I SCHNOPRN["PRN" S SCHNOPRN=$E(SCHNOPRN,1,$F(SCHNOPRN,"PRN")-5)
     217        . . ; Super call below:
     218        . . ; 1=File 51.1 3=Field 2 (Frequency in Minutes)
     219        . . ; 4=Packed format, Exact Match 5=Lookup Value
     220        . . ; 6=# of entries to return 7=Index 10=Return Array
     221        . . ;
     222        . . ; I do not account for the fact that two schedules can be
     223        . . ; spelled identically (ie duplicate entry). In that case,
     224        . . ; I get the first. That's just a bad pharmacy pkg maintainer.
     225        . . N C0C515
     226        . . D FIND^DIC(51.1,,"@;2","PX",SCHNOPRN,1,"B",,,"C0C515")
     227        . . N INTERVAL S INTERVAL="" ; Default
     228        . . ; If there are entries found, get it
     229        . . I +$G(C0C515("DILIST",0)) S INTERVAL=$P(C0C515("DILIST",1,0),U,2)
     230        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDINTERVALVALUE")=INTERVAL
     231        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDINTERVALUNIT")="Minute"
     232        . . ; Duration is 10M minutes, 10H hours, 10D for Days
     233        . . ; 10W for weeks, 10L for months. I smell $Select
     234        . . ; But we don't need to do that if there isn't a duration
     235        . . I +$G(SIGDATA(4)) D
     236        . . . N DURUNIT S DURUNIT=$E(SIGDATA(4),$L(SIGDATA(4))) ; get last char
     237        . . . N DURTXT S DURTXT=$S(DURUNIT="M":"Minutes",DURUNIT="H":"Hours",DURUNIT="D":"Days",DURUNIT="W":"Weeks",DURUNIT="L":"Months",1:"Days")
     238        . . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDURATIONVALUE")=+SIGDATA(4)
     239        . . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDURATIONUNIT")=DURTXT
     240        . . E  D
     241        . . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDURATIONVALUE")=""
     242        . . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDURATIONUNIT")=""
     243        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDPRNFLAG")=$G(SIGDATA(4))["PRN"
     244        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDPROBLEMOBJECTID")="" ; when avail
     245        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDPROBLEMTYPETXT")=""
     246        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDPROBLEMDESCRIPTION")=""
     247        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDPROBLEMCODEVALUE")=""
     248        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDPROBLEMCODINGSYSTEM")=""
     249        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDPROBLEMCODINGVERSION")=""
     250        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDPROBLEMSOURCEACTORID")=""
     251        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDSTOPINDICATOR")="" ; not stored
     252        . . ; Another confusing line; I am pretty bad:
     253        . . ; If there is another entry in the FMSIG array (i.e. another line
     254        . . ; in the sig), set the direction count indicator.
     255        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDDIRSEQ")=""  ; Default
     256        . . S:+$O(FMSIG(FMSIGNUM)) @MAP@("M","DIRECTIONS",DIRCNT,"MEDDIRSEQ")=DIRCNT
     257        . . S @MAP@("M","DIRECTIONS",DIRCNT,"MEDMULDIRMOD")=$G(SIGDATA(5))
     258        . ;
     259        . ; --- END OF DIRECTIONS ---
     260        . ;
     261        . ; Med instructions is a WP field, thus the acrobatics
     262        . ; Notice buffer overflow protection set at 10,000 chars
     263        . ; -- 1. Med Patient Instructions
     264        . N MEDPTIN1 S MEDPTIN1=$$GET1^DIQ(52,RXIEN,115,,"MEDPTIN1")
     265        . N MEDPTIN2,J  S (MEDPTIN2,J)=""
     266        . I $L(MEDPTIN1) F  S J=$O(@MEDPTIN1@(J)) Q:J=""  Q:$L(MEDPTIN2)>10000  S MEDPTIN2=MEDPTIN2_@MEDPTIN1@(J)_" "
     267        . S @MAP@("MEDPTINSTRUCTIONS")=MEDPTIN2
     268        . K J
     269        . ; -- 2. Med Provider Instructions
     270        . N MEDPVIN1 S MEDPVIN1=$$GET1^DIQ(52,RXIEN,39,,"MEDPVIN1")
     271        . N MEDPVIN2,J S (MEDPVIN2,J)=""
     272        . I $L(MEDPVIN1) F  S J=$O(@MEDPVIN1@(J)) Q:J=""  Q:$L(MEDPVIN2)>10000  S MEDPVIN2=MEDPVIN2_@MEDPVIN1@(J)_" "
     273        . S @MAP@("MEDFULLFILLMENTINSTRUCTIONS")=MEDPVIN2
     274        . ;
     275        . ; Remaining refills
     276        . S @MAP@("MEDRFNO")=$P(MEDS(MEDCNT),U,6)
     277        . ; ------ END OF MAPPING
     278        . ;
     279        . ; ------ BEGIN XML INSERTION
     280        . N RESULT S RESULT=$NA(^TMP("C0CCCR",$J,"MAPPED"))
     281        . K @RESULT
     282        . D MAP^C0CXPATH(MINXML,MAP,RESULT)
     283        . ; D PARY^C0CXPATH(RESULT)
     284        . ; MAPPING DIRECTIONS
     285        . N MEDDIR1,DIRXML1 S DIRXML1="MEDDIR1" ; VARIABLE AND NAME VARIABLE TEMPLATE
     286        . N MEDDIR2,DIRXML2 S DIRXML2="MEDDIR2" ; VARIABLE AND NAME VARIABLE RESULT
     287        . D QUERY^C0CXPATH(MINXML,"//Medications/Medication/Directions",DIRXML1)
     288        . D REPLACE^C0CXPATH(RESULT,"","//Medications/Medication/Directions")
     289        . ; N MDZ1,MDZNA
     290        . N DIRCNT S DIRCNT=""
     291        . I +$O(@MAP@("M","DIRECTIONS",DIRCNT)) D  ; IF THERE ARE DIRCTIONS
     292        . . F DIRCNT=$O(@MAP@("M","DIRECTIONS",DIRCNT)) D  ; FOR EACH DIRECTION
     293        . . . S MDZNA=$NA(@MAP@("M","DIRECTIONS",DIRCNT))
     294        . . . D MAP^C0CXPATH(DIRXML1,MDZNA,DIRXML2)
     295        . . . D INSERT^C0CXPATH(RESULT,DIRXML2,"//Medications/Medication")
     296        . D:MEDCNT=1 CP^C0CXPATH(RESULT,OUTXML) ; First one is a copy
     297        . D:MEDCNT>1 INSINNER^C0CXPATH(OUTXML,RESULT) ; AFTER THE FIRST, INSERT INNER XML
     298        N MEDTMP,MEDI
     299        D MISSING^C0CXPATH(OUTXML,"MEDTMP") ; SEARCH XML FOR MISSING VARS
     300        I MEDTMP(0)>0 D  ; IF THERE ARE MISSING VARS - MARKED AS @@X@@
     301        . W "MEDICATION MISSING ",!
     302        . F MEDI=1:1:MEDTMP(0) W MEDTMP(MEDI),!
     303        Q
     304        ;
     305GETRXN(NDC)     ; Extrinsic Function; PUBLIC; NDC to RxNorm
     306        ;; Get RxNorm Concept Number for a Given NDC
     307        ;
     308        S NDC=$TR(NDC,"-")  ; Remove dashes
     309        N RXNORM,C0CZRXN,DIERR
     310        D FIND^DIC(176.002,,"@;.01","PX",NDC,"*","NDC",,,"C0CZRXN","DIERR")
     311        I $D(DIERR) D ^%ZTER BREAK
     312        S RXNORM(0)=+C0CZRXN("DILIST",0) ; RxNorm(0) will be # of entries
     313        N I S I=0
     314        F  S I=$O(C0CZRXN("DILIST",I)) Q:I=""  S RXNORM(I)=$P(C0CZRXN("DILIST",I,0),U,2)
     315        ; At this point, RxNorm(0) is # of entries; RxNorm(1...) are the entries
     316        ; If RxNorm(0) is 1, then we only have one entry, and that's it.
     317        I RXNORM(0)=1 QUIT RXNORM(1)  ; RETURN RXNORM(1)
     318        ; Otherwise, we need to find out which one is the semantic
     319        ; clinical drug. I built an index on 176.001 (RxNorm Concepts)
     320        ; for that purpose.
     321        I RXNORM(0)>1 D
     322        . S I=0
     323        . F  S I=$O(RXNORM(I)) Q:I=""  D  Q:$G(RXNORM)
     324        . . N RXNIEN S RXNIEN=$$FIND1^DIC(176.001,,,RXNORM(I),"SCD")
     325        . . I +$G(RXNIEN)=0 QUIT  ; try the next entry...
     326        . . E  S RXNORM=RXNORM(I) QUIT  ; We found the right code
     327        QUIT +$G(RXNORM)  ; RETURN RXNORM; if we couldn't find a clnical drug, return with 0
     328       
  • ccr/trunk/p/C0CPARMS.m

    r395 r422  
    1 GPLPARMS ; CCDCCR/GPL - CCR/CCD PARAMETER PROCESSING ; 1/29/09
    2  ;;0.3;CCDCCR;nopatch;noreleasedate
    3  ;Copyright 2008 WorldVistA.  Licensed under the terms of the GNU
    4  ;General Public License See attached copy of the License.
    5  ;
    6  ;This program is free software; you can redistribute it and/or modify
    7  ;it under the terms of the GNU General Public License as published by
    8  ;the Free Software Foundation; either version 2 of the License, or
    9  ;(at your option) any later version.
    10  ;
    11  ;This program is distributed in the hope that it will be useful,
    12  ;but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  ;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  ;GNU General Public License for more details.
    15  ;
    16  ;You should have received a copy of the GNU General Public License along
    17  ;with this program; if not, write to the Free Software Foundation, Inc.,
    18  ;51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    19  ;
    20 SET(INPARMS) ;INITIALIZE RUNTIME PARMS USING INPARMS TO OVERRIDE DEFAULTS
    21  ; PARAMETERS ARE PASSED AS A STRING: "PARM1:VALUE1^PARM2:VALUE2^ETC"
    22  ; THE SAME FORMAT IS USED BY RPC AND COMMAND LINE ENTRY POINTS
    23  ;
    24  N PTMP ;
    25  S C0CPARMS=$NA(^TMP("C0CPARMS",$J)) ;BASE FOR THIS RUN
    26  ;K @C0CPARMS ;START WITH EMPTY PARMS; MAY NOT WANT TO DO THIS KILL
    27  I $G(INPARMS)'="" D  ; OVERRIDES PROVIDED
    28  . N C0CI S C0CI=""
    29  . N C0CN S C0CN=1
    30  . F  S C0CI=$P(INPARMS,"^",C0CN) Q:C0CI=""  D  ;
    31  . . S C0CN=C0CN+1 ;NEXT PARM
    32  . . N C1,C2
    33  . . S C1=$P(C0CI,":",1) ; PARAMETER
    34  . . S C2=$P(C0CI,":",2) ; VALUE
    35  . . I C2="" S C2=1
    36  . . S @C0CPARMS@(C1)=C2
    37  . I C0CN=1 S @C0CPARMS@($P(INPARMS,":",1))=$P(C0CI,":",2) ; ONLY ONE
    38  ; THIS IS WHERE WE WILL INSERT CALLS TO THE PARAMETER FILE FOR DEFAULTS
    39  ; IF THEY FAIL, THE FOLLOWING WILL BE HARDCODED DEFAULTS
    40  I '$D(@C0CPARMS@("LABLIMIT")) S @C0CPARMS@("LABLIMIT")="T-360" ;ONE YR WORTH
    41  I '$D(@C0CPARMS@("LABSTART")) S @C0CPARMS@("LABSTART")="T" ;TODAY
    42  I '$D(@C0CPARMS@("VITLIMIT")) S @C0CPARMS@("VITLIMIT")="T-360" ;ONE YR VITALS
    43  I '$D(@C0CPARMS@("VITSTART")) S @C0CPARMS@("VITSTART")="T" ;TODAY
    44  I '$D(@C0CPARMS@("MEDSTART")) S @C0CPARMS@("MEDSTART")="T" ; TODAY
    45  I '$D(@C0CPARMS@("MEDSLIMIT")) S @C0CPARMS@("MEDLIMIT")="T-360" ; ONE YR MEDS
    46  I '$D(@C0CPARMS@("MEDACTIVE")) S @C0CPARMS@("MEDACTIVE")=1 ; YES
    47  I '$D(@C0CPARMS@("MEDPENDING")) S @C0CPARMS@("MEDPENDING")=0 ; NO
    48  I '$D(@C0CPARMS@("MEDALL")) S @C0CPARMS@("MEDALL")=0 ; NON-PENDING NON-ACTIVE
    49  Q
    50  ;
    51 CHECK ; CHECK TO SEE IF PARMS ARE PRESENT, ELSE RUN SET
    52  ;
    53  I '$D(C0CPARMS) S C0CPARMS=$NA(^TMP("C0CPARMS",$J)) ;SHOULDN'T HAPPEN
    54  I '$D(@C0CPARMS) D SET("SETWITHCHECK:1")
    55  Q
    56  ;
    57 GET(WHICHP) ;EXTRINSIC TO RETURN THE VALUE OF PARAMETER WHICHP
    58  ;
    59  D CHECK ; SHOULDN'T HAPPEN BUT TO BE SAFE
    60  N GTMP
    61  Q $G(@C0CPARMS@(WHICHP)) ;PULL THE PARM FROM THE TABLE
    62  ;
     1C0CPARMS        ; CCDCCR/GPL - CCR/CCD PARAMETER PROCESSING ; 1/29/09
     2        ;;0.3;CCDCCR;nopatch;noreleasedate
     3        ;Copyright 2008 WorldVistA.  Licensed under the terms of the GNU
     4        ;General Public License See attached copy of the License.
     5        ;
     6        ;This program is free software; you can redistribute it and/or modify
     7        ;it under the terms of the GNU General Public License as published by
     8        ;the Free Software Foundation; either version 2 of the License, or
     9        ;(at your option) any later version.
     10        ;
     11        ;This program is distributed in the hope that it will be useful,
     12        ;but WITHOUT ANY WARRANTY; without even the implied warranty of
     13        ;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14        ;GNU General Public License for more details.
     15        ;
     16        ;You should have received a copy of the GNU General Public License along
     17        ;with this program; if not, write to the Free Software Foundation, Inc.,
     18        ;51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     19        ;
     20SET(INPARMS)    ;INITIALIZE RUNTIME PARMS USING INPARMS TO OVERRIDE DEFAULTS
     21        ; PARAMETERS ARE PASSED AS A STRING: "PARM1:VALUE1^PARM2:VALUE2^ETC"
     22        ; THE SAME FORMAT IS USED BY RPC AND COMMAND LINE ENTRY POINTS
     23        ;
     24        N PTMP ;
     25        S C0CPARMS=$NA(^TMP("C0CPARMS",$J)) ;BASE FOR THIS RUN
     26        ;K @C0CPARMS ;START WITH EMPTY PARMS; MAY NOT WANT TO DO THIS KILL
     27        I $G(INPARMS)'="" D  ; OVERRIDES PROVIDED
     28        . N C0CI S C0CI=""
     29        . N C0CN S C0CN=1
     30        . F  S C0CI=$P(INPARMS,"^",C0CN) Q:C0CI=""  D  ;
     31        . . S C0CN=C0CN+1 ;NEXT PARM
     32        . . N C1,C2
     33        . . S C1=$P(C0CI,":",1) ; PARAMETER
     34        . . S C2=$P(C0CI,":",2) ; VALUE
     35        . . I C2="" S C2=1
     36        . . S @C0CPARMS@(C1)=C2
     37        . I C0CN=1 S @C0CPARMS@($P(INPARMS,":",1))=$P(C0CI,":",2) ; ONLY ONE
     38        ; THIS IS WHERE WE WILL INSERT CALLS TO THE PARAMETER FILE FOR DEFAULTS
     39        ; IF THEY FAIL, THE FOLLOWING WILL BE HARDCODED DEFAULTS
     40        I '$D(@C0CPARMS@("LABLIMIT")) S @C0CPARMS@("LABLIMIT")="T-360" ;ONE YR WORTH
     41        I '$D(@C0CPARMS@("LABSTART")) S @C0CPARMS@("LABSTART")="T" ;TODAY
     42        I '$D(@C0CPARMS@("VITLIMIT")) S @C0CPARMS@("VITLIMIT")="T-360" ;ONE YR VITALS
     43        I '$D(@C0CPARMS@("VITSTART")) S @C0CPARMS@("VITSTART")="T" ;TODAY
     44        I '$D(@C0CPARMS@("MEDSTART")) S @C0CPARMS@("MEDSTART")="T" ; TODAY
     45        I '$D(@C0CPARMS@("MEDSLIMIT")) S @C0CPARMS@("MEDLIMIT")="T-360" ; ONE YR MEDS
     46        I '$D(@C0CPARMS@("MEDACTIVE")) S @C0CPARMS@("MEDACTIVE")=1 ; YES
     47        I '$D(@C0CPARMS@("MEDPENDING")) S @C0CPARMS@("MEDPENDING")=0 ; NO
     48        I '$D(@C0CPARMS@("MEDALL")) S @C0CPARMS@("MEDALL")=0 ; NON-PENDING NON-ACTIVE
     49        Q
     50        ;
     51CHECK   ; CHECK TO SEE IF PARMS ARE PRESENT, ELSE RUN SET
     52        ;
     53        I '$D(C0CPARMS) S C0CPARMS=$NA(^TMP("C0CPARMS",$J)) ;SHOULDN'T HAPPEN
     54        I '$D(@C0CPARMS) D SET("SETWITHCHECK:1")
     55        Q
     56        ;
     57GET(WHICHP)     ;EXTRINSIC TO RETURN THE VALUE OF PARAMETER WHICHP
     58        ;
     59        D CHECK ; SHOULDN'T HAPPEN BUT TO BE SAFE
     60        N GTMP
     61        Q $G(@C0CPARMS@(WHICHP)) ;PULL THE PARM FROM THE TABLE
     62        ;
Note: See TracChangeset for help on using the changeset viewer.