Compile function PM_Services(@Service, @Params)
#pragma precomp SRP_PreCompiler

$Insert APP_INSERTS
$Insert SERVICE_SETUP
$Insert PM_EQUATES
$Insert PM_SPEC_EQUATES
$Insert TOOL_EQUATES

EQU COL$PMSKEY       TO 1
EQU COL$STATUS       TO 2
EQU COL$NOTIFICAITON TO 3
EQU COL$DUEBY        To 4
EQU COL$CURRPMKEY    To 5

Declare subroutine Database_Services, Error_Services, Set_Status, obj_PM_Spec, Tool_Services, Btree.Extract
Declare subroutine Logging_Services, Pm_Services, RList, Obj_Notes, PM_Spec_Services
Declare function   Datetime, Database_Services, Error_Services, obj_PM_Spec, obj_Tool, Environment_Services, LCASE
Declare function Logging_Services, Pm_Services, NextKey, SRP_Datetime, Lsl_Users_Services, Active_Directory_Services

LogPath     = Environment_Services('GetApplicationRootPath') : '\LogFiles\Tool'
LogDate     = Oconv(Date(), 'D4/')
LogTime     = Oconv(Time(), 'MTS')
LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' Tool Log.csv'
Headers     = 'Logging DTM' : @FM : 'ToolID' : @FM : 'Notes' : @FM : 'Error'
objLog      = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ',', Headers, '', False$, False$)

LogPath         = Environment_Services('GetApplicationRootPath') : '\LogFiles\Scrubbers\PMCompletion'
LogDate         = Oconv(Date(), 'D4/')
LogTime         = Oconv(Time(), 'MTS')
LogFileName     = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' Tool Log.csv'
Headers         = 'Logging DTM' : @FM : 'ToolID' : @FM : 'Notes' : @FM : 'Message'
objLogScrubbers = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ',', Headers, '', False$, False$)

LogPath             = Environment_Services('GetApplicationRootPath') : '\LogFiles\PM\Notifications'
LogDate             = Oconv(Date(), 'D4/')
LogTime             = Oconv(Time(), 'MTS')
LogFileName         = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' PM_Notifications.csv'
Headers             = 'Logging DTM' : @FM : 'ToolID' : @FM : 'Message'
objLogNotifications = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ',', Headers, '', False$, False$)

LoggingDTM  = LogDate : ' ' : LogTime   ; // Logging DTM

ChangeModes = Database_Services('ReadDataRow', 'APP_INFO', 'QUAL_CHANGE_MODES')

GoToService

Return Response or ""

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN     = True$, False$
Options PM_CLASSES = 'SCRUBBER', '5S'
Options AREAS = 'CLEANROOM', 'SHIPPING/RECEIVING', 'MAINTENANCE'

//-----------------------------------------------------------------------------
// SERVICES
//-----------------------------------------------------------------------------

Service StartPM(PMNo, UserID, StartDTM)
    
    If PMNo NE '' then
        If UserID EQ '' then UserID = @User4
        If StartDTM EQ '' then StartDTM = Datetime()
        PMRec  = Database_Services('ReadDataRow', 'PM', PMNo)
        If Error_Services('NoError') then
            PMSNo         = PMRec<PM_PMS_ID$>
            ToolID = Xlate('PM_SPEC', PMSNo, PM_SPEC_TOOL_ID$, 'X')
            If ( (PMSNo NE '') and (ToolID NE '') ) then
                EarlyStartDTM = IConv(Xlate('PM_SPEC', PMSNo, 'EARLY_START', 'X'), 'DT')
                If StartDTM GE EarlyStartDTM then
                    // Only change the tool mode if the tool is in one of the modes listed in the APP_INFO*QUAL_CHANGE_MODES
                    // record! This is to preserve other tool modes as the current mode such as SCHED_MTC.
                    CurrMode    = Xlate('TOOL', ToolID, 'CURR_MODE', 'X')<1,1>
                    Locate CurrMode in ChangeModes using @FM setting fPos then
                        Reason  = 'PM No. ':PMNo:' Started'
                        NewMode = 'VER'
                        Tool_Services('ChangeToolMode', ToolID, NewMode, Reason, UserID, True$)
                    end else
                        LogData    = ''
                        LogData<1> = OConv(Datetime(), 'DT2/^H')
                        LogData<2> = ToolID
                        LogData<3> = 'Unable to locate curr mode in the list of modes to change from.'
                        LogData<4> = ''
                        Logging_Services('AppendLog', objLog, LogData, @RM, @FM)    
                    end
                    If Error_Services('NoError') then
                        PMRec<PM_START_BY$>  = UserID
                        PMRec<PM_START_DTM$> = StartDTM
                        Database_Services('WriteDataRow', 'PM', PMNo, PMRec, True$, False$, True$)
                    end else
                        Error_Services('Add', 'Error in ':Service:' service. Error calling Tool_Services("ChangeToolMode") Error code: ':Error_Services('GetMessage'))
                    end
                end else
                    // It is too early to start this PM
                    Error_Services('Add', 'Error in ':Service:' service. Too early to start PMNo ':PMNo:'.')
                end
            end else
                // Null PMSNo or ToolID error
                Error_Services('Add', 'Error in ':Service:' service. Null PM_SPEC ID or ToolID for PMNo ':PMNo:'.')
            end
        end
    end else
        // Null PMNo error
        Error_Services('Add', 'Error in ':Service:' service. Null PMNo passed in.')
    end
    
End Service


