COMPILE FUNCTION obj_WO_Log(Method,Parms)
/*
	Methods for the Work Order Log (WO_LOG) table
    
	08/16/2004 JCH - Initial Coding
	
	02/11/2025 DJM - Added logging to SAPCreate
     
    Properties:
     
    Methods:
    
    Find()					;* Lookup Work Order Log number
    Create(OrderNo)			;* Create new WO Log entry using sequential counter in DICT.WO_LOG*%SK%	
    OpenWONos()				;* List of Work Orders with open RDS's on them
	
*/
#pragma precomp SRP_PreCompiler

DECLARE FUNCTION Get_Status, Msg, Utility, obj_Tables, Dialog_Box,NextKey, Popup, obj_RDS, obj_WO_Mat, obj_WM_Out
DECLARE FUNCTION Environment_Services, Logging_Services, Error_Services, Set_Property, obj_Sched, Database_Services
DECLARE SUBROUTINE Set_Status, Msg, obj_Tables, Send_Dyn, Btree.Extract, ErrMsg, Send_Dyn, RList, obj_Order_Det
DECLARE SUBROUTINE obj_Order_Change, obj_Vision, obj_Notes, obj_WM_In, obj_WM_Out, Msg, obj_WO_Mat, obj_Reprocess
DECLARE SUBROUTINE obj_WO_Wfr, obj_WO_Step, Send_Info, obj_RDS2, obj_RDS, obj_Post_Log, obj_WO_Mat_Log, Sleepery
DECLARE SUBROUTINE Environment_Services, Logging_Services, Error_Services, Database_Services, Update_Index
DECLARE SUBROUTINE Work_Order_Services, Delay, Transaction_Services, RDS_Services, WM_In_Services, WM_Out_Services

$INSERT MSG_EQUATES
$INSERT ORDER_EQU
$INSERT ORDER_DET_EQUATES
$INSERT WO_LOG_EQUATES
$INSERT WO_MAT_EQUATES
$INSERT WO_STEP_EQU
$INSERT WM_OUT_EQUATES
$INSERT SCHEDULE_EQU
$INSERT QUOTE_EQU
$INSERT RDS_EQU
$INSERT QUOTE_SPEC_EQU
$INSERT PROD_SPEC_EQUATES
$INSERT Popup_Equates
$INSERT QUOTE_SIGS_EQU
$INSERT NOTIFICATION_EQU
$INSERT PROD_VER_EQUATES
$INSERT SAP_LOG_EQUATES
$INSERT EPI_PART_EQUATES
$INSERT COMPANY_EQUATES
$INSERT REACT_RUN_EQUATES
$INSERT DICT_EQUATES
$INSERT CUST_EPI_PART_EQUATES
$INSERT PRS_STAGE_EQUATES
$INSERT PRS_LAYER_EQUATES
$INSERT LOGICAL
$INSERT APPCOLORS
$INSERT WM_IN_EQUATES

EQU NUM_RETRIES$ TO 60

EQU CRLF$	TO \0D0A\
EQU COMMA$  TO ','

EQU TARGET_ACTIVELIST$ TO 5

ErrTitle = 'Error in Stored Procedure "obj_WO_Log"'
ErrorMsg = ''

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

LogFileName   = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' Release Log.csv'
Headers       = 'Logging DTM' : @FM : 'User' : @FM : 'Work Order No' : @FM : 'Notes'
objReleaseLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, COMMA$, Headers, '', False$, False$)

LogFileName   = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' Ship Qty Log.csv'
Headers       = 'Logging DTM' : @FM : 'User' : @FM : 'Work Order No' : @FM : 'Calculated Ship Qty' : @FM : 'Stored Ship Qty'
objShipQtyLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, COMMA$, Headers, '', False$, False$)

LogFileName   = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' Trace Log.csv'
Headers       = 'Logging DTM' : @FM : 'User' : @FM : 'ProdOrdNo' : @FM : 'Step' : @FM : 'Errors'
objTraceLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, COMMA$, Headers, '', False$, False$)

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

IF NOT(ASSIGNED(Method))	THEN ErrorMsg = 'Unassigned parameter "Method" passed to subroutine'
IF NOT(ASSIGNED(Parms))		THEN Parms = ''

IF ErrorMsg NE '' THEN
	Set_Status(-1,ErrTitle:@SVM:ErrorMsg)
	RETURN ''
END

Result = ''

BEGIN CASE
	CASE Method = 'Find'				; GOSUB Find
	CASE Method = 'Create'				; GOSUB Create
	CASE Method = 'SAPCreate'			; GOSUB SAPCreate
	CASE Method = 'Delete'				; GOSUB Delete
	CASE Method = 'CurrStatus'			; GOSUB CurrStatus
	CASE Method = 'OpenWONos'			; GOSUB OpenWONos
	CASE Method = 'ShipWONos'			; GOSUB ShipWONos
	CASE Method = 'WOStepStatus'		; GOSUB WOStepStatus
	CASE Method = 'ReleaseCassette'	    ; GOSUB ReleaseCassette
	CASE Method = 'RecallWO'			; GOSUB RecallWO
	CASE Method = 'ChangeLotNo'			; GOSUB ChangeLotNo
	CASE Method = 'ChangeCassQty'		; GOSUB ChangeCassQty
	CASE Method = 'ChangePONo'			; GOSUB ChangePONo
	CASE Method = 'AddOrderItem'		; GOSUB AddOrderItem
	CASE Method = 'RemOrderItem'		; GOSUB RemOrderItem
	CASE Method = 'SetPromiseDt'		; GOSUB SetPromiseDt
	CASE Method = 'QuoteChange'			; GOSUB QuoteChange
	CASE Method = 'SetWOSteps'			; GOSUB SetWOSteps
	CASE Method = 'NextWORun'			; GOSUB NextWORun
	CASE Method = 'AddCassNo'			; GOSUB AddCassNo
	CASE Method = 'RemoveCassettes'		; GOSUB RemoveCassettes
	CASE Method = 'SetPartNo'			; GOSUB SetPartNo
	CASE Method = 'RefreshSigProfile'	; GOSUB RefreshSigProfile
	CASE Method = 'RelQty'				; GOSUB RelQty
	CASE Method = 'RelDTMs'				; GOSUB RelDTMS
	CASE Method = 'RxQty'				; GOSUB RxQty
	CASE Method = 'ShipQty'				; GOSUB ShipQty
	CASE Method = 'ShipPropTarg'		; GOSUB ShipPropTarg
	CASE Method = 'CloseComp'			; GOSUB CloseComp
	CASE Method = 'Route'				; GOSUB Route
	CASE Method = 'Unroute'				; GOSUB Unroute
	CASE Method = 'GetAvgCycleTimes'	; GOSUB GetAvgCycleTimes
	CASE Method = 'TimeTarget'			; GOSUB TimeTarget
	CASE Method = 'PcntComp'			; GOSUB PcntComp
	CASE Method = 'EstComp'				; GOSUB EstComp
	CASE Method = 'SchedReacts'			; GOSUB SchedReacts
	CASE 1
		ErrorMsg = 'Unknown Method ':QUOTE(Method):' passed to routine.'
		
END CASE

IF ErrorMsg NE '' THEN
	Set_Status(-1,ErrTitle:@SVM:ErrorMsg)
	RETURN ''
END

RETURN Result


* * * * * * *
Find:
* * * * * * *
	
	OrderKeys = Dialog_Box( 'DIALOG_WO_FIND', @WINDOW, '' )
	
	Result = OrderKeys
	
RETURN


* * * * * * *
SAPCreate:
* * * * * * *
	
	FileIn = Parms[1,@RM]
	
	TimeStamp = ICONV(OCONV(Date(),'D4/'):' ':OCONV(Time(),'MTH'),'DT')
	
	* Create the WO_LOG Record
	
	ProdOrdNo		= FileIn<1,1>
	CustPONo		= FileIn<1,2>
	PromiseShipDt	= FileIn<1,3>
	EpiPartNo		= FileIn<1,4>
	SubPartNo		= FileIn<1,5>
	SubRevNo		= FileIn<1,6>
	WOQty			= FileIn<1,7>
	VendCd			= FileIn<1,8>
	
	LogData    = ''
    LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
    LogData<2> = @User4
    LogData<3> = ProdOrdNo
    LogData<4> = 'SAPCreate Start.'
    LogData<5> = ''
    Logging_Services('AppendLog', objTraceLog, LogData, @RM, @FM)
    
	* Add Parameter checking here -> problems then log errors and message Cust Service, no problems just the message
	
	ErrFields = ''
	ErrValues = ''
	ErrDescs = ''
	ErrCnt = 0
	
	IF ProdOrdNo = '' THEN
		ErrCnt += 1
		ErrFields<1,ErrCnt>	= 'PROD_ORD_NO'
		ErrDescs<1,ErrCnt>	= 'Null Value'
		ErrValues<1,ErrCnt> = '<null>'
	END
	
	IF NOT( ProdOrdNo MATCHES "'M'6N'.1'" OR ProdOrdNo MATCHES "7X'.1'" ) THEN
		ErrCnt += 1
		ErrFields<1,ErrCnt>	= 'PROD_ORD_NO'
		ErrDescs<1,ErrCnt>	= 'Incorrect Format'
		ErrValues<1,ErrCnt> = ProdOrdNo
	END
	
	LogData    = ''
    LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
    LogData<2> = @User4
    LogData<3> = ProdOrdNo
    LogData<4> = 'First parameter check.'
    If ErrDescs NE '' then
        ParsedErrors = ErrDescs
        Swap @VM with '|' in ParsedErrors
        LogData<5> = ParsedErrors
    end else
        LogData<5> = ''
    end
    Logging_Services('AppendLog', objTraceLog, LogData, @RM, @FM)
	
	* * * * * * Section added 12/2/2011 JCH for duplicate Prod_Ord_No checking from SAP
	
	OPEN 'DICT.WO_LOG' TO WOLogDictVar ELSE
		RETURN
	END
	
	SearchString		= 'PROD_ORD_NO':@VM:ProdOrdNO:@FM
	ExistingWOMatKey	= ''
	Option 				= ''
	Flag				= ''	
	
	Btree.Extract(SearchString,'WO_LOG',WOLogDictVar,ExistingWOMatKey,Option,Flag)
	
	IF Get_Status(errCode) THEN
	    LogData    = ''
        LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
        LogData<2> = @User4
        LogData<3> = ProdOrdNo
        LogData<4> = 'WO_LOG BTree Extract'
        LogData<5> = 'Error in BTree extract. ErrorCode: ' : errCode
        Logging_Services('AppendLog', objTraceLog, LogData, @RM, @FM)
	    RETURN
	end else
	    LogData    = ''
        LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
        LogData<2> = @User4
        LogData<3> = ProdOrdNo
        LogData<4> = 'WO_LOG BTree Extract'
        LogData<5> = ''
        Logging_Services('AppendLog', objTraceLog, LogData, @RM, @FM)
	end
	
	
	IF ExistingWOMatKey NE '' THEN
		Result = 1
		LogData    = ''
        LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
        LogData<2> = @User4
        LogData<3> = ProdOrdNo
        LogData<4> = 'Existing WO_MAT check.'
        LogData<5> = 'WO_MAT does not exist.'
        Logging_Services('AppendLog', objTraceLog, LogData, @RM, @FM)
		RETURN						;* 3/12/2013 JCH
	END else
	    LogData    = ''
        LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
        LogData<2> = @User4
        LogData<3> = ProdOrdNo
        LogData<4> = 'Existing WO_MAT check.'
        LogData<5> = ''
        Logging_Services('AppendLog', objTraceLog, LogData, @RM, @FM)
	end
	
	
	* * * * * * * 
	
	IF CustPONo = '' THEN
		ErrCnt += 1
		ErrFields<1,ErrCnt>	= 'CUST_PO_NO'
		ErrDescs<1,ErrCnt>	= 'Null Value'
		ErrValues<1,ErrCnt> = '<null>'
	END
	
	IF PromiseShipDt = '' THEN
		ErrCnt += 1
		ErrFields<1,ErrCnt>	= 'PROMISE_SHIP_DT'
		ErrDescs<1,ErrCnt>	= 'Null Value'
		ErrValues<1,ErrCnt> = '<null>'
	END
	
	IF EpiPartNo = '' THEN
		ErrCnt += 1
		ErrFields<1,ErrCnt>	= 'EPI_PART_NO'
		ErrDescs<1,ErrCnt>	= 'Null Value'
		ErrValues<1,ErrCnt> = '<null>'
	END
	
	IF WOQty = '' THEN
		ErrCnt += 1
		ErrFields<1,ErrCnt>	= 'QTY'
		ErrDescs<1,ErrCnt>	= 'Null Value'
		ErrValues<1,ErrCnt> = '<null>'
	END
	
	thisPromiseShipDt = ICONV(PromiseShipDt,'D')
	
	IF thisPromiseShipDt = '' THEN
		ErrCnt += 1
		ErrFields<1,ErrCnt>	= 'PROMISE_SHIP_DT'
		ErrDescs<1,ErrCnt>	= 'Invalid Data'
		ErrValues<1,ErrCnt> = PromiseShipDt
	END
	
	// Check for VRM SAP part number conversion record
	* Open 'DICT.EPI_PART' to hDictEpiPart then
	*    IntEpiPartNo = ''
	*    Flag         = ''
	*    Option       = 'E' ; // Suppress error messages
	*    SearchString = 'VARM_PART_NO':@VM:EpiPartNo:@FM
	*    Btree.Extract(SearchString, 'EPI_PART', hDictEpiPart, IntEpiPartNo, '', Flag)
	*    If Flag EQ 0 then
	*        If IntEpiPartNo NE '' then
	*            // Transate Varm part no to IFX part no
	*            EpiPartNo = IntEpiPartNo
	*        end
	*    end else
	*        ErrCnt              += 1
	*        ErrFields<1,ErrCnt>  = 'Btree.Extract'
	*        ErrDescs<1,ErrCnt>   = 'EPI_PART lookup failed.'
	*        ErrValues<1,ErrCnt>  = IntEpiPartNo  
	*    end
	* end
	
	EpiPartRec	= XLATE('EPI_PART',EpiPartNo,'','X')
	ProdVerNos		= EpiPartRec<EPI_PART_PROD_VER_NO$>
	
	IF EpiPartRec = '' THEN
		ErrCnt += 1
		ErrFields<1,ErrCnt>	= 'EPI_PART_NO'
		ErrDescs<1,ErrCnt>	= 'Invalid EpiPart No'
		ErrValues<1,ErrCnt> = EpiPartNo
	END
	
	LogData    = ''
    LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
    LogData<2> = @User4
    LogData<3> = ProdOrdNo
    LogData<4> = 'Second Parameter check.'
    If ErrDescs NE '' then
        ParsedErrors = ErrDescs
        Swap @VM with '|' in ParsedErrors
        LogData<5> = ParsedErrors
    end else
        LogData<5> = ''
    end
    Logging_Services('AppendLog', objTraceLog, LogData, @RM, @FM)
	
	IF ErrFields NE '' THEN
		
		LogNo = NextKey('SAP_LOG')
		LogRec = ''
		LogRec<SAP_LOG_TIMESTAMP$>		= ICONV(OCONV(Date(),'D4/'):' ':OCONV(Time(),'MTS'),'DT')
		LogRec<SAP_LOG_LOG_DESC$>		= 'Missing or Invalid Order Release from SAP Received'
		LogRec<SAP_LOG_PROD_ORD_NO$>	= ProdOrdNo
		LogRec<SAP_LOG_FIELD_NAME$>		= ErrFields
		LogRec<SAP_LOG_ERR_DESC$>		= ErrDescs
		LogRec<SAP_LOG_SAP_VALUE$> 		= ErrValues
		
		logParms = 'SAP_LOG':@RM:LogNo:@RM:@RM:LogRec
		obj_Tables('WriteRec',logParms)
		
		Recipients		= Xlate('SEC_GROUPS', 'SAP_ADMIN', 'USER', 'X')
		SentFrom		= "SAP Posting Process"
		Subject			= 'SAP Error Logged ':LogNo
		Message			= 'Work Order Posting Error from SAP'
		AttachWindow	= 'SAP_LOG'
		AttachKey		= LogNo   
		SendToGroup		= ''   
		
		Parms = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
		obj_Notes('Create',Parms)
		
		LogData    = ''
        LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
        LogData<2> = @User4
        LogData<3> = ProdOrdNo
        LogData<4> = 'ErrFields check failure.'
        If ErrDescs NE '' then
            ParsedErrors = ErrDescs
            Swap @VM with '|' in ParsedErrors
            LogData<5> = ParsedErrors
        end else
            LogData<5> = ''
        end
        Logging_Services('AppendLog', objTraceLog, LogData, @RM, @FM)
		
		RETURN
		
	END ELSE
		Result = 1	;* Set to 1 if we were successful in creating the WO_LOG Record, 0 if we just logged the problems.
	END
	
	NextWOLogNo = NextKey('WO_LOG')
	
	LogData    = ''
    LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
    LogData<2> = @User4
    LogData<3> = ProdOrdNo
    LogData<4> = 'Next WO_LOG key.'
    If ErrDescs NE '' then
        ParsedErrors = ErrDescs
        Swap @VM with '|' in ParsedErrors
        LogData<5> = ParsedErrors
    end else
        LogData<5> = ''
    end
    Logging_Services('AppendLog', objTraceLog, LogData, @RM, @FM)
	
	WOLogRec = ''
	
	IF WOQty > 2475 THEN
		
		Recipients		= Xlate('SEC_GROUPS', 'SAP_ADMIN', 'USER', 'X')  ; 
		SentFrom		= "SAP Posting Process"
		Subject			= 'SAP WO Qty > 2475 when received on ':LogNo
		Message			= 'WO Qty changed from ':WOQty:' to 2475 (SAP Maximum) prior to WO_LOG record creation'
		AttachWindow	= 'SAP_LOG'
		AttachKey		= LogNo   
		SendToGroup		= ''   
		
		Parms = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
		obj_Notes('Create',Parms)
		
		WOQty = 2475			;* Don't throw an error for this just set the qty to 2475
		
		LogData    = ''
        LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
        LogData<2> = @User4
        LogData<3> = ProdOrdNo
        LogData<4> = 'Check for maximum SAP WO Qty.'
        If ErrDescs NE '' then
            ParsedErrors = ErrDescs
            Swap @VM with '|' in ParsedErrors
            LogData<5> = ParsedErrors
        end else
            LogData<5> = ''
        end
        Logging_Services('AppendLog', objTraceLog, LogData, @RM, @FM)
		
	END	;* End of check for maximum SAP WO Qty.  This is 99 cassettes
	
	
	WOLogRec<WO_LOG_ENTRY_ID$>			= 'SAP'
	WOLogRec<WO_LOG_ENTRY_DATE$>		= Date()
	WOLogRec<WO_LOG_WO_QTY$>			= WOQty
	WOLogRec<WO_LOG_SAP_ORD_QTY$>		= WOQty
	WOLogRec<WO_LOG_EPI_PART_NO$>		= EpiPartNo
	WOLogRec<WO_LOG_PROMISE_SHIP_DT$>	= ICONV(PromiseShipDt,'D')
	WOLogRec<WO_LOG_PROD_ORD_NO$>		= ProdOrdNo
	WOLogRec<WO_LOG_ORD_SUB_PART_NO$>	= SubPartNo
	WOLogRec<WO_LOG_ORD_SUB_PART_REV$>	= SubRevNo
	WOLogRec<WO_LOG_CUST_PO_NO$>		= CustPONo
	WOLogRec<WO_LOG_ORIGIN$>			= 'S'										;* Originated from SAP System
	WOLogRec<WO_LOG_PRIORITY$>			= 'P3'										;* 
	WOLogRec<WO_LOG_EXP_VEND_CD$>		= VendCd									;* Added 4/4/2014 JCH
	
	obj_Tables('WriteRec','WO_LOG':@RM:NextWOLogNo:@RM:@RM:WOLogRec)				;* WO Record created
	
	IF Get_Status(errCode) THEN
	    LogData    = ''
        LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
        LogData<2> = @User4
        LogData<3> = ProdOrdNo
        LogData<4> = 'WO_LOG ' : NextWOLogNo ' Write'
        LogData<5> = 'Error writing WO_LOG ' : NextWOLogNo '. ErrorCode: ' : errCode
        Logging_Services('AppendLog', objTraceLog, LogData, @RM, @FM)
	end else
	    LogData    = ''
        LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
        LogData<2> = @User4
        LogData<3> = ProdOrdNo
        LogData<4> = 'WO_LOG ' : NextWOLogNo ' Write'
        LogData<5> = ''
        Logging_Services('AppendLog', objTraceLog, LogData, @RM, @FM)
	end
	
	CustType = XLATE('EPI_PART',EpiPartNo,'CUST_TYPE','X')<1,1>
	
	Recipients = XLATE('NOTIFICATION','WO_ENTRY',NOTIFICATION_USER_ID$,'X')
	SentFrom   = @USER4
	Message    = CustType:' WO ':NextWOLogNo:' (ProdOrder ':ProdOrdNo:') Created'
	NewForm    = Xlate('APP_INFO', 'NEW_WO_FORM', '', 'X')
	If NewForm then
		AttachWindow	= 'NDW_WO_LOG'
	end else
		AttachWindow	= 'WO_LOG2'
	end
	AttachKey		= NextWOLogNo
	SendToGroup		= ''   
	
	Subject	= CustType:' WO ':NextWOLogNo:' (ProdOrder ':ProdOrdNo:') Created'
	
	Parms = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
	obj_Notes('Create',Parms)
	
	IF Get_Status(errCode) THEN
	    LogData    = ''
        LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
        LogData<2> = @User4
        LogData<3> = ProdOrdNo
        LogData<4> = 'End SAPCreate'
        LogData<5> = 'Error creating note. ErrorCode: ' : errCode
        Logging_Services('AppendLog', objTraceLog, LogData, @RM, @FM)
	end else
	    LogData    = ''
        LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
        LogData<2> = @User4
        LogData<3> = ProdOrdNo
        LogData<4> = 'End SAPCreate'
        LogData<5> = ''
        Logging_Services('AppendLog', objTraceLog, LogData, @RM, @FM)
	end
	
