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

Declare subroutine Error_Services, Database_Services, Btree.Extract, Logging_Services, SRP_JSON

Declare function Rti_Createguid, Database_Services, Return_To_Fab_Services, Datetime, Error_Services
Declare function Logging_Services, Environment_Services, SRP_JSON, MemberOf, Lot_Services, RTF_CreateGUID
Declare function Lot_Operation_Services, Date_Services
Declare subroutine obj_notes, SRP_Run_Command, Lot_Services, Return_To_Fab_Services, Lot_Event_Services
Declare subroutine Lot_Operation_Services

$insert LOGICAL
$Insert APP_INSERTS
$Insert RETURN_TO_FAB_LOTS_EQUATES
$Insert RETURN_TO_FAB_RESULT_OPTION_EQUATES
$Insert WO_MAT_EQUATES
$Insert RDS_EQUATES
$Insert NOTIFICATION_EQUATES
$Insert LOT_EQUATES
$Insert PRS_STAGE_EQUATES
$Insert LOT_OPERATION_EQUATES
$Insert OPERATION_EQUATES

LogPath    = Environment_Services('GetApplicationRootPath') : '\LogFiles\Return_To_Fab_Services'; //Define the directory where the log will be saved to. This happens the first time of the day that the log is written to.
LogDate    = Oconv(Date(), 'D4/')
LogTime    = Oconv(Time(), 'MTS')
LoggingDTM = LogDate : ' ' : LogTime   ; // Logging DTM

LogFileName       = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' ReturnToFabServicesLog.csv'
Headers           = 'Logging DTM' : @FM : 'Cass Id' : @FM: 'User' : @FM : 'ReturnToFabId' : @FM : 'Message'; //Define the column names in the log file, delimited by a Field Mark.
objReturnToFabLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ',', Headers, '', False$, False$); //Actually creates the log.

GoToService

Return Response or ""

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

Service CreateReturnToFabRecord(CassId, UserId)
    
    ErrorMessage = ''
    NewRTFId     = ''
    If CassId NE '' then
        CassType = ''
        Begin Case
            Case RowExists('RDS', CassId)
                CassType = 'RDS'
            Case RowExists('WM_OUT', CassId)
                CassType = 'WM_OUT'
            Case Otherwise$
                ErrorMessage = 'Error creating return to fab record, Cassette ID not found.'
        End Case
        If ErrorMessage EQ '' then
            OpenRTFRecordExists = Return_To_Fab_Services('GetOpenReturnToFabRecordIdByCassId', CassId) NE ''
            If Not(OpenRTFRecordExists) then
                If RowExists('LSL_USERS', UserId) then
                    //Validation: Need to ensure the lot has a batch number to ensure it "Has Left The Fab"
                    SAPBatchNo = ''
                    Begin Case
                        Case CassType EQ 'RDS'
                            WONo       = Database_Services('ReadDataColumn', 'RDS', CassId, RDS_WO$, True$, 0, False$)
                            CassNo     = Database_Services('ReadDataColumn', 'RDS', CassId, RDS_CASS_NO$, True$, 0, False$)
                            WOMatKeyId = WONo : '*' : CassNo
                            SAPBatchNo = Database_Services('ReadDataColumn', 'WO_MAT', WOMatKeyId, WO_MAT_SAP_BATCH_NO$, True$, 0, False$)
                        Case CassType EQ 'WM_OUT'
                            WONo       = Field(CassId, '*', 1)
                            CassNo     = Field(CassId, '*', 3)
                            WOMatKeyId = WONo : '*' : CassNo
                            SAPBatchNo = Database_Services('ReadDataColumn', 'WO_MAT', WOMatKeyId, WO_MAT_SAP_BATCH_NO$, True$, 0, False$)
                    End Case
                    If SAPBatchNo NE '' then
                        NewRTFId                                         = Rti_Createguid()
                        RTFRecord                                        = ''
                        RTFRecord<RETURN_TO_FAB_LOTS_CASS_ID$>           = CassId
                        RTFRecord<RETURN_TO_FAB_LOTS_LOT_TYPE$>          = CassType
                        RTFRecord<RETURN_TO_FAB_LOTS_REQUESTOR_USER_ID$> = UserId
                        RTFRecord<RETURN_TO_FAB_LOTS_START_DTM$>         = Datetime()
                        RTFRecord<RETURN_TO_FAB_LOTS_COMPLETED$>         = False$
                        Database_Services('WriteDataRow', 'RETURN_TO_FAB_LOTS', NewRTFId, RTFRecord, True$, False$, True$)
                        If Error_Services('NoError') then
                            //Check to see if a lot already exists. If not create it.
                            NGLotId = Lot_Services('GetLotIdByLegacyLotIdAndType', CassId, CassType)
                            If NGLotId EQ '' then
                                EpiPartNo = XLATE('WO_LOG', WONo, WO_LOG_EPI_PART_NO$, 'X')
                                ProdVerNo = XLATE('WO_LOG', WONo, WO_LOG_PROD_VER_NO$, 'X')
                                NGProdName = EpiPartNo : '*' : ProdVerNo
                                NGLotId = Lot_Services('CreateNewLot', CassType, NGProdName, '', '', '', '', UserId, '', CassId)
                                If Error_Services('NoError') then
                                     
                                end
                            end
                            If NGLotId NE '' then
                                //Assign default return to fab operations and move in.
                                Return_To_Fab_Services('AddDefaultRTFOperations', NGLotId)
                                If Error_Services('NoError') then
                                    //Move in the lot
                                    Lot_Services('MoveInLot', NGLotId, UserId)
                                    If Error_Services('NoError') then
                                        Lot_Services('MoveOutLot', NGLotId, UserId)
                                        If Error_Services('NoError') then
                                            //Send notification that a return to fab record was created.
                                            Message            = 'Return to fab form created for ' : CassId : ' by ' : UserId : '.' : CRLF$
                                            Message           := 'Link to Return To Fab form: https://goto.infineon.com/oiwizard/ReturnToFab'
                                            Recipients         = XLATE('NOTIFICATION','SHIPPING',NOTIFICATION_USER_ID$,'X')
                                            Recipients<1, -1>  = XLATE('NOTIFICATION','RETURN_TO_FAB_ENG',NOTIFICATION_USER_ID$,'X')
                                            Recipients<1, -1>  = XLATE('NOTIFICATION','RETURN_TO_FAB_MANUF',NOTIFICATION_USER_ID$,'X')
                                            Recipients<1, -1>  = UserId
                                            SentFrom           = 'OI_ADMIN'
                                            Subject            = 'Return To Fab Form Created'
                                            SendToGroup        = ''
                                            AttachWindow       = ''
                                            AttachKey          = ''
                                            Parms              = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
                                            obj_Notes('Create',Parms)
                                        end else
                                            ErrorMessage = 'Error moving lot out of the first RTF operation.'
                                        end
                                    end else
                                        ErrorMessage = 'Error moving lot into the first RTF operation.'
                                    end
                                end else
                                    ErrorMessage = 'Error initializaing lot operation records'
                                end
                            end else
                                ErrorMessage = 'Error getting NG Lot Id.'    
                            end
                        end else
                            ErrorMessage = Error_Services('GetMessage')
                        end
                    end else
                        ErrorMessage = 'Error creating return to fab record, Cassette ID is not currently in SAP and cannot be returned to fab.'    
                    end
                end else
                    ErrorMessage = 'Error creating return to fab record, User not found.' 
                end
            end else
                ErrorMessage = 'Error creating return to fab record, an active return to fab for this lot already exists.'
            end
        end
    end else
        ErrorMessage = 'Error creating return to fab record, Cassette ID was null'
    end
    If ErrorMessage EQ '' AND NewRTFId NE '' then
        LogData    = ''
        LogData<1> = LoggingDTM
        LogData<2> = CassId
        LogData<3> = UserId
        LogData<4> = NewRTFId
        LogData<5> = 'Successfully created new RETURN_TO_FAB_LOTS record'
        Logging_Services('AppendLog', objReturnToFabLog, LogData, @RM, @FM, False$)
        Response   = NewRTFId
    end else
        LogData    = ''
        LogData<1> = LoggingDTM
        LogData<2> = CassId
        LogData<3> = UserId
        LogData<4> = NewRTFId
        LogData<5> = ErrorMessage
        Logging_Services('AppendLog', objReturnToFabLog, LogData, @RM, @FM, False$)
        Response   = NewRTFId
        Error_Services('Add', ErrorMessage)
    end
    
End Service