Service CompletePM(PMNo, UserID, CompDTM)
    
    If PMNo NE '' then
        PMRec = Database_Services('ReadDataRow', 'PM', PMNo)
        If Error_Services('NoError') then
            PMSNo  = PMRec<PM_PMS_ID$>
            ToolID = Xlate('PM_SPEC', PMSNo, PM_SPEC_TOOL_ID$, 'X')
            If ( (PMSNo NE '') and (ToolID NE '') ) then
                If UserID  EQ '' then UserID  = @User4
                If CompDTM EQ '' then CompDTM = Datetime()
                ToolCycleCnt = Xlate('PM_SPEC', PMSNo, 'TOOL_CYCLE_CNT', 'X')
                If ToolCycleCnt EQ '' then ToolCycleCnt = '0'
                Overdue      = False$
                // Scan for other overdue quals. Only place tool into PROD if all quals are complete.
                Open 'DICT.PM_SPEC' to PMSDict then
                    ToolPMSpecKeys = ''
                    Option         = ''
                    Flag           = ''
                    // Ignore archived PM_SPEC!
                    Query          = 'TOOL_ID':@VM:ToolID:@FM:'ARCHIVED':@VM:'#1':@FM
                    Btree.Extract(Query, 'PM_SPEC', PMSDict, ToolPMSpecKeys, Option, Flag)
                    If Flag EQ 0 then
                        If ToolPMSpecKeys NE '' then
                            Today   = Date()
                            CurrDtm	= ICONV(OCONV(Date(),'D'):' ':OCONV(Time(),'MT'), 'DT' )
                            CurrCnt	= XLATE('TOOL', ToolID, TOOL_CYCLE_CNT$, 'X')
                            For each PMSpecKey in ToolPMSpecKeys using @VM
                                If PMSpecKey NE PMSNo then
                                    // Check for overdue qual PM for this PM_SPEC
                                    PMSpecRec = Database_Services('ReadDataRow', 'PM_SPEC', PMSpecKey)
                                    ActPMKeys = PMSpecRec<PM_SPEC_PM_KEYS$>
                                    Units     = PMSpecRec<PM_SPEC_UNITS$>
                                    Conv      = ''
                                    If Units = 'D' then	Conv = 'D'
                                    If Units = 'T' then Conv = 'DT'
                                    If Units = 'Q' then Conv = 'MD0'
                                    
                                    Now     = ''
                                    If Units = 'D' then Now = Today
                                    If Units = 'T' then Now = CurrDtm
                                    If Units = 'Q' then Now = CurrCnt
                                    
                                    pmCnt = COUNT(ActPMKeys,@VM) + (ActPMKeys NE '')
                                    
                                    If pmCnt = 0 then pmCnt = 1
                                    
                                    SchedStarts	= obj_PM_Spec('SchedStart',PMSpecKey:@RM:PMSpecRec)
                                    EarlyStarts	= obj_PM_Spec('EarlyStart',PMSpecKey:@RM:PMSpecRec)
                                    LateStarts	= obj_PM_Spec('LateStart', PMSpecKey:@RM:PMSpecRec)
                                    
                                    For I = 1 to pmCnt
                                        SchedStart = SchedStarts<1,I>
                                        EarlyStart = EarlyStarts<1,I>
                                        LateStart  = LateStarts<1,I>
                                        
                                        If Conv NE '' then
                                            SchedStartIn = ICONV(SchedStart,Conv)
                                            EarlyStartIn = ICONV(EarlyStart,Conv)
                                            LateStartIn = ICONV(LateStart,Conv)
                                        end else
                                            SchedStartIn = SchedStart
                                            EarlyStartIn = EarlyStart
                                            LateStartIn	 = LateStart
                                        end
                                        
                                        If ( ( (LateStartIn = '') AND (Now = SchedStartIn) ) or (Now > LateStartIn) ) then
                                            // Tool is overdue for a qual.
                                            Overdue = True$
                                        end		
                                    Until Overdue
                                    Next I
                                end
                            Until Overdue
                            Next PMSpecKey
                        end
                    end
                end
                
                If Not(Overdue) then
                    NewMode = 'PROD'
                    Reason  = 'PM No. ':PMNo:' completed.'
                end else
                    NewMode = 'QUAL_OVERDUE'
                    Reason  = 'PM No. ':PMNo:' completed, but another qual is overdue.'
                end
                
                // Only change the tool mode if the tool is in one of the modes listed in the APP_INFO*QUAL_CHANGE_MODES
                // record! This is to preserve other tool modes as the current mode such as SCHED_MTC.
                CurrMode = Xlate('TOOL', ToolID, 'CURR_MODE', 'X')<1,1>
                Locate CurrMode in ChangeModes using @FM setting fPos then 
                    Tool_Services('ChangeToolMode', ToolID, NewMode, Reason, UserID, True$)
                end else
                    LogData    = ''
                    LogData<1> = OConv(Datetime(), 'DT2/^H')
                    LogData<2> = ToolID
                    LogData<3> = 'Unable to locate curr mode in the list of modes to change from.'
                    LogData<4> = ''
                    Logging_Services('AppendLog', objLog, LogData, @RM, @FM)    
                end
                
                If Error_Services('NoError') then
                    PMRec<PM_COMP_BY$>  = UserID
                    PMRec<PM_COMP_DTM$> = CompDTM
                    PMRec<PM_COMP_QTY$> = ToolCycleCnt
                    Database_Services('WriteDataRow', 'PM', PMNo, PMRec, True$, False$, True$)
                    If Error_Services('NoError') then
                        // Update Last PM Comp DTM in PM_SPEC record
                        PM_Spec_Services('UpdatePMCompDtm', PMSNo)
                        If Error_Services('NoError') then 
                            Set_Status(0)
                            ErrCode = ''
                            obj_PM_Spec('SchedNewPM',PMSNo:@RM:OCONV(Date(),'D4'):@RM:OCONV(Time(),'MTS'):@RM:ToolCycleCnt:@RM:PMNo)
                            If Get_Status(ErrCode) then
                                ErrorMsg  = 'Error in ':Service:' service. Error calling obj_PM_Spec("SchedNewPM") for '
                                ErrorMsg := 'PM_SPEC ':PMSNo:' and PM ':PMNo:'. Error code: ':ErrCode
                                Error_Services('Add', ErrorMsg)
                            end
                        end
                    end
                end else
                    ErrorMsg  = 'Error in ':Service:' service. Error calling Tool_Services("ChangeToolMode") '
                    ErrorMsg := 'PM ':PMNo:' for PM_SPEC ':PMSNo:' not completed! Error code: ':Error_Services('GetMessage')
                    Error_Services('Add', ErrorMsg)
                end
            end else
                Error_Services('Add', 'Error in ':Service:' service. Null PM_SPEC ID or ToolID for PMNo ':PMNo:'.')
            end
        end
    end else
        Error_Services('Add', 'Error in ':Service:' service. Null PMNo passed in.')
    end
    
end service