RETURN


* * * * * * *
SetWOSteps:
* * * * * * *
	
	* This has moved to the Route method for SAP
	
	WONo = Parms[1,@RM]
	
	IF WONo = '' THEN RETURN
	
	otParms = 'WO_LOG':@RM:WONo
	WOLogRec = obj_Tables('ReadRec',otParms)
	
	IF Get_Status(errCode) THEN RETURN
	
	ProdVerNo = WOLogRec<WO_LOG_PROD_VER_NO$>
	
	ProdVerRec = XLATE('PROD_VER',ProdVerNo,'','X')
	
	ProcSteps	= ProdVerRec<PROD_VER_PROC_STEP_NO$>
	ProcPSNs	= ProdVerRec<PROD_VER_PROC_STEP_PSN$>
	ProcDescs	= ProdVerRec<PROD_VER_PROC_STEP_DESC$>
	
	ProcPSNStatuses = XLATE('PROD_SPEC',ProcPSNs,PROD_SPEC_STATUS$,'X')
	
	FOR P = 1 TO COUNT(ProcPSNStatuses,@VM) + (ProcPSNStatuses NE '')
		IF ProcPSNStatuses<1,P> NE 'A' THEN
			ErrorMsg = 'Inactive Product Spec on Prod Ver No.'
			obj_Tables('UnlockRec',otParms)
			
			RETURN
		END
	NEXT P
	
	DefWMOCassQtys = XLATE('PROD_SPEC',ProcPSNs,PROD_SPEC_WMO_LOAD_CNT$,'X')
	
	WOStepKeys = ''
	DefWMOCassQty = ''
	
	FOR N = 1 TO COUNT(ProcSteps,@VM) + (ProcSteps NE '')
		
		ProcStep	= ProcSteps<1,N>
		ProcPSN		= ProcPSNs<1,N>
		ProcDesc	= ProcDescs<1,N>
		
		obj_WO_Step('Create',WONo:@RM:ProcStep:@RM:ProcPSN:@RM:ProcDesc)
		
		IF DefWMOCassQtys<1,N> NE '' THEN DefWMOCassQty = DefWMOCassQtys<1,N>
		
		WOStepKeys<1,N> = WONo:'*':ProcStep
		
	NEXT N
	
	WOLogRec<WO_LOG_OUT_CASS_LOAD_QTY$> = DefWMOCassQty
	
	otParms = FieldStore(otParms,@RM,4,1,WOLogRec)
	obj_Tables('WriteRec',otParms)
	
RETURN


* * * * * * *
Create:
* * * * * * *
	
	OrderNo			= Parms[1,@RM]
	OrderItemNos	= Parms[COL2()+1,@RM]
	QuoteNo			= Parms[COL2()+1,@RM]
	
	IF OrderNo = '' OR OrderItemNos = '' OR QuoteNo = '' THEN RETURN
	
	QuoteRec = XLATE('QUOTE',QuoteNo,'','X')
	
	ProcSteps	= QuoteRec<QUOTE_PROC_STEP$>
	ProcPSNs	= QuoteRec<QUOTE_PROC_STEP_PSN$>
	ProcDescs	= QuoteRec<QUOTE_PROC_STEP_DESC$>
	
	
	ProcPSNStatuses = XLATE('PROD_SPEC',ProcPSNs,PROD_SPEC_STATUS$,'X')
	
	FOR I = 1 TO COUNT(ProcPSNStatuses,@VM) + (ProcPSNStatuses NE '')
		IF ProcPSNStatuses<1,I> NE 'A' THEN
			ErrorMsg = "The Process Step PSN ":QUOTE(ProcPSNs<1,I>):" on this Quote is Inactive.":CRLF$:CRLF$:"Unable to Create a Work Order."
			RETURN
		END
	NEXT I
	
	NextWOLogNo = NextKey('WO_LOG')
	
	UserName = @USER4
	
	WOLogRec = ''
	WOLogRec<WO_LOG_ORDER_NO$> 		= OrderNo
	WOLogRec<WO_LOG_ORDER_ITEM$>	= OrderItemNos
	WOLogRec<WO_LOG_ENTRY_ID$>		= UserName
	WOLogRec<WO_LOG_ENTRY_DATE$>	= Date()
	WOLogRec<WO_LOG_QUOTE_NO$>		= QuoteNo
	WOLogRec<WO_LOG_ORIGIN$>		= 'M'				;* Work Originated in Mesa MES system
	
	* Following updated 9/1/2011 JCH  *********************************
	
	WOQty = ''
	ProdVerNo = ''
	
	FOR I = 1 TO COUNT(OrderItemNos,@VM) + (OrderItemNos NE '')
		IF I = 1 THEN
			OrderDetRec	= XLATE('ORDER_DET',OrderNo:'*':OrderItemNos<1,I>,'','X')
			
			WOLogRec<WO_LOG_PROD_VER_NO$>		= OrderDetRec<ORDER_DET_PROD_VER_NO$>
			WOLogRec<WO_LOG_EPI_PART_NO$>		= OrderDetRec<ORDER_DET_EPI_PN$>
			WOLogRec<WO_LOG_CUST_PART_NO$>		= OrderDetRec<ORDER_DET_CUST_PN$>
			WOLogRec<WO_LOG_CUST_PART_INBOUND$>	= OrderDetRec<ORDER_DET_CUST_PART_NO_INBOUND$>
			WOLogRec<WO_LOG_CUST_SUB_PART_NO$>	= OrderDetRec<ORDER_DET_CUST_SUB_PART_NO$>
			WOLogRec<WO_LOG_CUST_SUB_MFR$>		= OrderDetRec<ORDER_DET_CUST_SUB_MFR$>
		END
		WOQty += XLATE('ORDER_DET',OrderNo:'*':OrderItemNos<1,I>,ORDER_DET_ITEM_QTY$,'X')
		
	NEXT I
	
	WOLogRec<WO_LOG_WO_QTY$> = WOQty
	
	* end of new code **************************************************
	
	
	WOLogRec<WO_LOG_CUST_NO$>		= QuoteRec<QUOTE_CUST_NO$>			;* Changed from ORDER table 9/1/2005 JCH - J.C. Henry & Co., Inc.
	
	DefWMOCassQtys = XLATE('PROD_SPEC',ProcPSNs,PROD_SPEC_WMO_LOAD_CNT$,'X')
	DefWMOCassQty = ''
	
	FOR I = 1 TO COUNT(ProcSteps,@VM) + (ProcSteps NE '')
		
		ProcStep	= ProcSteps<1,I>
		ProcPSN		= ProcPSNs<1,I>
		ProcDesc	= ProcDescs<1,I>
		
		obj_WO_Step('Create',NextWOLogNo:@RM:ProcStep:@RM:ProcPSN:@RM:ProcDesc)
		
		IF DefWMOCassQtys<1,I> NE '' THEN DefWMOCassQty = DefWMOCassQtys<1,I>
		
	NEXT I
	
	WOLogRec<WO_LOG_OUT_CASS_LOAD_QTY$> = DefWMOCassQty
	
	obj_Tables('WriteRec','WO_LOG':@RM:NextWOLogNo:@RM:@RM:WOLogRec)				;* WO Record created
	
	Recipients = XLATE('NOTIFICATION','WO_ENTRY',NOTIFICATION_USER_ID$,'X')
	SentFrom   = @USER4
	Subject    = 'New Work Order Created ':NextWOLogNo
	Message    = 'New Work Order Created.'
	NewForm    = Xlate('APP_INFO', 'NEW_WO_FORM', '', 'X')
	If NewForm then
		AttachWindow	= 'NDW_WO_LOG'
	end else
		AttachWindow	= 'WO_LOG2'
	end
	AttachKey		= NextWOLogNo
	SendToGroup		= ''   
	
	Parms = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
	obj_Notes('Create',Parms)
	* 7/11/19 - TODO - create similar notification mechanism for Priscila's GaN team for GaN related work orders
	IF Get_Status(errCode) THEN
		ErrMsg(errCode)
	END
	
	IF Get_Status(errCode) ELSE Result = NextWOLogNo
	