Service AddDefaultRTFOperations(LotId)
    
    ErrorMessage = ''
    If LotId NE '' then
		// Todo: add these to a configuration for return to fab.
		CurrentOperationsSeq = Lot_Services('GetLotOperationSequence', LotId)
		if CurrentOperationsSeq EQ '' then
			CurrSeq = 0
		end else
			CurrSeq = DCount(CurrentOperationsSeq, @FM)
		end
		Lot_Operation_Services('AddOperationToLot', LotId, 'RTF_START', CurrSeq + 1, 'SYSTEM')
		If Error_Services('NoError') then
			Lot_Operation_Services('AddOperationToLot', LotId, 'RTF_ASSIGN_REASON', CurrSeq + 2, 'SYSTEM')
		end else
			ErrorMessage = Error_Services('GetMessage')
		end
		If Error_Services('NoError') then
		   Lot_Operation_Services('AddOperationToLot', LotId, 'RTF_ASSIGN_OPERATIONS', CurrSeq + 3, 'SYSTEM') 
		end else
			ErrorMessage = Error_Services('GetMessage')
		end
		If Error_Services('NoError') then
			Lot_Operation_Services('AddOperationToLot', LotId, 'RTF_INIT_BIN_TO_BIN', CurrSeq + 4, 'SYSTEM')
		end else
			ErrorMessage = Error_Services('GetMessage')
		end
		If Error_Services('NoError') then
		   Lot_Operation_Services('AddOperationToLot', LotId, 'RTF_DISPO', CurrSeq + 5, 'SYSTEM') 
		end else
			ErrorMessage = Error_Services('GetMessage')
		end
		If Error_Services('NoError') then
		   Lot_Operation_Services('AddOperationToLot', LotId, 'RTF_FINAL_BIN_TO_BIN', CurrSeq + 6, 'SYSTEM') 
		end else
			ErrorMessage = Error_Services('GetMessage')
		end
		If Error_Services('NoError') then
		   Lot_Operation_Services('AddOperationToLot', LotId, 'RTF_CLOSE', CurrSeq + 7, 'SYSTEM')
		end else
			ErrorMessage = Error_Services('GetMessage')
		end
    end else
    	ErrorMessage = 'LotID Parameter was null.'
    end
    If ErrorMessage NE '' then
        Error_Services('Add', ErrorMessage)
    end
    
end service


Service GetReturnToFabResultOptions()
    
    ErrorMessage        = ''
    RTFResultOptions    = ''
    RTFResultOptionKeys = ''
    table = "RETURN_TO_FAB_RESULT_OPTION"
    open "DICT ":table To @DICT then
        srch_strng  = "ACTIVE":@VM:True$:@FM
        option      = ""
        flag        = ""
        Btree.Extract(srch_strng, table, @DICT, RTFResultOptionKeys, option, flag)
        for each RTFOptionID in RTFResultOptionKeys using @VM setting rPos
            RTFResultOptions<1, rPos> = RTFOptionID
            ResultDesc                = Database_Services('ReadDataColumn', table, RTFOptionID, RETURN_TO_FAB_RESULT_OPTION_RESULT$, True$, 0, False$)
            RTFResultOptions<2, rPos> = ResultDesc
        Next RTFReasonID
    end else
        ErrorMessage = 'Error opening RETURN_TO_FAB_RESULT_OPTION dictionary'
    end

    If ErrorMessage EQ '' then
        Response = RTFResultOptions
    end else
        LogData    = ''
        LogData<1> = LoggingDTM;
        LogData<2> = ''
        LogData<3> = ''
        LogData<4> = ''
        LogData<5> = ErrorMessage
        Logging_Services('AppendLog', objReturnToFabLog, LogData, @RM, @FM, False$)
        Error_Services('Add', ErrorMessage)
    end
    
end service

Service ConvertReturnToFabRecordToJSON(RTFId, UserId)
    
    ErrorMessage = ''
    JsonString   = ''
    If RowExists('RETURN_TO_FAB_LOTS', RTFId) then
        objJSON = ''
        If SRP_JSON(objJSON, 'New', 'Object') then
            RTFRecord = Database_Services('ReadDataRow', 'RETURN_TO_FAB_LOTS', RTFId, True$, 0, False$)
            If Error_Services('NoError') AND RTFRecord NE '' then
                If SRP_JSON(objRTF, 'New', 'Object') then
                    SRP_JSON(objRTF, 'SetValue', 'ReturnToFabLotsId', RTFId)
                    CassId = RTFRecord<RETURN_TO_FAB_LOTS_CASS_ID$>
                    CassType = RTFRecord<RETURN_TO_FAB_LOTS_LOT_TYPE$>
                    SRP_JSON(objRTF, 'SetValue', 'CassId', CassId)
                    SRP_JSON(objRTF, 'SetValue', 'LotType', CassType)
                    NGLotId = Lot_Services('GetLotIdByLegacyLotIdAndType', CassId, CassType)
                    LotJsonString = Lot_Services('ConvertLotRecordToJson', NGLotId, '', UserId)
                    If SRP_Json(objLot, 'Parse', LotJsonString) EQ '' then
                        If SRP_Json(objLotSub, 'PARSE', SRP_Json(objLot, 'GetValue', 'Lot')) EQ '' then
                            SRP_Json(objRTF, 'Set', 'AssociatedLot' ,objLotSub)
                            SRP_Json(objLotSub, 'Release')
                        end
                        SRP_Json(objLot, 'Release')
                    end
                    SRP_JSON(objRTF, 'SetValue', 'RequestorUserId', RTFRecord<RETURN_TO_FAB_LOTS_REQUESTOR_USER_ID$>)
                    SRP_JSON(objRTF, 'SetValue', 'StartDtm', OConv(RTFRecord<RETURN_TO_FAB_LOTS_START_DTM$>, 'DT'))
                    SRP_JSON(objRTF, 'SetValue', 'MHInitUserId', RTFRecord<RETURN_TO_FAB_LOTS_MH_INIT_USER_ID$>)
                    SRP_JSON(objRTF, 'SetValue', 'MHInitDtm', OConv(RTFRecord<RETURN_TO_FAB_LOTS_MH_INIT_DTM$>, 'DT'))
                    SRP_JSON(objRTF, 'SetValue', 'EvalUserId', RTFRecord<RETURN_TO_FAB_LOTS_EVAL_USER_ID$>)
                    SRP_JSON(objRTF, 'SetValue', 'EvalResultId', RTFRecord<RETURN_TO_FAB_LOTS_EVAL_RESULT_ID$>, 'Number')
                    if RTFRecord<RETURN_TO_FAB_LOTS_EVAL_RESULT_ID$> NE '' then
                        EvaluationDescription = Database_Services('ReadDataColumn', 'RETURN_TO_FAB_RESULT_OPTION', RTFRecord<RETURN_TO_FAB_LOTS_EVAL_RESULT_ID$>, RETURN_TO_FAB_RESULT_OPTION_RESULT$, True$, 0, False$)
                    end else
                        EvaluationDescription = ''
                    end
                    SRP_JSON(objRTF, 'SetValue', 'EvalDesc', EvaluationDescription)
                    SRP_JSON(objRTF, 'SetValue', 'EvalDtm', OConv(RTFRecord<RETURN_TO_FAB_LOTS_EVAL_DTM$>, 'DT'))
                    SRP_JSON(objRTF, 'SetValue', 'FinalCompleteUserId', RTFRecord<RETURN_TO_FAB_LOTS_FINAL_COMPLETE_USER_ID$>)
                    SRP_JSON(objRTF, 'SetValue', 'FinalCompleteDtm', OConv(RTFRecord<RETURN_TO_FAB_LOTS_FINAL_COMPLETE_DTM$>, 'DT'))
                    SRP_JSON(objRTF, 'SetValue', 'Completed', RTFRecord<RETURN_TO_FAB_LOTS_COMPLETED$>, 'Boolean')
                    SRP_JSON(objRTF, 'SetValue', 'CompletedDtm', OConv(RTFRecord<RETURN_TO_FAB_LOTS_COMPLETED_DTM$>,'DT'))
                    SRP_JSON(objRTF, 'SetValue', 'Reason', RTFRecord<RETURN_TO_FAB_LOTS_REASON$>)
                    CurrStepId = Return_To_Fab_Services('GetRTFCurrStep', RTFId)
                    SRP_Json(objRTF, 'SetValue', 'CurrStepId', CurrStepId, 'Number')
                    Notes      = RTFRecord<RETURN_TO_FAB_LOTS_NOTES$>
                    NotesUser  = RTFRecord<RETURN_TO_FAB_LOTS_NOTES_USER$>
                    If Notes NE '' then
                        JsonArrayNotes = ''
                        If SRP_JSON(JsonArrayNotes, 'New', 'Array') then
                            For each Note in Notes using @VM setting vPos
                                objSingleNote = ''
                                If SRP_Json(objSingleNote, 'New', 'Object') then
                                    SRP_Json(objSingleNote, 'SetValue', 'NoteText', Notes<1,vPos>, 'String')
                                    SRP_Json(objSingleNote, 'SetValue', 'NoteUser', NotesUser<1,vPos>, 'String')
                                    SRP_Json(JsonArrayNotes, 'Add', objSingleNote)
                                    SRP_Json(objSingleNote, 'Release')
                                end
                            Next Note
                            SRP_JSON(objRTF, 'Set', 'Notes', JsonArrayNotes)
                            SRP_JSON(JsonArrayNotes, 'Release')
                        end
                    end else
                        SRP_JSON(objRTF, 'SetValue', 'Notes', '')
                    end
                    SRP_JSON(objJSON, 'Set', 'ReturnToFab', objRTF)
                    SRP_JSON(objRTF, 'Release')
                end else
                    ErrorMessage = 'Error creating new Json Object'
                end
            end else
                ErrorMessage = 'Error reading RTFRecord from database...' 
            end
            JsonString = SRP_JSON(objJSON, 'Stringify', 'Styled')
            SRP_JSON(objJSON, 'Release')
        end else
            ErrorMessage = 'Error creating new Json Object'
        end
    end else
        ErrorMessage = 'Error Converting RTF record to JSON. RTFId not found in database.'
    end
    
    If ErrorMessage NE '' then
        LogData    = ''
        LogData<1> = LoggingDTM;//Defined at entry of subroutine
        LogData<2> = ''
        LogData<3> = ''
        LogData<4> = ''
        LogData<5> = ErrorMessage
        Logging_Services('AppendLog', objReturnToFabLog, LogData, @RM, @FM, False$)
        Error_Services('Add', ErrorMessage)
    end
    
    Response = JsonString
    
