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

$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 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 = 'ReleaseCassettes'	; GOSUB ReleaseCassettes
	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
		
		IF 1=0 THEN
			
			StepKeys		= WORec<WO_LOG_WO_STEP_KEY$>
			StepStatusCodes = XLATE('WO_STEP',StepKeys,'CURR_STATUS','X')
			
			StepCnt = COUNT(StepKeys,@VM) + (StepKeys NE '')
			
			IF StepCnt > 1 THEN
				LastStatus = StepStatusCodes<1,StepCnt>				;* 8/10/2009
				IF LastStatus = 'RX' THEN
					Result = StepStatusCodes<1,(StepCnt - 1)>
				END ELSE
					Result = LastStatus
				END
			END ELSE
				Result = StepStatusCodes
			END
			RETURN
		END ELSE
			
			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
	END
	
	
	IF WORec<WO_LOG_WO_MAT_KEY$> = '' THEN
		* Material not here yet
		
		/*		
			OrderNo	= WORec<WO_LOG_ORDER_NO$>
			IF OrderNo = '' THEN
				Result = 'NORD'
				RETURN
			END
			
			FirstOrderItem	= WORec<WO_LOG_ORDER_ITEM$><1,1>
			IF FirstOrderItem = '' THEN
				Result = 'INC'
				RETURN
			END
			*/
		
		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 = 'CURR_STATUS':@VM:'RX':@VM:'INPR':@VM:'RTS':@VM:'SHIP':@VM:'HOLD':@FM		;* Inactivated by dkk 4/3/14
	SelectStatement = 'WO_STATUS':@VM:'OPEN':@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 = "INPR" '
	SelectStatement := ' OR WITH CURR_STATUS = "RTS"'
	SelectStatement := ' OR WITH CURR_STATUS = "SHIP"'
	SelectStatement := ' OR WITH CURR_STATUS = "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


