Compile subroutine Material_Track(RptColumns, LocationFilter)
/***********************************************************************************************************************

    Name        :   Report_Services

    Description :   Handler program for all Report services.

    Notes       :   Application errors should be logged using the Error Services module. There are a few methodological
                    assumptions built into way errors are managed which are important to understand in order to properly
                    work with Error Services:

                    - The term 'top' refers to the originating procedure of a call stack and the term 'bottom' refers to
                      the last routine (or the current routine) within a call stack. Within the OpenInsight Debugger
                      this will appear backwards since the originating procedure always appears at the bottom of the
                      list and the current routine appears at the top of the list. We are using this orientation because
                      it is common to refer to the process of calling other procedures as 'drilling down'.

                    - The reason for defining the orientation of the call stack is because Error_Services allows for
                      multiple error conditions to be appended to an original error. In most cases this will happen when
                      a procedure at the bottom of the stack generates an error condition and then returns to its
                      calling procedure. This higher level procedure can optionally add more information relevant to
                      itself. This continues as the call stack 'bubbles' its way back to the top to where the
                      originating procedure is waiting.

                    - Native OpenInsight commands that handle errors (e.g., Set_Status, Set_FSError, Set_EventStatus)
                      preserve their error state until explicitly cleared. This can hinder the normal execution of code
                      since subsequent procedures (usually SSPs) will fail if a pre-existing error condition exists.
                      Our philosophy is that error conditions should automatically be cleared before a new procedure
                      is executed to avoid this problem. However, the nature of Basic+ does not make this easy to
                      automate for any given stored procedure. Therefore, if a stored procedure wants to conform to our
                      philosophy then it should include a call into the 'Clear' service request at the top of the
                      program. Alternatively this can be done through a common insert (see SERVICE_SETUP for example.)

                    - Service modules will use the SERVICE_SETUP insert and therefore automatically clear out any
                      error conditions that were set before.

    Parameters  :
        Service         [in] -- Name of the service being requested
        Param1-10   [in/out] -- Additional request parameter holders
        Response       [out] -- Response to be sent back to the Controller (MCP) or requesting procedure

    Metadata    :

    History     :   (Date, Initials, Notes)
        10/30/20    djs     Original programmer.
														

***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler

$Insert LOGICAL
$Insert OIPRINT_EQUATES
$Insert SCHED_DET_EQUATES
$Insert WO_LOG_EQUATES
$Insert APPCOLORS
$Insert MSG_EQUATES
$Insert SCHEDULE_EQU
$Insert LOCATION_EQUATES
$Insert RLIST_EQUATES

Declare subroutine Utility, ErrMsg, Set_Status, Set_Printer, RList, SRP_Stopwatch, Btree.Extract, Error_Services, V119
Declare function   Set_Printer, Get_Printer, Msg, Get_Status, Printer_Select, obj_Install, Dialog_Box, obj_Location
Declare function   Schedule_Services, Error_Services, Location_Services, SRP_Array, Signature_Services
Declare function   Epi_Part_Services, SRP_Math

Equ TAB$               TO \09\

GetMaterialTrackReport:

    // All Possible Report Columns
    AllRptColumns        = ''
    AllRptColumns<1, 1>  = 'React No'
    AllRptColumns<1, 2>  = 'React Type'
    AllRptColumns<1, 3>  = 'WO No'
    AllRptColumns<1, 4>  = 'SAP Prod No'
    AllRptColumns<1, 5>  = 'Sub Part No'
    AllRptColumns<1, 6>  = 'Epi Part No'
    AllRptColumns<1, 7>  = 'WO Qty'
    AllRptColumns<1, 8>  = 'RX Qty'
    AllRptColumns<1, 9>  = 'UnRel Qty'
    AllRptColumns<1, 10> = 'Kit Location'
    AllRptColumns<1, 11> = 'Kit Qty'
    AllRptColumns<1, 12> = '+/-'
    AllRptColumns<1, 13> = 'Kit RO'
    AllRptColumns<1, 14> = 'PTI RO'
    AllRptColumns<1, 15> = 'Load'
    AllRptColumns<1, 16> = 'Comments'
    
    If Index(RptColumns, 'Comments', 1) then
        AllColFmt        = ''
        AllColFmt<1, 1>  = '+^720'
        AllColFmt<1, 2>  = '+<720'
        AllColFmt<1, 3>  = '+^1000'
        AllColFmt<1, 4>  = '+^1100'
        AllColFmt<1, 5>  = '+^1300'
        AllColFmt<1, 6>  = '+^1200'
        AllColFmt<1, 7>  = '+>720'
        AllColFmt<1, 8>  = '+>720'
        AllColFmt<1, 9>  = '+>720'
        AllColFmt<1, 10> = '+^1260'
        AllColFmt<1, 11> = '+^720'
        AllColFmt<1, 12> = '+^500'
        AllColFmt<1, 13> = '+^1300'
        AllColFmt<1, 14> = '+^1300'
        AllColFmt<1, 15> = '+^700'
        AllColFmt<1, 16> = '+^1300'    
    end else
        AllColFmt        = ''
        AllColFmt<1, 1>  = '+^720'
        AllColFmt<1, 2>  = '+<720'
        AllColFmt<1, 3>  = '+^1000'
        AllColFmt<1, 4>  = '+^1100'
        AllColFmt<1, 5>  = '+^1300'
        AllColFmt<1, 6>  = '+^1200'
        AllColFmt<1, 7>  = '+>720'
        AllColFmt<1, 8>  = '+>720'
        AllColFmt<1, 9>  = '+>720'
        AllColFmt<1, 10> = '+^1260'
        AllColFmt<1, 11> = '+^720'
        AllColFmt<1, 12> = '+^500'
        AllColFmt<1, 13> = '+^1800'
        AllColFmt<1, 14> = '+^1800'
        AllColFmt<1, 15> = '+^1100'
        AllColFmt<1, 16> = ''
    end

    ErrorTitle  =  'Error in subroutine Material_Track'
    ErrCode		= ''
    ErrorMsg	= ''

    OPEN 'SCHED_DET' TO SchedDetTable then
        OPEN 'DICT.SCHED_DET' TO @DICT then
            Today   = OCONV(Date(),'D4/')
            EndDate	= OCONV(Date()+13,'D4/')

            ReactList 		= ''
            WOList			= ''
            SchedDetKeys	= ''
            PrevReactNo     = ''
            PrevWO          = ''

            SelectSent  = 'SELECT SCHED_DET WITH SCHED_DT GE ':QUOTE(Today):' BY REACT_NO'

            RList(SelectSent,TARGET_ACTIVELIST$,'','','')
            IF Get_Status(errCode) THEN
                ErrMsg(errCode)
                RETURN
            END

            Done = 0
            @ID  = ''
            LOOP
                PrevSchedDetKey = @ID
                READNEXT @ID ELSE Done = 1
            UNTIL Done
                ReactNo = @ID[1,'*']
                SchedDt	= @ID[COL2()+1,'*']
                SeqNo	= @ID[COL2()+1,'*']
                
                READ SchedDetRec FROM SchedDetTable,@ID THEN
                    
                    WONo = SchedDetRec<SCHED_DET_WO_NO$>
                    
                    LOCATE ReactNo IN ReactList BY 'AR' USING @FM  SETTING Pos ELSE
                        ReactList = INSERT(ReactList,Pos,0,0,ReactNo)
                    END
                    
                    PrevReactNo     = Field(PrevSchedDetKey, '*', 1)
                    PrevSchedDt     = Field(PrevSchedDetKey, '*', 2)
                    
                    LOCATE WONo IN WOList<Pos> USING @VM SETTING WPos ELSE	
                        WOList 			= INSERT(WOList,Pos,-1,0,WONo)
                        // Patch added on 10/24/18 to resolve scheduling conflicts on the same day for
                        // the material track report. - djs                         
                        If (PrevReactNo EQ ReactNo) and (PrevSchedDt EQ SchedDt) then
                            PrevSeqNo   = Field(PrevSchedDetKey, '*', 3)
                            NumWO       = DCount(WOList<Pos>, @VM)
                            PrevWONo    = WOList<Pos, NumWO - 1>
                            SchedEvents = Schedule_Services('GetScheduleEventSummary', ReactNo, WONo, SchedDt, SeqNo, True$)
                            StartDt     = IConv(SchedEvents<SCHEDULE_ENTRY_DATE$>, 'D')
                            PrevSchedEvents = Schedule_Services('GetScheduleEventSummary', ReactNo, PrevWONo, PrevSchedDt, PrevSeqNo, True$)
                            PrevStartDt = IConv(PrevSchedEvents<SCHEDULE_ENTRY_DATE$>, 'D')
                            If StartDt GT PrevStartDt then
                                // This is the common case
                                SchedDetKeys = INSERT(SchedDetKeys,-1,0,0,@ID)
                            end else
                                // Scheduling irregularity - Insert this key in the second to last position.
                                NumKeys      = DCount(SchedDetKeys, @FM)
                                InsertPos    = NumKeys
                                SchedDetKeys = INSERT(SchedDetKeys,InsertPos,0,0,@ID)
                            end
                        end else
                            SchedDetKeys = INSERT(SchedDetKeys,-1,0,0,@ID)
                        end
                    END
                END
                
            REPEAT

            CALL Make.List(0,SchedDetKeys,SchedDetTable,@DICT)

            Header		= "'D'":@VM:obj_Install('Get_Prop','CompTitle'):' Material Tracking by Reactor':@VM:"Page  'P'"
            MinDemand	= 0
            Set_Status(0)

            * Start of printing process
            FileName = 'C:\Users\StieberD\Desktop\Material_Demand.pdf'
            Title    = 'Printing Material Demand'

            TopMargin		= 1.0
            BottomMargin	= 0.75
            LeftMargin		= 0.25
            RightMargin		= 0.25

            Margins = LeftMargin:@FM:TopMargin:@FM:RightMargin:@FM:BottomMargin

            PageSetup       = '1'		;* LandScape
            PrintSetup      = '2'		;* Preview Normal
            PrintSetup<1,2> = '0'	;* All buttons
            PrintSetup<1,5> = '1'	;* Page Range
            PrintSetup<1,6> = 7		;* full mouse and keyboard support

            PrintPath = ''
            stat      = Set_Printer('INIT',FileName,Title,Margins,PageSetup,PrintSetup,PrintPath)

            IF stat < 0 THEN
                ErrorMsg	= 'Stat = ' : Stat : ', PrintPath = ' : PrintPath
                GOTO OIPrintErr
            end
            DateRange = 'Effective ':OCONV(Date(),'D4')

            Header<-1> = "'T'"
            Header<-1> = ''																;* Blank line following heading

            font	= 'Arial'
            font<2>	= '10'
            font<4>	= '0'		;* Bold

            stat = Set_Printer('FONTHEADFOOT',font)	; IF stat < 0 THEN GOTO OIPrintErr
            stat = Set_Printer('HEADER',Header)		; IF stat < 0 THEN GOTO OIPrintErr

            Footer = " 'D' 'T'":@VM:@VM:"Page:  'P'"
            stat = Set_Printer('FOOTER',Footer)		; IF stat < 0 THEN GOTO OIPrintErr

            @RECCOUNT	= 0
            FirstPass	= 1
            LastRecord	= 0
            FirstLine 	= 1
            fontSpacing	= 100

            * Make Column Heading
            ColHead = ''
            ColFmt  = ''
            
            For each Column in RptColumns using @VM setting rcPos
                Locate Column in AllRptColumns using @VM setting dataPos then
                    ColHead<0, -1> = Column
                    ColFmt<0, -1>  = AllColFmt<0, dataPos>
                end
            Next Column

            * Zero Accumulators For Each Break

            Prev.ReactNo       = ''
            Last.ReactNo.Break = 1
            
            GoTo ReadRecord

        end else
            ErrorMsg = 'Unable to open "SCHED_DET" table.'
            ErrMsg(ErrorTitle:@SVM:ErrorMsg)
        end
    end else
        ErrorMsg  =  'Unable to open "SCHED_DET" table.'
        ErrMsg(ErrorTitle:@SVM:ErrorMsg)       
    end
    
return


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

ReadRecord:
    
    * Zero Break Flags To False
    
    ReactNo.Break=0
    
    READNEXT @ID, Which.Value ELSE
        LastRecord    = 1
        ReactNo.Break = 1
        ReactNo       = Prev.ReactNo
    END
    
    S.ATID = @ID
    
    IF FirstPass AND LastRecord THEN
        GOTO Bail
    END
    
    IF LastRecord THEN GOTO BREAKS
    
    READO @RECORD FROM SchedDetTable,@ID ELSE
        GOTO ReadRecord
    END
    
    @RECCOUNT += 1
    
    * Calculate Value(s) For Column(s)
    
    S.ATID			= {@ID}
    I.ATID			= S.ATID
    S.ReactNo		= {REACT_NO}
    I.ReactNo		= S.ReactNo
    S.WoNo			= {WO_NO}
    I.WoNo			= S.WoNo
    S.SubPartNo		= XLATE('WO_LOG',S.WoNo,'ORD_SUB_PART_NO','X')
    I.SubPartNo		= S.SubPartNo
    S.EpiPartNo		= XLATE('WO_LOG',S.WoNo,WO_LOG_EPI_PART_NO$,'X')
    I.EpiPartNo		= S.EpiPartNo
    S.WO_Qty		= {WO_QTY}
    I.WO_Qty		= S.WO_Qty
    S.WO_RX_Qty 	= {WO_RX_QTY}
    I.WO_RX_Qty 	= S.WO_RX_Qty
    S.WO_UnRel_QTY	= {WO_UNREL_QTY}
    I.WO_UnRel_QTY	= S.WO_UnRel_QTY
    S.Sched_DT		= {SCHED_DT}
    I.Sched_DT		= S.Sched_DT
    S.REACT_TYPE    = {REACTOR_TYPE}
    S.ProdOrdNo		= {PROD_ORD_NO}

    Locate 'SR*KTR]' in LocationFilter using @VM setting vPos then
        KitData = Location_Services('GetLocationCassInfo', S.WONo, 'SR*KTR]')    
        SWAP CRLF$ WITH @VM IN KitData
    end else
        KitData = ''
    end
    
    S.KitLocation = KitData<1>
    I.KitLocation = S.KitLocation
    
    S.KitQty		= OCONV(SUM(KitData<2>) * 25,'MD0,Z')
    I.KitQty		= S.KitQty
    
    S.KitCassCnt	= COUNT(KitData<3>,',') + (KitData<3> NE '')
    I.KitCassCnt	= S.KitCassCnt
    
    KitCassList = KitData<3>

    Locate '1K*PTI' in LocationFilter using @VM setting vPos then
        PTIData = Location_Services('GetLocationCassInfo', S.WONo, '1K*PTI')
        SWAP CRLF$ WITH @VM IN PTIData    
    end else
        PTIData = ''
    end
    PTICassList = PTIData<3>
    
    CRLocs        = ''
    CRLocs<0, -1> = 'CR*BE'
    CRLocs<0, -1> = 'CR*BO'
    CRLocs<0, -1> = 'CR*TUN'
    CRLocs<0, -1> = 'CR*EPR'
    CRLocs<0, -1> = 'CR*FE'
    CRLocs<0, -1> = 'CR*FEH'
    CRLocs<0, -1> = 'CR*FO'
    CRLocs<0, -1> = 'CR*FOH'
    
    LoadedData     = ''
    LocQueryList   = ''
    For each Loc in CRLocs using @VM setting crPos
        Locate Loc in LocationFilter using @VM setting vPos then
            LocQueryList<0, -1> = Loc    
        end
    Next Loc
    
    LoadedCassList = ''
    ReactType      = Xlate('WO_LOG', S.WONo, 'REACT_TYPE', 'X')
    If ReactType NE 'EPP' then
        If LocQueryList NE '' then
            LoadedData     = Location_Services('GetLocationCassInfo', S.WONo, LocQueryList)
            Swap CRLF$ with @VM in LoadedData
            CassList       = LoadedData<3>
            For each CassNo in CassList using ','
                If ( (S.WONo NE '') and (CassNo NE '') ) then
                    WOMatKey      = S.WONo:'*':CassNo
                    UnloadSigComp = Signature_Services('CheckSignature', WOMatKey, 'UNLOAD')
                    If UnloadSigComp then
                        // Add this cassette to the PTI list instead of the Load list
                        PTICassList<0, -1> = CassNo
                    end else
                        LoadedCassList<0, -1> = CassNo
                    end
                end
            Next CassNo
        end
    end
    
    * TEST FOR CONTROL BREAK(S)
    
    IF (S.ReactNo NE Prev.ReactNo) OR ReactNo.Break THEN
        ReactNo			= Prev.ReactNo
        Prev.ReactNo	= S.ReactNo
        ReactNo.Break  += 1
    END
    
    IF FirstPass THEN
        FirstPass=0
        GOTO DETAIL
    END
  
  
BREAKS:
    
    * Print Break Total(s) And Accumulate Total(s)    
    IF ReactNo.Break THEN stat = Set_Printer('TEXT')      

    * Perform Last Record Output If Done  
    IF LastRecord THEN        
        colData = ''
        GOTO Bail        
    END
    
    
DETAIL:
    
    * Do Conversion If Any

    IF S.REACTNO NE "" 		THEN S.REACTNO		= OCONV(S.REACTNO,"MD0,")
    IF S.WONO NE "" 		THEN S.WONO			= OCONV(S.WONO,"MD0")
    IF S.WO_QTY NE "" 		THEN S.WO_QTY		= OCONV(S.WO_QTY,"MD0,")
    IF S.WO_RX_QTY NE ""	THEN S.WO_RX_QTY	= OCONV(S.WO_RX_QTY,"MD0,")
    IF S.WO_UNREL_QTY NE "" THEN S.WO_UNREL_QTY	= OCONV(S.WO_UNREL_QTY,"MD0,")
    IF S.SCHED_DT NE "" 	THEN S.SCHED_DT		= OCONV(S.SCHED_DT,"D4/")
    
    * PRINT DETAIL LINE
    
    COLDATA        = ''
    RowNumber      = 0

    /*  ascending sort  */
    Convert @VM to ',' in KitCassList
    Convert @VM to ',' in PTICassList
    Convert @VM to ',' in LoadedCassList
    KitCassList    = SRP_Array('SortSimpleList', KitCassList, 'AscendingNumbers', ',')
    PTICassList    = SRP_Array('SortSimpleList', PTICassList, 'AscendingNumbers', ',')
    LoadedCassList = SRP_Array('SortSimpleList', LoadedCassList, 'AscendingNumbers', ',')
    
    Convert ',' to @VM in KitCassList
    Convert ',' to @VM in PTICassList
    Convert ',' to @VM in LoadedCassList

    NumKitCass = DCount(KitCassList, @VM)
    If NumKitCass GT 4 then
        For CassIndex = 4 to NumKitCass Step 4
            CassNo                     = KitCassList<0, CassIndex>
            CassNo                    := CRLF$
            KitCassList<0, CassIndex>  = CassNo
        Next CassIndex
    end
    NumPTICass = DCount(PTICassList, @VM)
    If NumPTICass GT 4 then
        For CassIndex = 4 to NumPTICass Step 4
            CassNo                     = PTICassList<0, CassIndex>
            CassNo                    := CRLF$
            PTICassList<0, CassIndex>  = CassNo
        Next CassIndex
    end
    NumLoadedCass = DCount(LoadedCassList, @VM)
    If NumLoadedCass GT 2 then
        For CassIndex = 2 to NumLoadedCass Step 2
            CassNo                        = LoadedCassList<0, CassIndex>
            CassNo                       := CRLF$
            LoadedCassList<0, CassIndex>  = CassNo
        Next CassIndex
    end
    Convert @VM to ',' in KitCassList
    Convert @VM to ',' in PTICassList
    Convert @VM to ',' in LoadedCassList
    
    CassNeeded = ''
    EpiPartNo  = Xlate('WO_LOG', S.WONo, 'EPI_PART_NO', 'X')
    If EpiPartNo NE '' then
        WPDAdjusted = Epi_Part_Services('GetAdjustedWafersPerDayScheduler', EpiPartNo, S.React_Type)
        If WPDAdjusted NE '' then
            CPDAdjusted = SRP_Math('CEILING', (WPDAdjusted/25) )
            CassInCR    = DCount(KittCassList, ',') + DCount(PTICassList, ',') + DCount(LoadedCassList, ',')
            CassNeeded  = CassInCR - CPDAdjusted
        end
    end

    Swap '.1' with '' in S.ProdOrdNo
    AllReportData     = ''
    AllReportData<1>  = S.ReactNo
    AllReportData<2>  = S.React_Type
    AllReportData<3>  = S.WONo
    AllReportData<4>  = S.ProdOrdNo
    AllReportData<5>  = S.SubPartNo
    AllReportData<6>  = S.EpiPartNo
    AllReportData<7>  = S.WO_Qty
    AllReportData<8>  = S.WO_RX_Qty
    AllReportData<9>  = S.WO_UnRel_Qty
    AllReportData<10> = S.KitLocation
    AllReportData<11> = S.KitQty
    AllReportData<12> = CassNeeded					
    AllReportData<13> = KitCassList
    AllReportData<14> = PTICassList
    AllReportData<15> = LoadedCassList
    AllReportData<16> = ''
    
    If ( (KitCassList NE '') or (PTICassList NE '') or (LoadedCassList NE '') ) then
        RowNumber += 1              
        For each RptColumn in RptColumns using @VM setting rcPos
            Locate RptColumn in AllRptColumns using @VM setting dataPos then
                COLDATA<RowNumber,rcPos> = AllReportData<dataPos>
            end  
        Next RptColumn
        If COLDATA NE '' then GoSub PrintTable
    END
        
    GOTO ReadRecord   
    