RETURN


* * * * * * *
Delete:
* * * * * * *
	
	WONo = Parms[1,@RM]
	
	IF WONo	= ''			THEN ErrorMsg = 'Null parameter WONo passed to routine (':Method:').'
	IF ErrorMsg NE ''		THEN RETURN
	
	WOLogRec = XLATE('WO_LOG',WONo,'','X')
	WOStepKeys = WOLogRec<WO_LOG_WO_STEP_KEY$>
	
	FOR I = 1 TO COUNT(WOStepKeys,@VM) + (WOStepKeys NE '')
		WOStepRec = XLATE('WO_STEP',WOStepKeys<1,I>,'','X')
		
		IF WOStepRec<WO_STEP_RDS_KEY$> NE '' THEN
			ErrorMsg = 'Work Order Step currently has RDS records attached and may not be deleted.'
		END
		
		IF WOStepRec<WO_STEP_WM_IN_KEYS$> NE '' THEN
			ErrorMsg = 'Work Order Step currently has WM_IN records attached and may not be deleted.'
		END
		
		IF WOStepRec<WO_STEP_WM_OUT_KEYS$> NE '' THEN
			ErrorMsg = 'Work Order Step currently has WM_OUT records attached and may not be deleted.'
		END
		
		IF ErrorMsg NE '' THEN RETURN
	NEXT I
	
	
	FOR I = 1 TO COUNT(WOStepKeys,@VM) + (WOStepKeys NE '')
		WOStepKey = WOStepKeys<1,I>
		CONVERT '*' TO @RM IN WOStepKey
		Set_Status(0)
		obj_WO_Step('Delete',WOStepKey)
		IF Get_Status(errCode) THEN RETURN
	NEXT I
	
	TableVar = ''
	OtParms = 'WO_LOG':@RM:WONo:@RM:TableVar 
	WOLogRec = obj_Tables('DeleteRec',OtParms)			;* Locks and reads record for update
	
	IF Get_Status(errCode) THEN ErrMsg(errCode)
	
RETURN


* * * * * * *
CurrStatus:
* * * * * * *
	
	IF NOT(ASSIGNED(WONo)) THEN WONo = Parms[1,@RM]
	IF NOT(ASSIGNED(WORec)) THEN WORec = Parms[COL2()+1,@RM]
	
	IF WONo = ''	THEN RETURN			;* This is used in the dictionary -> don't throw an error for a null parmeter
	
	IF WORec= '' THEN WORec = XLATE('WO_LOG',WONo,'','X')
	
	IF WORec<WO_LOG_CLOSE_DATE$> NE '' THEN
		Result = 'CL'						;* Manual Close
		RETURN
	END
	
	IF WORec<WO_LOG_ORDER_NO$> = '' AND WORec<WO_LOG_PROD_ORD_NO$> = '' THEN
		Result = 'NORD'						;* Junk from conversion
		RETURN
	END
	
	IF WORec<WO_LOG_PROD_ORD_NO$> NE '' AND WORec<WO_LOG_PROD_VER_NO$> = '' THEN
		Result = 'UNR'
		RETURN
	END
	
	WOQty = WORec<WO_LOG_WO_QTY$>
	
	GOSUB ShipQty
	
	ShipQty = Result
	
	StaticShipQty = WORec<WO_LOG_STATIC_SHIP_QTY$>
	
	If ShipQty NE StaticShipQty then
		// Log the discrepancy
		LogData    = ''
		LogData<1> = LoggingDTM
		LogData<2> = @User4
		LogData<3> = WONo
		LogData<4> = ShipQty
		LogData<5> = StaticShipQty
		Logging_Services('AppendLog', objShipQtyLog, LogData, @RM, @FM)
	end
	
	IF ShipQty = '' THEN ShipQty = 0
	
	Result = ''
	
	StepKeys = WORec<WO_LOG_WO_STEP_KEY$>
	FirstStepRDSKeys = XLATE('WO_STEP',StepKeys<1,1>,WO_STEP_RDS_KEY$,'X')
	
	FirstWOMatKey = WORec<WO_LOG_WO_MAT_KEY$,1>
	
	FirstWOMatRelDTM = XLATE('WO_MAT',FirstWOMatKey,WO_MAT_REL_DTM$,'X')
	FirstWOMatRxDTM = XLATE('WO_MAT',FirstWOMatKey,WO_MAT_RX_DTM$,'X')
	
	IF FirstWOMatRelDTM NE '' OR FirstStepRDSKeys NE '' THEN
			
        BEGIN CASE
            CASE ShipQty = 0		; Result = 'INPR'
            CASE ShipQty < WOQty	; Result = 'SHIP'
            CASE ShipQty >= WOQty	; Result = 'COMP'
        END CASE
        
        IF Result NE '' THEN RETURN
        
        IF FirstWOMatRelDTM NE '' THEN
            Result = 'REL'
            RETURN
        END
        
        IF FirstWOMatRxDTM NE '' THEN
            Result = 'AWR'
            RETURN
        END

	END
	
	
	IF WORec<WO_LOG_WO_MAT_KEY$> = '' THEN
		EpiPN         = WORec<WO_LOG_EPI_PART_NO$>
		SubSuppliedby = XLATE('EPI_PART',EpiPN,EPI_PART_SUB_SUPP_BY$,'X')
		CustLotNos    = WORec<WO_LOG_CUST_LOT_NO$>
		IF SubSuppliedBy = 'C' THEN
			IF CustLotNos = '' THEN
				Result = 'ASN'
			END ELSE
				Result = 'AWM'
			END
		END ELSE
			Result = 'RTP'
		END
	END
	
	IF Result NE '' THEN RETURN
	
	IF FirstWOMatRelDTM NE '' THEN
		Result = 'REL'
		RETURN
	END
	
	IF FirstWOMatRxDTM NE '' THEN
		Result = 'AWR'
		RETURN
	END
	
	IF Result = '' THEN Result = 'INC'
	
RETURN


* * * * * * *
OpenWONos:
* * * * * * *
	
	OPEN 'WO_LOG' TO WOLogTable ELSE
		ErrorMsg = 'Unable to Open WO_LOG table in obj_WO_LOG for index lookup'
		RETURN
	END
	
	OPEN 'DICT.WO_LOG' TO DictWOLogTable ELSE
		RETURN
	END
	
	MsgUp = Msg(@WINDOW,'','SELECT_OPEN_WO')
	
	WOKeys = ''
	
	SelectStatement = 'CLOSE_DATE':@VM:'':@FM		;* Added by dkk 4/3/14
	
	Btree.Extract(SelectStatement,'WO_LOG',DictWOLogTable,WOKeys,'','')
	
	IF Get_Status(errCode) THEN
		ErrMsg(errCode)
		Msg(@WINDOW,MsgUp)
		RETURN
	END
	
	Msg(@WINDOW,MsgUp)
	
	TypeOver = ''
	TypeOver<PDISPLAY$> = WOKeys
	TypeOver<PMODE$>	= 'K'
	
	WONo = Popup(@WINDOW,TypeOver,'OPEN_WORK_ORDERS')
	
	IF Get_Status(errCode) THEN
		ErrMsg(errCode)
		RETURN
	END
	
	Result = WONo
	
RETURN


* * * * * * *
ShipWONos:
* * * * * * *
	
	OPEN 'WO_LOG' TO WOLogTable ELSE
		RETURN
	END
	
	MsgUp = Msg(@WINDOW,'','SELECT_OPEN_WO')
	
	IF Get_Status(errCode) THEN RETURN
	
	SelectStatement  = 'SELECT WO_LOG WITH CURR_STATUS_STATIC = "INPR" '
	SelectStatement := ' OR WITH CURR_STATUS_STATIC = "RTS"'
	SelectStatement := ' OR WITH CURR_STATUS_STATIC = "SHIP"'
	SelectStatement := ' OR WITH CURR_STATUS_STATIC = "HOLD"'
	SelectStatement := ' BY COMMIT_DATE'
	
	RList(SelectStatement, TARGET_ACTIVELIST$, '','','')
	
	IF Get_Status(errCode) THEN
		ErrMsg(errCode)
		Msg(@WINDOW,MsgUp)
		RETURN
	END
	
	Msg(@WINDOW,MsgUp)
	
	WONo = Popup(@WINDOW,TypeOver,'OPEN_WORK_ORDERS')
	
	IF Get_Status(errCode) THEN
		ErrMsg(errCode)
		RETURN
	END
	
	Result = WONo
	
RETURN


* * * * * * *
WOStepStatus:
* * * * * * *
	
	* Method to maintain WO_STEP Status codes from the WO_Step table.
	
	WONo		= Parms[1,@RM]
	WOStepKey	= Parms[COL2()+1,@RM]
	CurrStatus	= Parms[COL2()+1,@RM]
	
	IF WONo = '' THEN RETURN							;* Called from dictionary so don't throw an error
	IF WOStepKey = '' THEN RETURN		
	
	TableVar = ''
	OtParms = 'WO_LOG':@RM:WONo:@RM:TableVar 
	WOLogRec = obj_Tables('ReadRec',OtParms)			;* Locks and reads record for update
	
	LOCATE WOStepKey IN WOLogRec<WO_LOG_WO_STEP_KEY$> USING @VM SETTING Pos THEN
		WOLogRec<WO_LOG_WO_STEP_STATUS$,Pos> = CurrStatus
		OtParms = FieldStore(OtParms,@RM,4,1,WOLogRec)
		obj_Tables('WriteRec',OtParms)
	END ELSE
		obj_Tables('UnlockRec',OtParms)
	END
	
RETURN