Service CompleteNonToolPM(PMNo, UserID, CurrDTM)
    
    If PMNo NE '' then
        If UserID EQ '' then UserID = @User4
        If CurrDTM EQ '' then StartDTM = Datetime()
        PMRec = Database_Services('ReadDataRow', 'PM', PMNo)
        PMSNo = PMRec<PM_PMS_ID$>
        If Error_Services('NoError') then
            EarlyStartDTM = IConv(Xlate('PM_SPEC', PMSNo, 'EARLY_START', 'X'), 'DT')
            If CurrDTM GE EarlyStartDTM then
                PMRec<PM_START_BY$>  = UserID
                PMRec<PM_START_DTM$> = CurrDTM
                PMRec<PM_COMP_BY$>   = UserID
                PMRec<PM_COMP_DTM$>  = CurrDTM
                PMRec<PM_COMP_QTY$>  = 0
                Database_Services('WriteDataRow', 'PM', PMNo, PMRec, True$, False$, True$)
                If Error_Services('NoError') then
                    // Update Last PM Comp DTM in PM_SPEC record
                    PM_Spec_Services('UpdatePMCompDtm', PMSNo)
                    If Error_Services('NoError') then 
                        Set_Status(0)
                        ErrCode = ''
                        obj_PM_Spec('SchedNewPM',PMSNo:@RM:OCONV(Date(),'D4'):@RM:OCONV(Time(),'MTS'):@RM:0:@RM:PMNo)
                        //Pm_Services('ScheduleNextPM', PMSNo, PMNo)
                        If Error_Services('HasError') then
                            ErrorMsg  = 'Error in ':Service:' service. Error calling obj_PM_Spec("SchedNewPM") for '
                            ErrorMsg := 'PM_SPEC ':PMSNo:' and PM ':PMNo:'. Error code: ':ErrCode
                            Error_Services('Add', ErrorMsg)
                        end
                    end
                end
            end else
                Error_Services('Add', 'Error in ':Service:' service. Too early to start PMNo ':PMNo:'.')
            end
        end
    end
    
    
end service


Service MonitorQuals()
    
    hSysLists = Database_Services('GetTableHandle', 'SYSLISTS')
    Lock hSysLists, ServiceKeyID then
        Open 'TOOL' to hTool then
            ToolIDs = obj_Tool('KeysByType')		
            For each ToolID in ToolIDs using @VM
                NotDue       = True$
                DueSoon      = False$
                CurrentlyDue = False$
                Overdue      = False$
                NotScheduled = False$
                ReadV OrigPMStatus from hTool, ToolID, TOOL_PM_STATUS$ then
                    
                    Open 'DICT.PM_SPEC' to PMSDict then
                        ToolPMSpecKeys = ''
                        Option         = ''
                        Flag           = ''
                        Query          = 'TOOL_ID':@VM:ToolID:@FM:'ARCHIVED':@VM:'#1':@FM
                        Btree.Extract(Query, 'PM_SPEC', PMSDict, ToolPMSpecKeys, Option, Flag)
                        If Flag EQ 0 then
                            If ToolPMSpecKeys NE '' then
                                Today   = Date()
                                CurrDtm	= ICONV(OCONV(Date(),'D'):' ':OCONV(Time(),'MT'), 'DT' )
                                CurrCnt	= XLATE('TOOL', ToolID, TOOL_CYCLE_CNT$, 'X')
                                For each PMSpecKey in ToolPMSpecKeys using @VM
                                    PMSpecRec = Database_Services('ReadDataRow', 'PM_SPEC', PMSpecKey)
                                    ActPMKeys = PMSpecRec<PM_SPEC_PM_KEYS$>
                                    Units     = PMSpecRec<PM_SPEC_UNITS$>
                                    Conv      = ''
                                    If Units = 'D' then	Conv = 'D'
                                    If Units = 'T' then Conv = 'DT'
                                    If Units = 'Q' then Conv = 'MD0'
                                    
                                    Now     = ''
                                    If Units = 'D' then Now = Today
                                    If Units = 'T' then Now = CurrDtm
                                    If Units = 'Q' then Now = CurrCnt
                                    
                                    pmCnt = COUNT(ActPMKeys,@VM) + (ActPMKeys NE '')
                                    
                                    If pmCnt = 0 then pmCnt = 1
                                    
                                    SchedStarts	= obj_PM_Spec('SchedStart',PMSpecKey:@RM:PMSpecRec)
                                    EarlyStarts	= obj_PM_Spec('EarlyStart',PMSpecKey:@RM:PMSpecRec)
                                    LateStarts	= obj_PM_Spec('LateStart', PMSpecKey:@RM:PMSpecRec)
                                    
                                    For I = 1 to pmCnt
                                        SchedStart = SchedStarts<1,I>
                                        EarlyStart = EarlyStarts<1,I>
                                        LateStart  = LateStarts<1,I>
                                        
                                        If Conv NE '' then
                                            SchedStartIn = ICONV(SchedStart,Conv)
                                            EarlyStartIn = ICONV(EarlyStart,Conv)
                                            LateStartIn = ICONV(LateStart,Conv)
                                        end else
                                            SchedStartIn = SchedStart
                                            EarlyStartIn = EarlyStart
                                            LateStartIn	 = LateStart
                                        end
                                        
                                        BEGIN CASE
                                            
                                            CASE SchedStartIn = ''											; NotScheduled = True$
                                            CASE EarlyStartIn = '' AND Now LE SchedStartIn					; NotDue       = True$
                                            CASE Now <	EarlyStartIn										; NotDue       = True$
                                            CASE Now <	SchedStartIn										; DueSoon      = True$
                                            CASE LateStartIn = '' AND Now = SchedStartIn					; CurrentlyDue = True$
                                            CASE LateStartIn = '' AND Now > SchedStartIn					; Overdue      = True$
                                            CASE Now > LateStartIn											; Overdue      = True$
                                            CASE Now GE SchedStartIn										; CurrentlyDue = True$													;
                                                
                                        END CASE
                                        
                                    Next I
                                Next PMSpecKey
                                
                                PMStatus = ''
                                Begin Case
                                    Case Overdue
                                        PMStatus           = 'OVERDUE'
                                        ToolClass          = Xlate('TOOL', ToolID, 'CLASS', 'X')
                                        MonitoredToolTypes = 'FTIR,4PP,HGCV'
                                        Locate ToolClass in MonitoredToolTypes using ',' setting Dummy then
                                            // Only change the tool mode if the tool is in one of the modes listed below.
                                            // record! This is to preserve other tool modes as the current mode such as SCHED_MTC.
                                            CurrMode     = Xlate('TOOL', ToolID, 'CURR_MODE', 'X')<1,1>
                                            ServiceModes = 'PROD':@FM:'LIM':@FM:'VER'
                                            Locate CurrMode in ServiceModes using @FM setting fPos then
                                                PMDesc = PMSpecRec<PM_SPEC_DESC$>
                                                Reason = 'Verification not performed.'
                                                Tool_Services('ChangeToolMode', ToolID, 'QUAL_OVERDUE', Reason, 'OI_ADMIN', True$)
                                            end
                                        end
                                    Case CurrentlyDue
                                        PMStatus = 'CURRENTLY_DUE'
                                    Case DueSoon
                                        PMStatus = 'DUE_SOON'
                                    Case NotScheduled
                                        PMStatus = 'NOT_SCHEDULED'
                                    Case NotDue
                                        PMStatus = 'NOT_DUE'
                                    Case Otherwise$
                                        PMStatus = 'ERROR'
                                End Case
                                
                                If OrigPMStatus _NEC PMStatus then
                                    // Only write the column if the PM status has changed.
                                    WriteV PMStatus on hTool, ToolID, TOOL_PM_STATUS$ else null
                                end
                                
                            end else
                                
                                // No PM_SPEC records defined for this tool
                                If OrigPMStatus _NEC 'NOT_SCHEDULED' then
                                    // Only write the column if the PM status has changed.
                                    WriteV 'NOT_SCHEDULED' on hTool, ToolID, TOOL_PM_STATUS$ else null
                                end
                                
                            end
                        end
                    end
                end
            Next ToolID
        end
        Unlock hSysLists, ServiceKeyID else Null
    end
    
