ACPT28PE ;IHS/VEN/TOAD - ACPT*2.08*1 postinit step 6 ; 04/20/2008 23:32
;;2.08;CPT FILES;**1**;DEC 17, 2007
;
; This subroutine of the post-init for ACPT*2.08*1 activates the 2008
; HCPCS codes and deactivates the deleted ones. See routine ACPT28PA
; for the complete algorithm and overview, and LOADCODE^ACPT28PC for
; the data import and the set up of the flags that drive ACTIV8 and
; INACTIV8.
;
QUIT ; This routine should not be called at the top or anywhere
; else. It is only to be called at STEP6 by ACPT28PA as part of the
; post-init for ACPT*2.08*1.
;
; 2007 01 Shonda Render (IHS) edited to set the status flag with a new
; call to DIE, replacing the prior setting of DIC("DR") input to the
; DIC calls.
;
; 2008 03 Rick Marshall (VEN/CNI/IHS) commented the routine top to
; bottom while tracking down a bug: the status flag was found during
; verification of ACPT*2.08*1 to be set inconsistently, suggesting
; fragility in the algorithm. I also took the opportunity to tighten up
; variable scoping to help make the code a bit more robust. I also got
; rid of the calls to DOTS^ACPTPOST as unnecessary calls for such
; simple code, half of which (U IO(0)) we should only do once at the top
; not for every CPT code we traverse. I fixed a bug in which the dots
; not printing out nearly as often as the original designer expected. I
; also eliminated all code not related to HCPCS codes specifically.
;
; 2008 04 17-20 Rick Marshall renamed this routine from ACPTSINF to
; ACPT28PE to make its relationship to the other post-init routines
; clearer and to follow the standard for naming poast-inits. I also
; redid many of the comments, introduced a label for ACPT28PA to call,
; and otherwise brought it in line with the other ACPT28P* routines. I
; also radically simplify ACTIV8's logic in synch with the overhaul of
; LOADCODE^ACPT28PC that did likewise; a lesser simplification was also
; done on INACTIV8's logic.
;
; The original routine ACPTSINF was the work of IHS/ASDST/DMJ and
; Shonda Render (SDR).
;
; Called only by routine ACPT28PA as part of the post-init that imports
; and installs the CPT data from the text files. This subroutine
; traverses the CPT file (81) and corrects the Inactive Flag; new codes
; have their Date Added set to a real date; deleted codes have their
; Date Deleted set to a real date and a corresponding Effective Date's
; Status set to INACTIVE.
;
; The reason none of this is done up front in ACPT28PC is because this
; might be a test site installing prior to the codes' activation (&
; deactivation) dates; for example, a test site might be installing the
; patch for the 2008 codes in December, 2007, so we do not want to
; activate them yet. Instead, ACPT28PC imports the codes but does not
; activate them; it flags them for later activation and queues STEP6 as
; a task to run Jan 1, 2008 at 6:00 a.m., at which point STEP6 will
; activate the new codes and deactivate any HCPCS codes that exist but
; were not included in the 2008 codeset. STEP6 has to be able to handle
; both this test-site situation, in which it runs as a task long after
; the post-init, and a non-test-site situation, in which it is called
; during the post-init and runs immediately.
;
; This subroutine's main inputs and outputs are the HCPCS entries in the
; CPT file itself.
;
;
STEP6 ; post-init step 6: activate 2008 HCPCS codes, deactivate deleted ones
;
; private: called only by step 6 of routine ACPT28PC
;
; input: ACPTYR = 3080000, to use as the flag value for the Date Deleted
; field.
;
; loop: traverse the entries for HCPCS codes in the CPT file (81)).
; For each, activate if new, inactivate if deleted.
;
D
. N ACPTDA S ACPTDA=99999 ; CPT file entry #, from just before HCPCS
. N ACPTDOTS ; count, so that a dot is printed every 100 codes
. F ACPTDOTS=1:1 S ACPTDA=$O(^ICPT(ACPTDA)) Q:'ACPTDA!(ACPTDA>999999) D
. . D ACTIV8(ACPTDA,ACPTYR) ; activate 2008 HCPCS codes
. . D DEACTIV8(ACPTDA,ACPTYR) ; deact codes not in 2008 HCPCS codeset
. . Q:$D(ZTQUEUED) ; if this has been queued, skip the dots
. . W:'(ACPTDOTS#100) "." ; otherwise, write a dot for every 100 codes
;
QUIT ; end of STEP6
;
;
ACTIV8(ACPTDA,ACPTYR) ; activate 2008 HCPCS codes
;
; private: called only by STEP6 above
;
; called only by the main procedure above; only ACPTDA passed in (by
; value), though the major input is the corresponding CPT record;
; likewise the output is to the record: the Inactive Flag field (5) of
; the CPT record, the creation if missing of a new Effective Date
; subfile (60/81.02) record, and the Status field (.02) of that
; subrecord. The Status Field is a set of codes: 0 = INACTIVE,
; 1 = ACTIVE.
;
; This code no longer worries about the Effective Date subfile, which
; has been completely handled by the overhauled LOADCODE^ACPT28PC. It
; only has to clear the Inactive Flag and set the Date Added to a real
; date.
;
; Likewise, the logic deciding which entries to activate has been
; simplified. It is only looking for inactive entries with a Date Added
; set to 3080000. We no longer worry about checking for whether we are
; running too soon; we leave that protection up to ACPT28PA to decide
; when and how we are called.
;
N ACPTNODE S ACPTNODE=$G(^ICPT(ACPTDA,0)) ; get CPT's header node
Q:ACPTNODE="" ; skip bad records with no header
;
N ACPTADD S ACPTADD=$P(ACPTNODE,U,6) ; CPT's Date Added (7)
Q:ACPTADD'=ACPTYR ; if new, Date Added = 3080000 from LOADCODE^ACPT28PC
;
N ACPTINAC S ACPTINAC=$P(ACPTNODE,U,4) ; CPT's Inactive Flag (5)
Q:'ACPTINAC ; new codes also have this flag set to INACTIVE (1)
;
S $P(ACPTNODE,U,4)="" ; clear the Inactive Flag
S $P(ACPTNODE,U,6)=3080101 ; set Date Added to a real date
;
S ^ICPT(ACPTDA,0)=ACPTNODE ; copy results back to CPT's header node
;
QUIT ; end of ACTIV8
;
;
DEACTIV8(ACPTDA,ACPTYR) ; deactivate codes not in 2008 HCPCS codeset
;
; private: called only by STEP6 above
;
; called only by the main procedure above; only ACPTDA passed in (by
; value), though the major input is the corresponding CPT record;
; likewise the output is to the record: the Inactive Flag (5) and Date
; Deleted (8) fields of the CPT record, the creation if missing of a new
; Effective Date subfile (60/81.02) record, and the Status field (.02)
; of that subrecord. The Status Field is a set of codes: 0 = INACTIVE,
; 1 = ACTIVE.
;
; Which codes this inactivates is driven by the CPT's Date Deleted field
; (8). Step 3 of the post-init (in PREPCODE^ACPT28PB) processes HCPCS
; codes to set Date Deleted to 3080000 for those that do not already
; have a Date Deleted, and then in step 4 (in LOADCODE^ACPT28PC) it
; clears the Date Deleted value for each HCPCS code brought in by the
; update from AMA, that is, for every new, changed, or merely preserved
; code in the set. The result should be that codes deleted from the new
; AMA set will have their Date Deleted set to 3080000.
;
; A code is inactivated by setting its Inactive Flag to 1, its Date
; Deleted to a real date, and also each year, as long as a "deleted"
; code remains "deleted", it gets a new Effective Date entry created for
; that year with the Status field for that year set to INACTIVE.
;
N ACPTDEL S ACPTDEL=$P($G(^ICPT(ACPTDA,0)),U,7) ; CPT's Date Deleted (8)
Q:ACPTDEL'=ACPTYR ; skip codes not deleted by this post-init
;
; otherwise, let's inactivate it:
;
S $P(^ICPT(ACPTDA,0),U,4)=1 ; first, set the Inactive Flag
S $P(^ICPT(ACPTDA,0),U,7)=3080101 ; 2nd, set Date Deleted to a real date
;
; third, let's find or add the current Effective Date (1/1/2008)
N DA S DA(1)=ACPTDA ; parent record, i.e., the CPT code
D
. N DIC S DIC="^ICPT("_DA(1)_",60," ; Effective Date subfile (60/81.02)
. S DIC(0)="L" ; allow LAYGO (Learn As You Go, i.e., add if not found)
. S DIC("P")=$P(^DD(81,60,0),"^",2) ; subfile # & specifier codes
. N X S X="01/01/2008" ; value to lookup in the subfile
. N DLAYGO,Y,DTOUT,DUOUT ; other parameters for DIC
. D ^DIC ; Fileman Lookup call
. S DA=+Y ; save IEN of found/added record for next call below
;
D ; third, let's inactivate it
. N DIE S DIE="^ICPT("_DA(1)_",60," ; Effective Date subfile (60/81.02)
. N DR S DR=".02////0" ; set Status field to INACTIVE
. N DIDEL,DTOUT ; other parameters for DIE
. D ^DIE ; Fileman Data Edit call
;
QUIT ; end of DEACTIV8
;
;
; end of routine ACPT28PE
ACPT28PE ;IHS/VEN/TOAD - ACPT*2.08*1 postinit step 6 ; 04/20/2008 23:32
+1 ;;2.08;CPT FILES;**1**;DEC 17, 2007
+2 ;
+3 ; This subroutine of the post-init for ACPT*2.08*1 activates the 2008
+4 ; HCPCS codes and deactivates the deleted ones. See routine ACPT28PA
+5 ; for the complete algorithm and overview, and LOADCODE^ACPT28PC for
+6 ; the data import and the set up of the flags that drive ACTIV8 and
+7 ; INACTIV8.
+8 ;
+9 ; This routine should not be called at the top or anywhere
QUIT
+10 ; else. It is only to be called at STEP6 by ACPT28PA as part of the
+11 ; post-init for ACPT*2.08*1.
+12 ;
+13 ; 2007 01 Shonda Render (IHS) edited to set the status flag with a new
+14 ; call to DIE, replacing the prior setting of DIC("DR") input to the
+15 ; DIC calls.
+16 ;
+17 ; 2008 03 Rick Marshall (VEN/CNI/IHS) commented the routine top to
+18 ; bottom while tracking down a bug: the status flag was found during
+19 ; verification of ACPT*2.08*1 to be set inconsistently, suggesting
+20 ; fragility in the algorithm. I also took the opportunity to tighten up
+21 ; variable scoping to help make the code a bit more robust. I also got
+22 ; rid of the calls to DOTS^ACPTPOST as unnecessary calls for such
+23 ; simple code, half of which (U IO(0)) we should only do once at the top
+24 ; not for every CPT code we traverse. I fixed a bug in which the dots
+25 ; not printing out nearly as often as the original designer expected. I
+26 ; also eliminated all code not related to HCPCS codes specifically.
+27 ;
+28 ; 2008 04 17-20 Rick Marshall renamed this routine from ACPTSINF to
+29 ; ACPT28PE to make its relationship to the other post-init routines
+30 ; clearer and to follow the standard for naming poast-inits. I also
+31 ; redid many of the comments, introduced a label for ACPT28PA to call,
+32 ; and otherwise brought it in line with the other ACPT28P* routines. I
+33 ; also radically simplify ACTIV8's logic in synch with the overhaul of
+34 ; LOADCODE^ACPT28PC that did likewise; a lesser simplification was also
+35 ; done on INACTIV8's logic.
+36 ;
+37 ; The original routine ACPTSINF was the work of IHS/ASDST/DMJ and
+38 ; Shonda Render (SDR).
+39 ;
+40 ; Called only by routine ACPT28PA as part of the post-init that imports
+41 ; and installs the CPT data from the text files. This subroutine
+42 ; traverses the CPT file (81) and corrects the Inactive Flag; new codes
+43 ; have their Date Added set to a real date; deleted codes have their
+44 ; Date Deleted set to a real date and a corresponding Effective Date's
+45 ; Status set to INACTIVE.
+46 ;
+47 ; The reason none of this is done up front in ACPT28PC is because this
+48 ; might be a test site installing prior to the codes' activation (&
+49 ; deactivation) dates; for example, a test site might be installing the
+50 ; patch for the 2008 codes in December, 2007, so we do not want to
+51 ; activate them yet. Instead, ACPT28PC imports the codes but does not
+52 ; activate them; it flags them for later activation and queues STEP6 as
+53 ; a task to run Jan 1, 2008 at 6:00 a.m., at which point STEP6 will
+54 ; activate the new codes and deactivate any HCPCS codes that exist but
+55 ; were not included in the 2008 codeset. STEP6 has to be able to handle
+56 ; both this test-site situation, in which it runs as a task long after
+57 ; the post-init, and a non-test-site situation, in which it is called
+58 ; during the post-init and runs immediately.
+59 ;
+60 ; This subroutine's main inputs and outputs are the HCPCS entries in the
+61 ; CPT file itself.
+62 ;
+63 ;
STEP6 ; post-init step 6: activate 2008 HCPCS codes, deactivate deleted ones
+1 ;
+2 ; private: called only by step 6 of routine ACPT28PC
+3 ;
+4 ; input: ACPTYR = 3080000, to use as the flag value for the Date Deleted
+5 ; field.
+6 ;
+7 ; loop: traverse the entries for HCPCS codes in the CPT file (81)).
+8 ; For each, activate if new, inactivate if deleted.
+9 ;
+10 Begin DoDot:1
+11 ; CPT file entry #, from just before HCPCS
NEW ACPTDA
SET ACPTDA=99999
+12 ; count, so that a dot is printed every 100 codes
NEW ACPTDOTS
+13 FOR ACPTDOTS=1:1
SET ACPTDA=$ORDER(^ICPT(ACPTDA))
IF 'ACPTDA!(ACPTDA>999999)
QUIT
Begin DoDot:2
+14 ; activate 2008 HCPCS codes
DO ACTIV8(ACPTDA,ACPTYR)
+15 ; deact codes not in 2008 HCPCS codeset
DO DEACTIV8(ACPTDA,ACPTYR)
+16 ; if this has been queued, skip the dots
IF $DATA(ZTQUEUED)
QUIT
+17 ; otherwise, write a dot for every 100 codes
IF '(ACPTDOTS#100)
WRITE "."
End DoDot:2
End DoDot:1
+18 ;
+19 ; end of STEP6
QUIT
+20 ;
+21 ;
ACTIV8(ACPTDA,ACPTYR) ; activate 2008 HCPCS codes
+1 ;
+2 ; private: called only by STEP6 above
+3 ;
+4 ; called only by the main procedure above; only ACPTDA passed in (by
+5 ; value), though the major input is the corresponding CPT record;
+6 ; likewise the output is to the record: the Inactive Flag field (5) of
+7 ; the CPT record, the creation if missing of a new Effective Date
+8 ; subfile (60/81.02) record, and the Status field (.02) of that
+9 ; subrecord. The Status Field is a set of codes: 0 = INACTIVE,
+10 ; 1 = ACTIVE.
+11 ;
+12 ; This code no longer worries about the Effective Date subfile, which
+13 ; has been completely handled by the overhauled LOADCODE^ACPT28PC. It
+14 ; only has to clear the Inactive Flag and set the Date Added to a real
+15 ; date.
+16 ;
+17 ; Likewise, the logic deciding which entries to activate has been
+18 ; simplified. It is only looking for inactive entries with a Date Added
+19 ; set to 3080000. We no longer worry about checking for whether we are
+20 ; running too soon; we leave that protection up to ACPT28PA to decide
+21 ; when and how we are called.
+22 ;
+23 ; get CPT's header node
NEW ACPTNODE
SET ACPTNODE=$GET(^ICPT(ACPTDA,0))
+24 ; skip bad records with no header
IF ACPTNODE=""
QUIT
+25 ;
+26 ; CPT's Date Added (7)
NEW ACPTADD
SET ACPTADD=$PIECE(ACPTNODE,U,6)
+27 ; if new, Date Added = 3080000 from LOADCODE^ACPT28PC
IF ACPTADD'=ACPTYR
QUIT
+28 ;
+29 ; CPT's Inactive Flag (5)
NEW ACPTINAC
SET ACPTINAC=$PIECE(ACPTNODE,U,4)
+30 ; new codes also have this flag set to INACTIVE (1)
IF 'ACPTINAC
QUIT
+31 ;
+32 ; clear the Inactive Flag
SET $PIECE(ACPTNODE,U,4)=""
+33 ; set Date Added to a real date
SET $PIECE(ACPTNODE,U,6)=3080101
+34 ;
+35 ; copy results back to CPT's header node
SET ^ICPT(ACPTDA,0)=ACPTNODE
+36 ;
+37 ; end of ACTIV8
QUIT
+38 ;
+39 ;
DEACTIV8(ACPTDA,ACPTYR) ; deactivate codes not in 2008 HCPCS codeset
+1 ;
+2 ; private: called only by STEP6 above
+3 ;
+4 ; called only by the main procedure above; only ACPTDA passed in (by
+5 ; value), though the major input is the corresponding CPT record;
+6 ; likewise the output is to the record: the Inactive Flag (5) and Date
+7 ; Deleted (8) fields of the CPT record, the creation if missing of a new
+8 ; Effective Date subfile (60/81.02) record, and the Status field (.02)
+9 ; of that subrecord. The Status Field is a set of codes: 0 = INACTIVE,
+10 ; 1 = ACTIVE.
+11 ;
+12 ; Which codes this inactivates is driven by the CPT's Date Deleted field
+13 ; (8). Step 3 of the post-init (in PREPCODE^ACPT28PB) processes HCPCS
+14 ; codes to set Date Deleted to 3080000 for those that do not already
+15 ; have a Date Deleted, and then in step 4 (in LOADCODE^ACPT28PC) it
+16 ; clears the Date Deleted value for each HCPCS code brought in by the
+17 ; update from AMA, that is, for every new, changed, or merely preserved
+18 ; code in the set. The result should be that codes deleted from the new
+19 ; AMA set will have their Date Deleted set to 3080000.
+20 ;
+21 ; A code is inactivated by setting its Inactive Flag to 1, its Date
+22 ; Deleted to a real date, and also each year, as long as a "deleted"
+23 ; code remains "deleted", it gets a new Effective Date entry created for
+24 ; that year with the Status field for that year set to INACTIVE.
+25 ;
+26 ; CPT's Date Deleted (8)
NEW ACPTDEL
SET ACPTDEL=$PIECE($GET(^ICPT(ACPTDA,0)),U,7)
+27 ; skip codes not deleted by this post-init
IF ACPTDEL'=ACPTYR
QUIT
+28 ;
+29 ; otherwise, let's inactivate it:
+30 ;
+31 ; first, set the Inactive Flag
SET $PIECE(^ICPT(ACPTDA,0),U,4)=1
+32 ; 2nd, set Date Deleted to a real date
SET $PIECE(^ICPT(ACPTDA,0),U,7)=3080101
+33 ;
+34 ; third, let's find or add the current Effective Date (1/1/2008)
+35 ; parent record, i.e., the CPT code
NEW DA
SET DA(1)=ACPTDA
+36 Begin DoDot:1
+37 ; Effective Date subfile (60/81.02)
NEW DIC
SET DIC="^ICPT("_DA(1)_",60,"
+38 ; allow LAYGO (Learn As You Go, i.e., add if not found)
SET DIC(0)="L"
+39 ; subfile # & specifier codes
SET DIC("P")=$PIECE(^DD(81,60,0),"^",2)
+40 ; value to lookup in the subfile
NEW X
SET X="01/01/2008"
+41 ; other parameters for DIC
NEW DLAYGO,Y,DTOUT,DUOUT
+42 ; Fileman Lookup call
DO ^DIC
+43 ; save IEN of found/added record for next call below
SET DA=+Y
End DoDot:1
+44 ;
+45 ; third, let's inactivate it
Begin DoDot:1
+46 ; Effective Date subfile (60/81.02)
NEW DIE
SET DIE="^ICPT("_DA(1)_",60,"
+47 ; set Status field to INACTIVE
NEW DR
SET DR=".02////0"
+48 ; other parameters for DIE
NEW DIDEL,DTOUT
+49 ; Fileman Data Edit call
DO ^DIE
End DoDot:1
+50 ;
+51 ; end of DEACTIV8
QUIT
+52 ;
+53 ;
+54 ; end of routine ACPT28PE