* * * * * * *
ReleaseCassette:
* * * * * * *
	
	WONo		= Parms[1,@RM]
	CassNo		= Parms[COL2()+1,@RM]
	ReleaseUser = Parms[COL2()+1,@RM]
	RelDtm      = Parms[COL2()+1,@RM]
	
	LogData    = ''
	LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
	LogData<2> = ReleaseUser
	LogData<3> = WONo
	LogData<4> = 'WONo: ':WONo:' CassNo: ':CassNo:' ReleaseUser: ':ReleaseUser:' ||| Beginning ReleaseCassette routine.'
	Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
	
	IF WONo	= ''			THEN ErrorMsg = 'Null parameter WONo passed to routine (':Method:').'
	IF ErrorMsg NE ''		THEN RETURN
	
	TableVar = ''
	OtParms  = 'WO_LOG':@RM:WONo:@RM:TableVar 
	
	WORec = Database_Services('ReadDataRow', 'WO_LOG', WONo)
	If Error_Services('NoError') then 
	
        * Added 5/21/2015 JCH to check for previous releases on this work order
        
        WOMatKeys = WORec<WO_LOG_WO_MAT_KEY$>
        
        IF Get_Status(errCode) THEN Return
        
        OrderNo		= WORec<WO_LOG_ORDER_NO$>
        OrderItems	= WORec<WO_LOG_ORDER_ITEM$>
        CustNo		= WORec<WO_LOG_CUST_NO$>
        PromiseDt	= WORec<WO_LOG_PROMISE_SHIP_DT$>
        WOStepKeys	= WORec<WO_LOG_WO_STEP_KEY$
        ProdVerNo	= WORec<WO_LOG_PROD_VER_NO$>
        EPIPartNo	= WORec<WO_LOG_EPI_PART_NO$>
        ReactType	= WORec<WO_LOG_REACT_TYPE$>		;* Added 5/28/2016 JCH
        
        IF OrderNo = '' AND ProdVerNo = '' THEN ErrorMsg = 'Both Order No and Prod Ver No blank on Work Order. WO Not Released. (':Method:')'
        
        IF CustNo		= '' THEN ErrorMsg = 'No Cust Number on Work Order. WO Not Released. (':Method:')'
        IF WOStepKeys	= '' THEN ErrorMsg = 'Missing WO Step Keys. WO Not Released. (':Method:')'
        
        IF ErrorMsg NE '' THEN
            obj_Tables('UnlockRec',OtParms)
            RETURN
        END
        
        IF ProdVerNo NE '' THEN
            ReactorType = XLATE('PROD_VER',ProdVerNo,PROD_VER_REACT_TYPE$,'X')
            IF ReactorType NE 'EPP' THEN
                IF WORec<WO_LOG_WO_START_DTM$> = '' THEN
                    CurrDTM = ICONV(OCONV(Date(),'D4/'):' ':OCONV(Time(),'MTHS'),'DT')
                    WORec<WO_LOG_WO_START_DTM$> = CurrDTM
                END
            END
        END
        
        IF OrderNo = '' THEN
            OrderWaferQty	= WORec<WO_LOG_WO_QTY$>
            PONo			= WORec<WO_LOG_CUST_PO_NO$>
            VisionOrderNo	= WORec<WO_LOG_PROD_ORD_NO$>		;* SAP Production Order Number
            VisionLineNos	= ''
            WMOLoadQty		= XLATE('CUST_EPI_PART',CustNo:'*':EPIPartNo,CUST_EPI_PART_WMO_LOAD_CNT$,'X')
        END ELSE
            OrderRec = XLATE('ORDER',OrderNo,'','X')
            OrderWaferQty	= 0
            
            FOR I = 1 TO COUNT(OrderItems,@VM) + (OrderItems NE '')
                OrderDetRec = XLATE('ORDER_DET',OrderNo:'*':OrderItems<1,I>,'','X')
                IF NOT(INDEX(OrderDetRec<ORDER_DET_EPI_PN$>,'MISC',1)) THEN
                    OrderWaferQty = OrderWaferQty + OrderDetRec<ORDER_DET_ITEM_QTY$>
                END
            NEXT I
            
            PONo			= OrderRec<ORDER_PO_NO$>
            VisionOrderNo	= OrderRec<ORDER_VISION_ORDER_NO$>
            VisionLineNos	= XLATE('ORDER_DET',OrderItems,ORDER_DET_VISION_LINE_NO$,'X')
        END
        
        OrdSummary = ''	;* Holds Order Detail Lot Numbers and Associated Order Item Numbers
        
        WOMKey = WONo:'*':CassNo
        
        WOMTableVar = Database_Services('GetTableHandle', 'WO_MAT')
        
        IF Get_Status(errCode) THEN
            obj_Tables('UnlockRec',OtParms)	
            RETURN
        END
        
        LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
        LogData<4> = 'WONo:':WONo:' CassNo:':CassNo:' ||| Trace 1'
        Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
        
        EpiPN		= WORec<WO_LOG_EPI_PART_NO$>
        EpiPartRec	= XLATE('EPI_PART',EpiPN,'','X')
        SubSupplyBy	= EpiPartRec<EPI_PART_SUB_SUPP_BY$>
        ProdVerRec  = XLATE('PROD_VER',ProdVerNo,'','X')
        ProcStepNos = ProdVerRec<PROD_VER_PROC_STEP_NO$>
        ProcPSNs	= ProdVerRec<PROD_VER_PROC_STEP_PSN$>
        ReactorType	= ProdVerRec<PROD_VER_REACT_TYPE$>
        WOStepCnt   = COUNT(ProcPSNs,@VM) + (ProcPSNs NE '')
        
        LastStep = ''
        
        FOR WOStep = 1 TO WOStepCnt
            
            WOStepKey = WORec<WO_LOG_WO_STEP_KEY$,WOStep>
            WOStepRec = XLATE('WO_STEP',WOStepKey,'','X')
            
            IF WOStep = WOStepCnt THEN LastStep = 1 ELSE LastStep = 0
            
            ProcPSN			= ProcPSNs<1,WOStep>
            
            SubPreClean		= XLATE('PRS_STAGE',ProcPSN:'*PRE',PRS_STAGE_CLEAN_TOOL$,'X')
            SubPostClean	= XLATE('PRS_STAGE',ProcPSN:'*POST',PRS_STAGE_CLEAN_TOOL$,'X')
            
            // Log variables before obj_WM_Out('Create')
            LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
            LogData<4> = 'WONo:':WONo:' WOStep:':WOStep:' CassNo:':CassNo:' WMOLoadQty:':WMOLoadQty
            Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
            
            IF ReactorType = 'EPP' THEN
                Send_Info('Creating WM_OUT records for WOStep ':WOStep:'...')						
                OutOnlyCassIDs = obj_WM_Out('Create',WONO:@RM:WOStep:@RM:CassNo:@RM:WMOLoadQty)
            END ELSE
                OutOnlyCassIDs = ''
            END
            
            StepRDSNos = ''
            
            // Log variables after obj_WM_Out('Create')
            LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
            LogData<4> = 'WONo:':WONo:' WOStep:':WOStep:' CassNo:':CassNo:' WMOLoadQty:':WMOLoadQty
            Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
            
            LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
            LogData<4> = 'WONo:':WONo:' WOStep:':WOStep:' CassNo:':CassNo:' WMOLoadQty:':WMOLoadQty:' ||| Trace 2'
            Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
            
            IF ReactorType EQ 'EPP' THEN
                
                CassWaferQty = XLATE('WO_MAT',WONo:'*':CassNo,WO_MAT_WAFER_QTY$,'X')
                WMIKey = WONo:'*':WOStep:'*':CassNo
                obj_WM_IN('Create',WONo:@RM:WOStep:@RM:CassNo:@RM:CassWaferQty)	
                
            END ELSE
                
                WOMatRec   = XLATE('WO_MAT',WoNo:'*':CassNo,'','X')
                RDSNoCheck = WOMatRec<WO_MAT_RDS_NO$>
                If RDSNoCheck EQ '' then 
                    
                    CassLotNo      = WOMatRec<WO_MAT_LOT_NO$>
                    CassWaferQty   = WOMatRec<WO_MAT_WAFER_QTY$>
                    CassCustPartNo = WOMatRec<WO_MAT_CUST_PART_NO$>
                    CassSubPartNo  = WOMatRec<WO_MAT_SUB_PART_NO$>
                    CassSubInvID   = ''
                    CassOrderItem  = WOMatRec<WO_MAT_ORDER_ITEM$>
                    ReprocessedMat = WOMatRec<WO_MAT_REPROCESSED_MAT$>
                    CassSubVendCd  = WOMatRec<WO_MAT_SUB_VEND_CD$>
                    
                    IF OrderNo = '' THEN
                        QuoteNo = ''
                    END ELSE
                        QuoteNo	= XLATE('ORDER_DET',OrderNo:'*':CassOrderItem,ORDER_DET_QUOTE_NO$,'X')
                    END	
                    
                    Parms  = WONo:@RM
                    Parms := WOStep:@RM
                    Parms := LastStep:@RM
                    Parms := CassNo:@RM
                    Parms := QuoteNo:@RM
                    Parms := OrderNo:@RM
                    Parms := CassOrderItem:@RM
                    Parms := CustNo:@RM
                    Parms := PONo:@RM 
                    Parms := ProcPSN:@RM
                    Parms := SubSupplyBy:@RM
                    Parms := SubPreClean:@RM
                    Parms := SubPostClean:@RM
                    Parms := PromiseDt:@RM 
                    Parms := CassLotNo:@RM
                    Parms := CassCustPartNo:@RM
                    Parms := CassWaferQty:@RM
                    Parms := CassSubPartNo:@RM
                    Parms := '':@RM				;* QXJ Flag
                    Parms := CassSubVendCd
                    
                    IF ReactorType NE 'GAN' then
                        
                        LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
                        LogData<4> = 'WONo:':WONo:' WOStep:':WOStep:' CassNo:':CassNo:' WMOLoadQty:':WMOLoadQty:' ||| Trace 2.1 - Start obj_RDS("Create")'
                        Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
                        Done       = False$
                        For AttemptIndex = 1 to NUM_RETRIES$
                            If (AttemptIndex GT 1) then Delay(1)
                            NewRDSNo   = obj_RDS('Create',Parms)
                            errCode    = ''
                            Begin Case
                                Case Get_Status(errCode)
                                    LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
                                    LogData<4> = 'WONo:':WONo:' WOStep:':WOStep:' CassNo:':CassNo:' WMOLoadQty:':WMOLoadQty:' ||| Trace 2.1.1 - Attempt ':AttemptIndex:'. Error calling obj_RDS("Create"). Error message: ':errCode
                                    Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)							            
                                Case (NewRDSNo EQ 0) or (NewRDSNo EQ '')
                                    LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
                                    LogData<4> = 'WONo:':WONo:' WOStep:':WOStep:' CassNo:':CassNo:' WMOLoadQty:':WMOLoadQty:' ||| Trace 2.1.1 - Attempt ':AttemptIndex:'. Error calling obj_RDS("Create"). Invalid RDSNo ':Quote(RDSNo):' returned.'
                                    Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)							        
                                Case RowExists('RDS', NewRDSNo)
                                    Done = True$
                            End Case
                        Until Done
                        Next AttemptIndex
                        
                        LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
                        LogData<4> = 'WONo:':WONo:' WOStep:':WOStep:' CassNo:':CassNo:' WMOLoadQty:':WMOLoadQty:' ||| Trace 2.2 - End obj_RDS("Create")'
                        Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
                        
                        If ( (NewRDSNo EQ 0) or (NewRDSNo EQ '') ) then
                            
                            ErrMsg(errCode)
                            ErrorMsg = "RDS '" : NewRDSNo : "' Create Failure - Check for missing data on Work Order"
                            If Error_Services('HasError') then
                                ErrMsg    = Error_Services('GetMessage')
                                LogData   = LoggingDTM : ',' : ReleaseUser : ',' : WONo : ',' : ErrMsg				    
                                Logging_Services('AppendLog', objLog, LogData, CRLF$, COMMA$, False$, '', LogData)
                            end
                            
                            RTParms = 'RDS'
                            FOR I = 1 TO COUNT(StepRdsNos,@VM) + (StepRdsNos NE '')
                                RdsNo = StepRdsNos<1,I>
                                RTParms = FieldStore(RTParms, @RM, 2, 1, RdsNo)
                                obj_Tables('DeleteRec',RTParms)
                            NEXT I
                            RETURN		
                        END else
                            // No error creating RDS record -> add it to the batch list.
                            StepRDSNos<1,-1> = NewRDSNo
                        end
                        
                        IF ReprocessedMat THEN
                            OrgRDSNo = CassLotNo
                            obj_Reprocess('FixUp',OrgRDSNo:@RM:NewRDSNo)	
                        END
                        
                    END	;* End of check for GAN reactor
                END		;* End of Check for existing RDS
            END		;* End of check for EpiPRO reactor type
        NEXT WOStep        
        
        LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
        LogData<4> = 'WONo:':WONo:' WOStep:':WOStep:' CassNo:':CassNo:' WMOLoadQty:':WMOLoadQty:' ||| Trace 3'
        Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
        
        If RelDtm EQ '' then 
            RelDTM = OCONV(Date(),'D4/'):' ':OCONV(Time(),'MTHS')		;* 12/31/2014 JCH & DKK moved to prevent time incrementing time during release
        end else
            If Num(RelDtm) then
                RelDtm = OConv(RelDtm, 'DT4/^HS')
            end else
                RelDtm = OConv(IConv(RelDtm, 'DT'), 'DT4/^HS')
            end
        end
        PtiDTM = OCONV(Date(),'D4/'):' ':OCONV(Time()+5,'MTHS')
        
        MaxShipQty    = Xlate('WO_LOG', WONo, 'CUST_EPI_PART_SHIP_QTY', 'X')
        
        CassNo = FIELD(WOMKey,'*',2)
        // Keep trying to get the lock. Another process may be updating this record at the same time.
        Done   = False$
        For AttemptIndex = 1 to NUM_RETRIES$
            
            LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
            LogData<4> = 'WONo:':WONo:' WOStep:':WOStep:' CassNo:':CassNo:' WMOLoadQty:':WMOLoadQty:' ||| Trace 3.':AttemptIndex
            Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
                            
            If (AttemptIndex GT 1) then Delay(1)
            HaveLock    = Database_Services('GetKeyIDLock', 'WO_MAT', WOMKey, True$)
            If HaveLock then
                
                LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
                LogData<4> = 'WONo:':WONo:' WOStep:':WOStep:' CassNo:':CassNo:' WMOLoadQty:':WMOLoadQty:' ||| Trace 3.':AttemptIndex:' Have lock!'
                Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)                    
                
                WOMatRec = XLATE('WO_MAT',WOMKey,'','X')			;* We have the lock, so just get the record this way
                
                IF WOMatRec<WO_MAT_REL_DTM$> = '' THEN
                    WOMatRec<WO_MAT_REL_DTM$>		= IConv(RelDTM,'DT')
                    WOMatRec<WO_MAT_REL_BY$>		= ReleaseUser
                    WOMatRec<WO_MAT_ORG_COMMIT_DT$>	= PromiseDt
                    
                    IF SubPreClean = 'No' OR SubPreClean = '' THEN
                        WOMatRec<WO_MAT_WMI_CURR_STATUS$> = 'RTU'
                    END ELSE
                        WOMatRec<WO_MAT_WMI_CURR_STATUS$> = 'PREC'
                    END
                    
                    WOMatRec<WO_MAT_WMO_CURR_STATUS$> = 'RTB'
                    
                    thisInvDTM = ICONV(RelDTM,'DT')
                    
                    WHCd		= 'SR'
                    LocCd		= 'RB'
                    InvAction	= 'REL'
                    ScanUserID	= ReleaseUser
                    Tag			= ''
                    ToolID		= ''
                    
                    LOCATE thisInvDTM IN WOMatRec<WO_MAT_INV_DTM$> BY 'AR' USING @VM SETTING Pos ELSE
                        
                        WOMatRec = INSERT(WOMatRec,WO_MAT_INV_WH$,Pos,0,WHCd)
                        WOMatRec = INSERT(WOMatRec,WO_MAT_INV_LOCATION$,Pos,0,LocCd)
                        WOMatRec = INSERT(WOMatRec,WO_MAT_INV_ACTION$,Pos,0,InvAction)
                        WOMatRec = INSERT(WOMatRec,WO_MAT_INV_DTM$,Pos,0,thisInvDTM)
                        WOMatRec = INSERT(WOMatRec,WO_MAT_INV_USER$,Pos,0,ScanUserID)
                        WOMatRec = INSERT(WOMatRec,WO_MAT_INV_TAG$,Pos,0,Tag)
                        WOMatRec = INSERT(WOMatRec,WO_MAT_INV_TOOL_ID$,Pos,0,ToolID)
                        WOMatRec = INSERT(WOMatRec,WO_MAT_INV_SCAN_ENTRY$,Pos,0,False$)
                        
                    END 
                    
                    WOMatParms = 'WO_MAT':@RM:WOMKey:@RM:WOMTableVar:@RM:WOMatRec
                    obj_Tables('WriteRec',WOMatParms)					;* This writes and unlocks the WO_MAT records                                          
                    
                    If Not(Get_Status(errCode)) then
                        Done       = True$
                        LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
                        LogData<4> = 'WONo:':WONo:' WOStep:':WOStep:' CassNo:':CassNo:' WMOLoadQty:':WMOLoadQty:' ||| Trace 3.':AttemptIndex:' Successfully updated WO_MAT record ':WOMKey:' with REL operation.'
                        Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)                              
                    end else
                        LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
                        LogData<4> = 'WONo:':WONo:' WOStep:':WOStep:' CassNo:':CassNo:' WMOLoadQty:':WMOLoadQty:' ||| Trace 3.':AttemptIndex:' Failed to update WO_MAT record ':WOMKey:' with REL operation.'
                        Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)                              
                    end
                    
                    IF ReactType = 'EPP' OR ReactType = 'GAN' THEN
                        obj_WO_Wfr('CassRel',WOMKey)					;* Added 3/17/2016 JCH for wafer history 
                    END
                END else
                    LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
                    LogData<4> = 'WONo:':WONo:' WOStep:':WOStep:' CassNo:':CassNo:' WMOLoadQty:':WMOLoadQty:' ||| Trace 3.':AttemptIndex:' Error! REL_DTM is not null.'
                    Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)                         
                end
            end
        Until Done
        Next AttemptIndex
            
        LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
        LogData<4> = 'WONo:':WONo:' WOStep:':WOStep:' CassNo:':CassNo:' WMOLoadQty:':WMOLoadQty:' ||| Trace 4'
        Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
        
        OutOnlyCnt        = DCount(OutOnlyCassIDs, @VM)
        ExistingWOMatKeys = WORec<WO_LOG_WO_MAT_KEY$>
        NewWOMatKeys      = ExistingWOMatKeys
        FOR I = 1 TO OutOnlyCnt
            OutOnlyCassID = OutOnlyCassIDs<1,I>
            LOCATE OutOnlyCassID IN ExistingWOMatKeys BY 'AR' USING @VM SETTING Pos ELSE
                NewWOMatKeys<0, CassNo> = OutOnlyCassID
                Transaction_Services('PostWriteFieldTransaction', 'WO_LOG', WONo, WO_LOG_WO_MAT_KEY$, OutOnlyCassID, CassNo)
            END
        NEXT I
        
        LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
        LogData<4> = 'WONo:':WONo:' WOStep:':WOStep:' CassNo:':CassNo:' WMOLoadQty:':WMOLoadQty:' ||| Trace 5'
        Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
        
        ReactNos = obj_Sched('GetReactNos',WONo)		; // 5/26/2-15 JCH Added schedule ReactNos and check for WO_START_DTM$
        
        rnCnt = COUNT(ReactNos,@VM) + (ReactNos NE '')
        
        IF rnCnt GE 1 THEN
            
            BEGIN CASE
                CASE rnCnt = 1	
                    Message = CassCnt:' Cassettes Released for Reactor No: ':ReactNos
                    
                CASE rnCnt = 2
                    SWAP @VM WITH ' and ' IN ReactNos
                    Message	 = CassCnt:' Cassettes Released for Reactor Nos: ':ReactNos
                    
                CASE 1
                    LastReact = ReactNos<1,rnCnt>
                    RestOfReacts = FIELD(ReactNos,@VM,1,rnCnt - 1)
                    SWAP @VM WITH ', ' IN RestOfReacts
                    Message = CassCnt:' Cassettes Release for Reactor Nos: ':RestOfReacts:', and ':LastReact
                    
            END CASE
            
            IF WORec<WO_LOG_WO_START_DTM$> NE '' THEN
                Recipients = XLATE('NOTIFICATION','WO_RELEASE',NOTIFICATION_USER_ID$,'X')
                SentFrom   = ReleaseUser
                Subject    = 'Work Order Release on ':WONo
                IF ReactorType = 'EPP' THEN
                    AttachWindow = 'WO_PROD_EPI'
                END ELSE
                    AttachWindow = 'WO_PROD'
                END
                AttachKey 		= WONo:'*':1
                SendToGroup		= ''   
                Parms = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
                obj_Notes('Create',Parms)
                IF Get_Status(errCode) THEN
                    ErrMsg(errCode)
                END
            END
        END	;* WO is not on the schedule
        
    end else
        ErrorMsg = 'Error reading WO_LOG record ':WONo:'. in routine (':Method:').'
    end
    
    If ErrorMsg NE '' then
        LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
        LogData<4> = 'WONo:':WONo:' WOStep:':WOStep:' CassNo:':CassNo:' WMOLoadQty:':WMOLoadQty:'  ||| Error Message: ':ErrorMsg
        Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)        
    end
	
	LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
	LogData<4> = 'WONo:':WONo:' WOStep:':WOStep:' CassNo:':CassNo:' WMOLoadQty:':WMOLoadQty:'  ||| Ending ReleaseCassette routine'
	Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
	