end service

Service CreateReturnToFabReportJson(ShowOpenReport)

    ErrorMessage = ''
    JsonString   = ''
    objJSON = ''
    Begin Case
        Case ShowOpenReport
            RTFIdList = Return_To_Fab_Services('GetAllReturnToFabRecords', True$)
        Case Otherwise$
            RTFIdList = Return_To_Fab_Services('GetAllReturnToFabRecords', False$)
    End Case
    If SRP_JSON(objJSON, 'New', 'Object') then
        If SRP_Json(objReturnToFabReport, 'New', 'Array') then
            for each RTFId in RTFIdList using @VM
                RTFRecord = Database_Services('ReadDataRow', 'RETURN_TO_FAB_LOTS', RTFId, True$, 0, False$)
                If Error_Services('NoError') and RTFRecord NE '' then
                    hRTFJsonSingle = ''
                    if SRP_Json(hRTFJsonSingle, 'New', 'Object') then
                        
                        SRP_JSON(hRTFJsonSingle, 'SetValue', 'ReturnToFabLotsId', RTFId)
                        CassId = RTFRecord<RETURN_TO_FAB_LOTS_CASS_ID$>
                        SRP_JSON(hRTFJsonSingle, 'SetValue', 'CassId', CassId)
                        CassType = RTFRecord<RETURN_TO_FAB_LOTS_LOT_TYPE$>
                        SRP_JSON(hRTFJsonSingle, 'SetValue', 'LotType', CassType)
                        NGLotId = Lot_Services('GetLotIdByLegacyLotIdAndType', CassId, CassType)
                        LotJsonString = Lot_Services('ConvertLotRecordToJson', NGLotId, '', UserId, False$)
                        If SRP_Json(objLot, 'Parse', LotJsonString) EQ '' then
                            If SRP_Json(objLotSub, 'PARSE', SRP_Json(objLot, 'GetValue', 'Lot')) EQ '' then
                                SRP_Json(hRTFJsonSingle, 'Set', 'AssociatedLot' ,objLotSub)
                                SRP_Json(objLotSub, 'Release')
                            end
                            SRP_Json(objLot, 'Release')
                        end
                        SRP_JSON(hRTFJsonSingle, 'SetValue', 'RequestorUserId', RTFRecord<RETURN_TO_FAB_LOTS_REQUESTOR_USER_ID$>)
                        StartDtm = Date_Services('ConvertDateTimeToISO8601', RTFRecord<RETURN_TO_FAB_LOTS_START_DTM$>)
                        If StartDtm NE '' then
                            SRP_JSON(hRTFJsonSingle, 'SetValue', 'StartDtm', StartDtm)
                        end
                        if RTFRecord<RETURN_TO_FAB_LOTS_EVAL_RESULT_ID$> NE '' then
                            EvaluationDescription = Database_Services('ReadDataColumn', 'RETURN_TO_FAB_RESULT_OPTION', RTFRecord<RETURN_TO_FAB_LOTS_EVAL_RESULT_ID$>, RETURN_TO_FAB_RESULT_OPTION_RESULT$, True$, 0, False$)
                        end else
                            EvaluationDescription = ''
                        end
                        SRP_JSON(hRTFJsonSingle, 'SetValue', 'EvalDesc', EvaluationDescription)
                        FinalCompleteDtm = Date_Services('ConvertDateTimeToISO8601', RTFRecord<RETURN_TO_FAB_LOTS_FINAL_COMPLETE_DTM$>)
                        If FinalCompleteDtm NE '' then
                           SRP_JSON(hRTFJsonSingle, 'SetValue', 'FinalCompleteDtm', FinalCompleteDtm) 
                        end
                        SRP_JSON(hRTFJsonSingle, 'SetValue', 'Completed', RTFRecord<RETURN_TO_FAB_LOTS_COMPLETED$>, 'Boolean')
                        CompletedDtm = Date_Services('ConvertDateTimeToISO8601',RTFRecord<RETURN_TO_FAB_LOTS_COMPLETED_DTM$>)
                        If CompletedDtm NE '' then
                           SRP_JSON(hRTFJsonSingle, 'SetValue', 'CompletedDtm', CompletedDtm) 
                        end
                        CurrStepId = Return_To_Fab_Services('GetRTFCurrStep', RTFId)
                        SRP_Json(hRTFJsonSingle, 'SetValue', 'CurrStepId', CurrStepId, 'Number')
                        SRP_Json(objReturnToFabReport, 'Add', hRTFJsonSingle)
                        SRP_Json(hRTFJsonSingle, 'Release')
                    end
                end else
                    Error_Services('Clear')
                end
            Next RTFId
            SRP_JSON(objJSON, 'Set', 'ReturnToFabReport', objReturnToFabReport)
            SRP_JSON(objReturnToFabReport, 'Release')
        end
        JsonString = SRP_JSON(objJSON, 'Stringify', 'Styled')
        SRP_JSON(objJSON, 'Release')
    end else
        ErrorMessage = 'Error creating root JSON object.'
    end
    
    If ErrorMessage NE '' then
        LogData    = ''
        LogData<1> = LoggingDTM
        LogData<2> = ''
        LogData<3> = ''
        LogData<4> = ''
        LogData<5> = ErrorMessage
        Logging_Services('AppendLog', objReturnToFabLog, LogData, @RM, @FM, False$)
        Error_Services('Add', ErrorMessage)
    end
    
    Response = JsonString
    
end service

Service GetReturnToFabRecordIdByCassId(CassId)
    
    ErrorMessage = ''
    RTFRecords   = ''
    If CassId NE '' then
        table = "RETURN_TO_FAB_LOTS"
        open "DICT ":table To @DICT then
            srch_strng  = "CASS_ID":@VM:CassId:@FM
            option      = ""
            flag        = ""
            Btree.Extract(srch_strng, table, @DICT, RTFRecords, option, flag)
        end else
            ErrorMessage = 'Error opening RETURN_TO_FAB_LOTS dictionary'
        end
    end else
        ErrorMessage = 'Error getting return to fab record by cass. ID. Cassette ID was null'
    end
    
    If ErrorMessage EQ '' then
        Response = RTFRecords
    end else
        LogData    = ''
        LogData<1> = LoggingDTM;//Defined at entry of subroutine
        LogData<2> = CassId
        LogData<3> = ''
        LogData<4> = ''
        LogData<5> = ErrorMessage
        Logging_Services('AppendLog', objReturnToFabLog, LogData, @RM, @FM, False$)
        Error_Services('Add', ErrorMessage)
    end
    
End Service

Service GetAllReturnToFabRecords(ShowOnlyOpen)
    
    ErrorMessage = ''
    RTFRecords   = ''
    table = "RETURN_TO_FAB_LOTS"
    open "DICT ":table To @DICT then
        srch_strng  = "CASS_ID":@VM:"#NULL":@FM
        if ShowOnlyOpen then
            srch_strng := "COMPLETED":@VM:"#1":@FM
        end
        option      = ""
        flag        = ""
        Btree.Extract(srch_strng, table, @DICT, RTFRecords, option, flag)
    end else
        ErrorMessage = 'Error opening RETURN_TO_FAB_LOTS dictionary'
    end
    
    If ErrorMessage EQ '' then
        Response = RTFRecords
    end else
        LogData    = ''
        LogData<1> = LoggingDTM
        LogData<2> = ''
        LogData<3> = ''
        LogData<4> = ''
        LogData<5> = ErrorMessage
        Logging_Services('AppendLog', objReturnToFabLog, LogData, @RM, @FM, False$)
        Error_Services('Add', ErrorMessage)
    end
    
