Compile function Hold_Services(@Service, @Params)
/***********************************************************************************************************************

    Name        :   Hold_Services

    Description :   Handler program for all Hold services.

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

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

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

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

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

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

    Metadata    :

    History     :   (Date, Initials, Notes)
        6/28/24    djm     Original programmer.

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

$Insert APP_INSERTS
$Insert SERVICE_SETUP
$Insert MSG_EQUATES
$Insert DICT_EQUATES
$Insert WO_MAT_EQUATES
$Insert NOTIFICATION_EQU

Declare function   Database_Services, Error_Services, Obj_Wm_In, Obj_Wm_Out, Unassigned, Wm_In_Services, Wm_Out_Services
Declare function   PSN_Services, SRP_Rotate_Array, Datetime, Hold_Services, Memberof, Error_Services, Rds_Services
Declare function   Environment_Services, Utility, Logging_Services
Declare subroutine Database_Services, Error_Services, Obj_notes, Hold_Services, Obj_Wm_In, Obj_Wm_Out, Wm_In_Services
Declare subroutine Wm_Out_Services, Rds_Services, Lot_Event_Services, Logging_Services

GoToService else
	Error_Services('Add', Service : ' is not a valid service request within the ' : ServiceModule : ' module.')
end

Return Response or ""

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


//----------------------------------------------------------------------------------------------------------------------
// ToggleHold
//
// WOMatKey		- [Required]
// HoldEntity	- [Required]
// HoldEntityID - [Required]
// CtrlEntID	- [Optional] *Required for ship hold checks
// OriginFlag	- [Optional]
// HoldData		- [Optional]
// OperatorID   - [Optional]
//
// Toggles hold status from on to off, or from off to on.
//----------------------------------------------------------------------------------------------------------------------
Service ToggleHold(WOMatKey, HoldEntity, HoldEntityID, CtrlEntID, OriginFlag, HoldData, OperatorID)
	
	If ( (WOMatKey EQ '') or (HoldEntity EQ '') or (HoldEntityID EQ '') ) then
		Error_Services('Add', 'Null parameter WOMatKey, HoldEntity, or HoldEntityID passed to service.')
	end else
		HoldCheck = Hold_Services("CheckForHold", WOMatKey, CtrlEntID)
		If Unassigned(OperatorID) then OperatorID = ''
		Begin Case
			Case Index(CtrlEntID,'SHIP_HOLD',1)	; HoldType = 'SHOLD'	; * Ship Hold
			Case Otherwise$						; HoldType = 'HOLD'		; * Production or Engineering Hold
		End Case
		If Error_Services("NoError") then
			If HoldCheck = False$ then
				Hold_Services("OnHold", WOMatKey, HoldEntity, HoldEntityID, HoldType, HoldData, OperatorID, OriginFlag)
			end else
				Hold_Services("OffHold", WOMatKey, HoldEntity, HoldEntityID, HoldType, HoldData, OperatorID, OriginFlag)
			end
			If Error_Services("NoError") then
				Response = True$
			end else
				Response = Error_Services("GetMessage")
			end
		end else
			Response = Error_Services("GetMessage")
		end
	end
	
End Service


//----------------------------------------------------------------------------------------------------------------------
// ToggleMultipleHolds
//
// WOMatKeys	 - [Required]	@FM delimited array, count must match HoldEntityIDs
// HoldEntity	 - [Required]
// HoldEntityIDs - [Required]	@FM delimited, count must match WOMatKeys
// CtrlEntID	 - [Required]
// OriginFlag	 - [Optional]
// HoldData		 - [Required]
//
// Toggles hold status for multiple lots from on to off, or from off to on.
//----------------------------------------------------------------------------------------------------------------------
Service ToggleMultipleHolds(WOMatKeys, HoldEntity, HoldEntityIDs, CtrlEntID, OriginFlag, HoldData)
	
	IF WOMatKeys = '' or HoldEntity = '' or HoldEntityIDs = '' or CtrlEntID = '' or HoldData = '' THEN
		Error_Services('Add', 'Null parameter WOMatKeys, HoldEntity, HoldEntityIDs, CtrlEntID, or HoldData passed to service.')
	end else
		BEGIN CASE
			CASE INDEX(CtrlEntID,'SHIP_HOLD',1)	; HoldType = 'SHOLD'	; * Ship Hold
			CASE 1								; HoldType = 'HOLD'		; * Production or Engineering Hold
		END CASE
		WOMatCount      = DCount(WOMatKeys, @FM)
		HoldEntityCount = Dcount(HoldEntityIDs, @FM)
		Reason          = HoldData<2>
		If WOMatCount NE HoldEntityCount then
			Error_Services('Add', 'WOMatKeys count must match HoldEntityIDs count.')
		end else
			For I = 1 to WOMatCount
				Hold_Services('ToggleHold', WOMatKeys<I>, HoldEntity, HoldEntityIDs<I>, CtrlEntID, OriginFlag, HoldData)
				If Error_Services("NoError") then
					Hold_Services("HoldNotification", HoldEntity, HoldEntityIDs<I>, Reason, HoldCheck, HoldType)
				end else
					Response = Error_Services("GetMessage")
				end
			Next I
		end
	end
	
end service


//----------------------------------------------------------------------------------------------------------------------
// EnableMultipleHolds
//
// WOMatKeys	 - [Required]	@FM delimited array, count must match HoldEntityIDs
// HoldEntity	 - [Required]
// HoldEntityIDs - [Required]	@FM delimited, count must match WOMatKeys
// CtrlEntID	 - [Required]
// OriginFlag	 - [Optional]
// HoldData		 - [Required]
//
// Toggles hold status for multiple lots from off to on.
//----------------------------------------------------------------------------------------------------------------------
Service EnableMultipleHolds(WOMatKeys, HoldEntity, HoldEntityIDs, CtrlEntID, OriginFlag, HoldData)
	
	IF WOMatKeys = '' or HoldEntity = '' or HoldEntityIDs = '' or HoldData = '' THEN
		Error_Services('Add', 'Null parameter WOMatKeys, HoldEntity, HoldEntityIDs, CtrlEntID, or HoldData passed to service.')
	end else
		BEGIN CASE
			CASE INDEX(CtrlEntID,'SHIP_HOLD',1)	; HoldType = 'SHOLD'	; * Ship Hold
			CASE 1								; HoldType = 'HOLD'		; * Production or Engineering Hold
		END CASE
		Reason = HoldData<2>
		WOMatCount      = DCount(WOMatKeys, @FM)
		HoldEntityCount = Dcount(HoldEntityIDs, @FM)
		If WOMatCount NE HoldEntityCount then
			Error_Services('Add', 'WOMatKeys count must match HoldEntityIDs count.')
		end else
			If CtrlEntID EQ 'NDW_RDS_QUERY' OR CtrlEntID EQ 'NDW_WM_OUT_QUICK_QUERY' then
				Def              = ""
				Def<MCAPTION$>   = "Processing..."
				Def<MTYPE$ >     = "G"
				Def<MEXTENT$>    = HoldEntityCount
				Def<MTEXTWIDTH$> = 400
				Def<MCOL$>       = -2        ;* message h-pos in pixels, or -2 (center screen, the default), -1 (center parent)
				Def<MROW$>       = -2        ;* message v-pos in pixels
				MsgUp            = Msg(@window, Def)
			end
			For I = 1 to WOMatCount
				If Hold_Services('CheckForHold', WOMatKeys<I>) EQ False$ then
					Hold_Services('OnHold', WOMatKeys<I>, HoldEntity, HoldEntityIDs<I>, HoldType, HoldData)
				end
				If CtrlEntID EQ 'NDW_RDS_QUERY' OR CtrlEntID EQ 'NDW_WM_OUT_QUICK_QUERY' then Msg(@window, MsgUp, I, MSGINSTUPDATE$)
			Next I
			If CtrlEntID EQ 'NDW_RDS_QUERY' OR CtrlEntID EQ 'NDW_WM_OUT_QUICK_QUERY' then retval = Msg(@window, MsgUp) ;* take down the gauge
		end
	end
	
end service


//----------------------------------------------------------------------------------------------------------------------
// DisableMultipleHolds
//
// WOMatKeys	 - [Required]	@FM delimited array, count must match HoldEntityIDs
// HoldEntity	 - [Required]
// HoldEntityIDs - [Required]	@FM delimited, count must match WOMatKeys
// CtrlEntID	 - [Required]
// OriginFlag	 - [Optional]
// HoldData		 - [Required]
//
// Toggles hold status for multiple lots from on to off.
//----------------------------------------------------------------------------------------------------------------------
Service DisableMultipleHolds(WOMatKeys, HoldEntity, HoldEntityIDs, CtrlEntID, OriginFlag, HoldData)
	
	IF WOMatKeys = '' or HoldEntity = '' or HoldEntityIDs = '' or HoldData = '' THEN
		Error_Services('Add', 'Null parameter WOMatKeys, HoldEntity, HoldEntityIDs, CtrlEntID, or HoldData passed to service.')
	end else
		BEGIN CASE
			CASE INDEX(CtrlEntID,'SHIP_HOLD',1)	; HoldType = 'SHOLD'	; * Ship Hold
			CASE 1								; HoldType = 'HOLD'		; * Production or Engineering Hold
		END CASE
		WOMatCount      = DCount(WOMatKeys, @FM)
		HoldEntityCount = Dcount(HoldEntityIDs, @FM)
		Reason = HoldData<2>
		If WOMatCount NE HoldEntityCount then
			Error_Services('Add', 'WOMatKeys count must match HoldEntityIDs count.')
		end else
				If CtrlEntID EQ 'NDW_RDS_QUERY' OR CtrlEntID EQ 'NDW_WM_OUT_QUICK_QUERY' then
				Def              = ""
				Def<MCAPTION$>   = "Processing..."
				Def<MTYPE$ >     = "G"
				Def<MEXTENT$>    = HoldEntityCount
				Def<MTEXTWIDTH$> = 400
				Def<MCOL$>       = -2        ;* message h-pos in pixels, or -2 (center screen, the default), -1 (center parent)
				Def<MROW$>       = -2        ;* message v-pos in pixels
				MsgUp            = Msg(@window, Def)
				end
			For I = 1 to WOMatCount
				If Hold_Services('CheckForHold', WOMatKeys<I>) EQ True$ then
					Hold_Services('OffHold', WOMatKeys<I>, HoldEntity, HoldEntityIDs<I>, HoldType, HoldData)
				end
				If CtrlEntID EQ 'NDW_RDS_QUERY' OR CtrlEntID EQ 'NDW_WM_OUT_QUICK_QUERY' then Msg(@window, MsgUp, I, MSGINSTUPDATE$)
			Next I
			If CtrlEntID EQ 'NDW_RDS_QUERY' OR CtrlEntID EQ 'NDW_WM_OUT_QUICK_QUERY' then retval = Msg(@window, MsgUp) ;* take down the gauge
		end
	end
	
end service


//----------------------------------------------------------------------------------------------------------------------
// OnHold
//
// WOMatKey		- [Required]
// HoldEntity	- [Required]
// HoldEntityID - [Required]
// HoldType		- [Required]
// HoldData		- [Optional]
// OperatorID   - [Optional]
//
// Places a lot on hold.
//----------------------------------------------------------------------------------------------------------------------
Service OnHold(WOMatKey, HoldEntity, HoldEntityID, HoldType, HoldData, OperatorID, OriginFlag)
    
	IF WOMatKey = '' or HoldEntity = '' or HoldEntityID = '' or HoldType = '' THEN
		Error_Services('Add', 'Null parameter WOMatKey, HoldEntity, HoldEntityID, or HoldType passed to service.')
	end else
		If Hold_Services('CheckForHold', WOMatKey) EQ False$ then
			//Turn hold on
			CustInfo = XLATE('WO_MAT',WOMatKey,'CUST_NAME','X')
			WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey, '', '', '')
			If HoldData EQ '' then
				Begin Case
					Case OriginFlag EQ 'P' ;*Packaging form
						HoldData<1> = OperatorID
						HoldData<2> = 'Packaging scanned data mismatch.'
						HoldData<3> = False$
					Case OriginFlag EQ 'PTO' ;*PTO/PSVER form
						HoldData<1> = OperatorID
						HoldData<2> = 'PTO/PSVER scanned data mismatch.'
						HoldData<3> = False$
					Case OriginFlag EQ 'H' ;*Auto-hold service
						HoldData<1> = OperatorID
						HoldData<2> = 'Makeup box is older than three years.'
						HoldData<3> = False$
				End Case
			end
			UserID   = HoldData<1>
			Reason   = HoldData<2>
			Extended = HoldData<3>
			Stage    = HoldData<4>
			Interrupted = HoldData<5>
			
			CurrDate = OCONV(Date(),'D4/')
			CurrTime = OCONV(Time(),'MTS')
			CurrDTM  = ICONV(CurrDate:' ':CurrTime,'DT')
			IF HoldType = 'HOLD' THEN
				
				WOMatRec<WO_MAT_HOLD$>	= 1
				
				WOMatRec = INSERT(WOMatRec,WO_MAT_HOLD_START_DTM$,1,0,CurrDTM)
				WOMatRec = INSERT(WOMatRec,WO_MAT_HOLD_START_USER$,1,0,UserID)
				WOMatRec = INSERT(WOMatRec,WO_MAT_HOLD_START_REASON$,1,0,Reason)
				WOMatRec = INSERT(WOMatRec,WO_MAT_HOLD_EXTENDED$,1,0,Extended)
				WOMatRec = INSERT(WOMatRec,WO_MAT_HOLD_STOP_DTM$,1,0,'')
				WOMatRec = INSERT(WOMatRec,WO_MAT_HOLD_STOP_USER$,1,0,'')
				WOMatRec = INSERT(WOMatRec,WO_MAT_HOLD_STOP_REASON$,1,0,'')
				WOMatRec = INSERT(WOMatRec,WO_MAT_HOLD_ENTITY$,1,0,HoldEntity)
				WOMatRec = INSERT(WOMatRec,WO_MAT_HOLD_ENTITY_ID$,1,0,HoldEntityID)
				WOMatRec<WO_MAT_HOLD_STAGE$> = Stage
				WOMatRec<WO_MAT_HOLD_INTERRUPTED$> = Interrupted
				***********************************************************
				
				// - djs - 10/29/2019
				// Updated material log entry method to be more reliable.
				// Material log entries in quick succession were failing to be recorded.
				NumTimestamps = Dcount(WOMatRec<WO_MAT_INV_WH$>, @VM)
				NewEntryPos   = NumTimestamps + 1
				CurrWH		= WOMatRec<WO_MAT_INV_WH$,          NewEntryPos - 1>			;* WH before hold
				CurrLoc		= WOMatRec<WO_MAT_INV_LOCATION$,    NewEntryPos - 1>		;* LOC before hold
				CurrTool	= WOMatRec<WO_MAT_INV_TOOL_ID$,     NewEntryPos - 1>	;* ToolID before hold
				WOMatRec = INSERT(WOMatRec, WO_MAT_INV_WH$,         NewEntryPos, 0, CurrWH)
				WOMatRec = INSERT(WOMatRec, WO_MAT_INV_LOCATION$,   NewEntryPos, 0, CurrLoc)
				WOMatRec = INSERT(WOMatRec, WO_MAT_INV_ACTION$,     NewEntryPos, 0, 'HOLD_ON')
				WOMatRec = INSERT(WOMatRec, WO_MAT_INV_DTM$,        NewEntryPos, 0, CurrDTM)
				WOMatRec = INSERT(WOMatRec, WO_MAT_INV_USER$,       NewEntryPos, 0, UserID)
				WOMatRec = INSERT(WOMatRec, WO_MAT_INV_TAG$,        NewEntryPos, 0, '')
				WOMatRec = INSERT(WOMatRec, WO_MAT_INV_TOOL_ID$,    NewEntryPos, 0, CurrTool)
				
			END ELSE
				
				WOMatRec<WO_MAT_SHIP_HOLD$>	= 1
				
				WOMatRec = INSERT(WOMatRec,WO_MAT_SHIP_HOLD_START_DTM$,1,0,CurrDTM)
				WOMatRec = INSERT(WOMatRec,WO_MAT_SHIP_HOLD_START_USER$,1,0,UserID)
				WOMatRec = INSERT(WOMatRec,WO_MAT_SHIP_HOLD_START_REASON$,1,0,Reason)
				WOMatRec = INSERT(WOMatRec,WO_MAT_SHIP_HOLD_EXTENDED$,1,0,Extended)
				WOMatRec = INSERT(WOMatRec,WO_MAT_SHIP_HOLD_STOP_DTM$,1,0,'')
				WOMatRec = INSERT(WOMatRec,WO_MAT_SHIP_HOLD_STOP_USER$,1,0,'')
				WOMatRec = INSERT(WOMatRec,WO_MAT_SHIP_HOLD_STOP_REASON$,1,0,'')
				WOMatRec<WO_MAT_HOLD_STAGE$> = Stage
				WOMatRec<WO_MAT_HOLD_INTERRUPTED$> = Interrupted
			END
			
			IF HoldEntity = 'WM_OUT' THEN
				WOMatRec<WO_MAT_WMO_CURR_STATUS$> = 'HOLD'		;* JCH 7/14/2009
			END
			
			IF HoldEntity = 'WM_IN' THEN
				WOMatRec<WO_MAT_WMI_CURR_STATUS$> = 'HOLD'		;* JCH 7/14/2009
			END
			
			Database_Services("WriteDataRow", "WO_MAT", WOMatKey, WOMatRec, True$, False$, '')
			If Error_Services("NoError") then
				Hold_Services("HoldNotification", HoldEntity, HoldEntityID, Reason, True$, HoldType, OperatorID)
				Hold_Services("CreateComment", HoldEntity, HoldEntityID, Reason, True$, HoldType, OperatorID)
				LotKey = ''
				Begin Case
					Case HoldEntity EQ 'WM_IN'
						WONo    = Field(WOMatKey, '*', 1)
						StepNo  = 1
						CassNo  = Field(WOMatKey, '*', 2)
						WMInKey = WONo : '*' : StepNo : '*' : CassNo
						LotKey  = 'I':WMInKey
						Convert '*' to '.' in LotKey
					Case HoldEntity EQ 'WM_OUT'
						WONo     = Field(WOMatKey, '*', 1)
						StepNo   = 1
						CassNo   = Field(WOMatKey, '*', 2)
						WMOutKey = WONo : '*' : StepNo : '*' : CassNo
						LotKey   = 'O':WMOutKey
						Convert '*' to '.' in LotKey
					Case HoldEntity EQ 'RDS'
						RDSNo  = Xlate('WO_MAT', WOMatKey, WO_MAT_RDS_NO$, 'X')
						LotKey = 'R':RDSNo
						Convert '*' to '.' in LotKey
					Case HoldEntity EQ 'WO_MAT'
						LotKey = 'W':WOMatKey
						Convert '*' to '.' in LotKey
				End Case
                Machine        = Environment_Services('GetServer')
                Headers        = 'Logging DTM' : @FM : 'Machine' : @FM : 'Log'
                ColumnWidths   = 20 : @FM : 15 : @FM : 300
                LogPath        = Environment_Services('GetApplicationRootPath') : '\LogFiles\Lot'
                makeDirSuccess = Utility("MAKEDIR", LogPath)
                LogFileName    = LotKey:'.csv'
                objLog         = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ' ', Headers, ColumnWidths, False$, False$)   				
                LogData        = ''
                LogData<1>     = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS') ; // Logging DTM
                LogData<2>     = Machine
                LogData<3>     = 'Lot ':LotKey:' of type ':HoldEntity:' placed on hold by user ':OperatorId
                Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$)				
			end
		end else
			Error_Services('Add', 'Lot is already on hold.')
		end
	end
	
End Service


//----------------------------------------------------------------------------------------------------------------------
// OffHold
//
// WOMatKey		- [Required]
// HoldEntity	- [Required]
// HoldEntityID - [Required]
// HoldType		- [Required]
// HoldData		- [Optional]
// OperatorID   - [Optional]
//
// Removes a hold placed on a lot.
//----------------------------------------------------------------------------------------------------------------------
Service OffHold(WOMatKey, HoldEntity, HoldEntityID, HoldType, HoldData, OperatorID, OriginFlag)
    
	IF WOMatKey = '' or HoldEntity = '' or HoldEntityID = '' or HoldType = '' THEN
		Error_Services('Add', 'Null parameter WOMatKey, HoldEntity, HoldEntityID, or HoldType passed to service.')
	end else
		If OperatorID EQ '' then OperatorID = @USER4
		if MemberOf(OperatorID, 'ENG_TECH') OR MemberOf(OperatorID, 'LEAD') OR MemberOf(OperatorID, 'SUPERVISOR') then
			//Turn hold off
			If Hold_Services('CheckForHold', WOMatKey) EQ True$ then
				CustInfo	= XLATE('WO_MAT',WOMatKey,'CUST_NAME','X')
				WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey, '', '', '')
				If HoldData EQ '' then
					Begin Case
						Case OriginFlag EQ 'P' ;*Packaging form
							HoldData<1> = OperatorID
							HoldData<2> = 'Packaging scanned data mismatch.'
							HoldData<3> = False$
						Case OriginFlag EQ 'PTO' ;*PTO/PSVER form
							HoldData<1> = OperatorID
							HoldData<2> = 'PTO/PSVER scanned data mismatch.'
							HoldData<3> = False$
						Case OriginFlag EQ 'H' ;*Auto-hold service
							HoldData<1> = OperatorID
							HoldData<2> = 'Makeup box is older than three years.'
							HoldData<3> = False$
					End Case
				end
				UserID		= HoldData<1>
				Reason		= HoldData<2>
				Extended	= HoldData<3>
				
				CurrDate = OCONV(Date(),'D4/')
				CurrTime = OCONV(Time(),'MTS')
				CurrDTM = ICONV(CurrDate:' ':CurrTime,'DT')
				IF HoldType = 'HOLD' THEN
					
					WOMatRec<WO_MAT_HOLD$> = 0
					
					WOMatRec<WO_MAT_HOLD_STOP_DTM$,1> = CurrDTM
					WOMatRec<WO_MAT_HOLD_STOP_USER$,1> = UserID
					WOMatRec<WO_MAT_HOLD_STOP_REASON$,1> = Reason
					WOMatRec<WO_MAT_HOLD_EXTENDED$,1> = 0
					WOMatRec<WO_MAT_HOLD_STAGE$> = ''
					WOMatRec<WO_MAT_HOLD_INTERRUPTED$> = ''
					
					***********************************************************
					
					LOCATE CurrDTM IN WOMatRec<WO_MAT_INV_DTM$> BY 'AR' USING @VM SETTING Pos ELSE
						
						IF Pos > 1 THEN
							CurrWH		= WOMatRec<WO_MAT_INV_WH$,Pos-1>		;* WH before hold
							CurrLoc		= WOMatRec<WO_MAT_INV_LOCATION$,Pos-1>	;* LOC before hold
							CurrTool	= WOMatRec<WO_MAT_INV_TOOL_ID$,Pos-1>	;* ToolID before hold
							
							
							WOMatRec = INSERT(WOMatRec,WO_MAT_INV_WH$,Pos,0,CurrWH)
							WOMatRec = INSERT(WOMatRec,WO_MAT_INV_LOCATION$,Pos,0,CurrLoc)
							WOMatRec = INSERT(WOMatRec,WO_MAT_INV_ACTION$,Pos,0,'HOLD_OFF')
							WOMatRec = INSERT(WOMatRec,WO_MAT_INV_DTM$,Pos,0,CurrDTM)
							WOMatRec = INSERT(WOMatRec,WO_MAT_INV_USER$,Pos,0,UserID)
							WOMatRec = INSERT(WOMatRec,WO_MAT_INV_TAG$,Pos,0,'')
							WOMatRec = INSERT(WOMatRec,WO_MAT_INV_TOOL_ID$,Pos,0,CurrTool)
							
						END	;* End of check for Pos > 1  Rcvd is always the first transaction
						
					END	;* End of DTM locate
					
					************************************************************** 
					
				END ELSE
					WOMatRec<WO_MAT_SHIP_HOLD$> = 0
					
					WOMatRec<WO_MAT_SHIP_HOLD_STOP_DTM$,1> = CurrDTM
					WOMatRec<WO_MAT_SHIP_HOLD_STOP_USER$,1> = UserID
					WOMatRec<WO_MAT_SHIP_HOLD_STOP_REASON$,1> = Reason
					WOMatRec<WO_MAT_SHIP_HOLD_EXTENDED$,1> = 0
					WOMatRec<WO_MAT_HOLD_STAGE$> = ''
					WOMatRec<WO_MAT_HOLD_INTERRUPTED$> = ''
				END
				
				IF HoldEntity = 'WM_OUT' THEN
					WOMatRec<WO_MAT_WMO_CURR_STATUS$> = obj_WM_Out('CurrStatus',HoldEntityID:@RM:@RM:WOMatRec)
				END
				
				IF HoldEntity = 'WM_IN' THEN
					WOMatRec<WO_MAT_WMI_CURR_STATUS$> = obj_WM_In('CurrStatus',HoldEntityID:@RM:@RM:WOMatRec)
				END
				
				Database_Services("WriteDataRow", "WO_MAT", WOMatKey, WOMatRec, True$, False$, '')
				If Error_Services("NoError") then
					Hold_Services("HoldNotification", HoldEntity, HoldEntityID, Reason, False$, HoldType, OperatorID)
					Hold_Services("CreateComment", HoldEntity, HoldEntityID, Reason, False$, HoldType, OperatorID)
					LotKey = ''
                    Begin Case
                        Case HoldEntity EQ 'WM_IN'
                            WONo    = Field(WOMatKey, '*', 1)
                            StepNo  = 1
                            CassNo  = Field(WOMatKey, '*', 2)
                            WMInKey = WONo : '*' : StepNo : '*' : CassNo
                            LotKey  = 'I':WMInKey
                            Convert '*' to '.' in LotKey
                        Case HoldEntity EQ 'WM_OUT'
                            WONo     = Field(WOMatKey, '*', 1)
                            StepNo   = 1
                            CassNo   = Field(WOMatKey, '*', 2)
                            WMOutKey = WONo : '*' : StepNo : '*' : CassNo
                            LotKey   = 'O':WMOutKey
                            Convert '*' to '.' in LotKey
                        Case HoldEntity EQ 'RDS'
                            RDSNo  = Xlate('WO_MAT', WOMatKey, WO_MAT_RDS_NO$, 'X')
                            LotKey = 'R':RDSNo
                        Case HoldEntity EQ 'WO_MAT'
                            LotKey = WOMatKey
                            Convert '*' to '.' in LotKey
                    End Case
                    
                    Machine        = Environment_Services('GetServer')
                    Headers        = 'Logging DTM' : @FM : 'Machine' : @FM : 'Log'
                    ColumnWidths   = 20 : @FM : 15 : @FM : 300
                    LogPath        = Environment_Services('GetApplicationRootPath') : '\LogFiles\Lot'
                    makeDirSuccess = Utility("MAKEDIR", LogPath)
                    LogFileName    = LotKey:'.csv'
                    objLog         = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ' ', Headers, ColumnWidths, False$, False$)                        
                    
                    LogData    = ''
                    LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS') ; // Logging DTM
                    LogData<2> = Machine
                    LogData<3> = 'Lot ':LotKey:' of type ':HoldEntity:' taken off hold by user ':OperatorId
                    Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$)                    
				end
			end else
				Error_Services('Add', 'Lot is not on hold.')
			end
		end else
			Error_Services("Add", "User does not have permission to remove lot holds.")
		end
	end
	
End Service


//----------------------------------------------------------------------------------------------------------------------
// CheckForHold
//
// WOMatKey		- [Required]
// CtrlEntID	- [Optional]
//
// Returns whether or not a lot is on hold.
//----------------------------------------------------------------------------------------------------------------------
Service CheckForHold(WOMatKey, CtrlEntID)
	
	IF WOMatKey = '' THEN
		
		Error_Services('Add', 'Null parameter WOMatKey passed to service.')
		
	end else
		
		WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey, '', '', '')
		
		BEGIN CASE
			CASE Index(CtrlEntID,'SHIP_HOLD',1)	; HoldType = 'SHOLD'	; * Ship Hold
			CASE Otherwise$						; HoldType = 'HOLD'		; * Production or Engineering Hold
		END CASE
		
		IF HoldType = 'SHOLD' THEN
			HoldCheck = WOMatRec<WO_MAT_SHIP_HOLD$>
		END ELSE
			HoldCheck = WOMatRec<WO_MAT_HOLD$>
		END
		
		If HoldCheck EQ '' then HoldCheck = False$
		
		Response = HoldCheck
		
	End
	
End Service


//----------------------------------------------------------------------------------------------------------------------
// HoldNotification
//
// HoldEntity	- [Required]
// HoldEntityID - [Required]
// Reason		- [Required]
// Transition   - [Required]
// HoldType		- [Required]
//
// Notifies specified users of changes in lot holds.
//----------------------------------------------------------------------------------------------------------------------
Service HoldNotification(HoldEntity, HoldEntityID, Reason, Transition, HoldType, OperatorID)
	
	IF HoldEntity = '' or HoldEntityID = '' or Reason = '' or Transition = '' or HoldType = '' THEN
		Error_Services('Add', 'Null parameter WOMatKey, HoldEntity, HoldEntityID, HoldType, or HoldData passed to service.')
	end else
		BEGIN CASE
			CASE HoldEntity = 'RDS'
				IF Transition EQ True$ THEN
					Subject	= 'Material Placed on Hold ':HoldEntityID
					Message = 'Material Placed on Hold'
				END ELSE
					Subject	= 'Material Taken off Hold ':HoldEntityID
					Message = 'Material Taken off Hold'
				END
				
				AttachWindow = HoldEntity
				AttachKey    = HoldEntityID
				
			CASE HoldEntity = 'WO_MAT'
				IF Transition EQ True$  THEN
					IF HoldType = 'HOLD' THEN
						Subject	= 'Material Placed on Hold ':HoldEntityID
						Message = 'Material Placed on Hold'
					END ELSE
						Subject	= 'Material Placed on Ship Hold ':HoldEntityID
						Message = 'Material Placed on Ship Hold'
					END
				END ELSE
					IF HoldType = 'HOLD' THEN
						Subject	= 'Material Taken off Hold ':HoldEntityID
						Message = 'Material Taken off Hold'
					END ELSE
						Subject	= 'Material Taken off Ship Hold ':HoldEntityID
						Message = 'Material Taken off Ship Hold'
					END
				END
				
				AttachWindow	= HoldEntity
				AttachKey		= HoldEntityID
				
				
			CASE HoldEntity = 'REACT_RUN'
				IF Transition EQ True$  THEN
					Subject	= 'Material  Placed on Hold ':HoldEntityID
					Message = 'Material  Placed on Hold'
				END ELSE
					Subject	= 'Material Taken off Hold ':HoldEntityID
					Message = 'Material Taken off Hold'
				END
				
				AttachWindow	= 'REACT_RUN'
				AttachKey		= HoldEntityID
				
				
			CASE HoldEntity = 'WM_IN'
				
				IF Transition EQ True$  THEN
					Subject	= 'Material Placed on Hold ':HoldEntityID
					Message = 'Material  Placed on Hold'
				END ELSE
					Subject	= 'Material Taken off Hold ':HoldEntityID
					Message = 'Material  Taken off Hold'
				END 
				
				AttachWindow	= HoldEntity
				AttachKey		= HoldEntityID
				
			CASE HoldEntity = 'WM_OUT'
				IF Transition EQ True$  THEN
					IF HoldType = 'HOLD' THEN
						Subject	= 'Material Placed on Hold ':HoldEntityID
						Message = 'Material  Placed on Hold'
					END ELSE
						Subject	= 'Material Placed on Ship Hold ':HoldEntityID
						Message = 'Material  Placed on Ship Hold'
					END
				END ELSE
					IF HoldType = 'HOLD' THEN
						Subject	= 'Material Taken off Hold ':HoldEntityID
						Message = 'Material  Taken off Hold'
					END ELSE
						Subject	= 'Material Taken off Ship Hold ':HoldEntityID
						Message = 'Material  Taken off Ship Hold'
					END
				END
				
				AttachWindow	= HoldEntity
				AttachKey		= HoldEntityID
				
		END CASE
		Message := ' - ':Reason
		
		IF HoldType = 'SHOLD' THEN
			
			Recipients		= XLATE('NOTIFICATION','SHIP_HOLD',NOTIFICATION_USER_ID$,'X')
			If OperatorID NE '' then
				SentFrom = OperatorID
			end else
				SentFrom = @USER4
			end
			
			SendToGroup		= ''   
			
			Parms = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
			obj_Notes('Create',Parms)
			
		END
		
		Recipients		= XLATE('NOTIFICATION','RDS_HOLD',NOTIFICATION_USER_ID$,'X')
		If OperatorID NE '' then
			SentFrom = OperatorID
		end else
			SentFrom = @USER4
		end
		
		SendToGroup		= ''   
		
		Parms = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
		obj_Notes('Create',Parms)
	end
	
end service


//----------------------------------------------------------------------------------------------------------------------
// EditHoldReason
//
// WOMatKey	  - [Required]
// ColName	  - [Required]
// ColValNo   - [Required]
// UpdatedText - [Required]
//
// Edits the reason for a lot's hold status.
//----------------------------------------------------------------------------------------------------------------------
Service EditHoldReason(WOMatKey, ColName, ColValNo, UpdatedText)
	
	IF WOMatKey = '' OR ColName = '' OR ColValNo = '' OR UpdatedText = '' THEN
		Error_Services('Add', 'Null parameter WOMatKey, ColName, ColValNo, or UpdatedText passed to service.')
	end else
		WOMatRec = Database_Services("ReadDataRow", "WO_MAT", WOMatKey, "", "", "")
		If Error_Services("NoError") then
			WOMatRec = Database_Services("ReadDataRow", "WO_MAT", WOMatKey, "", "", FALSE$)
			
			IF INDEX(ColName,'START',1)  THEN
				HoldStartReason		= WOMatRec<WO_MAT_HOLD_START_REASON$,ColValNo>
				WOMatRec<WO_MAT_HOLD_START_REASON$,ColValNo> = UpdatedText
			END ELSE
				IF INDEX(ColName,'STOP',1)  THEN
					HoldStopReason                              = WOMatRec<WO_MAT_HOLD_STOP_REASON$,ColValNo>
					WOMatRec<WO_MAT_HOLD_STOP_REASON$,ColValNo> = UpdatedText
				END
			END
			
			Database_Services("WriteDataRow", "WO_MAT", WoMatKey, WOMatRec, "", "", "")
		end else
			Respose = Error_Services("GetMessage")
		end
	end
	
End Service


//----------------------------------------------------------------------------------------------------------------------
// CreateComment
//
// HoldEntity	- [Required]
// HoldEntityID - [Required]
// Reason		- [Required]
// Transition   - [Required]
// HoldType		- [Required]
//
// Creates a HoldEntity comment marking changes in lot holds.
//----------------------------------------------------------------------------------------------------------------------
Service CreateComment(HoldEntity, HoldEntityID, Reason, Transition, HoldType, OperatorID)
	
	IF HoldEntity = '' or HoldEntityID = '' or Reason = '' or Transition = '' or HoldType = '' THEN
		Error_Services('Add', 'Null parameter WOMatKey, HoldEntity, HoldEntityID, HoldType, or HoldData passed to service.')
	end else
		BEGIN CASE
				
			CASE HoldEntity = 'WO_MAT' OR HoldEntity = 'RDS'
				If HoldEntity = 'WO_MAT' then
					RDSNo = Xlate('WO_MAT', HoldEntityID, 'RDS_NO', 'X', '')
				end else
					RDSNo = HoldEntityID
				end
				IF Transition EQ True$  THEN
					IF HoldType = 'HOLD' THEN
						Subject	= 'Material Placed on Hold ':HoldEntityID : ' by user ': OperatorID 
					END ELSE
						Subject	= 'Material Placed on Ship Hold ':HoldEntityID : ' by user ': OperatorID 
					END
				END ELSE
					IF HoldType = 'HOLD' THEN
						Subject	= 'Material Taken off Hold ':HoldEntityID : ' by user ': OperatorID 
					END ELSE
						Subject	= 'Material Taken off Ship Hold ':HoldEntityID : ' by user ': OperatorID 
					END
				END
				Subject := ' - ':Reason
				Rds_Services('AddComment', RDSNo, Subject, '')
				
				
			CASE HoldEntity = 'WM_IN'
				
				IF Transition EQ True$  THEN
					Subject	= 'Material Placed on Hold ':HoldEntityID : ' by user ': OperatorID 
				END ELSE
					Subject	= 'Material Taken off Hold ':HoldEntityID : ' by user ': OperatorID 
				END 
				Subject := ' - ':Reason
				Wm_In_Services('AddComment', HoldEntityID, Subject)
				
			CASE HoldEntity = 'WM_OUT'
				IF Transition EQ True$  THEN
					IF HoldType = 'HOLD' THEN
						Subject	= 'Material Placed on Hold ':HoldEntityID : ' by user ': OperatorID 
					END ELSE
						Subject	= 'Material Placed on Ship Hold ':HoldEntityID : ' by user ': OperatorID 
					END
				END ELSE
					IF HoldType = 'HOLD' THEN
						Subject	= 'Material Taken off Hold ':HoldEntityID : ' by user ': OperatorID 
					END ELSE
						Subject	= 'Material Taken off Ship Hold ':HoldEntityID : ' by user ': OperatorID 
					END
				END
				Subject := ' - ':Reason
				Wm_Out_Services('AddComment', HoldEntityID, Subject)
		END CASE
	end
	
end service