RETURN


* * * * * * *
RecallWO:
* * * * * * *
	
	WONo = Parms[1,@RM]
	
	IF WONo	= ''			THEN ErrorMsg = 'Null parameter WONo passed to routine (':Method:').'
	IF ErrorMsg NE ''		THEN RETURN
	
	WORec = XLATE('WO_LOG',WONo,'','X')
	
	
	CassNos = XLATE('WO_LOG',WONo,'WO_MAT_CASS_NO','X')
	
	CassCnt = COUNT(CassNos,@VM) + (CassNos NE '')
	
	WOMKeys = ''
	FOR K = 1 TO CassCnt
		WOMKeys<1,K> = WONo:'*':CassNos<1,K>
	NEXT K
	
	WOMTableVar = obj_WO_Mat('LockSet',WOMKeys)			;* Locks all WO_MAT records on the Work Order
	IF Get_Status(errCode) THEN RETURN					;* Couldn't lock all of the cassettes
	
	
	WOMCnt = COUNT(WOMKeys,@VM) + (WOMKeys NE '')
	
	FOR I = 1 TO WOMCnt
		WOMKey = WOMKeys<1,I>
		
		WOMatRec = XLATE('WO_MAT',WOMKey,'','X')			;* We have the lock, so just get the record this way	
		
		WMIKey = WOMatRec<WO_MAT_WMI_KEY$>
		WMOKey = WOMatRec<WO_MAT_WMO_KEY$>
		
		IF WMIKey NE '' THEN obj_WM_In('Delete',WMIKey)
		IF WMOKey NE '' THEN obj_WM_Out('Delete',WMOKey)
		
		IF WOMatRec<WO_MAT_REL_DTM$> NE '' THEN
			
			IF WOMatRec<WO_MAT_RDS_NO$> NE '' THEN
				
				RDSCnt = COUNT(WOMatRec<WO_MAT_RDS_NO$>,@VM) + (WOMatRec<WO_MAT_RDS_NO$> NE '')
				
				FOR N = 1 TO RDSCnt
					Set_Status(0)
					obj_RDS('Delete',WOMatRec<WO_MAT_RDS_NO$,N>)
				NEXT I
			END
			
			IF WMIKey NE '' THEN obj_WM_In('Delete',WMIKey)
			IF WMOKey NE '' THEN obj_WM_Out('Delete',WMOKey)
			
			obj_WO_Wfr('CassDel',WOMKey)			;* Added 3/17/2016 JCH for wafer tracking *********************************
			
			WOMatRec<WO_MAT_REL_DTM$>		= ''
			WOMatRec<WO_MAT_REL_BY$>		= ''
			WOMatRec<WO_MAT_ORG_COMMIT_DT$>	= ''
			
			WOMatParms = 'WO_MAT':@RM:WOMKey:@RM:WOMTableVar:@RM:WOMatRec
			obj_Tables('WriteRec',WOMatParms)					;* This writes and unlocks the WO_MAT records
			
		END ELSE
			obj_Tables('UnlockRec','WO_MAT':@RM:WOMKey)
			ErrorMsg := " WO_Mat Record ":QUOTE(WOMKey):' has not been released':CRLF$
		END
		
	NEXT I
	
	
RETURN


* * * * * * *
ChangeLotNo:
* * * * * * *
	
	WONo			= Parms[1,@RM]
	OrgLotNo		= Parms[COL2()+1,@RM]
	NewLotNo		= Parms[COL2()+1,@RM]
	Reason			= Parms[COL2()+1,@RM]
	CassNos			= Parms[COL2()+1,@RM]
	
	IF WONo			= '' THEN ErrorMsg = 'Null parameter "WONo" passed to routine. (':Method:')'
	IF OrgLotNo		= '' THEN ErrorMsg = 'Null parameter "Org Lot No" passed to routine. (':Method:')'
	IF NewLotNo		= '' THEN ErrorMsg = 'Null parameter "New Lot No" passed to routine. (':Method:')'
	IF Reason		= '' THEN ErrorMsg = 'Null parameter "Reason" passed to routine. (':Method:')'
	IF CassNos		= '' THEN ErrorMsg = 'Null parameter "CassNos" passed to routine. (':Method:')'
	
	
	WOMatKeys = ''
	
	cCnt = COUNT(CassNos,@VM) + (CassNos NE '')
	
	FOR I = 1 TO cCnt
		WOMatKeys<1,I> = WONo:'*':CassNos<1,I>
	NEXT I
	
	
	WOMCnt = COUNT(WOMatKeys,@VM) + (WOMatKeys NE '')
	
	FOR I = 1 TO WOMCnt
		WOMatKey = WOMatKeys<1,I>
		WOMatRec = XLATE('WO_MAT',WOMatKey,'','X')
		
		IF WOMatRec<WO_MAT_LOT_NO$> = OrgLotNo THEN
			RDSNos = WOMatRec<WO_MAT_RDS_NO$>
			RDSCnt = COUNT(RDSNos,@VM) + (RDSNos NE '')
			FOR N = 1 TO RDSCnt
				oPLParms  = 'RDS':@RM
				oPLParms := RDSNos<1,N>:@RM
				oPLParms := RDS_LOT_NUM$:@RM
				oPLParms := NewLotNo
				
				obj_Post_Log('Create',oPLParms)
				
			NEXT N
			
			oPLParms  = 'WO_MAT':@RM
			oPLParms := WOMatKey:@RM
			oPLParms := WO_MAT_LOT_NO$:@RM
			oPLParms := NewLotNo
			
			obj_Post_Log('Create',oPLParms)
			
			
		END
	NEXT I
	
RETURN


* * * * * * *
ChangeCassQty:
* * * * * * *
	
	WONo			= Parms[1,@RM]
	CassNo			= Parms[COL2()+1,@RM]
	NewCassQty		= Parms[COL2()+1,@RM]
	Reason			= Parms[COL2()+1,@RM]
	
	IF WONo			= '' THEN ErrorMsg = 'Null parameter "WONo" passed to routine. (':Method:')'
	IF CassNo		= '' THEN ErrorMsg = 'Null parameter "CassNo" passed to routine. (':Method:')'
	IF NewCassQty 	= '' THEN ErrorMsg = 'Null parameter "NewCassQty" passed to routine. (':Method:')'
	IF Reason		= '' THEN ErrorMsg = 'Null parameter "Reason" passed to routine. (':Method:')'
	
	IF ErrorMsg NE '' THEN RETURN
	
	WOMatRec = XLATE('WO_MAT',WONo:'*':CassNo,'','X')
	
	FirstRDS = WOMatRec<WO_MAT_RDS_NO$,1>
	
	If FirstRDS NE '' then
		// There will only be an RDS if the cassette has been released already, otherwise this will fail.
		obj_RDS('SetSchedWfrQty',FirstRDS:@RM:NewCassQty)
		IF Get_Status(errCode) THEN RETURN
		end
	
	CurrWfrCnt = WOMatRec<WO_MAT_WAFER_QTY$>
	PrevWfrCnt = obj_WO_Mat('SetWfrQty',WONo:'*':CassNo:@RM:NewCassQty)
	
	IF Get_Status(errCode) THEN
		obj_RDS('SetSchedWfrQty',FirstRDS:@RM:CurrWfrCnt)	;* Reset RDS Sched Qty to original
		RETURN
	END
	
	WOQtyDelta = PrevWfrCnt - NewCassQty
	
	IF WOQtyDelta NE 0 THEN
		WOLogRec = Database_Services('ReadDataRow', 'WO_LOG', WONo)
		If Error_Services('HasError') then
			Set_Status(Error_Services('GetMessage'))
			return
		end
		WOLogRec<WO_LOG_WO_QTY$> = WOLogRec<WO_LOG_WO_QTY$> + WOQtyDelta
		Database_Services('WriteDataRow', 'WO_LOG', WONo, WOLogRec, True$, False$, False$)
	END
	
RETURN


* * * * * * *
ChangePONo:
* * * * * * *
	
RETURN


* * * * * * *
AddOrderItem:
* * * * * * *
	
	WONo	= Parms[1,@RM]
	OrderNo	= Parms[COL2()+1,@RM]
	ItemNo	= Parms[COL2()+1,@RM]
	
	IF WONo		= '' THEN ErrorMsg = 'Null parameter "WONo" passed to routine. (':Method:')'
	IF OrderNo	= '' THEN ErrorMsg = 'Null parameter "OrderNo" passed to routine. (':Method:')'
	IF ItemNo 	= '' THEN ErrorMsg = 'Null parameter "ItemNo" passed to routine. (':Method:')'
	
	IF ErrorMsg NE '' THEN RETURN
	
	WTParms = 'WO_LOG':@RM:WONo
	WORec = obj_Tables('ReadRec',WTParms)
	
	IF WORec<WO_LOG_ORDER_NO$> = OrderNo THEN
		LOCATE ItemNo IN WORec<WO_LOG_ORDER_ITEM$> BY 'AR' USING @VM SETTING Pos ELSE
			WORec = INSERT(WORec,WO_LOG_ORDER_ITEM$,Pos,0,ItemNo)
		END
		WTParms = FieldStore(WTParms,@RM,4,1,WORec)
		obj_Tables('WriteRec',WTParms)
	END ELSE
		obj_Tables('UnlockRec',WTParms)
	END
	
RETURN


* * * * * * *
RemOrderItem:
* * * * * * *
	
	WONo	= Parms[1,@RM]
	OrderNo	= Parms[COL2()+1,@RM]
	ItemNo	= Parms[COL2()+1,@RM]
	
	IF WONo		= '' THEN ErrorMsg = 'Null parameter "WONo" passed to routine. (':Method:')'
	IF OrderNo	= '' THEN ErrorMsg = 'Null parameter "OrderNo" passed to routine. (':Method:')'
	IF ItemNo 	= '' THEN ErrorMsg = 'Null parameter "ItemNo" passed to routine. (':Method:')'
	
	IF ErrorMsg NE '' THEN RETURN
	
	
	WTParms = 'WO_LOG':@RM:WONo
	WORec = obj_Tables('ReadRec',WTParms)
	
	IF WORec<WO_LOG_ORDER_NO$> = OrderNo THEN
		LOCATE ItemNo IN WORec<WO_LOG_ORDER_ITEM$> BY 'AR' USING @VM SETTING Pos THEN
			WORec = DELETE(WORec,WO_LOG_ORDER_ITEM$,Pos,0)
		END
		WTParms = FieldStore(WTParms,@RM,4,1,WORec)
		obj_Tables('WriteRec',WTParms)
	END ELSE
		obj_Tables('UnlockRec',WTParms)
	END
	
RETURN