end service

Service GetOpenReturnToFabRecordIdByCassId(CassId)
    
    ErrorMessage   = ''
    OpenRTFRecords = ''
    If CassId NE '' then
        table = "RETURN_TO_FAB_LOTS"
        open "DICT ":table To hRDS then
            srch_strng  = "CASS_ID":@VM:CassId:@FM:"COMPLETED":@VM:"#1":@FM
            option      = ""
            flag        = ""
            Btree.Extract(srch_strng, table, hRDS, OpenRTFRecords, option, flag)
        end else
            ErrorMessage = 'Error opening RETURN_TO_FAB_LOTS dictionary'
        end
    end else
        ErrorMessage = 'Error getting return to fab record by cass. ID. Cassette ID was null'
    end
    If ErrorMessage EQ '' then
        Response = OpenRTFRecords
    end else
        LogData    = ''
        LogData<1> = LoggingDTM;//Defined at entry of subroutine
        LogData<2> = ''
        LogData<3> = ''
        LogData<4> = ''
        LogData<5> = ErrorMessage
        Logging_Services('AppendLog', objReturnToFabLog, LogData, @RM, @FM, False$)
        Error_Services('Add', ErrorMessage)
    end
    
End Service

Service SetReasonForReturn(RTFId, UserId, Reason)
    
    ErrorMessage = ''
    If RTFId NE '' then
        If RowExists('RETURN_TO_FAB_LOTS', RTFId) then
            RTFRecord         = Database_Services('ReadDataRow', 'RETURN_TO_FAB_LOTS', RTFId, True$, 0, False$)
            LegacyLotId = RTFRecord<RETURN_TO_FAB_LOTS_CASS_ID$>
            LegacyLotType = RTFRecord<RETURN_TO_FAB_LOTS_LOT_TYPE$>
            NGLotId = Lot_Services('GetLotIdByLegacyLotIdAndType', LegacyLotId, LegacyLotType)
            CurrOperation = Lot_Services('GetLotCurrOperationName', NGLotId)
            If CurrOperation EQ 'RTF_ASSIGN_REASON' then
                
                RTFRecordComplete = RTFRecord<RETURN_TO_FAB_LOTS_COMPLETED$>
                If RTFRecordComplete NE True$ then
                    If UserId NE '' then
                        if RowExists('LSL_USERS', UserId) then
                            If Reason NE '' then
                                RTFRecord<RETURN_TO_FAB_LOTS_REASON$> = Reason
                                Database_Services('WriteDataRow', 'RETURN_TO_FAB_LOTS', RTFId, RTFRecord, True$, False$, False$)
                                If Error_Services('NoError') then
                                    Lot_Services('MoveInLot', NGLotId, UserId)
                                    If Error_Services('NoError') then
                                        Lot_Services('MoveOutLot', NGLotId, UserId)
                                        If Error_Services('HasError') then
                                            ErrorMessage = Error_Services('GetMessage')
                                        end
                                    end else
                                        ErrorMessage = Error_Services('GetMessage')
                                    end
                                end else
                                    ErrorMessage = Error_Services('GetMessage')
                                end
                            end else
                                ErrorMessage = 'Error setting return to fab reason. Reason was null.'  
                            end
                        end else
                            ErrorMessage = 'Error setting return to fab reason. User not found in openinsight.'
                        end
                    end else
                        ErrorMessage = 'Error setting return to fab reason. User ID was null.'
                    end
                end else
                    ErrorMessage = 'Error setting return to fab reason. Return to fab record has already been completed.' 
                end
            end else
                ErrorMessage = 'Error setting Return To Fab reason. Form is currently at step ': CurrOperation :'.' 
            end
        end else
            ErrorMessage = 'Error setting return to fab reason. Return to fab record did not exists'
        end
    end else
        ErrorMessage = 'Error setting return to fab reason. Return to fab record id was null'
    end
    
    if ErrorMessage EQ '' then
        LogData    = ''
        LogData<1> = LoggingDTM
        LogData<2> = ''
        LogData<3> = UserId
        LogData<4> = RTFId
        LogData<5> = 'Successfully set reason for return on RETURN_TO_FAB_LOTS record'
        Logging_Services('AppendLog', objReturnToFabLog, LogData, @RM, @FM, False$)
    end else
        LogData    = ''
        LogData<1> = LoggingDTM
        LogData<2> = ''
        LogData<3> = UserId
        LogData<4> = RTFId
        LogData<5> = ErrorMessage
        Logging_Services('AppendLog', objReturnToFabLog, LogData, @RM, @FM, False$) 
        Error_Services('Add', ErrorMessage) 
    end
    
end service

Service StartAssignOperation(RTFId, UserId)
    
    ErrorMessage = ''
    If RTFId NE '' then
        If RowExists('RETURN_TO_FAB_LOTS', RTFId) then
            RTFRecord         = Database_Services('ReadDataRow', 'RETURN_TO_FAB_LOTS', RTFId, True$, 0, False$)
            LegacyLotId = RTFRecord<RETURN_TO_FAB_LOTS_CASS_ID$>
            LegacyLotType = RTFRecord<RETURN_TO_FAB_LOTS_LOT_TYPE$>
            NGLotId = Lot_Services('GetLotIdByLegacyLotIdAndType', LegacyLotId, LegacyLotType)
            CurrOperationName = Lot_Services('GetLotCurrOperationName', NGLotId)
            If CurrOperationName EQ 'RTF_ASSIGN_OPERATIONS' then
                IsLotMovedIn = Lot_Services('IsLotMovedIn', NGLotId)
                If Not(IsLotMovedIn) then
                    //Moves the lot in if it already isn't
                    Lot_Services('MoveInLot', NGLotId, UserId)
                    If Error_Services('HasError') then
                        ErrorMessage = Error_Services('GetMessage')
                    end
                end
            end else
                ErrorMessage = 'Lot is not currently at the Assign Operations, operation.'
            end
        end else
           ErrorMessage = 'Return To Fab ID was not found' 
        end
    end else
        ErrorMessage = 'Return To Fab ID was null.'
    end
    If ErrorMessage NE '' then
        Error_Services('Add', ErrorMessage)
    end
    
end service

Service SetOpAssignComplete(RTFId, UserId)
    
    ErrorMessage = ''
    If RTFId NE '' then
        If RowExists('RETURN_TO_FAB_LOTS', RTFId) then
            RTFRecord         = Database_Services('ReadDataRow', 'RETURN_TO_FAB_LOTS', RTFId, True$, 0, False$)
            LegacyLotId = RTFRecord<RETURN_TO_FAB_LOTS_CASS_ID$>
            LegacyLotType = RTFRecord<RETURN_TO_FAB_LOTS_LOT_TYPE$>
            NGLotId = Lot_Services('GetLotIdByLegacyLotIdAndType', LegacyLotId, LegacyLotType)
            CurrOperationName = Lot_Services('GetLotCurrOperationName', NGLotId)
            If CurrOperationName EQ 'RTF_ASSIGN_OPERATIONS' then
                IsLotMovedIn = Lot_Services('IsLotMovedIn', NGLotId)
                If Not(IsLotMovedIn) then
                    //Moves the lot in if it already isn't
                    Lot_Services('MoveInLot', NGLotId, UserId)
                end
                If Error_Services('NoError') then
                    Lot_Services('MoveOutLot', NGLotId, UserId)
                    If Error_Services('HasError') then
                        ErrorMessage = Error_Services('GetMessage')
                    end
                end else
                    ErrorMessage = Error_Services('GetMessage')
                end
            end else
                ErrorMessage = 'Lot is not currently at the Assign Operations, operation.'
            end
        end else
           ErrorMessage = 'Return To Fab ID was not found' 
        end
    end else
        ErrorMessage = 'Return To Fab ID was null.'
    end
    If ErrorMessage NE '' then
        Error_Services('Add', ErrorMessage)
    end

end service