end service


Service FailedPM(PMNo, UserID, StartDTM)
    
    If UserID EQ '' then UserID = @User4
    If StartDTM EQ '' then StartDTM = Datetime()
    PMRec  = Database_Services('ReadDataRow', 'PM', PMNo)
    If Error_Services('NoError') then
        PMSNo         = PMRec<PM_PMS_ID$>
        ToolID = Xlate('PM_SPEC', PMSNo, PM_SPEC_TOOL_ID$, 'X')
        If ( (PMSNo NE '') and (ToolID NE '') ) then
            EarlyStartDTM = IConv(Xlate('PM_SPEC', PMSNo, 'EARLY_START', 'X'), 'DT')
            If StartDTM GE EarlyStartDTM then
                // Only change the tool mode if the tool is in one of the modes listed in the APP_INFO*QUAL_CHANGE_MODES
                // record! This is to preserve other tool modes as the current mode such as SCHED_MTC.
                CurrMode    = Xlate('TOOL', ToolID, 'CURR_MODE', 'X')<1,1>
                Locate CurrMode in ChangeModes using @FM setting fPos then
                    Reason  = 'PM No. ':PMNo:' Failed'
                    NewMode = 'VER_FAILED'
                    Tool_Services('ChangeToolMode', ToolID, NewMode, Reason, UserID, True$)
                end else
                    LogData    = ''
                    LogData<1> = OConv(Datetime(), 'DT2/^H')
                    LogData<2> = ToolID
                    LogData<3> = 'Unable to locate curr mode in the list of modes to change from.'
                    LogData<4> = ''
                    Logging_Services('AppendLog', objLog, LogData, @RM, @FM)    
                end
            end else
                // It is too early to start this PM
                Error_Services('Add', 'Error in ':Service:' service. Too early to start PMNo ':PMNo:'.')
            end
        end
    end
    
end service

Service ProcessQual(PSN, ToolID, CompDtm, Pass)
    
    StatusCode = 'UID001'
    Message    = ''
    If ( (PSN NE '') and (ToolID NE '') and (CompDtm NE '') and (Pass NE '') ) then
        // Find scheduled PM for this qual check.
        // There should only be one PM_SPEC defined for this qual check at this time.
        Option      = ''
        Flag        = ''
        PMSpecKeyID = ''
        Open 'DICT.PM_SPEC' to PmsDict then
            Query = 'TOOL_ID':@VM:ToolID:@FM:'DESC':@VM:'[':PSN:']':@FM:'ARCHIVED':@VM:'#1':@FM
            Btree.Extract(Query, 'PM_SPEC', PmsDict, PMSpecKeyID, '', Flag)
            CurrPMKey   = ''
            If Flag EQ 0 then
                If PMSpecKeyID NE '' then
                    CurrPMKey = Xlate('PM_SPEC', PMSpecKeyID, 'PM_KEYS', 'X')
                    If CurrPMKey NE '' then
                        CompDtm[-3, 1] = ''
                        PMDtm          = IConv(CompDtm, 'DT')
                        If CompDtm EQ '' then
                            PMDtm = Datetime()
                        end
                        If Pass then 
                            // The qual files do not contain which user performed the qual check, so just use OI_ADMIN for now.
                            // The qual files only contain the complete datetime. Use it for both the start and complete datetime.
                            PM_Services('StartPM', CurrPMKey, 'OI_ADMIN', PMDtm)
                            If Error_Services('NoError') then
                                PM_Services('CompletePM', CurrPMKey, 'OI_ADMIN', PMDtm)
                                If Error_Services('NoError') then
                                    StatusCode = 'UID000'
                                    Message    = Service : ' : PM ':CurrPMKey:' for PM_SPEC ':PMSpecKeyID:' completed successfully.'
                                end else
                                    StatusCode = 'UID002'
                                    Message    = Service : ' : ' : Error_Services('GetMessage')
                                end
                            end else
                                StatusCode = 'UID001'
                                Message    = Service : ' : ' : Error_Services('GetMessage')
                            end
                        end else
                            // Failing Qual
                            PM_Services('FailedPM', CurrPMKey, 'OI_ADMIN', PMDtm)
                            If Error_Services('NoError') then
                                StatusCode = 'UID001'
                                Message    = 'Qual fail for ':ToolID:' ':PSN:'. Qual NOT marked complete.'
                            end else
                                StatusCode = 'UID001'
                                Message    = Error_Services('GetMessage')                          
                            end
                        end
                    end else
                        StatusCode = 'UID001'
                        Message    = 'No scheduled PM found for ':ToolID:' ':PSN:'.'       
                    end
                end else
                    StatusCode = 'UID001'
                    Message    = 'No PM_SPEC record found for ':ToolID:' ':PSN:'.'                
                end
            end else
                StatusCode = 'UID002'
                Message    = 'Error calling Btree.Extract. Btree flag: ':Flag        
            end
        end else
            StatusCode = 'UID002'
            Message    = 'Error opening DICT.PM_SPEC.'
        end
    end else
        
    end
    Response = StatusCode:@FM:Message
    
end service


Service Get5SPMs(ShowArchived=BOOLEAN, Area=AREAS)
    
    Option  = ''
    Flag    = ''
    keylist = ''
    Query  = ''
    Open 'DICT.PM_SPEC' to PmsDict then
        if Not(ShowArchived) then
            Query := 'ARCHIVED':@VM:'#1':@FM 
        end
        If Area NE '' then
            Query := 'AREA':@VM:Area:@FM
        end
        Query := 'FIVE_S_FLAG':@VM:True$:@FM

        Btree.Extract(Query, 'PM_SPEC', PmsDict, keylist, '', Flag)
    end
    Response = keylist
    