* * * * * * *
SetPromiseDt:
* * * * * * *
	
	OrderNo			= Parms[1,@RM]
	OrderItems		= Parms[COL2()+1,@RM]
	WONo			= Parms[COL2()+1,@RM]
	PromiseDt		= Parms[COL2()+1,@RM]
	Reason			= Parms[COL2()+1,@RM]
	
	IF WONo			= '' THEN ErrorMsg = 'Null parameter "WONo" passed to routine. (':Method:')'
	IF PromiseDt	= '' THEN ErrorMsg = 'Null parameter "PromiseDt" passed to routine. (':Method:')'
	IF Reason		= '' THEN ErrorMsg = 'Null parameter "Reason" passed to routine. (':Method:')'
	
	IF ErrorMsg NE '' THEN RETURN
	
	thisPromiseDt = ICONV(PromiseDt,'D')
	IF thisPromiseDt = '' THEN ErrorMsg = 'Invalid PromiseDt ':QUOTE(PromiseDt):' passed to routine. (':Method:')'
	
	IF ErrorMsg NE '' THEN RETURN
	
	OPEN 'DICT.RDS'	TO DictVar	ELSE
		ErrorMsg = 'Unable to Open DICT.RDS table'
		RETURN
	END
	
	SearchString = 'WO':@VM:WONo:@FM
	Flag = ''
	Set_Status(0)
	Btree.Extract(SearchString, 'RDS', DictVar, RDSNos, '', Flag)			; * Get RDS numbers for this Work Order
	
	IF Get_Status(errCode) THEN
		RETURN
	END
	
	OPEN 'DICT.WM_OUT'	TO DictVar	ELSE
		ErrorMsg = 'Unable to Open DICT.WM_OUT table'
		RETURN
	END
	
	SearchString = 'WO_NO':@VM:WONo:@FM
	Flag = ''
	Set_Status(0)
	Btree.Extract(SearchString, 'WM_OUT', DictVar, WMOutKeys, '', Flag)		; * Get WM_OUT Keys for this Work Order
	
	IF Get_Status(errCode) THEN
		RETURN
	END
	
	RTParms			= 'RDS'
	WMParms			= 'WM_OUT'
	LockedRDSNos	= ''
	LockedWMOutKeys	= ''

	FOR I = 1 TO COUNT(RdsNos,@VM) + (RdsNos NE '')
		RdsNo = RdsNos<1,I>
		RTParms = FieldStore(RTParms, @RM, 2, 1, RdsNo)
		
		obj_Tables('LockRec',RTParms)
		IF Get_Status(errCode) THEN
			
			FOR N = 1 TO COUNT(LockedRDSNos,@VM) + (LockedRDSNos NE '')
				RTParms = FieldStore(RTParms, @RM, 2, 1, LockedRDSNos<1,N>)
				obj_Tables('UnlockRec',RTParms)		;* Unlock everything locked up to here
			NEXT N

			ErrorMsg = 'Unable to lock RDS ':QUOTE(RdsNo):' for delete.'
			RETURN
		END ELSE
			LockedRDSNos<1,-1> = RdsNo
		END
	NEXT I
	
	
	FOR I = 1 TO COUNT(WMOutKeys,@VM) + (WMOutKeys NE '')
		WMOutKey = WMOutKeys<1,I>
		WMParms = FieldStore(WMParms, @RM, 2, 1, WMOutKey)
		
		obj_Tables('LockRec',WMParms)
		IF Get_Status(errCode) THEN
			
			FOR M = 1 TO COUNT(LockedWMOutKeys,@VM) + (LockedWMOutKeys NE '')
				WMParms = FieldStore(WMParms, @RM, 2, 1, LockedWMOutKeys<1,M>)
				obj_Tables('UnlockRec',WMParms)		;* Unlock everything locked up to here
			NEXT M
			
			FOR N = 1 TO COUNT(LockedRDSNos,@VM) + (LockedRDSNos NE '')
				RTParms = FieldStore(RTParms, @RM, 2, 1, LockedRDSNos<1,N>)
				obj_Tables('UnlockRec',RTParms)		;* Unlock everything locked up to here
			NEXT N

			ErrorMsg = 'Unable to lock RDS ':QUOTE(WMOutKey):' for delete.'
			RETURN
		END ELSE
			LockedWMOutKeys<1,-1> = WMOutKey
		END
	NEXT I

	RDSTableVar		= FIELD(RTParms,@RM,3)
	WMOTableVar		= FIELD(WMParms,@RM,3)
	
	FOR I = 1 TO COUNT(LockedRDSNos,@VM) + (LockedRDSNos NE '')
		LockedRDSNo = LockedRDSNos<1,I>
		READ RDSRec FROM RDSTableVar,LockedRDSNo THEN
			OldValue = RDSRec<RDS_COMMIT_DATE_FINAL$>
			RDSRec<RDS_COMMIT_DATE_FINAL$> = thisPromiseDt
			RTParms = FieldStore(RTParms, @RM, 2, 1, LockedRDSNo)
			RTParms = FieldStore(RTParms, @RM, 4, 1, RDSRec)
			obj_Tables('WriteRec',RTParms)								;* Write and unlock RDS records
		END

	NEXT I
	
	FOR I = 1 TO COUNT(LockedWMOutKeys,@VM) + (LockedWMOutKeys NE '')
		LockedWMOutKey = LockedWMOutKeys<1,I>
		READ WMOutRec FROM WMOTableVar,LockedWMOutKey THEN
			OldValue = WMOutRec<WM_OUT_PROMISE_SHIP_DT$>
			WMOutRec<WM_OUT_PROMISE_SHIP_DT$> = thisPromiseDt
			WMParms = FieldStore(WMParms, @RM, 2, 1, LockedWMOutKey)
			WMParms = FieldStore(WMParms, @RM, 4, 1, WMOutRec)
			obj_Tables('WriteRec',WMParms)								;* Write and unlock RDS records
		END

	NEXT I
	
RETURN


* * * * * * *
QuoteChange:
* * * * * * *
	
	QuoteNo	= Parms[1,@RM]
	WONo	= Parms[COL2()+1,@RM]
	
	IF QuoteNo 		= '' THEN ErrorMsg = 'Null parameter "QuoteNo" passed to routine. (':Method:')'
	IF WONo			= '' THEN ErrorMsg = 'Null parameter "WONo" passed to routine. (':Method:')'
	
	QuoteRec = XLATE('QUOTE',QuoteNo,'','X')
	
	QuoteProcSteps = QuoteRec<QUOTE_PROC_STEP$>
	QuoteProcStepPSNs = QuoteRec<QUOTE_PROC_STEP_PSN$>
	
	WTParms = 'WO_LOG':@RM:WONo
	WORec = obj_Tables('ReadRec',WTParms)
	
	IF Get_Status(errCode) THEN
		ErrMsg(errCode)
		obj_Tables('UnlockRec',WTParms)
		RETURN
	END 
	
	WOStepKeys = WORec<WO_LOG_WO_STEP_KEY$>
	
	LockedWOStepKeys = ''
	wsParms = 'WO_STEP'
	
	FOR I = 1 TO COUNT(WOStepKeys,@VM) + (WOStepKeys NE '')
		WOStepKey = WOStepKeys<1,I>
		wsParms = FieldStore(wsParms, @RM, 2, 1, WOStepKey)
		
		obj_Tables('LockRec',wsParms)
		
		IF Get_Status(errCode) THEN
			
			FOR N = 1 TO COUNT(LockedWOStepKeys,@VM) + (LockedWOStepKeys NE '')
				wsParms = FieldStore(wsParms, @RM, 2, 1, LockedWOStepKeys<1,N>)
				obj_Tables('UnlockRec',wsParms)		;* Unlock everything locked up to here
			NEXT N
			
			ErrorMsg = 'Unable to lock WO_STEP ':QUOTE(WOStepKey):' for Update.'
			obj_Tables('UnlockRec',WTParms)
			RETURN
		END ELSE
			LockedWOStepKeys<1,-1> = WOStepKey
		END
	NEXT I
	
	FOR I = 1 TO COUNT(LockedWOStepKeys,@VM) + (LockedWOStepKeys NE '')
		LockedWOStepKey = LockedWOStepKeys<1,I>
		
		WOStepRec = XLATE('WO_STEP',LockedWOStepKey,'','X')
		ProcStep = FIELD(LockedWOStepKey,'*',2)
		LOCATE ProcStep IN QuoteProcSteps USING @VM SETTING Pos THEN
			StepPSN = QuoteProcStepPSNs<1,Pos>
			WOStepRec<WO_STEP_PROD_SPEC_ID$> = StepPSN
		END
		
		wsParms =  FieldStore(wsParms, @RM, 2, 1, LockedWOStepKey)
		wsParms =  FieldStore(wsParms, @RM, 4, 1, WOStepRec)
		
		obj_Tables('WriteRec',wsParms)
		
	NEXT I
	
	WORec<WO_LOG_QUOTE_NO$> = QuoteNo
	
	WTParms = FieldStore(WTParms,@RM,4,1,WORec)
	obj_Tables('WriteRec',WTParms)
	
RETURN


* * * * * * *
NextWORun:
* * * * * * *
	
	WONo	= Parms[1,@RM]
	WOStep	= Parms[COL2()+1,@RM]
	
	IF WONo = '' THEN RETURN
	IF WOStep = '' THEN WOStep = 1
	
	errCode = 0
	Cancelled = 0
	LOOP
		WTParms = 'WO_LOG':@RM:WONo
		WORec = obj_Tables('ReadRec',WTParms)
		dummy = Get_Status(errCode)
		
		IF errCode THEN
			Resp = Msg(@WINDOW,'','WO_NO_LOCKED')
			IF Resp = CHAR(27) THEN Cancelled = 1 
		END
	UNTIL errCode = '' OR Cancelled = 1
	REPEAT
	
	IF Cancelled THEN RETURN		;* Bailed out
	
	
	StepRDSNos = XLATE('WO_STEP',WONo:'*':WOStep,WO_STEP_RDS_KEY$,'X')
	IF (WONo:'*':WOStep = '162988*1') THEN
		CurrRuns = 3
	END ELSE
		CurrRuns = 0
	END
	FOR I = 1 TO COUNT(StepRDSNos,@VM) + (StepRDSNos NE '')
		IF RowExists('RDS',StepRDSNos<1,I>) THEN
			CurrRuns += 1
		END
	NEXT I
	
	NextRunNo = CurrRuns + 1
	Result    = NextRunNo								;* Next Run No returned to calling program
	WTParms   = FieldStore(WTParms,@RM,4,1,WORec)
	obj_Tables('WriteRec',WTParms)					;* Updates WO_LOG record and unlocks it.
	
RETURN


* * * * * * *
AddCassNo:
* * * * * * *
	
	
	WONo	= Parms[1,@RM]
	CassNo	= Parms[COL2()+1,@RM]
	
	IF WONo		= '' THEN ErrorMsg = 'Null parameter "WONo" passed to routine. (':Method:')'
	IF CassNo	= '' THEN ErrorMsg = 'Null parameter "CassNo" passed to routine. (':Method:')'
	
	IF ErrorMsg NE '' THEN RETURN
	
	WTParms = 'WO_LOG':@RM:WONo
	WORec	= obj_Tables('ReadRec',WTParms)
	
	IF Get_Status(errCode) THEN
		ErrMsg(errCode)
	END ELSE
		WOMatKey = WONo:'*':CassNo
		
		LOCATE WOMatKey IN WORec<WO_LOG_WO_MAT_KEY$> BY 'AR' USING @VM SETTING CassPos THEN
			obj_Tables('UnlockRec',WTParms)
		END ELSE
			WORec	= INSERT(WORec,WO_LOG_WO_MAT_KEY$,CassPos,0,WOMatKey)
			WTParms = FieldStore(WTParms,@RM,4,1,WORec)
			
			obj_Tables('WriteRec',WTParms)					;* Updates WO_LOG record and unlocks it.
		END
	END
	
RETURN


* * * * * * *
RemoveCassettes:
* * * * * * *
	
	ErrorMessage = ''
	WONo         = Parms[1,@RM]
	CassNos      = Parms[COL2()+1,@RM]
	
	IF WONo		= '' THEN ErrorMsg = 'Null parameter "WONo" passed to routine. (':Method:')'
	IF CassNos	= '' THEN ErrorMsg = 'Null parameter "CassNos" passed to routine. (':Method:')'
	
	IF ErrorMsg NE '' THEN RETURN
	
	
	AllCassIDs = ''
	CassCnt = COUNT(CassNos,@VM) + (CassNos NE '')
	FOR I = 1 TO CassCnt
		AllCassIDs<1,I> = WONo:'*':CassNos<1,I>
	NEXT I
	
	AllRDSNos = XLATE('WO_MAT',AllCassIDs,WO_MAT_RDS_NO$,'X')
	
	WORec = Database_Services('ReadDataRow', 'WO_LOG', WONo)
	If Error_Services('NoError') then
		
		FOR I = 1 TO COUNT(CassNos,@VM) + (CassNos NE '')
			CassNo = CassNos<1,I>
			
			Set_Status(0)
			obj_WO_Mat('Delete',WONo:@RM:CassNo)
			
			IF Get_Status(errCode) THEN
				ErrMsg(errCode)
			END ELSE
				WOMatKey = WONo:'*':CassNo
				LOCATE WOMatKey IN WORec<WO_LOG_WO_MAT_KEY$> USING @VM SETTING CassPos THEN
					WORec = DELETE(WORec,WO_LOG_WO_MAT_KEY$,CassPos,0)
				END
			END
			
		NEXT I
		Database_Services('WriteDataRow', 'WO_LOG', WONo, WORec)
		If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage')
	end else
		ErrorMessage = Error_Services('GetMessage')
	end
	
	If ErrorMessage NE '' then
		ErrMsg(ErrorMessage)
		LogData    = ''
		LogData<1> = LoggingDTM
		LogData<2> = @User4
		LogData<3> = WONo
		LogData<4> = 'Error in obj_WO_Log("RemoveCassettes"). Error message: ':ErrorMessage
		Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
	end
	
RETURN


* * * * * * *
SetPartNo:
* * * * * * *
	
	WONo		= Parms[1,@RM]
	NewPartNo	= Parms[COL2()+1,@RM]
	OrgPartNo	= Parms[COL2()+1,@RM]
	
	
	IF WONo			= '' THEN ErrorMsg = 'Null parameter "WONo" passed to routine. (':Method:')'
	IF NewPartNo	= '' THEN ErrorMsg = 'Null parameter "NewPartNo" passed to routine. (':Method:')'
	IF OrgPartNo	= '' THEN ErrorMsg = 'Null parameter "OrgPartNo" passed to routine. (':Method:')'
	
	IF ErrorMsg NE '' THEN RETURN
	
	WORec = XLATE('WO_LOG',WONo,'','X')
	
	WOMatKeys = WORec<WO_LOG_WO_MAT_KEY$>
	
	obj_WO_Mat('SetPartNo',WOMatKeys:@RM:NewPartNo)
	
RETURN


* * * * * * *
RefreshSigProfile:
* * * * * * *
	
	WONo = Parms[1,@RM]
	
	IF WONo			= '' THEN ErrorMsg = 'Null parameter "WONo" passed to routine. (':Method:')'
	
	IF ErrorMsg NE '' THEN RETURN
	
	WOMatKeys = XLATE('WO_LOG',WONo,WO_LOG_WO_MAT_KEY$,'X')
	
	WOMatCnt = COUNT(WOMatKeys,@VM) + (WOMatKeys NE '')
	
	FOR I = 1 TO WOMatCnt
		Set_Status(0)
		
		WOMatKey = WOMatKeys<1,I>
		obj_WO_Mat('RefreshSigProfile',WOMatKey)
		
		IF Get_Status(errCode) THEN ErrMsg(errCode)
		
	NEXT I
	
RETURN


* * * * * * *
RelQty:
* * * * * * *
	
	WONo	= Parms[1,@RM]
	WORec	= Parms[COL2()+1,@RM]
	
	IF WONo		= '' THEN RETURN
	
	IF WORec = '' THEN
		WORec = XLATE('WO_LOG',WONo,'','X')
	END
	
	IF WORec = '' THEN RETURN
	
	WOMatKeys = WORec<WO_LOG_WO_MAT_KEY$>
	
	LineCnt = COUNT(WOMatKeys,@VM) + (WOMatKeys NE '')
	
	FOR I = 1 TO LineCnt
		WOMatRec = XLATE('WO_MAT',WOMatKeys<1,I>,'','X')
	UNTIL WOMatRec<WO_MAT_REL_BY$> =  ''
		Result +=  WOMatRec<WO_MAT_WAFER_QTY$>
	NEXT I
	
RETURN


* * * * * * *
RelDTMs:
* * * * * * *
	
	WONo	= Parms[1,@RM]
	WORec	= Parms[COL2()+1,@RM]
	DtsOnly	= Parms[COL2()+1,@RM]
	
	IF WONo	= '' THEN RETURN
	
	IF WORec = '' THEN
		WORec = XLATE('WO_LOG',WONo,'','X')
	END
	
	IF WORec = '' THEN RETURN
	
	WOMatKeys = WORec<WO_LOG_WO_MAT_KEY$>
	
	AllCassRelDTMs = XLATE('WO_MAT',WOMatKeys,WO_MAT_REL_DTM$,'X')
	AllCassRelBys = XLATE('WO_MAT',WOMatKeys,WO_MAT_REL_BY$,'X')
	
	WOMatCnt = COUNT(WOMatKeys,@VM) + (WOMatKeys NE '')
	
	RelDTMs = ''
	RelDTs = ''
	Result = ''
	
	FOR N = 1 TO WOMatCnt
		
		AllCassRelDTM = AllCassRelDTMs<1,N>
		AllCassRelBy  = OCONV(AllCassRelBys<1,N>,'[XLATE_CONV,LSL_USERS*FIRST_LAST]')
		
		IF DtsOnly = 1 THEN
			RelDT = AllCassRelDTM[1,'.']
			
			LOCATE RelDT IN RelDTs BY 'AR' USING @VM SETTING DtPos ELSE
				RelDTs = INSERT(RelDTs,1,DtPos,0,RelDT)
			END
		END
		
		IF AllCassRelDTM NE '' THEN
			LOCATE AllCassRelDTM IN RelDTMs USING @VM  SETTING Pos THEN
				NULL
			END ELSE
				RelDTMS = INSERT(RelDTMS,1,Pos,0,AllCassRelDTM)
				Result	= INSERT(Result,1,Pos,0,OCONV(AllCassRelDTM,'DT4/^HS'):' - ':AllCassRelBy)
			END
		END
	NEXT N
	
	IF DtsOnly = 1 THEN
		Result = RelDTs
	END
	