Bail:
 
    stat = Set_Printer('TERM',1)

RETURN


OIPrintErr:
    
    ErrMsg(ErrorTitle:@SVM:ErrorMsg)
    ErrMsg(ErrorTitle:@SVM:'Set_Printer returned errorcode ':stat)
    stat = Set_Printer('TERM',1)
    
RETURN


PrintTable:
    
    PageHeight		= Get_Printer('PAGESIZE')<2>
    PrintableHeight = PageHeight - TopMargin - BottomMargin
    PrinterHeight   = Get_Printer('POS')<2>   
    stat			= Set_Printer('CALCTABLE',ColFmt:@FM:ColData)
    TableSize		= Get_Printer('CALCTABLE')  
    TableHeight		= TableSize<2>   
    fontSpacing			= 120
    
    IF ( TableHeight + PrinterHeight >= PrintableHeight ) OR FirstLine THEN
        IF NOT(FirstLine) THEN
            stat = Set_Printer('PAGEBREAK')
        END
        FirstLine = 0
        font<2> = 10
        font<4> = 1		;* Bold
        stat = Set_Printer('FONT',font,'100')       
        stat = Set_Printer('ADDTABLE',colFmt,colHead,'',LTGREY$,'',0,TB_ALL)                
        font<4> = 0
        stat = Set_Printer('FONT',font,fontSpacing)      
        stat = Set_Printer('ADDTABLE',colFmt,'',colData,LTGREY$,'',0,7)        
    END ELSE
        font<2> = 10
        font<4> = 0
        stat = Set_Printer('FONT',font,fontSpacing)
        stat = Set_Printer('ADDTABLE',colFmt,'',colData,LTGREY$,'',1,TB_ALL)       
    END
      
RETURN	 