end service

Service GetScrubberPMs(ShowArchived=BOOLEAN)
    
    Option  = ''
    Flag    = ''
    keylist = ''
    Query  = ''
    Open 'DICT.PM_SPEC' to PmsDict then
        if NOT(ShowArchived) then
            Query := 'PM_CLASS':@VM:'SCRUBBER':@FM
            Query := 'ARCHIVED':@VM:'#1':@FM 
        end else
            Query := 'PM_CLASS':@VM:'SCRUBBER':@FM
        end
        Btree.Extract(Query, 'PM_SPEC', PmsDict, keylist, '', Flag)
    end
    Response = keylist
    
end service

Service ScheduleNextPM(PMSID, PMNo, StartQty)
    
    //This service is designed to schedule the next PM based on the completion time of the last completion.
    //Rather than scheduling the next PM based on a set schedule.
    
    CurrDTM   = Datetime()
    CurrDt    = Date()
    PMSpecRec = Database_Services('ReadDataRow', 'PM_SPEC', PMSID)
    Interval  = PMSpecRec<PM_SPEC_INTERVAL$>
    Units = PMSpecRec<PM_SPEC_UNITS$>
    thisStartQty = ICONV(StartQty,'MD0')
    SchedDt  = ''
    SchedTm  = ''
    SchedQty = ''
    BEGIN CASE
        CASE Units = 'D'
            //SchedDt = CurrDTM + PMSpecRec<PM_SPEC_INTERVAL$>	;* Interval is in days
            SchedDt = SRP_Datetime('AddDays', CurrDt, Interval)
            
        CASE Units = 'T'
            Interval        = PMSpecRec<PM_SPEC_INTERVAL$>					;* Interval is in hours
            Interval        = ( Interval/24 )  								;* Convert hours to decimal part of day
            EarlyStartDelta = PMSpecRec<PM_SPEC_EARLY_START_DELTA$>
            SchedDTM        = CurrDTM + Interval
            SchedDTM     = OCONV(SchedDTM, 'DT/^S')
            SchedDt      = SchedDTM[1,' ']
            SchedTm      = SchedDTM[COL2()+1,' ']
            SchedDt      = ICONV(SchedDt,'D')
            SchedTm      = ICONV(SchedTm,'MT')
            
        CASE Units = 'Q'
            // Run-based PM
            if thisStartQty NE '' then
                SchedQty = Interval + thisStartQty
            end else
                Error_Services('Add', 'Start Qty not supplied to PM_Services -> ScheduleNextPM')
            end
            
        Case Units = 'M'
            //Month based PM
            SchedDt = SRP_Datetime('AddMonths', CurrDt, Interval)
        CASE 1
            * Missing Units
            RETURN
    END CASE
    if Error_Services('NoError') then
        PMNo                 = NextKey('PM')				;* Next PMKey
        PMRec                = ''
        PMRec<PM_PMS_ID$>    = PMSId						;* New PMRec
        PMrec<PM_ENTER_BY$>  = 'AUTO'						;* Automated process user
        PMRec<PM_ENTER_DTM$> = CurrDTM
        PMRec<PM_SCHED_DT$>  = SchedDt
        PMRec<PM_SCHED_TM$>  = SchedTm
        PMRec<PM_SCHED_QTY$> = OCONV(SchedQty,'MD0')
        Database_Services('WriteDataRow', 'PM', PMNo, PMRec)
    end
    
    
end service

Service GetPMNotificationRecipients(PMSID)
    Recipients = ''
    If PMSID NE '' then
        If RowExists('PM_SPEC', PMSID) then
            Recipients           := Lsl_Users_Services('GetOnShiftUsersByClass', 'Si Shift Supervisors', 0)
            Recipients           := @VM : Lsl_Users_Services('GetOnShiftUsersByClass', 'Lead Operator', 0)
            ADNotificationGroups  = XLATE('PM_SPEC', PMSID, PM_SPEC_AD_NOTIFICATION_GROUPS$, 'X')
            IF ADNotificationGroups NE '' then
                for each ADGroup in ADNotificationGroups using @VM
                    GroupMemberList = Active_Directory_Services('GetADGroupMembersByGroupName', ADGroup, 'INFINEON')
                    for each GroupMember in GroupMemberList using @FM
                        ADUsername        = LCASE(GroupMember<1,1>)
                        ADToLSLUserMap    = Database_Services('ReadDataRow', 'APP_INFO', 'AD_TO_LSL_USER_MAP')
                        ADToLSLUserMap<1> = LCASE(ADToLSLUserMap<1>)
                        Locate ADUsername in ADToLSLUserMap<1> using @VM setting userPos then
                            LSLUserID         = ADToLSLUserMap<2, userPos>
                            Recipients<1, -1> = LSLUserID
                        end
                    Next GroupMember
                Next ADGroup
            end
        end else
            Error_Services('Add', 'Error in GetPMNotificationRecipients: PM Spec record with key id ' : PMSID : 'does not exist.')
        end
    end else
        Error_Services('Add', 'Error in GetPMNotificationRecipients: PMSID was null')
    end
    Response = Recipients
end service