Service SetBinToBin(RTFId, MHUserId)
    
    ErrorMessage = ''
    If RTFId NE '' then
        If RowExists('RETURN_TO_FAB_LOTS', RTFId) then
            RTFRecord         = Database_Services('ReadDataRow', 'RETURN_TO_FAB_LOTS', RTFId, True$, 0, False$)
            LegacyLotId = RTFRecord<RETURN_TO_FAB_LOTS_CASS_ID$>
            LegacyLotType = RTFRecord<RETURN_TO_FAB_LOTS_LOT_TYPE$>
            NGLotId = Lot_Services('GetLotIdByLegacyLotIdAndType', LegacyLotId, LegacyLotType)
            CurrOperationName = Lot_Services('GetLotCurrOperationName', NGLotId)
            If CurrOperationName EQ 'RTF_INIT_BIN_TO_BIN' then
                RTFRecord         = Database_Services('ReadDataRow', 'RETURN_TO_FAB_LOTS', RTFId, True$, 0, False$)
                RTFRecordComplete = RTFRecord<RETURN_TO_FAB_LOTS_COMPLETED$>
                If RTFRecordComplete NE True$ then
                    If MHUserId NE '' then
                        If RowExists('LSL_USERS', MHUserId) then
                            If MemberOf(MHUserId, 'MATERIAL HANDLER') then
                                RTFRecord<RETURN_TO_FAB_LOTS_MH_INIT_USER_ID$> = MHUserId
                                RTFRecord<RETURN_TO_FAB_LOTS_MH_INIT_DTM$>     = Datetime()
                                Database_Services('WriteDataRow', 'RETURN_TO_FAB_LOTS', RTFId, RTFRecord, True$, False$, False$)
                                If Error_Services('NoError') then
                                    IsLotMovedIn = Lot_Services('IsLotMovedIn', NGLotId)
                                    If Not(IsLotMovedIn) then
                                        //Moves the lot in if it already isn't
                                        Lot_Services('MoveInLot', NGLotId, MHUserId)
                                    end
                                    If Error_Services('NoError') then
                                        Lot_Services('MoveOutLot', NGLotId, MHUserId)
                                        If Error_Services('NoError') then
                                            //Send notification that a return to fab record was created.
                                            CassId             = RTFRecord<RETURN_TO_FAB_LOTS_CASS_ID$>
                                            RTFOrigUser        = RTFRecord<RETURN_TO_FAB_LOTS_REQUESTOR_USER_ID$>
                                            Message            = 'Return to fab form updated for ' : CassId : ' by ' : MHUserId : '.' : CRLF$
                                            Message           := 'Initial Bin to Bin has been marked as completed.' : CRLF$
                                            Message           := 'Link to Return To Fab form: https://goto.infineon.com/oiwizard/ReturnToFab'
                                            Recipients         = XLATE('NOTIFICATION','SHIPPING',NOTIFICATION_USER_ID$,'X')
                                            Recipients<1, -1>  = XLATE('NOTIFICATION','RETURN_TO_FAB_ENG',NOTIFICATION_USER_ID$,'X')
                                            Recipients<1, -1>  = XLATE('NOTIFICATION','RETURN_TO_FAB_MANUF',NOTIFICATION_USER_ID$,'X')
                                            Recipients<1, -1>  = RTFOrigUser
                                            SentFrom           = 'OI_ADMIN'
                                            Subject            = 'Return To Fab Form Updated'
                                            SendToGroup        = ''
                                            AttachWindow       = ''
                                            AttachKey          = ''
                                            Parms              = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
                                            obj_Notes('Create',Parms)
                                        end else
                                           ErrorMessage = Error_Services('GetMessage') 
                                        end
                                    end else
                                        ErrorMessage = Error_Services('GetMessage')
                                    end
                                    
                                end else
                                    ErrorMessage = Error_Services('GetMessage')
                                end  
                            end else
                                ErrorMessage = 'Error setting Initial SAP Bin-to-Bin. User does not have permissions to perform this function. User must be apart of OI Security Group "MATERIAL HANDLER"'
                            end
                        end else
                            ErrorMessage = 'Error setting Initial SAP Bin-to-Bin. Material Handler User ID was not found in OpenInsight.'
                        end
                    end else
                        ErrorMessage = 'Error setting Initial SAP Bin-to-Bin. Material Handler User ID was null.'  
                    end
                end else
                    ErrorMessage = 'Error setting Initial SAP Bin-to-Bin. Return to fab record has already been completed.' 
                end    
            end else
                ErrorMessage = 'Error setting Initial SAP Bin-to-Bin. Form is currently at step ': CurrOperationName :'.'  
            end
        end else
            ErrorMessage = 'Error setting Initial SAP Bin-to-Bin. Return to fab record did not exists'
        end
    end else
        ErrorMessage = 'Error setting Initial SAP Bin-to-Bin. Return to fab record id was null'
    end
    
    If ErrorMessage EQ '' then
        LogData    = ''
        LogData<1> = LoggingDTM
        LogData<2> = ''
        LogData<3> = MHUserId
        LogData<4> = RTFId
        LogData<5> = 'Successfully set bin to bin complete on RETURN_TO_FAB_LOTS record'
        Logging_Services('AppendLog', objReturnToFabLog, LogData, @RM, @FM, False$)
    end else
        LogData    = ''
        LogData<1> = LoggingDTM
        LogData<2> = ''
        LogData<3> = MHUserId
        LogData<4> = RTFId
        LogData<5> = ErrorMessage
        Logging_Services('AppendLog', objReturnToFabLog, LogData, @RM, @FM, False$)
        Error_Services('Add', ErrorMessage)
    end
    
end service

Service SetRTFCompleted(RTFId, CompleteUserId)
    
    ErrorMessage = ''
    If RTFId NE '' then
        If RowExists('RETURN_TO_FAB_LOTS', RTFId) then
            RTFRecord         = Database_Services('ReadDataRow', 'RETURN_TO_FAB_LOTS', RTFId, True$, 0, False$)
            LegacyLotId = RTFRecord<RETURN_TO_FAB_LOTS_CASS_ID$>
            LegacyLotType = RTFRecord<RETURN_TO_FAB_LOTS_LOT_TYPE$>
            NGLotId = Lot_Services('GetLotIdByLegacyLotIdAndType', LegacyLotId, LegacyLotType)
            CurrOperationName = Lot_Services('GetLotCurrOperationName', NGLotId)
            If CurrOperationName EQ 'RTF_CLOSE' then
                RTFRecordComplete = RTFRecord<RETURN_TO_FAB_LOTS_COMPLETED$>
                If RTFRecordComplete NE True$ then
                    If CompleteUserId NE '' then
                        If RowExists('LSL_USERS', CompleteUserId) then
                            RTFRecord<RETURN_TO_FAB_LOTS_COMPLETED$>     = True$
                            RTFRecord<RETURN_TO_FAB_LOTS_COMPLETED_DTM$> = Datetime()
                            Database_Services('WriteDataRow', 'RETURN_TO_FAB_LOTS', RTFId, RTFRecord, True$, False$, False$)
                            If Error_Services('NoError') then
                                IsLotMovedIn = Lot_Services('IsLotMovedIn', NGLotId)
                                If Not(IsLotMovedIn) then
                                    //Moves the lot in if it already isn't
                                    Lot_Services('MoveInLot', NGLotId, CompleteUserId)
                                end
                                If Error_Services('NoError') then
                                    Lot_Services('MoveOutLot', NGLotId, CompleteUserId)
                                    If Error_Services('NoError') then
                                        //Send notification that a return to fab record was created.
                                        CassId             = RTFRecord<RETURN_TO_FAB_LOTS_CASS_ID$>
                                        RTFOrigUser        = RTFRecord<RETURN_TO_FAB_LOTS_REQUESTOR_USER_ID$>
                                        Message            = 'Return to fab form updated for ' : CassId : ' by ' : CompleteUserId : '.' : CRLF$
                                        Message           := 'Return to fab marked as completed.' : CRLF$
                                        Message           := 'Link to Return To Fab form: https://goto.infineon.com/oiwizard/ReturnToFab'
                                        Recipients         = XLATE('NOTIFICATION','SHIPPING',NOTIFICATION_USER_ID$,'X')
                                        Recipients<1, -1>  = XLATE('NOTIFICATION','RETURN_TO_FAB_ENG',NOTIFICATION_USER_ID$,'X')
                                        Recipients<1, -1>  = XLATE('NOTIFICATION','RETURN_TO_FAB_MANUF',NOTIFICATION_USER_ID$,'X')
                                        Recipients<1, -1>  = RTFRecord<RETURN_TO_FAB_LOTS_REQUESTOR_USER_ID$>
                                        SentFrom           = 'OI_ADMIN'
                                        Subject            = 'Return To Fab Form Completed'
                                        SendToGroup        = ''
                                        AttachWindow       = ''
                                        AttachKey          = ''
                                        Parms              = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
                                        obj_Notes('Create',Parms)
                                    end else
                                        ErrorMessage = 'Error moving lot out.'
                                    end
                                end else
                                    ErrorMessage = Error_Services('GetMessage')
                                end
                            end else
                                ErrorMessage = Error_Services('GetMessage')
                            end
                        end else
                            ErrorMessage = 'Error setting Return To Fab form as complete. User ID was not found in OpenInsight.'
                        end
                    end else
                        ErrorMessage = 'Error setting Return To Fab form as complete. User ID was null.'  
                    end
                end else
                    ErrorMessage = 'Error setting Return To Fab form as complete. Return to fab record has already been completed.' 
                end
            end else
                ErrorMessage = 'Lot is not currently at the RTF Close operation.'
            end
            
        end else
            ErrorMessage = 'Error setting Return To Fab form as complete. Return to fab record did not exists'
        end
    end else
        ErrorMessage = 'Error setting Return To Fab form as complete. Return to fab record id was null'
    end
    
    If ErrorMessage EQ '' then
        LogData    = ''
        LogData<1> = LoggingDTM
        LogData<2> = ''
        LogData<3> = CompleteUserId
        LogData<4> = RTFId
        LogData<5> = 'Successfully set bin to bin complete on RETURN_TO_FAB_LOTS record'
        Logging_Services('AppendLog', objReturnToFabLog, LogData, @RM, @FM, False$)
    end else
        LogData    = ''
        LogData<1> = LoggingDTM
        LogData<2> = ''
        LogData<3> = CompleteUserId
        LogData<4> = RTFId
        LogData<5> = ErrorMessage
        Logging_Services('AppendLog', objReturnToFabLog, LogData, @RM, @FM, False$)
        Error_Services('Add', ErrorMessage)
    end
    