RETURN


* * * * * * *
RxQty:
* * * * * * *
	
	WONo	= Parms[1,@RM]
	WORec	= Parms[COL2()+1,@RM]
	
	IF WONo		= '' THEN RETURN
	
	IF WORec = '' THEN
		WORec = XLATE('WO_LOG',WONo,'','X')
	END
	
	IF WORec = '' THEN RETURN
	
	WOMatKeys = WORec<WO_LOG_WO_MAT_KEY$>
	
	LineCnt = COUNT(WOMatKeys,@VM) + (WOMatKeys NE '')
	
	FOR I = 1 TO LineCnt
		WOMatRec = XLATE('WO_MAT',WOMatKeys<1,I>,'','X')
	UNTIL WOMatRec<WO_MAT_RX_BY$> =  ''
		Result +=  WOMatRec<WO_MAT_WAFER_QTY$>
	NEXT I
	
RETURN


* * * * * * *
ShipQty:
* * * * * * *
	
	IF NOT(ASSIGNED(WONo)) THEN WONo = Parms[1,@RM]
	IF NOT(ASSIGNED(WORec)) THEN WORec = Parms[COL2()+1,@RM]
	
	IF WONo		= '' THEN RETURN
	
	IF WORec = '' THEN
		WORec = XLATE('WO_LOG',WONo,'','X')
	END
	
	IF WORec = '' THEN RETURN
	
	WOMatKeys = WORec<WO_LOG_WO_MAT_KEY$>
	
	LineCnt = COUNT(WOMatKeys,@VM) + (WOMatKeys NE '')
	
	FOR I = 1 TO LineCnt
		WOMatKey = WOMatKeys<1,I>
		WOMatRec = XLATE('WO_MAT',WOMatKey,'','X')
		WMOKey = WOMatRec<WO_MAT_WMO_KEY$>
		
		IF WMOKey NE '' THEN
			
			WMOutRec = XLATE('WM_OUT',WMOKey,'','X')
			ShipNo = WMOutRec<WM_OUT_SHIP_NO$>
			IF ShipNo NE '' THEN
				CurrWfrCnt = XLATE('WM_OUT',WMOKey,'WAFER_CNT','X')
				Result += CurrWfrCnt
			END
		END ELSE
			
			IF WOMatRec<WO_MAT_SHIP_NO$> NE '' THEN
				CurrWfrCnt = obj_WO_Mat('CurrWaferCnt',WOMatKey:@RM:WOMatRec)
				Result += CurrWfrCnt
			END
		END
	NEXT I
	
RETURN


* * * * * * *
ShipPropTarg:
* * * * * * *
	
	IF NOT(ASSIGNED(WONo)) THEN WONo = Parms[1,@RM]
	IF NOT(ASSIGNED(WORec)) THEN WORec = Parms[COL2()+1,@RM]
	IF NOT(ASSIGNED(PropCd)) THEN PropCd = Parms[COL2()+1,@RM]
	
	IF WONo		= '' THEN RETURN
	
	IF WORec = '' THEN
		WORec = XLATE('WO_LOG',WONo,'','X')
	END
	
	IF WORec	= '' THEN RETURN
	IF PropCd	= '' THEN RETURN
	
	LastWOStepKey	= WORec<WO_LOG_WO_STEP_KEY$>[-1,'B':@VM]
	StepPSN			= XLATE('WO_STEP',LastWOStepKey,WO_STEP_PROD_SPEC_ID$,'X')
	PRSLayerKeys     = XLATE('PROD_SPEC',StepPSN,PROD_SPEC_PRS_LAYER_KEY$,'X')
	
	LastPRSLayerKey = PRSLayerKeys[-1,'B':@VM]
	
	LastLayerProps = XLATE('PRS_LAYER',LastPRSLayerKey,PRS_LAYER_PRS_PROP_KEY$,'X')
	
	PropCnt = COUNT(LastLayerProps,@VM) + (LastLayerProps NE '')
	
	FOR I = 1 TO PropCnt
		PropKey		= LastLayerProps<1,I>
		SpecPropCd	= FIELD(PropKey,'*',3)
		
		IF SpecPropCd[1,5] = PropCd THEN
			PropRec = XLATE('PRS_PROP',PropKey,'','X')
			MinVal = PropRec<2>
			MaxVal = PropRec<3>
			Target = MinVal + ((MaxVal - MinVal)/2)
			Result = OCONV( Target,'[MET_PROP_CONV,':PropCd:']')
		END           
	NEXT I
	
RETURN


* * * * * * 
CloseComp:
* * * * * *
	
	CompOrShipShort = Parms[1,@RM]
	
	IF CompOrShipShort = '' THEN RETURN
	
	MsgUp = Msg(@WINDOW,'','SELECT_OPEN_WO')
	
	IF Get_Status(errCode) THEN RETURN
	
	IF CompOrShipShort = 'Comp' THEN
		SelectStatement  = 'SELECT WO_LOG WITH CURR_STATUS_STATIC = "COMP" AND WITHOUT CLOSE_DATE '
	END ELSE
		SelectStatement  = 'SELECT WO_LOG WITH CURR_STATUS_STATIC = "INPR" "SHIP" AND WITHOUT CLOSE_DATE '
	END
	
	RList(SelectStatement, TARGET_ACTIVELIST$, '','','')
	
	IF Get_Status(errCode) THEN
		ErrMsg(errCode)
		Msg(@WINDOW,MsgUp)
		RETURN
	END
	
	Msg(@WINDOW,MsgUp)
	
	WONos = Popup(@WINDOW,'','OPEN_WORK_ORDERS')
	
	IF WONos = '' OR WONos = CHAR(27) THEN RETURN
	
	IF Get_Status(errCode) THEN
		ErrMsg(errCode)
		RETURN
	END
	
	DelCnt = COUNT(WONos,@VM) + (WONos NE '')
	
	Proceed = Msg(@WINDOW,'','WO_CLOSE','',DelCnt)
	
	IF Proceed = 0 THEN RETURN		;* Bailed Out
	
	Today = Date()
	
	Def = ""
	Def<MCAPTION$>		= "Closing Work Orders..."
	Def<MTYPE$ >		= "GC"
	Def<MEXTENT$>		= DelCnt
	Def<MTEXTWIDTH$>	= 200
	
	MsgUp = Msg(@window, Def)
	
	FOR I = 1 TO DelCnt
		WONo = WONos<1,I>
		
	WHILE Msg(@WINDOW,MsgUp,I,MSGINSTUPDATE$)
		
		otParms = 'WO_LOG':@RM:WONo
		WOLogRec = obj_Tables('ReadRec',otParms)		;* Reads and sets lock
		
		IF Get_Status(errCode) THEN 
			ErrMsg(errCode)
		END ELSE
			WOLogRec<WO_LOG_CLOSE_DATE$> = Today
			otParms = FIELDSTORE(otParms,@RM,4,0,WOLogRec)
			obj_Tables('WriteRec',otParms)
		END
	NEXT I
	
	Msg(@WINDOW, MsgUp) ;* take down the gauge
	
RETURN


* * * * * * *
Route:
* * * * * * *
	
	WONo		= Parms[1,@RM]
	ProdVerNo	= Parms[COL2()+1,@RM]
	
	IF WONo			= '' THEN ErrorMsg = 'Null parameter "WONo" passed to routine. (':Method:')'
	IF ProdVerNo	= '' THEN ErrorMsg = 'Null parameter "ProdVerNo" passed to routine. (':Method:')'
	
	IF ErrorMsg NE '' THEN RETURN
	
	otParms = 'WO_LOG':@RM:WONo
	WOLogRec = obj_Tables('ReadRec',otParms)		;* Reads and sets lock
	
	IF Get_Status(errCode) THEN RETURN
	
	WOStepKeys = WOLogRec<WO_LOG_WO_STEP_KEY$>
	
	IF WOStepKeys NE '' THEN
		WOStepPSN = Xlate('WO_STEP', WOStepKeys, 'PROD_SPEC_ID', 'X')
		If WOStepPSN NE '' then
			ErrorMsg = 'WO has WO_STEPS already defined.'
			obj_Tables('UnlockRec',otParms)
			RETURN
		END
	END
	
	* Good lock and WO_LOG record *
	
	ProdVerRec	= XLATE('PROD_VER',ProdVerNo,'','X')
	
	* Add WO_STEP records
	
	ProcSteps	= ProdVerRec<PROD_VER_PROC_STEP_NO$>
	ProcPSNs	= ProdVerRec<PROD_VER_PROC_STEP_PSN$>
	ProcDescs	= ProdVerRec<PROD_VER_PROC_STEP_DESC$>
	
	ProcPSNStatuses = XLATE('PROD_SPEC',ProcPSNs,PROD_SPEC_STATUS$,'X')
	ProcPSNReactTypes = Xlate('PROD_SPEC',ProcPSNs,PROD_SPEC_REACTOR_TYPE$,'X')
	
	FOR P = 1 TO COUNT(ProcPSNStatuses,@VM) + (ProcPSNStatuses NE '')
		IF ProcPSNStatuses<1,P> NE 'A' THEN
			ErrorMsg = 'Product Spec on Hold on Prod Ver No.'
			obj_Tables('UnlockRec',otParms)
			RETURN
		END
	NEXT P
	
	CustNo		= WOLogRec<WO_LOG_CUST_NO$>
	EpiPartNo	= WOLogRec<WO_LOG_EPI_PART_NO$>
	
	DefWMOCassQtys = XLATE('CUST_EPI_PART',CustNo:'*':EpiPartNo,CUST_EPI_PART_WMO_LOAD_CNT$,'X')
	
	WOStepKeys = ''
	DefWMOCassQty = ''
	
	FOR N = 1 TO COUNT(ProcSteps,@VM) + (ProcSteps NE '')
		
		ProcStep	= ProcSteps<1,N>
		ProcPSN		= ProcPSNs<1,N>
		ProcDesc	= ProcDescs<1,N>
		
		obj_WO_Step('Create',WONo:@RM:ProcStep:@RM:ProcPSN:@RM:ProcDesc)
		
		IF DefWMOCassQtys<1,N> NE '' THEN DefWMOCassQty = DefWMOCassQtys<1,N>
		
		WOStepKeys<1,N> = WONo:'*':ProcStep
		
	NEXT N
	
	WOLogRec<WO_LOG_WO_STEP_KEY$> 		= WOStepKeys		;* This is currently a relational target * 11/2/2011 jch, might change later
	WOLogRec<WO_LOG_OUT_CASS_LOAD_QTY$> = DefWMOCassQty
	WOLogRec<WO_LOG_REACT_TYPE$>		= ProcPSNReactTypes<1,1>		;* Assumes both steps run on same reactor type
	
	* Add rest of WO fields
	CustNo		= ProdVerRec<PROD_VER_CUST_NO$>
	EpiPN		= ProdVerRec<PROD_VER_EPI_PART_NO$>
	
	Captive = XLATE('COMPANY',CustNo,COMPANY_CAPTIVE$,'X')
	
	IF Captive = 1 THEN
		WOLogRec<WO_LOG_CUST_PART_NO$> = EpiPN
	END
	
	WOLogRec<WO_LOG_PROD_VER_NO$> = ProdVerNo
	WOLogRec<WO_LOG_CUST_NO$>     = CustNo
	
	WOQty = WOLogRec<WO_LOG_WO_QTY$>
	If WOQty EQ '' then
	    WOQty                    = 0
	    WOLogRec<WO_LOG_WO_QTY$> = WOQty
	end
	RxQty = WOLogRec<WO_LOG_RX_QTY_STATIC$>
	If RxQty EQ '' then
	    RxQty                           = 0
	    WOLOgRec<WO_LOG_RX_QTY_STATIC$> = RxQty
	end
	RelQty = WOLogRec<WO_LOG_REL_QTY_STATIC$>
	If RelQty EQ '' then
	    RelQty                           = 0
	    WOLogRec<WO_LOG_REL_QTY_STATIC$> = RelQty
	end
	UnRelQty = WOLogRec<WO_LOG_UNREL_QTY_STATIC$>
	If UnRelQty EQ '' then
	    UnRelQty = WOQty - RelQty
	end
	OpenQty = WOLogRec<WO_LOG_OPEN_QTY_STATIC$>
	If OpenQty EQ '' then
	    OpenQty                           = WOQty - RxQty
	    WOLogRec<WO_LOG_OPEN_QTY_STATIC$> = OpenQty
	end
	ScrapQty = WOLogRec<WO_LOG_SCRAP_QTY_STATIC$>
	If ScrapQty EQ '' then
	    ScrapQty                           = 0
	    WOLogRec<WO_LOG_SCRAP_QTY_STATIC$> = ScrapQty
	end
	ShippedQty = WOLogRec<WO_LOG_STATIC_SHIP_QTY$>
	If ShippedQty EQ '' then
	    ShippedQty                        = 0
	    WOLogRec<WO_LOG_STATIC_SHIP_QTY$> = ShippedQty
	end
	
	otParms = FIELDSTORE(otParms,@RM,4,0,WOLogRec)
	obj_Tables('WriteRec',otParms)
	
RETURN


* * * * * * *
Unroute:
* * * * * * *
	
	WONo	= Parms[1,@RM]
	
	IF WONo	= '' THEN ErrorMsg = 'Null parameter "WONo" passed to routine. (':Method:')'
	
	IF ErrorMsg NE '' THEN RETURN
	
	otParms = 'WO_LOG':@RM:WONo
	WOLogRec = obj_Tables('ReadRec',otParms)		;* Reads and sets lock
	
	IF Get_Status(errCode) THEN RETURN
	
	IF WOLogRec<WO_LOG_CASS_REL_DTM$> NE '' THEN
		ErrorMsg = 'WO has been released and may not Unrouted.'
		obj_Tables('UnlockRec',otParms)
		RETURN
	END
	
	WOStepKeys = WOLogRec<WO_LOG_WO_STEP_KEY$>
	
	StepCnt = COUNT(WOStepKeys,@VM) + (WOStepKeys NE '')
	
	FOR I = 1 TO StepCnt
		WOStepKey = WOStepKeys<1,I>
		StepNo = FIELD(WOStepKey,'*',2)
		
		obj_WO_Step('Delete',WONo:@RM:StepNo)
		IF Get_Status(errCode) THEN
			obj_Tables('UnlockRec',otParms)
			RETURN
		END
	NEXT I
	
	WOLogRec<WO_LOG_WO_STEP_KEY$>		= ''
	WOLogRec<WO_LOG_OUT_CASS_LOAD_QTY$>	= ''
	WOLogRec<WO_LOG_CUST_PART_NO$>		= ''
	WOLogRec<WO_LOG_PROD_VER_NO$>		= ''
	WOLogRec<WO_LOG_CUST_NO$>			= ''
	
	otParms = FIELDSTORE(otParms,@RM,4,0,WOLogRec)
	obj_Tables('WriteRec',otParms)
	