Service SendPMNotifications()
    hSysLists             = Database_Services('GetTableHandle', 'SYSLISTS')
    Lock hSysLists, ServiceKeyID then
        errMessage   = ''
        PMStatuses   = Pm_Services('GetPMStatuses')
        SentFrom     = 'OI_ADMIN'
        AttachWindow = ''
        AttachKey    = ''
        SendToGroup  = ''
        for each PMStatusLine in PMStatuses using @FM
            Status                = PMStatusLine<1,COL$STATUS>
            LastNotification      = PMStatusLine<1,COL$NOTIFICAITON>
            PMDesc                = XLATE('PM_SPEC', PMStatusLine<1,COL$PMSKEY>, PM_SPEC_DESC$, 'X')
            PMKey                 = PMStatusLine<1,COL$CURRPMKEY>
            
            PMRec                 = Database_Services('ReadDataRow', 'PM', PMKey)
            PMSpecKey             = PMStatusLine<1, COL$PMSKEY>
            PMSRec                = Database_Services('ReadDataRow', 'PM_SPEC', PMSpecKey)
            Tool                  = PMSRec<PM_SPEC_TOOL_ID$>
            SendEarlyNotification = PMSRec<PM_SPEC_SEND_EARLY_NOTIFICATION$>
            SendDueNotification   = PMSRec<PM_SPEC_SEND_DUE_NOTIFICATION$>
            SendLateNotification  = PMSRec<PM_SPEC_SEND_LATE_NOTIFICATION$>
            If LastNotification EQ '' then
                Begin Case
                    Case Status EQ 'EARLY'
                        IF SendEarlyNotification then
                            If PMRec<PM_EARLY_NOTIF_SENT$> EQ '' then
                                PMRec<PM_EARLY_NOTIF_SENT$> = Datetime()
                                Database_Services('WriteDataRow', 'PM', PMKey, PMRec, 1, 0, 1)
                                if Error_Services('NoError') then
                                    UpdatedPMRec               = Database_Services('ReadDataRow', 'PM', PMKey, True$, 0, False$)
                                    If UpdatedPMRec<PM_EARLY_NOTIF_SENT$> NE '' then
                                        Recipients = PM_Services('GetPMNotificationRecipients', PMSpecKey)
                                        if Error_Services('NoError') then
                                            LogData    = ''
                                            LogData<1> = LoggingDTM;//Defined at entry of subroutine
                                            LogData<2> = Tool
                                            LogData<3> = PMDesc
                                            LogData<4> = 'EARLY NOTIFICATIONS Prechecks passed, message okay to send.'
                                            Logging_Services('AppendLog', objLogNotifications, LogData, @RM, @FM, False$)
                                            
                                            Subject = 'PM Task Coming Due'
                                            Message = 'Tool: ': Tool : ' - ' :PMDesc:" is coming due. Scheduled due by " : OCONV(PMStatusLine<1,COL$DUEBY>, 'DT')
                                            Parms   = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
                                            obj_Notes('Create',Parms)
                                            
                                            LogData    = ''
                                            LogData<1> = LoggingDTM;//Defined at entry of subroutine
                                            LogData<2> = Tool
                                            LogData<3> = PMDesc
                                            LogData<4> = 'EARLY NOTIFICATIONS OBJ_Notes has been called by this point, message should have been sent.'
                                            Logging_Services('AppendLog', objLogNotifications, LogData, @RM, @FM, False$)
                                        end else
                                            errMessage = Error_Services('GetMessage')
                                            LogData    = ''
                                            LogData<1> = LoggingDTM;//Defined at entry of subroutine
                                            LogData<2> = Tool
                                            LogData<3> = PMDesc
                                            LogData<4> = 'EARLY notification failed - ' : errMessage
                                            Logging_Services('AppendLog', objLogNotifications, LogData, @RM, @FM, False$)
                                        end 
                                    end else
                                        errMessage = 'EARLY Notifcation wasn not marked as completed when it should have been.'
                                        LogData    = ''
                                        LogData<1> = LoggingDTM;//Defined at entry of subroutine
                                        LogData<2> = Tool
                                        LogData<3> = PMDesc
                                        LogData<4> = 'EARLY notification failed - ' : errMessage
                                        Logging_Services('AppendLog', objLogNotifications, LogData, @RM, @FM, False$)
                                    end
                                    
                                end else
                                    errMessage = Error_Services('GetMessage')
                                    LogData    = ''
                                    LogData<1> = LoggingDTM;//Defined at entry of subroutine
                                    LogData<2> = Tool
                                    LogData<3> = PMDesc
                                    LogData<4> = 'EARLY notification failed - ' : errMessage
                                    Logging_Services('AppendLog', objLogNotifications, LogData, @RM, @FM, False$)
                                end 
                            end else
                                LogData    = ''
                                LogData<1> = LoggingDTM;//Defined at entry of subroutine
                                LogData<2> = Tool
                                LogData<3> = PMDesc
                                LogData<4> = 'EARLY notification did not send because it has been marked as being already sent.'
                                Logging_Services('AppendLog', objLogNotifications, LogData, @RM, @FM, False$)
                            end
                        end
                    Case Status EQ 'DUE'
                        If SendDueNotification then
                            If PMRec<PM_DUE_NOTIF_SENT$> EQ '' then
                                PMRec<PM_DUE_NOTIF_SENT$> = Datetime()
                                Database_Services('WriteDataRow', 'PM', PMKey, PMRec, 1, 0, 1)
                                if Error_Services('NoError') then
                                    UpdatedPMRec               = Database_Services('ReadDataRow', 'PM', PMKey, True$, 0, False$)
                                    If UpdatedPMRec<PM_DUE_NOTIF_SENT$> NE '' then
                                        Recipients = PM_Services('GetPMNotificationRecipients', PMSpecKey)
                                        if Error_Services('NoError') then
                                            LogData    = ''
                                            LogData<1> = LoggingDTM;//Defined at entry of subroutine
                                            LogData<2> = Tool
                                            LogData<3> = PMDesc
                                            LogData<4> = 'DUE NOTIFICATIONS Prechecks passed, message okay to send.'
                                            Logging_Services('AppendLog', objLogNotifications, LogData, @RM, @FM, False$)
                                            
                                            Subject    = 'PM Task Due'
                                            Message    = 'Tool: ': Tool : ' - ' :PMDesc:" is due. Scheduled due by " : OCONV(PMStatusLine<1,COL$DUEBY>, 'DT')
                                            Parms      = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
                                            obj_Notes('Create',Parms)
                                            
                                            LogData    = ''
                                            LogData<1> = LoggingDTM;//Defined at entry of subroutine
                                            LogData<2> = Tool
                                            LogData<3> = PMDesc
                                            LogData<4> = 'DUE NOTIFICATIONS OBJ_Notes has been called by this point, message should have been sent.'
                                            Logging_Services('AppendLog', objLogNotifications, LogData, @RM, @FM, False$)
                                        end else
                                            errMessage = Error_Services('GetMessage')
                                            LogData    = ''
                                            LogData<1> = LoggingDTM;//Defined at entry of subroutine
                                            LogData<2> = Tool
                                            LogData<3> = PMDesc
                                            LogData<4> = 'DUE notification failed - ' : errMessage
                                            Logging_Services('AppendLog', objLogNotifications, LogData, @RM, @FM, False$)
                                        end
                                        
                                    end else
                                        errMessage = 'DUE Notifcation was not marked as completed when it should have been.'
                                        LogData    = ''
                                        LogData<1> = LoggingDTM;//Defined at entry of subroutine
                                        LogData<2> = Tool
                                        LogData<3> = PMDesc
                                        LogData<4> = 'DUE notification failed - ' : errMessage
                                        Logging_Services('AppendLog', objLogNotifications, LogData, @RM, @FM, False$)  
                                    end
                                end else
                                    errMessage = Error_Services('GetMessage')
                                    LogData    = ''
                                    LogData<1> = LoggingDTM;//Defined at entry of subroutine
                                    LogData<2> = Tool
                                    LogData<3> = PMDesc
                                    LogData<4> = 'DUE notification failed - ' : errMessage
                                    Logging_Services('AppendLog', objLogNotifications, LogData, @RM, @FM, False$)
                                end
                            end else
                                LogData    = ''
                                LogData<1> = LoggingDTM;//Defined at entry of subroutine
                                LogData<2> = Tool
                                LogData<3> = PMDesc
                                LogData<4> = 'DUE notification did not send because it has been marked as being already sent.'
                                Logging_Services('AppendLog', objLogNotifications, LogData, @RM, @FM, False$)
                            end
                        end
                    Case Status EQ 'LATE'
                        if SendLateNotification then
                            If PMRec<PM_LATE_NOTIF_SENT$> EQ '' then
                                PMRec<PM_LATE_NOTIF_SENT$> = Datetime()
                                Database_Services('WriteDataRow', 'PM', PMKey, PMRec, 1, 0, 1)
                                if Error_Services('NoError') then
                                    //Check to make sure this change is commited by rereading in the record
                                    UpdatedPMRec               = Database_Services('ReadDataRow', 'PM', PMKey, True$, 0, False$)
                                    If UpdatedPMRec<PM_LATE_NOTIF_SENT$> NE '' then
                                        Recipients = PM_Services('GetPMNotificationRecipients', PMSpecKey)
                                        if Error_Services('NoError') then
                                            LogData    = ''
                                            LogData<1> = LoggingDTM;//Defined at entry of subroutine
                                            LogData<2> = Tool
                                            LogData<3> = PMDesc
                                            LogData<4> = 'LATE NOTIFICATIONS Prechecks passed, message okay to send.'
                                            Logging_Services('AppendLog', objLogNotifications, LogData, @RM, @FM, False$)
                                            
                                            Subject    = 'PM overdue'
                                            Message    = 'Tool: ': Tool : ' - ' :PMDesc:" is overdue. Scheduled due by " : OCONV(PMStatusLine<1,COL$DUEBY>, 'DT')
                                            Parms      = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
                                            obj_Notes('Create',Parms)
                                            
                                            LogData    = ''
                                            LogData<1> = LoggingDTM;//Defined at entry of subroutine
                                            LogData<2> = Tool
                                            LogData<3> = PMDesc
                                            LogData<4> = 'LATE NOTIFICATIONS OBJ_Notes has been called by this point, message should have been sent.'
                                            Logging_Services('AppendLog', objLogNotifications, LogData, @RM, @FM, False$)
                                        end else
                                            errMessage = Error_Services('GetMessage')
                                            LogData    = ''
                                            LogData<1> = LoggingDTM;//Defined at entry of subroutine
                                            LogData<2> = Tool
                                            LogData<3> = PMDesc
                                            LogData<4> = 'LATE notification failed - ' : errMessage
                                            Logging_Services('AppendLog', objLogNotifications, LogData, @RM, @FM, False$)
                                        end
                                        
                                    end else
                                        errMessage = 'LATE Notifcation was not marked as completed when it should have been.'
                                        LogData    = ''
                                        LogData<1> = LoggingDTM;//Defined at entry of subroutine
                                        LogData<2> = Tool
                                        LogData<3> = PMDesc
                                        LogData<4> = 'LATE notification failed - ' : errMessage
                                        Logging_Services('AppendLog', objLogNotifications, LogData, @RM, @FM, False$)
                                    end
                                end else
                                    errMessage = Error_Services('GetMessage')
                                    LogData    = ''
                                    LogData<1> = LoggingDTM;//Defined at entry of subroutine
                                    LogData<2> = Tool
                                    LogData<3> = PMDesc
                                    LogData<4> = 'LATE notification failed - ' : errMessage
                                    Logging_Services('AppendLog', objLogNotifications, LogData, @RM, @FM, False$)
                                end
                                
                            end else
                                LogData    = ''
                                LogData<1> = LoggingDTM;//Defined at entry of subroutine
                                LogData<2> = Tool
                                LogData<3> = PMDesc
                                LogData<4> = 'LATE notification did not send because it has been marked as being already sent.'
                                Logging_Services('AppendLog', objLogNotifications, LogData, @RM, @FM, False$)
                            end
                        end
                End Case
            end
        Next PMStatus
        Unlock hSysLists, ServiceKeyID else Null
    end
    