end service

Service SetEvalInfo(RTFId, EvalUserId, ResultId)
    ErrorMessage = ''
    If RTFId NE '' then
        if RowExists('RETURN_TO_FAB_LOTS', RTFId) then
            RTFRecord         = Database_Services('ReadDataRow', 'RETURN_TO_FAB_LOTS', RTFId, True$, 0, False$)
            LegacyLotId = RTFRecord<RETURN_TO_FAB_LOTS_CASS_ID$>
            LegacyLotType = RTFRecord<RETURN_TO_FAB_LOTS_LOT_TYPE$>
            NGLotId = Lot_Services('GetLotIdByLegacyLotIdAndType', LegacyLotId, LegacyLotType)
            CurrOperationName = Lot_Services('GetLotCurrOperationName', NGLotId)
            If CurrOperationName EQ 'RTF_DISPO' then
                If EvalUserId NE '' then
                    if RowExists('LSL_USERS', EvalUserId) then
                        If ResultId NE '' then
                            If RowExists('RETURN_TO_FAB_RESULT_OPTION', ResultId) then
                                RTFRecord         = Database_Services('ReadDataRow', 'RETURN_TO_FAB_LOTS', RTFId, True$, 0, False$)
                                RTFRecordComplete = RTFRecord<RETURN_TO_FAB_LOTS_COMPLETED$>
                                If RTFRecordComplete NE True$ then
                                    RTFRecord<RETURN_TO_FAB_LOTS_EVAL_USER_ID$>   = EvalUserId
                                    RTFRecord<RETURN_TO_FAB_LOTS_EVAL_RESULT_ID$> = ResultId
                                    RTFRecord<RETURN_TO_FAB_LOTS_EVAL_DTM$>       = Datetime()
                                    Database_Services('WriteDataRow', 'RETURN_TO_FAB_LOTS', RTFId, RTFRecord, True$, False$, False$)
                                    If Error_Services('NoError') then
                                        IsLotMovedIn = Lot_Services('IsLotMovedIn', NGLotId)
                                        If Not(IsLotMovedIn) then
                                            //Moves the lot in if it already isn't
                                            Lot_Services('MoveInLot', NGLotId, EvalUserId)
                                        end
                                        If Error_Services('NoError') then
                                            Lot_Services('MoveOutLot', NGLotId, EvalUserId)
                                            If Error_Services('NoError') then
                                                ResultDescription  = XLate('RETURN_TO_FAB_RESULT_OPTION', ResultId, RETURN_TO_FAB_RESULT_OPTION_RESULT$, 'X')
                                                //Send notification that a return to fab record was created.
                                                CassId             = RTFRecord<RETURN_TO_FAB_LOTS_CASS_ID$>
                                                RTFOrigUser        = RTFRecord<RETURN_TO_FAB_LOTS_REQUESTOR_USER_ID$>
                                                Message            = 'Return to fab form updated for ' : CassId : ' by ' : EvalUserId : '.' : CRLF$
                                                Message           := 'Result has been set to ' : ResultDescription : '.' : CRLF$
                                                Message           := 'Link to Return To Fab form: https://goto.infineon.com/oiwizard/ReturnToFab'
                                                Recipients         = XLATE('NOTIFICATION','SHIPPING',NOTIFICATION_USER_ID$,'X')
                                                Recipients<1, -1>  = XLATE('NOTIFICATION','RETURN_TO_FAB_ENG',NOTIFICATION_USER_ID$,'X')
                                                Recipients<1, -1>  = XLATE('NOTIFICATION','RETURN_TO_FAB_MANUF',NOTIFICATION_USER_ID$,'X')
                                                Recipients<1, -1>  = RTFRecord<RETURN_TO_FAB_LOTS_REQUESTOR_USER_ID$>
                                                SentFrom           = 'OI_ADMIN'
                                                Subject            = 'Return To Fab Form Updated'
                                                SendToGroup        = ''
                                                AttachWindow       = ''
                                                AttachKey          = ''
                                                Parms              = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
                                                obj_Notes('Create',Parms)
                                            end else
                                                ErrorMessage = Error_Services('GetMessage')
                                            end
                                        end else
                                            ErrorMessage = 'Error moving lot out.'
                                        end
                                    end else
                                        ErrorMessage = Error_Services('GetMessage')
                                    end
                                end else
                                    ErrorMessage = 'Error setting Eval. info. Return to fab record has already been completed.' 
                                end
                                //Possbile to add auto-closing logic here.
                                
                            end else
                                ErrorMessage = 'Error setting Eval. info. Result was an invalid result option.'
                            end
                        end else
                            ErrorMessage = 'Error setting Eval. info. Result was null.'
                        end
                    end else
                        ErrorMessage = 'Error setting Eval. info. Evaluation user is not a valid OpenInsight user.' 
                    end
                end else
                    ErrorMessage = 'Error setting Eval. info. Evaluation user id was null.'
                end
            end else
                ErrorMessage = 'Error setting Eval. info. Form is currently at step ': CurrOperationName :'.'
            end
        end else
            ErrorMessage = 'Error setting Eval. info. Return to fab record was not found.'
        end
    end else
        ErrorMessage = 'Error setting Eval. info. Return to fab id was null.'
    end
    If ErrorMessage EQ '' then
        LogData    = ''
        LogData<1> = LoggingDTM;//Defined at entry of subroutine
        LogData<2> = ''
        LogData<3> = EvalUserId
        LogData<4> = RTFId
        LogData<5> = 'Successfully set evaluation result on RETURN_TO_FAB_LOTS record'
        Logging_Services('AppendLog', objReturnToFabLog, LogData, @RM, @FM, False$)
    end else
        LogData    = ''
        LogData<1> = LoggingDTM;//Defined at entry of subroutine
        LogData<2> = ''
        LogData<3> = EvalUserId
        LogData<4> = RTFId
        LogData<5> = ErrorMessage
        Logging_Services('AppendLog', objReturnToFabLog, LogData, @RM, @FM, False$)
        Error_Services('Add', ErrorMessage)
    end
end service

Service SetFinalBinToBin(RTFId, MHUserId)
    ErrorMessage = ''
    If RTFId NE '' then
        If RowExists('RETURN_TO_FAB_LOTS', RTFId) then
            RTFRecord         = Database_Services('ReadDataRow', 'RETURN_TO_FAB_LOTS', RTFId, True$, 0, False$)
            LegacyLotId = RTFRecord<RETURN_TO_FAB_LOTS_CASS_ID$>
            LegacyLotType = RTFRecord<RETURN_TO_FAB_LOTS_LOT_TYPE$>
            NGLotId = Lot_Services('GetLotIdByLegacyLotIdAndType', LegacyLotId, LegacyLotType)
            CurrOperationName = Lot_Services('GetLotCurrOperationName', NGLotId)
            If CurrOperationName EQ 'RTF_FINAL_BIN_TO_BIN' then
                RTFRecord         = Database_Services('ReadDataRow', 'RETURN_TO_FAB_LOTS', RTFId, True$, 0, False$)
                RTFRecordComplete = RTFRecord<RETURN_TO_FAB_LOTS_COMPLETED$>
                If RTFRecordComplete NE True$ then
                    If MHUserId NE '' then
                        If RowExists('LSL_USERS', MHUserId) then
                            If MemberOf(MHUserId, 'MATERIAL HANDLER') then
                                RTFRecord<RETURN_TO_FAB_LOTS_FINAL_COMPLETE_USER_ID$> = MHUserId
                                RTFRecord<RETURN_TO_FAB_LOTS_FINAL_COMPLETE_DTM$> = Datetime()
                                Database_Services('WriteDataRow', 'RETURN_TO_FAB_LOTS', RTFId, RTFRecord, True$, False$, False$)
                                If Error_Services('NoError') then
                                    IsLotMovedIn = Lot_Services('IsLotMovedIn', NGLotId)
                                    If Not(IsLotMovedIn) then
                                        //Moves the lot in if it already isn't
                                        Lot_Services('MoveInLot', NGLotId, MHUserId)
                                    end
                                    If Error_Services('NoError') then
                                        Lot_Services('MoveOutLot', NGLotId, MHUserId)
                                    end else
                                        ErrorMessage = 'Error moving out lot.'
                                    end
                                end else
                                    ErrorMessage = Error_Services('GetMessage')
                                end
                            end else
                                ErrorMessage = 'Error setting Final SAP Bin-to-Bin. User does not have permissions to perform this function. User must be apart of OI Security Group "MATERIAL HANDLER"' 
                            end
                        end else
                            ErrorMessage = 'Error setting Final SAP Bin-to-Bin. Material Handler User ID was not found in OpenInsight.'
                        end
                        
                    end else
                        ErrorMessage = 'Error setting Final SAP Bin-to-Bin. Material Handler User ID was null.'  
                    end
                end else
                    ErrorMessage = 'Error setting Final SAP Bin-to-Bin. Return to fab record has already been completed.' 
                end
            end else
                ErrorMessage = 'Error setting Final SAP Bin-to-Bin. Form is currently at step ': CurrOperationName :'.' 
            end
        end else
            ErrorMessage = 'Error setting Final SAP Bin-to-Bin. Return to fab record did not exists'
        end
    end else
        ErrorMessage = 'Error setting Final SAP Bin-to-Bin. Return to fab record id was null'
    end
    
    If ErrorMessage EQ '' then
        LogData    = ''
        LogData<1> = LoggingDTM
        LogData<2> = ''
        LogData<3> = MHUserId
        LogData<4> = RTFId
        LogData<5> = 'Successfully set final bin to bin on RETURN_TO_FAB_LOTS record'
        Logging_Services('AppendLog', objReturnToFabLog, LogData, @RM, @FM, False$)
    end else
        LogData    = ''
        LogData<1> = LoggingDTM
        LogData<2> = ''
        LogData<3> = MHUserId
        LogData<4> = RTFId
        LogData<5> = ErrorMessage
        Logging_Services('AppendLog', objReturnToFabLog, LogData, @RM, @FM, False$)
        Error_Services('Add', ErrorMessage)
    end
    