RETURN


* * * * * * *
GetAvgCycleTimes:
* * * * * * *
	
	IF NOT(Assigned(WONo)) 		THEN WONo		= Parms[1,@RM]
	IF NOT(Assigned(WOLogRec))	THEN WOLogRec	= Parms[COL2()+1,@RM]
	
	IF WONo = '' THEN RETURN
	IF WOLogRec = '' THEN
		WOLogRec = XLATE('WO_LOG',WONo,'','X')
		IF WOLogRec = '' THEN RETURN
	END
	
	ProdVerNo = WOLogRec<WO_LOG_PROD_VER_NO$>
	ReactType = XLATE('PROD_VER', ProdVerNo,PROD_VER_REACT_TYPE$, 'X' )
	
	IF ReactType = 'EPP' THEN
		
		* EpiPRO
		
		RelToVerTime = ''
		
		FirstWOMatKey = WOLogRec<WO_LOG_WO_MAT_KEY$,1>
		WOMatRec= XLATE('WO_MAT',FirstWOMatKey,'','X')
		StartDTM = WOMatRec<WO_MAT_REL_DTM$>
		
		WOStepKey = WOLogRec<WO_LOG_WO_STEP_KEY$,1>
		RDSNos = XLATE('WO_STEP',WOStepKey,WO_STEP_RDS_KEY$,'X')
		StopDTM = XLATE('REACT_RUN',RDSNos<1,1>,REACT_RUN_VER_SIG_DTM$,'X')
		
		IF StartDTM NE '' AND StopDTM NE '' THEN
			RelToVerTime = ICONV((StopDTM - StartDTM)*24,'MD1')
		END
		
		* Average Cycle Time
		
		TotCycleTime = 0
		TotCycleCnt = 0
		
		RDSCnt = COUNT(RDSNos,@VM) + (RDSNos NE '')
		
		FOR I = 1 TO RDSCnt
			StartDTM = ''
			StopDTM = ''
			ReactRunRec = XLATE('REACT_RUN',RDSNos<1,I>,'','X')
			StartDTM	= ReactRunRec<REACT_RUN_VER_SIG_DTM$>
			StopDTM		= ReactRunRec<REACT_RUN_UNLOAD_SIG_DTM$>
			
			IF StartDTM NE '' AND StopDTM NE '' THEN
				CycleTime = (StopDTM - StartDTM)*24			;* DTM's in decimal days
				TotCycleTime += CycleTime
				TotCycleCnt += 1
			END
		NEXT I
		
		IF TotCycleCnt > 0 THEN
			AvgCycleTime = ICONV(TotCycleTime/TotCycleCnt,'MD1')
		END ELSE
			AvgCycleTime = ''
		END
		
	END ELSE
		
		* ASM
		
		WOMatKeys = WOLogRec<WO_LOG_WO_MAT_KEY$>
		
		WOMatCnt = COUNT(WOMatKeys,@VM) + (WOMatKeys NE '')
		
		* RelToVerTime Calculation
		
		RelToVerTime = ''
		
		FirstWOMatKey = WOLogRec<WO_LOG_WO_MAT_KEY$,1>
		WOMatRec= XLATE('WO_MAT',FirstWOMatKey,'','X')
		StartDTM = WOMatRec<WO_MAT_REL_DTM$>
		
		RDSNos = WOMatRec<WO_MAT_RDS_NO$>
		StopDTM = XLATE('REACT_RUN',RDSNos<1,1>,REACT_RUN_VER_SIG_DTM$,'X')
		
		IF StartDTM NE '' AND StopDTM NE '' THEN
			RelToVerTime = ICONV((StopDTM - StartDTM)*24,'MD1')
		END
		
		TotCycleTime = 0
		TotCycleCnt = 0
		
		FOR I = 1 TO WOMatCnt
			
			CycleTime = obj_WO_Mat('GetCycleTime',WOMatKeys<1,I>:@RM:'':@RM:'VER':@RM:'QA')
			
			IF CycleTime NE '' THEN
				TotCycleTime += OCONV(CycleTime,'MD1')
				TotCycleCnt += 1
			END
			
		NEXT I
		
		IF TotCycleCnt > 0 THEN
			AvgCycleTime = ICONV(TotCycleTime/TotCycleCnt,'MD1')
		END ELSE
			AvgCycleTime = ''
		END
		
		
	END	;* End of check for EpiPRO (EPP) reactor type
	
	* QA To Ship Time
	
	WOMatKeys = WOLogRec<WO_LOG_WO_MAT_KEY$>
	
	WOMatCnt = COUNT(WOMatKeys,@VM) + (WOMatKeys NE '')
	
	TotQAShipTime = 0
	TotQAShipCnt = 0
	
	
	FOR I = 1 TO WOMatCnt
		WOMatKey = WOMatKeys<1,I>
		QAShipTime = obj_WO_Mat('GetCycleTime',WOMatKey:@RM:'':@RM:'QA':@RM:'SB')
		IF QAShipTime NE '' THEN
			TotQAShipTime += OCONV(QAShipTime,'MD1')
			TotQAShipCnt += 1
		END
	NEXT I
	
	IF TotQAShipCnt > 0 THEN
		AvgQAShipTime = ICONV(TotQAShipTime/TotQAShipCnt,'MD1')
	END ELSE
		AvgQAShipTime = ''
	END
	
	Result = RelToVerTime:@FM:AvgCycleTime:@FM:AvgQAShipTime
	
RETURN


* * * * * * *
TimeTarget:
* * * * * * *
	
	WONo		= Parms[1,@RM]
	WOLogRec	= Parms[COL2()+1,@RM]
	
	IF WONo = '' THEN RETURN
	IF WOLogRec = '' THEN
		WOLogRec = XLATE('WO_LOG',WONo,'','X')
		IF WOLogRec = '' THEN RETURN
	END
	
	GOSUB GetAvgCycleTimes
	
	WOAvgCycleTime = OCONV(Result<2>,'MD1')
	
	Result = ''	;* Clear result set by GetAvgCycleTimes method
	
	ProdVerNo = WOLogRec<WO_LOG_PROD_VER_NO$>
	ReactType = OCONV(XLATE('PROD_VER', ProdVerNo,PROD_VER_REACT_TYPE$, 'X' ),'[REACT_TYPE_CONV,OPSREF]')
	
	IF ReactType = '' THEN RETURN
	IF WOAvgCycleTime = '' THEN RETURN
	
	EpiPartNo		= WOLogRec<WO_LOG_EPI_PART_NO$>
	AllTargThick	= SUM(XLATE('EPI_PART',EpiPartNo,'EPI_THICK_TARG','X'))
	ThickOconv		= XLATE('DICT.EPI_PART','EPI_THICK_TARG',DICT_CONV$,'X')
	TargThick		= OCONV(AllTargThick,ThickOconv)
	
	BaseLine		= 5.5		;* 1st Wafer + Cleans + Tencor + QA + Bag  (from Chad)
	XFactor			= 0			;* Calculated periodically by Manufacturing Manager 
	
	BEGIN CASE
		CASE ReactType = 'ASM'
			t1 = 157.95
			t2 = 3.673*TargThick
			t3 = 0.1294*((TargThick - 17.5)*(TargThick - 17.5))
			
		CASE ReactType = 'ASM+'
			t1 = 185.81
			t2 = 4.276*TargThick
			t3 = 0.1485*((TargThick - 17.5)*(TargThick - 17.5))
			
		CASE ReactType = 'HTR'
			t1 = 263.274
			t2 = 2.7118*TargThick
			t3 = 0.04015*((TargThick - 35.0)*(TargThick - 35.0))
			
			
		CASE ReactType = 'EpiPro'
			t1 = 268.985
			t2 = 1.0867*TargThick
			t3 = 0.0059595*((TargThick - 67.5)*(TargThick - 67.5))
			
		CASE 1
			RETURN
			
	END CASE
	
	WfrsPerDay = t1 - t2 + t3
	HrsPerBox = 24/(WfrsPerDay/25)
	
	OutHrsPerBox = OCONV(ICONV(HrsPerBox,'MD1'),'MD1')
	
	CalcCycleTime = Baseline + OutHrsPerBox  + XFactor
	
	CycleTimeDelta = WOAvgCycleTime - CalcCycleTime
	
	Result = CycleTimeDelta
	
RETURN


* * * * * * *
PcntComp:
* * * * * * *
	
	WONo 		= Parms[1,@RM]
	WOLogRec	= Parms[COL2()+1,@RM]
	
	IF WONo = '' THEN RETURN
	
	IF WOLogRec = '' THEN
		WOLogRec = XLATE('WO_LOG',WONo,'','X')
	END
	
	IF WOLogRec = '' THEN RETURN
	
	StepNo	= WOLogRec<WO_LOG_WO_STEP_KEY$>[-1,'B*']	;* This is the shipping step for multi step WO's
	
	WOMatKeys = WOLogRec<WO_LOG_WO_MAT_KEY$>
	
	WOMatCnt = COUNT(WOMatKeys,@VM) + (WOMatKeys NE '')
	
	WOWfrQty	= SUM(XLATE('WO_MAT',WOMatKeys,WO_MAT_WAFER_QTY$,'X'))
	WOOrderQty	= WOLogRec<WO_LOG_WO_QTY$>
	
	* Split for reactor types here
	
	ProdVerNo = WOLogRec<WO_LOG_PROD_VER_NO$>
	
	ReactType =  XLATE('PROD_VER',ProdVerNo,PROD_VER_REACT_TYPE$,'X')
	
	
	IF ReactType = 'EPP' THEN
		* EpiPRO reactor
		WOLoadCnt	= SUM(XLATE('WO_MAT',WOMatKeys,'WMI_RDS_LOAD_CNT','X'))
		WOPreEpiRej	= SUM(XLATE('WO_MAT',WOMatKeys,'WM_IN_REJ_WFRS','X'))
		
		RRunNos	= XLATE('WO_STEP',WONo:'*':StepNo,6,'X')
		WOUnloadCnt	= SUM(XLATE('REACT_RUN',RRunNos,'EPI_PRO_UNLD_CNT','X'))
		WOPTCnt		= SUM(XLATE('REACT_RUN',RRunNos,'EPI_PRO_PT_CNT','X'))
		
		IF WOLoadCnt > 0 AND WOOrderQty > 0 THEN
			OrdPcntComp = ICONV(((WOPreEpiRej + WOUnloadCnt + WOPTCnt)/WOOrderQty)*100,'MD0')	
		END ELSE
			OrdPcntComp = 0
		END
		
		Result = OCONV(OrdPcntComp,'MD0S%')
		
	END ELSE
		
		SAPBatchNos	= XLATE('WO_MAT',WOMatKeys,'SAP_BATCH_NO','X')
		CompBoxCnt	= 0
		
		BoxCnt = COUNT(SAPBatchNos,@VM) + (SAPBatchNos NE '')
		
		FOR I = 1 TO BoxCnt
			IF SAPBatchNos<1,I> NE '' THEN CompBoxCnt += 1
		NEXT I
		
		IF CompBoxCnt = 0 THEN
			Result = OCONV(0,'MD0S%')
		END ELSE
			
			Result = OCONV(ICONV((CompBoxCnt/BoxCnt)*100,'MD0'),'MD0S%')
		END
		
	END
	
RETURN


* * * * * * *
EstComp:
* * * * * * *
	
	WONo 		= Parms[1,@RM]
	WOLogRec	= Parms[COL2()+1,@RM]
	
	IF WONo = '' THEN RETURN
	
	IF WOLogRec = '' THEN
		WOLogRec = XLATE('WO_LOG',WONo,'','X')
	END
	
	IF WOLogRec = '' THEN RETURN
	
	WOMatKeys	= WOLogRec<WO_LOG_WO_MAT_KEY$>
	
	SAPBatchNos = XLATE('WO_MAT',WOMatKeys,'SAP_BATCH_NO','X')
	
	CompBoxCnt = 0
	
	BoxCnt = COUNT(SAPBatchNos,@VM) + (SAPBatchNos NE '')
	
	FOR I = 1 TO BoxCnt
		IF SAPBatchNos<1,I> NE '' THEN CompBoxCnt += 1
	NEXT I
	
	OpenBoxCnt = BoxCnt - CompBoxCnt
	
	IF Method = 'EstComp' THEN
		GOSUB GetAvgCycleTimes
		
		AvgCycleTime = Result<2>	;* This is hours per box in internal MD1 format.
		
		Result = OCONV( (OpenBoxCnt * AvgCycleTime),'MD1')
		
	END
	
RETURN


* * * * * * *
SchedReacts:
* * * * * * *
	
	WONo = Parms[1,@RM]
	
	IF WONo = '' THEN RETURN
	
	OPEN 'DICT.SCHED_DET' TO DictVar THEN
		
		SearchString = 'WO_NO':@VM:WONo:@FM
		SchedDetKeys = ''
		Btree.Extract(SearchString, 'SCHED_DET_NG', DictVar, SchedDetKeys, '' , '')
		IF Get_Status(errCode) THEN
			RETURN
		END 
		
		IF SchedDetKeys NE '' THEN
			Reactors = ''
			StartDts = ''
			EndDts  = ''
			
			sdkCnt = COUNT(SchedDetKeys,@VM) + (SchedDetKeys NE '')
			
			FOR I = 1 TO sdkCnt
				SchedDetKey = SchedDetKeys<1,I>
				Reactor     = Xlate('SCHED_DET_NG', SchedDetKey, 'REACT_NO', 'X')
				SchedDt     = Xlate('SCHED_DET_NG', SchedDetKey, 'START_DTM', 'X')
				SchedDt     = SchedDt[1, 'F.']
				
				LOCATE Reactor IN Reactors BY 'AR' SETTING Pos THEN
					IF SchedDt < StartDts<1,I> THEN
						StartDts<1,Pos> = SchedDt
					END
					
					IF SchedDt > EndDts<1,I> THEN
						EndDts<1,Pos> = SchedDt
					END
				END ELSE
					
					Reactors	= INSERT(Reactors,1,Pos,0,Reactor)
					StartDts	= INSERT(StartDts,1,Pos,0,SchedDt)
					EndDts		= INSERT(EndDts,1,Pos,0,SchedDt)
					
				END
				
			NEXT I
			
			Result = Reactors:@FM:StartDts:@FM:EndDts
		END
	END
	
RETURN