end service

Service GetPMStatuses()
    
    SendEarlyCnt            = 0
    SendDueCnt              = 0
    SendLateCnt             = 0
    DuePMs                  = ''
    //Step 1: Get all PM's that are not complete
    equ TARGET_ACTIVELIST$ to 5
    Statement               = "SELECT PM_SPEC WITH ARCHIVED NE 1"
    rlist( Statement, target_activelist$, '', '', '' )
    PMSpecList              = ''
    IF @RecCount then
        EoF = 0
        NumKeys = @RecCount
        Cnt = 0
        Loop
            ReadNext PmsId Else EoF = 1
        until EoF
            PMSpecList<-1> = PmsId
        Repeat
    end
    for each PmsKey in PMSpecList using @FM
        CurrDt     = Date()
        CurrDtm    = Datetime()
        PmsRec     = Database_Services('ReadDataRow', 'PM_SPEC', PmsKey)
        Is5S       = PmsRec<PM_SPEC_FIVE_S_FLAG$>
        Units      = PmsRec<PM_SPEC_UNITS$>
        CurrPMId   = PmsRec<PM_SPEC_PM_KEYS$, 1>
        CurrPmRec  = Database_Services('ReadDataRow', 'PM', CurrPMId)
        Begin Case
            Case Units EQ 'T'
                EarlyStart = ICONV(obj_PM_Spec('EarlyStart',PmsKey:@RM:PmsRec), 'DT')
                DueStart   = ICONV(obj_PM_Spec('SchedStart',PmsKey:@RM:PmsRec), 'DT')
                LateStart  = ICONV(obj_PM_Spec('LateStart',PmsKey:@RM:PmsRec), 'DT')
            Case Units EQ 'D'
                EarlyStart = ICONV(obj_PM_Spec('EarlyStart',PmsKey:@RM:PmsRec), 'D')
                DueStart   = ICONV(obj_PM_Spec('SchedStart',PmsKey:@RM:PmsRec), 'D')
                LateStart  = ICONV(obj_PM_Spec('LateStart',PmsKey:@RM:PmsRec), 'D')
            Case 0
                EarlyStart = obj_PM_Spec('EarlyStart',PmsKey:@RM:PmsRec)
                DueStart   = obj_PM_Spec('SchedStart',PmsKey:@RM:PmsRec)
                LateStart  = obj_PM_Spec('LateStart',PmsKey:@RM:PmsRec)
        End Case
        
        
        SendEarly = false$
        SendDue   = false$
        SendLate  = false$
        NotDue    = false$
        
        Begin Case
            Case Units EQ 'D'
                
                Begin Case
                    Case CurrDt GE EarlyStart AND CurrDt LT DueStart
                        //Send Early Start
                        SendEarly = True$
                    Case CurrDt GE DueStart AND CurrDt LT LateStart
                        //Send Due Start
                        SendDue = True$
                    Case CurrDt GE LateStart
                        //Send Late Start
                        SendLate = True$
                    Case OTHERWISE$
                        NotDue = True$
                End Case
            Case Units EQ 'T'
                
                Begin Case
                    Case CurrDtm GE EarlyStart AND CurrDtm LT DueStart
                        //Send Early Start
                        SendEarly = True$
                    Case CurrDtm GE DueStart AND CurrDtm LT LateStart
                        //Send Due Start
                        SendDue = True$
                    Case CurrDtm GE LateStart
                        //Send Late Start
                        SendLate = True$
                    Case OTHERWISE$
                        NotDue = True$
                End Case
            Case Units EQ 'Q'
                
        End Case
        
        
        If SendEarly then
            SendEarlyCnt     += 1
            NotificationSent  = CurrPMRec<PM_EARLY_NOTIF_SENT$>
            DuePMs<-1>        = PmsKey : @VM : 'EARLY' : @VM : NotificationSent : @VM : LateStart : @VM : CurrPMId
        end
        If SendDue then
            SendDueCnt += 1
            NotificationSent  = CurrPMRec<PM_DUE_NOTIF_SENT$>
            DuePMs<-1>  = PmsKey : @VM : 'DUE' : @VM: NotificationSent : @VM : LateStart : @VM : CurrPMId
        end
        
        If SendLate then
            SendLateCnt += 1
            NotificationSent  = CurrPMRec<PM_LATE_NOTIF_SENT$>
            DuePMs<-1>   = PmsKey : @VM : 'LATE' : @VM : NotificationSent : @VM : LateStart : @VM : CurrPMId
        end
        If NotDue then
            DuePMs<-1> = PmsKey : @VM : 'Not Due'
        end
    Next PmsKey
    Response = DuePMs
    