end service

Service AddMiscNote(RTFId, Note, UserId)
    
    ErrorMessage = ''
    If RTFId NE '' then
        If RowExists('RETURN_TO_FAB_LOTS', RTFId) then
            RTFRecord         = Database_Services('ReadDataRow', 'RETURN_TO_FAB_LOTS', RTFId, True$, 0, False$)
            RTFRecordComplete = RTFRecord<RETURN_TO_FAB_LOTS_COMPLETED$>
            If RTFRecordComplete NE True$ then
                If UserId NE '' then
                    If RowExists('LSL_USERS', UserId) then
                        RTFRecord<RETURN_TO_FAB_LOTS_NOTES$>      = Insert(RTFRecord<RETURN_TO_FAB_LOTS_NOTES$>, 1, -1, 0, Note)
                        RTFRecord<RETURN_TO_FAB_LOTS_NOTES_USER$> = Insert(RTFRecord<RETURN_TO_FAB_LOTS_NOTES_USER$>, 1, -1, 0, UserId)
                        Database_Services('WriteDataRow', 'RETURN_TO_FAB_LOTS', RTFId, RTFRecord, True$, False$, False$)
                        If Error_Services('HasError') then
                            ErrorMessage = Error_Services('GetMessage')
                        end 
                    end else
                        ErrorMessage = 'Error adding note to RTF Record. User ID was not found in OpenInsight.'
                    end
                end else
                    ErrorMessage = 'Error adding note to RTF Record. User ID was null.'  
                end
            end else
                ErrorMessage = 'Error adding note to RTF Record. Return to fab record has already been completed.' 
            end
        end else
            ErrorMessage = 'Error adding note to RTF Record. Return to fab record did not exists'
        end
    end else
        ErrorMessage = 'Error adding note to RTF Record. Return to fab record id was null'
    end
    
    If ErrorMessage EQ '' then
        LogData    = ''
        LogData<1> = LoggingDTM
        LogData<2> = ''
        LogData<3> = UserId
        LogData<4> = RTFId
        LogData<5> = 'Successfully added note to RETURN_TO_FAB_LOTS record'
        Logging_Services('AppendLog', objReturnToFabLog, LogData, @RM, @FM, False$)
    end else
        LogData    = ''
        LogData<1> = LoggingDTM
        LogData<2> = ''
        LogData<3> = UserId
        LogData<4> = RTFId
        LogData<5> = ErrorMessage
        Logging_Services('AppendLog', objReturnToFabLog, LogData, @RM, @FM, False$)
        Error_Services('Add', ErrorMessage)
    end
    
end service

Service GetRTFCurrStep(RTFId)
    CurrStep  = 0
    RTFRecord = Database_Services('ReadDataRow', 'RETURN_TO_FAB_LOTS', RTFId, True$, 0, False$)
    If RTFRecord NE '' then
        RTFRecord         = Database_Services('ReadDataRow', 'RETURN_TO_FAB_LOTS', RTFId, True$, 0, False$)
        LegacyLotId = RTFRecord<RETURN_TO_FAB_LOTS_CASS_ID$>
        LegacyLotType = RTFRecord<RETURN_TO_FAB_LOTS_LOT_TYPE$>
        NGLotId = Lot_Services('GetLotIdByLegacyLotIdAndType', LegacyLotId, LegacyLotType)
        CurrOperationName = Lot_Services('GetLotCurrOperationName', NGLotId)
        
        Begin Case
            Case CurrOperationName EQ 'RTF_START'
                CurrStep = 1
            Case CurrOperationName EQ 'RTF_ASSIGN_REASON'
                CurrStep = 2
            Case CurrOperationName EQ 'RTF_ASSIGN_OPERATIONS'
                CurrStep = 3
            Case CurrOperationName EQ 'RTF_INIT_BIN_TO_BIN'
                CurrStep = 4
            Case CurrOperationName EQ 'RTF_DISPO'
                CurrStep = 5
            Case CurrOperationName EQ 'RTF_FINAL_BIN_TO_BIN'
                CurrStep = 6
            Case CurrOperationName EQ 'RTF_CLOSE'
                CurrStep = 7
            Case Otherwise$
                CurrStep = 0
        End Case
    end
    Response = CurrStep
end service

Service OpenOIWizardReturnToFabInBrowser(RTFId)
    
    Command = 'explorer https://goto.infineon.com/oiwizard/returntofab/' : RTFId
    SRP_Run_Command(Command)
    
end service

Service GetReturnedToFab(CassID)
    If CassID NE '' then
    RTFRecords = ''
    ErrorMessage = ''
    If CassId NE '' then
        table = "RETURN_TO_FAB_LOTS"
        Open "DICT ":table To @DICT Else
            ErrorMessage = 'Error opening RETURN_TO_FAB_LOTS dictionary'
        End
        If ErrorMessage EQ '' then
            srch_strng  = "CASS_ID":@VM:CassId:@FM
            option      = ""
            flag        = ""
            Btree.Extract(srch_strng, table, @DICT, RTFRecords, option, flag)
        end
        end else
            ErrorMessage = 'Error getting return to fab record by cass. ID. Cassette ID was null'
        end
    end else
        ErrorMessage = 'Missing CassID parameter.'
    end
    If ErrorMessage EQ '' then
        If RTFRecords = '' then
            Response = False$
        end else
            Response = True$
        end
    end else
        Error_Services('Add', ErrorMessage)
    end
    
end service
Service InitializeReturnToFabLotOperations(LotId)
    
    ErrorMessage = ''
    OperationsToInitialize = ''
    OperationsToInitialize<1, 1> = 'RTF_CLOSE'
    For each Operation in OperationsToInitialize using @VM setting sequence
        Lot_Services('AddLotOperationIntoSequence', LotId, Operation, sequence)
        If Error_Services('HasError') then
            ErrorMessage = Error_Services('GetMessage')
        end
    Until ErrorMessage NE ''
    Next Operation
    If ErrorMessage NE '' then
        Error_Services('Add', 'Error in ' : Service : ' : ' : ErrorMessage)
    end
    
end service