* * * * * * *
ReleaseCassettes:
* * * * * * *
	
	WONo		= Parms[1,@RM]
	CassNos		= Parms[COL2()+1,@RM]
	
	LogData    = ''
	LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
	LogData<2> = @User4
	LogData<3> = WONo
	LogData<4> = 'Beginning ReleaseCassettes routine.'
	Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
	
	IF WONo	= ''			THEN ErrorMsg = 'Null parameter WONo passed to routine (':Method:').'
	IF ErrorMsg NE ''		THEN RETURN
	
	NewForm = Xlate('APP_INFO', 'NEW_WO_FORM', '', 'X')
	If NewForm then
		Form = 'NDW_WO_LOG'
	end else
		Form = 'WO_LOG2'
	end
	OrgColor = Set_Property(Form:'.STATUSLINE_FIX','BACKCOLOR',YELLOW$)	;* //////// Messaging
	
	TableVar = ''
	OtParms = 'WO_LOG':@RM:WONo:@RM:TableVar 
	WORec = obj_Tables('ReadRec',OtParms)			;* Locks and reads record for update
	
	* 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
	
	* * * * * * * * * * * * * * * * * * * * * * * * * * *
	
	Send_Info("Collecting Data for release...")								;* //////// Messaging
	
	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
	
	CassCnt = COUNT(CassNos,@VM) + (CassNos NE '')
	
	WOMKeys = ''
	FOR K = 1 TO CassCnt
		WOMKeys<1,K> = WONo:'*':CassNos<1,K>
	NEXT K
	
	Send_Info('Locking WOMat records for update...')
	
	* WOMTableVar = obj_WO_Mat('LockSet',WOMKeys)
	WOMTableVar = Database_Services('GetTableHandle', 'WO_MAT')
	
	IF Get_Status(errCode) THEN
		obj_Tables('UnlockRec',OtParms)		;* Unlock WO_LOG record
		
		Send_Info(STR(' ',60))														;** - Messaging - **
		
		NewForm = Xlate('APP_INFO', 'NEW_WO_FORM', '', 'X')
		If NewForm then
			Form = 'NDW_WO_LOG'
		end else
			Form = 'WO_LOG2'
		end
		
		Dummy = Set_Property(Form:'.STATUSLINE_FIX','BACKCOLOR',OrgColor)			;** - Messaging - **
		RETURN
	END
	
	LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
	LogData<4> = 'Trace 1'
	Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
	
	* At this point the WO_LOG is locked and the WO_MAT (cassettes) are all locked for update
	
	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 '')
	
	TableVar = ''
	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:' CassNos:':CassNos:' WMOLoadQty:':WMOLoadQty
		Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
		
		IF ReactorType = 'EPP' THEN
			
			Send_Info('Creating WM_OUT records for WOStep ':WOStep:'...')						;** - Messaging - **
			
			OutOnlyCassIDS = obj_WM_Out('Create',WONO:@RM:WOStep:@RM:CassNos:@RM:WMOLoadQty)	;* Changed WMOLoadQty 9/14/2012 JCH *********
			
		END ELSE
			OutOnlyCassIDs = ''
		END
		
		StepRDSNos = ''
		
		CassCnt = COUNT(CassNos,@VM) + (CassNos NE '')
		
		// Log variables after obj_WM_Out('Create')
		LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
		LogData<4> = 'WONo:':WONo:' WOStep:':WOStep:' CassNos:':CassNos:' CassCnt:':CassCnt:' WMOLoadQty:':WMOLoadQty
		Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
		
		Def = ""
		Def<MCAPTION$>		= "Releasing Cassettes for WO Step ":WOStep:"..."
		Def<MTYPE$>			= "G"
		Def<MEXTENT$>		= CassCnt
		Def<MTEXTWIDTH$>	= 600
		
		MsgUp = Msg(@WINDOW, Def)
		
		ReprocessedRDSNos = ''
		
		LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
		LogData<4> = 'Trace 2'
		Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
		
		FOR N = 1 TO CassCnt
			
			LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
			LogData<4> = 'Trace 2.':N
			Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
			
			CassNo = CassNos<1,N>
			
			Void = Msg(@WINDOW, MsgUp, N, MSGINSTUPDATE$)
			
			IF ReactorType = 'EPP' THEN
				CassWaferQty = XLATE('WO_MAT',WONo:'*':CassNo,WO_MAT_WAFER_QTY$,'X')
				
				WMIKey = WONo:'*':WOStep:'*':CassNo
				Send_Info('Creating WM_IN record "':WMIKey:'"...')							;** - Messaging - **
				
				obj_WM_IN('Create',WONo:@RM:WOStep:@RM:CassNo:@RM:CassWaferQty)				;* ********************************   EpiPro 5000 Reactor -> create WM_IN records
				
			END ELSE
				
				IF WOStepRec<WO_STEP_RDS_KEY$,CassNo> = '' THEN
					WOMatRec = XLATE('WO_MAT',WoNo:'*':CassNo,'','X')
					
					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
					
					Send_Info('Creating RDS for Cass No: ':CassNo:'...') 			;** - Messaging - **
					
					IF ReactorType = 'GAN' THEN
						
						NULL
						
					END ELSE
						
						LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
						LogData<4> = 'Trace 2.':N:'.1 - Start obj_RDS("Create")'
						Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
						
						NewRDSNo	= obj_RDS('Create',Parms)
						
						Loop
						While (NewRDSNo EQ 0 or NewRDSNo EQ '')
							MsgTxt = 'An error occured due to multiple users attempting to create an RDS simultaneously. ' |
							: @SVM : 'Would you like to retry?'
							Response  = Msg(@Window, '', 'RETRY', '', MsgTxt)
							Begin Case
								Case Response EQ 1
									Retry = False$       ; // User Clicked Abort
								Case Response EQ 2
									Retry = True$        ; // User Clicked Retry
								Case Response EQ char(27)
									Retry = False$       ; // User Pressed Escape Key
							End Case
							If Retry EQ True$ then
								NewRDSNo = obj_RDS('Create', Parms)
							end
						Until Retry EQ False$
						Repeat
						
						LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
						LogData<4> = 'Trace 2.':N:'.2 - End obj_RDS("Create")'
						Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
						
						If (Get_Status(errCode)) or (Error_Services('HasError')) or (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')
								EmailAddr = 'dstieber@srpcs.com,Dan.Crisp@infineon.com,jonathan.ouellette@infineon.com'
								LogData   = LoggingDTM : ',' : @USER4 : ',' : WONo : ',' : ErrMsg				    
								Logging_Services('AppendLog', objLog, LogData, CRLF$, COMMA$, False$, EmailAddr, 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
							Msg(@WINDOW, MsgUp) ;* take down the gauge			
							RETURN		;*************************** Check this for WO_LOG being cleared
						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 on this WO_Step*CassetteNo 
			END		;* End of check for EpiPRO reactor type
		NEXT N
		Msg(@WINDOW, MsgUp) ;* take down the gauge
	NEXT WOStep
	
	LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
	LogData<4> = 'Trace 3'
	Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
	
	Send_Info("Updating WO_Mat Records with release data...")
	
	RelDTM = OCONV(Date(),'D4/'):' ':OCONV(Time(),'MTHS')		;* 12/31/2014 JCH & DKK moved to prevent time incrementing time during release
	PtiDTM = OCONV(Date(),'D4/'):' ':OCONV(Time()+5,'MTHS')
	
	WOLogRec      = Database_Services('ReadDataRow', 'WO_LOG', WONo)
	* AvailOutSlots = WOLogRec<WO_LOG_AVAIL_OUT_SLOTS$>
	MaxShipQty    = Xlate('WO_LOG', WONo, 'CUST_EPI_PART_SHIP_QTY', 'X')
	
	IF WOLogRec<WO_LOG_NEXT_OUT_SLOT$> EQ '' then WOLogRec<WO_LOG_NEXT_OUT_SLOT$> = '1*1'
	
	FOR N = 1 TO CassCnt
		WOMKey = WOMKeys<1,N>
		CassNo = FIELD(WOMKey,'*',2)
		
		// Keep trying to get the lock. Another process may be updating this record at the same time.
		For Attempt = 1 to 100
			HaveLock = Database_Services('GetKeyIDLock', 'WO_MAT', WOMKey)
			If HaveLock then
				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$>		= @USER4
					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	= @USER4
					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 ReactType = 'EPP' OR ReactType = 'GAN' THEN
						obj_WO_Wfr('CassRel',WOMKey)						;* Added 3/17/2016 JCH for wafer history ***************************************
					END
				END
			end else
				Sleepery(1000)
			end
		Until HaveLock EQ True$
		Next Attempt
		
	NEXT N
	
	Database_Services('WriteDataRow', 'WO_LOG', WONo, WOLogRec, True$, False$, True$)
	
	LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
	LogData<4> = 'Trace 4'
	Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
	
	Send_Info(STR(' ',60))															;** - Messaging - **
	NewForm = Xlate('APP_INFO', 'NEW_WO_FORM', '', 'X')
	If NewForm then
		Form = 'NDW_WO_LOG'
	end else
		Form = 'WO_LOG2'
	end
	Dummy = Set_Property(Form:'.STATUS_LINE_FIX','BACKCOLOR',OrgColor)			;** - Messaging - **
	
	
	* * * * * *  WO_LOG record write was here
	
	OutOnlyCnt = COUNT(OutOnlyCassIDs,@VM) + (OutOnlyCassIDs NE '')
	
	ExistingWOMatKeys = WORec<WO_LOG_WO_MAT_KEY$>
	
	FOR I = 1 TO OutOnlyCnt
		OutOnlyCassID = OutOnlyCassIDs<1,I>
		LOCATE OutOnlyCassID IN ExistingWOMatKeys BY 'AR' USING @VM SETTING Pos ELSE
			ExistingWOMatKeys = INSERT(ExistingWOMatKeys,1,Pos,0,OutOnlyCassID)
		END
	NEXT I
	
	WORec<WO_LOG_WO_MAT_KEY$> = ExistingWOMatKeys	;* Add OutOnly Cassettetes to list inWO_LOG record.
	
	Send_Info('Saving WO_LOG record...')
	
	OtParms = FieldStore(OtParms,@RM,4,1,WORec)
	
	obj_Tables('WriteRec',OtParms)		;* Writes and unlocks the record  It only has one value updated
	
	LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
	LogData<4> = 'Trace 5'
	Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM)
	
	Send_Info(STR(' ',60))															;** - Messaging - **
	
	* * * * * * * * * * 
	
	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		= @USER4
			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
	
	* * * * * * * * * *
	LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS')
	LogData<4> = 'Ending ReleaseCassettes 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 OrderNo 		= '' THEN ErrorMsg = 'Null parameter "OrderNo" passed to routine. (':Method:')'
	*IF OrderItems	= '' THEN ErrorMsg = 'Null parameter "OrderItems" passed to routine. (':Method:')'
	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
	
	/*
	OrderDetKeys = ''
	FOR I = 1 TO COUNT(OrderItems,@VM) + (OrderItems NE '')
		OrderDetKeys<1,-1> = OrderNo:'*':OrderItems<1,I>
	NEXT I
	*/
	
	*OTParms		= 'ORDER_DET'
	RTParms			= 'RDS'
	WMParms			= 'WM_OUT'
	*LockedODKeys	= ''
	LockedRDSNos	= ''
	LockedWMOutKeys	= ''
	
	/*
	FOR M = 1 TO COUNT(OrderDetKeys,@VM) + (OrderDetKeys NE '')
		OrderDetKey = OrderDetKeys<1,M>
		OTParms = FieldStore(OTParms, @RM, 2, 1, OrderDetKey)
		obj_Tables('LockRec',OTParms)
		IF Get_Status(errCode) THEN
			FOR L = 1 TO COUNT(LockedODKeys,@VM) + (LockedODKeys NE '')
				OTParms = FieldStore(OTParms, @RM, 2, 1, LockedODKeys<1,L>)
				obj_Tables('UnlockRec',OTParms)		;* Unlock everything locked up to here
			NEXT L
				
			ErrorMsg = 'Unable to lock ORDER_DET record ':QUOTE(OrderDetKey):' for Update.'
			RETURN
		END ELSE
			LockedODKeys<1,-1> = OrderDetKey
		END
	NEXT M
	*/
	
	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
			
			*FOR L = 1 TO COUNT(LockedODKeys,@VM) + (LockedODKeys NE '')
			*	OTParms = FieldStore(OTParms, @RM, 2, 1, LockedODKeys<1,L>)
			*	obj_Tables('UnlockRec',OTParms)		;* Unlock everything locked up to here
			*NEXT L
			
			ErrorMsg = 'Unable to lock RDS ':QUOTE(RdsNo):' for delete.'
			*obj_Tables('UnlockRec',OTParms)
			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
			
			*FOR L = 1 TO COUNT(LockedODKeys,@VM) + (LockedODKeys NE '')
			*	OTParms = FieldStore(OTParms, @RM, 2, 1, LockedODKeys<1,L>)
			*	obj_Tables('UnlockRec',OTParms)		;* Unlock everything locked up to here
			*NEXT L
			
			ErrorMsg = 'Unable to lock RDS ':QUOTE(WMOutKey):' for delete.'
			*obj_Tables('UnlockRec',OTParms)
			RETURN
		END ELSE
			LockedWMOutKeys<1,-1> = WMOutKey
		END
	NEXT I
	
	*OCTableNames	= ''			;* Buckets for stuff to pass to obj_Order_Change
	*OCRecordKeys	= ''
	*OCColumns		= ''
	*OCValues		= ''
	*OCOldValues		= ''
	*OCNewValues		= ''
	*OCCnt			= 0
	
	*OrderTableVar	= FIELD(OTParms,@RM,3)
	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
		
		*OCCnt += 1
		*OCTableNames<1,OCCnt>	= 'RDS'
		*OCRecordKeys<1,OCCnt>	= LockedRDSNo
		*OCColumns<1,OCCnt>		= 'COMMIT_DATE_FINAL'
		*OCValues<1,OCCnt>		= ''
		*OCOldValues<1,OCCnt> 	= OldValue
		*OCNewValues<1,OCCnt>	= thisPromiseDt
		
	NEXT I
	
	**************************** This section added 6/29/2006 JCH J.C. Henry & Co.
	
	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
		
		*OCCnt += 1
		*OCTableNames<1,OCCnt>	= 'WM_OUT'
		*OCRecordKeys<1,OCCnt>	= LockedWMOutKey
		*OCColumns<1,OCCnt>		= 'COMMIT_DT'
		*OCValues<1,OCCnt>		= ''
		*OCOldValues<1,OCCnt> 	= OldValue
		*OCNewValues<1,OCCnt>	= thisPromiseDt
		
	NEXT I
	
	*****************************
	/*
	FOR I = 1 TO COUNT(LockedODKeys,@VM) + (LockedODKeys NE '')
		OrderDetKey = LockedODKEys<1,I>
		READ OrderDetRec FROM OrderTableVar,OrderDetKey THEN
			OldValue = OrderDetRec<ORDER_DET_PROMISE_DT$>
			OrderDetRec<ORDER_DET_PROMISE_DT$> = thisPromiseDt
			OTParms = FieldStore(OTParms,@RM,2,1,OrderDetKey)
			OTParms = FieldStore(OTParms,@RM,4,1,OrderDetRec)
			obj_Tables('WriteRec',OTParms)									;* Write and unlock ORDER_DET record
			
			OCCnt += 1
			OCTableNames<1,OCCnt>	= 'ORDER_DET'
			OCRecordKeys<1,OCCnt>	= OrderDetKey
			OCColumns<1,OCCnt>		= 'PROMISE_DT'
			OCValues<1,OCCnt>		= ''
			OCOldValues<1,OCCnt>	= OldValue
			OCNewValues<1,OCCnt>	= thisPromiseDt
	
		END ELSE
			obj_Tables('UnlockRec',OTParms)
		END
	NEXT I
	*/
	
	*obj_Order_Change('Create',OrderNo:@RM:OCTableNames:@RM:OCRecordKeys:@RM:OCColumns:@RM:OCValues:@RM:OCOldValues:@RM:OCNewValues:@RM:Reason)
	
	
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
	*WORec<WO_LOG_NEXT_RUN_NO$> = NextRunNo + 1
	
	
	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


CassRelUsers = XLATE('WO_MAT',@RECORD<31>,28,'X')
TimeStamps = ''
Tmp = ''
FOR I = 1 TO COUNT(CassRelDTMs,@VM) + (CassRelDTMs NE '')
	CassRelDTM = CassRelDTMs<1,I>
	CassRelUser = CassRelUsers<1,I>
	LOCATE CassRelDTM IN TimeStamps  SETTING Pos ELSE
		TimeStamps = INSERT(TimeStamps,1,Pos,0,CassRelDTM)
		Tmp = INSERT(Tmp,1,Pos,0,OCONV(CassRelDTM,'DT2/^HS'):'    ':OCONV(CassRelUser,'[XLATE_CONV,LSL_USERS*FIRST_LAST]'))
	END
NEXT I

@ANS = Tmp




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 = "COMP" AND WITHOUT CLOSE_DATE '
	END ELSE
		SelectStatement  = 'SELECT WO_LOG WITH CURR_STATUS = "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
	
	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