end service

Service CompleteScrubberPM(ScrubberID)
    Option  = ''
    Flag    = ''
    keylist = ''
    Query  = ''
    Open 'DICT.PM_SPEC' to PmsDict then
        Query := 'TOOL_ID':@VM:ScrubberID:@FM
        Btree.Extract(Query, 'PM_SPEC', PmsDict, keylist, '', Flag)
    end
    ScrubberPMSpecKeys = keylist
    If DCOUNT(ScrubberPMSpecKeys, @VM) GT 0 then
        for each PMSKey in keylist using @VM
            PMKeys = XLATE('PM_SPEC', PMSKey, 'PM_KEYS', 'X')
            If DCount(PMKeys, @VM GT 0) then
                for each PMKey in PMKeys using @VM
                    Pm_Services('CompleteNonToolPM', PMKey, 'SYSTEM', DateTime())
                    If Error_Services('HasError') then
                        ErrMsg = Error_Services('GetMessage')
                        Error_Services('Add', 'Error trying to complete Scrubber PM:' : ErrMsg)
                        LogData    = ''
                        LogData<1> = OConv(Datetime(), 'DT2/^H')
                        LogData<2> = ScrubberID
                        LogData<3> = 'Error'
                        LogData<4> = 'PM ' : PMKey : '. ' : ErrMsg 
                        Logging_Services('AppendLog', objLogScrubbers, LogData, @RM, @FM)
                    end else
                        LogData    = ''
                        LogData<1> = OConv(Datetime(), 'DT2/^H')
                        LogData<2> = ScrubberID
                        LogData<3> = 'Success'
                        LogData<4> = 'PM ' : PMKey : ' Completed successfully'
                        Logging_Services('AppendLog', objLogScrubbers, LogData, @RM, @FM)
                    end
                Next PMKey
            end else
                ErrMsg     = 'There were no scheduled PMs for ' : ScrubberID
                Error_Services('Add', ErrMsg)
                LogData    = ''
                LogData<1> = OConv(Datetime(), 'DT2/^H')
                LogData<2> = ScrubberID
                LogData<3> = 'Error'
                LogData<4> = ErrMsg
                Logging_Services('AppendLog', objLogScrubbers, LogData, @RM, @FM)
            end
        Next PMSKey
    end else
        ErrMsg     = 'There were no defined PMs for ' : ScrubberID
        Error_Services('Add', ErrMsg)
        
        Error_Services('Add', ErrMsg)
        LogData    = ''
        LogData<1> = OConv(Datetime(), 'DT2/^H')
        LogData<2> = ScrubberID
        LogData<3> = 'Error'
        LogData<4> = ErrMsg
        Logging_Services('AppendLog', objLogScrubbers, LogData, @RM, @FM)
    end
    
end service

Service GetActivePMsByToolId(ToolId)
    ErrorMessage   = ''
    ActivePMIdList = ''
    If ToolId NE '' then
        Open 'DICT.PM_SPEC' to @DICT then
            Option      = ''
            Flag        = ''
            PMSpecList  = ''
            SearchStr   = 'TOOL_ID':@VM:ToolId:@FM
            SearchStr  := 'ARCHIVED':@VM:'#1':@FM 
            Btree.Extract(SearchStr, 'PM_SPEC', @DICT, PMSpecList, '', Flag)
            If Flag EQ 0 AND PMSpecList NE '' then
                for each PMSpecId in PMSpecList using @VM
                    ActivePMKeys         = Database_Services('ReadDataColumn', 'PM_SPEC', PMSpecId, PM_SPEC_PM_KEYS$, True$, 0, False$)
                    If ActivePMKeys NE '' then
                        ActivePMIdList<1,-1> = ActivePMKeys
                    end
                Next PMSpecId
            end else
                ErrorMessage = 'Error in PM_Services -> GetActivePMsByToolIdAndType, unable to find active PM Specs for this tool id'
            end
        end else
           ErrorMessage = 'Error in PM_Services -> GetActivePMsByToolIdAndType, error opening PM_SPEC dictionary' 
        end
        
    end else
        ErrorMessage = 'Error in PM_Services -> GetActivePMsByToolIdAndType, null tool id passed to routine'
    end
    Response = ActivePMIdList
end service

Processing:
  ctr += 1
return