Service PrescribeReturnToFabOperation(LegacyLotId, OperationId, PrescribedSequence, UserId)
    
    ErrorMessage = ''
    //Check that the lot has a valid return to fab record.
    ExistingReturnToFabRecord = Return_To_Fab_Services('GetOpenReturnToFabRecordIdByCassId', LegacyLotId)
    If ExistingReturnToFabRecord then
        ReturnToFabLotRec = Database_Services('ReadDataRow', 'RETURN_TO_FAB_LOTS', ExistingReturnToFabRecord, True$, 0, False$)
        LotType = ReturnToFabLotRec<RETURN_TO_FAB_LOTS_LOT_TYPE$>
        NGLotId = Lot_Services('GetLotIdByLegacyLotIdAndType', LegacyLotId, LotType)
        If NGLotId NE '' then
            If RowExists('OPERATION', OperationID) then
                If PrescribedSequence NE '' then
                    CurrentPrescribedOperations = Lot_Services('GetLotOperationSequence', NGLotId)
                    CurrentOperation = Lot_Services('GetLotCurrOperationName', NGLotId)
                    Lot_Services('AddLotOperationIntoSequence', NGLotId, OperationId, PrescribedSequence)
                    If Error_Services('NoError') then
                        Lot_Services('CreateLotEvent', NGLotId, Datetime(), 'SYSTEM_COMMENT', 'Prescribed ' : OperationId : '.', '', UserId) 
                    end else
                        ErrorMessage = Error_Services('GetMessage')
                    end
                end else
                    ErrorMessage = 'Prescribed Sequence was null.'
                end
            end else
                ErrorMessage = 'Specified operation was not found.'
            end
        end else
            ErrorMessage = LegacyLotId : ' not found in LOT table.'
        end
    end else
        ErrorMessage = 'Lot ' : LegacyLotId : 'does not have an active return to fab record.'
    end
    
    If ErrorMessage NE '' then
        Error_Services('Add', 'Error in ' : service : ' : ' : ErrorMessage)
    end
    
end service

/*
Returns a @VM delimited list of RTF Operations available to be prescribed
*/
Service GetRTFOperationIDs()
    
    ErrorMessage = ''
    RTFOperationKeys = ''
    
    Open 'DICT.OPERATION' to DICT then
        SearchString = 'OPERATION_CLASS':@VM:'RTF':@FM
        SearchString := 'ACTIVE':@VM:True$:@FM
        Option = ''
        Flag = ''
        Btree.Extract(SearchString, 'OPERATION', DICT, RTFOperationKeys, Option, Flag)
    end else
        ErrorMessage = 'Error opening OPERATION table dictionary.'
    end
    
    If ErrorMessage EQ '' then
        Response = RTFOperationKeys
    end else
        Error_Services('Add', 'Error in ' : Service : ' : ' ErrorMessage)
    end
    
end service

Service MigrateLegacyRTFRecord(RTFRecordId)
    
    RTFRecord = Database_Services('ReadDataRow', 'RETURN_TO_FAB_LOTS', RTFRecordId, True$, 0, False$)
    
    //First create a lot record if none already exist
    CassId = RTFRecord<RETURN_TO_FAB_LOTS_CASS_ID$>
    CassType = RTFRecord<RETURN_TO_FAB_LOTS_LOT_TYPE$>
    LotId = Lot_Services('GetLotIdByLegacyLotIdAndType', CassId, CassType)
    If LotId EQ '' then
        LotId = Lot_Services('CreateNewLot', CassType, '', '', '', '', '', 'SYSTEM', '', CassId)
    end
    If LotId NE '' then
        Return_To_Fab_Services('AddDefaultRTFOperations', LotId)
        If Error_Services('NoError') then
            //Now get all the created lot Operation records
            LotOperationIds = Lot_Services('GetLotOperationSequence', LotId)
            //Loop through all the lot operation record and fill them out.
            for each LotOperationId in LotOperationIds using @FM
                LotOperationRec = Database_Services('ReadDataRow', 'LOT_OPERATION', LotOperationId, True$, 0, False$)
                OperationId = LotOperationRec<LOT_OPERATION_OPERATION_ID$>
                Begin Case
                    Case OperationId EQ 'RTF_START'
                        LotOperationRec<LOT_OPERATION_DATETIME_IN$> = RTFRecord<RETURN_TO_FAB_LOTS_START_DTM$>
                        LotOperationRec<LOT_OPERATION_DATETIME_OUT$> = RTFRecord<RETURN_TO_FAB_LOTS_START_DTM$>
                        LotOperationRec<LOT_OPERATION_OPERATOR_IN_ID$> = RTFRecord<RETURN_TO_FAB_LOTS_REQUESTOR_USER_ID$>
                        LotOperationRec<LOT_OPERATION_OPERATOR_OUT_ID$> = RTFRecord<RETURN_TO_FAB_LOTS_REQUESTOR_USER_ID$>
                    Case OperationId EQ 'RTF_ASSIGN_REASON'
                        LotOperationRec<LOT_OPERATION_DATETIME_IN$> = RTFRecord<RETURN_TO_FAB_LOTS_START_DTM$>
                        LotOperationRec<LOT_OPERATION_DATETIME_OUT$> = RTFRecord<RETURN_TO_FAB_LOTS_START_DTM$>
                        LotOperationRec<LOT_OPERATION_OPERATOR_IN_ID$> = RTFRecord<RETURN_TO_FAB_LOTS_REQUESTOR_USER_ID$>
                        LotOperationRec<LOT_OPERATION_OPERATOR_OUT_ID$> = RTFRecord<RETURN_TO_FAB_LOTS_REQUESTOR_USER_ID$>
                    Case OperationId EQ 'RTF_ASSIGN_OPERATIONS'
                        LotOperationRec<LOT_OPERATION_DATETIME_IN$> = RTFRecord<RETURN_TO_FAB_LOTS_START_DTM$>
                        LotOperationRec<LOT_OPERATION_DATETIME_OUT$> = RTFRecord<RETURN_TO_FAB_LOTS_START_DTM$>
                        LotOperationRec<LOT_OPERATION_OPERATOR_IN_ID$> = RTFRecord<RETURN_TO_FAB_LOTS_REQUESTOR_USER_ID$>
                        LotOperationRec<LOT_OPERATION_OPERATOR_OUT_ID$> = RTFRecord<RETURN_TO_FAB_LOTS_REQUESTOR_USER_ID$>
                    Case OperationId EQ 'RTF_INIT_BIN_TO_BIN'
                        LotOperationRec<LOT_OPERATION_DATETIME_IN$> = RTFRecord<RETURN_TO_FAB_LOTS_MH_INIT_DTM$>
                        LotOperationRec<LOT_OPERATION_DATETIME_OUT$> = RTFRecord<RETURN_TO_FAB_LOTS_MH_INIT_DTM$>
                        LotOperationRec<LOT_OPERATION_OPERATOR_IN_ID$> = RTFRecord<RETURN_TO_FAB_LOTS_MH_INIT_USER_ID$>
                        LotOperationRec<LOT_OPERATION_OPERATOR_OUT_ID$> = RTFRecord<RETURN_TO_FAB_LOTS_MH_INIT_USER_ID$>
                    Case OperationId EQ 'RTF_DISPO'
                        LotOperationRec<LOT_OPERATION_DATETIME_IN$> = RTFRecord<RETURN_TO_FAB_LOTS_EVAL_DTM$>
                        LotOperationRec<LOT_OPERATION_DATETIME_OUT$> = RTFRecord<RETURN_TO_FAB_LOTS_EVAL_DTM$>
                        LotOperationRec<LOT_OPERATION_OPERATOR_IN_ID$> = RTFRecord<RETURN_TO_FAB_LOTS_EVAL_USER_ID$>
                        LotOperationRec<LOT_OPERATION_OPERATOR_OUT_ID$> = RTFRecord<RETURN_TO_FAB_LOTS_EVAL_USER_ID$>
                    Case OperationId EQ 'RTF_FINAL_BIN_TO_BIN'
                        LotOperationRec<LOT_OPERATION_DATETIME_IN$> = RTFRecord<RETURN_TO_FAB_LOTS_FINAL_COMPLETE_DTM$>
                        LotOperationRec<LOT_OPERATION_DATETIME_OUT$> = RTFRecord<RETURN_TO_FAB_LOTS_FINAL_COMPLETE_DTM$>
                        LotOperationRec<LOT_OPERATION_OPERATOR_IN_ID$> = RTFRecord<RETURN_TO_FAB_LOTS_FINAL_COMPLETE_USER_ID$>
                        LotOperationRec<LOT_OPERATION_OPERATOR_OUT_ID$> = RTFRecord<RETURN_TO_FAB_LOTS_FINAL_COMPLETE_USER_ID$>
                    Case OperationId EQ 'RTF_CLOSE'
                        LotOperationRec<LOT_OPERATION_DATETIME_IN$> = RTFRecord<RETURN_TO_FAB_LOTS_COMPLETED_DTM$>
                        LotOperationRec<LOT_OPERATION_DATETIME_OUT$> = RTFRecord<RETURN_TO_FAB_LOTS_COMPLETED_DTM$>
                        LotOperationRec<LOT_OPERATION_OPERATOR_IN_ID$> = RTFRecord<RETURN_TO_FAB_LOTS_FINAL_COMPLETE_USER_ID$>
                        LotOperationRec<LOT_OPERATION_OPERATOR_OUT_ID$> = RTFRecord<RETURN_TO_FAB_LOTS_FINAL_COMPLETE_USER_ID$>
                End Case
                Database_Services('WriteDataRow', 'LOT_OPERATION', LotOperationId, LotOperationRec)
            Next LotOperationId
            
        end
    end
    
end service


