diff --git a/LSL2/STPROC/LOT_EVENT_SERVICES.txt b/LSL2/STPROC/LOT_EVENT_SERVICES.txt index 01eec8e..71b0cc2 100644 --- a/LSL2/STPROC/LOT_EVENT_SERVICES.txt +++ b/LSL2/STPROC/LOT_EVENT_SERVICES.txt @@ -1,16 +1,64 @@ Compile function Lot_Event_Services(@Service, @Params) +/*********************************************************************************************************************** + + Name : Lot_Event_Services + + Description : Handler program for all LOT_EVENT 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) + 07/01/25 djs Modified CreateLotEvent to use Transaction Queue instead of Proc Queue to avoid locking + errors on LOT table. Updated error throwing. + +***********************************************************************************************************************/ #pragma precomp SRP_PreCompiler -Declare function Error_Services, Logging_Services, Environment_Services, Database_Services, RTI_CreateGUID, Lot_Services -Declare function Lot_Event_Services - -Declare subroutine Error_Services, Logging_Services, Database_Services, Lot_Services, Service_Services - -$insert LOGICAL +$Insert SERVICE_SETUP +$insert APP_INSERTS $Insert LOT_EVENT_EQUATES $Insert LOT_EQUATES $Insert LOT_OPERATION_EQUATES +Declare function Error_Services, Logging_Services, Environment_Services, Database_Services, RTI_CreateGUID +Declare function Lot_Event_Services, Lot_Services +Declare subroutine Error_Services, Logging_Services, Database_Services, Lot_Services, Service_Services +Declare subroutine Transaction_Services + Options EVENT_TYPES = 'MOVE_IN', 'MOVE_OUT', 'HOLD_ON', 'HOLD_OFF', 'REDUCE_WAFER_QTY', 'BONUS_WAFER_QTY', 'COMMENT', 'LOCATION', 'LOAD', 'UNSIGN_LOAD', 'TW_USE', 'CLOSE', 'SIGN_FQA', 'UNSIGN_FQA' Options LOT_TYPES = 'TW', 'RDS', 'WM_OUT', 'WM_IN', 'WO_MAT', 'LOT' Options LEGACY_LOT_TYPES = 'RDS', 'WM_OUT', 'WM_IN' @@ -20,152 +68,165 @@ GoToService Return Response or "" -//----------------------------------------------------------------------------- -// SERVICES -//----------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------------- +// Services +//---------------------------------------------------------------------------------------------------------------------- Service CreateLotEvent(LotId, EventDateTime, EventType=EVENT_TYPES, EventNote, EventEquipmentId, OperatorId, IsLegacyLotId=BOOLEAN, LegacyLotType=LEGACY_LOT_TYPES) - - GoSub InitEventLog - ErrorMessage = '' - //Handle Legacy Lots - If IsLegacyLotId then - If LegacyLotType NE '' then - LegacyLotId = LotId - LotId = Lot_Services('GetLotIdByLegacyLotIdAndType', LotId, LegacyLotType) - If LotID EQ '' then - LotId = Lot_Services('CreateNewLot', LegacyLotType, '', '', '', '', '', OperatorId, '', LegacyLotId) - end - end else - LotId = '' - end - end - If RowExists('LOT', LotId) then - NewEventId = RTI_CreateGUID() - If NewEventId NE '' then - NewEventSequence = Lot_Event_Services('GetLotEventNextSequence', LotId) - If Error_Services('NoError') then - NewEventRec = '' - NewEventRec = LotId - NewEventRec = EventType - NewEventRec = EventDatetime - NewEventRec = EventNote - NewEventRec = EventEquipmentId - NewEventRec = OperatorId - NewEventRec = NewEventSequence - Database_Services('WriteDataRow', 'LOT_EVENT', NewEventId, NewEventRec) - If Error_Services('NoError') then - Service_Services('PostProcedure', 'LOT_EVENT_SERVICES', 'SetLatestLotEvent':@VM:LotId:@VM:NewEventId) - end else - ErrorMessage = 'Error creating new event : ' : Error_Services('GetMessage') - end - end else - ErrorMessage = Error_Services('GetMessage') - end - end else - ErrorMessage = 'Error creating an event Id.' - end - end else - ErrorMessage = 'Error in Create Lot Event routine, Lot id was not found.' - end - If ErrorMessage EQ '' then - LogData = '' - LogData<1> = LoggingDTM - LogData<2> = LotId - LogData<3> = EventType - LogData<4> = OperatorId - LogData<9> = 'Successfully logged event.' - Logging_Services('AppendLog', objLotEventLog, LogData, @RM, @FM, False$) - end else - LogData = '' - LogData<1> = LoggingDTM - LogData<2> = LotId - LogData<3> = EventType - LogData<4> = OperatorId - LogData<9> = ErrorMessage - Logging_Services('AppendLog', objLotEventLog, LogData, @RM, @FM, False$) - Error_Services('Add', ErrorMessage) - end - + + GoSub InitEventLog + ErrorMessage = '' + // Handle Legacy Lots + If IsLegacyLotId then + If LegacyLotType NE '' then + LegacyLotId = LotId + LotId = Lot_Services('GetLotIdByLegacyLotIdAndType', LotId, LegacyLotType) + If LotID EQ '' then + LotId = Lot_Services('CreateNewLot', LegacyLotType, '', '', '', '', '', OperatorId, '', LegacyLotId) + end + end else + LotId = '' + end + end + If RowExists('LOT', LotId) then + NewEventId = RTI_CreateGUID() + If NewEventId NE '' then + NewEventSequence = Lot_Event_Services('GetLotEventNextSequence', LotId) + If Error_Services('NoError') then + NewEventRec = '' + NewEventRec = LotId + NewEventRec = EventType + NewEventRec = EventDatetime + NewEventRec = EventNote + NewEventRec = EventEquipmentId + NewEventRec = OperatorId + NewEventRec = NewEventSequence + Database_Services('WriteDataRow', 'LOT_EVENT', NewEventId, NewEventRec) + If Error_Services('NoError') then + Transaction_Services('PostWriteFieldTransaction', 'LOT', LotId, LOT_MOST_RECENT_LOT_EVENT_ID$, NewEventId) + If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage') + end else + ErrorMessage = 'Error creating new event : ' : Error_Services('GetMessage') + end + end else + ErrorMessage = Error_Services('GetMessage') + end + end else + ErrorMessage = 'Error creating an event Id.' + end + end else + ErrorMessage = 'Error in Create Lot Event routine, Lot id was not found.' + end + If ErrorMessage EQ '' then + LogData = '' + LogData<1> = LoggingDTM + LogData<2> = LotId + LogData<3> = EventType + LogData<4> = OperatorId + LogData<9> = 'Successfully logged event.' + Logging_Services('AppendLog', objLotEventLog, LogData, @RM, @FM, False$) + end else + LogData = '' + LogData<1> = LoggingDTM + LogData<2> = LotId + LogData<3> = EventType + LogData<4> = OperatorId + LogData<9> = ErrorMessage + Logging_Services('AppendLog', objLotEventLog, LogData, @RM, @FM, False$) + Error_Services('Add', ErrorMessage) + end + end service + Service GetLotEventNextSequence(LotId) - - ErrorMessage = '' - NextSequence = 1 - If LotID NE '' then - If RowExists('LOT', LotId) then - LotEvents = XLATE('LOT', LotId, LOT_LOT_EVENTS$, 'X') - for each LotEvent in LotEvents using @VM - ThisEventSequence = XLATE('LOT_EVENT', LotEvent, LOT_EVENT_SEQUENCE$, 'X') - If ThisEventSequence GE NextSequence then NextSequence = ThisEventSequence + 1 - Next LotEvent - end else - ErrorMessage = 'Unable to get lot event sequence: Lot ID not found.' - end - end else - ErrorMessage = 'Unable to get lot event sequence: Lot ID was null.' - end - If ErrorMessage EQ '' then - Response = NextSequence - end else - Error_Services('Add', ErrorMessage) - end + + ErrorMessage = '' + NextSequence = 1 + If LotID NE '' then + If RowExists('LOT', LotId) then + LotEvents = XLATE('LOT', LotId, LOT_LOT_EVENTS$, 'X') + for each LotEvent in LotEvents using @VM + ThisEventSequence = XLATE('LOT_EVENT', LotEvent, LOT_EVENT_SEQUENCE$, 'X') + If ThisEventSequence GE NextSequence then NextSequence = ThisEventSequence + 1 + Next LotEvent + end else + ErrorMessage = 'Unable to get lot event sequence: Lot ID not found.' + end + end else + ErrorMessage = 'Unable to get lot event sequence: Lot ID was null.' + end + If ErrorMessage EQ '' then + Response = NextSequence + end else + Error_Services('Add', ErrorMessage) + end + end service -//Returns a @FM delimited list of events in sequence + +// Returns a @FM delimited list of events in sequence Service GetLotEventsInSequence(LotId) - LotEventsUnsorted = '' - LotEventsSorted = '' - LotEventsToReturn = '' - If LotID NE '' then - //Get Operations - LotEvents = Xlate('LOT', LotId, LOT_LOT_EVENTS$, 'X') - for each LotEvent in LotEvents using @VM - ThisEventSequence = XLATE('LOT_EVENT', LotEvent, LOT_EVENT_SEQUENCE$, 'X') - LotEventsToReturn = LotEvent - Next LotOperation - end else - //error: lot id was null - end - Response = LotEventsToReturn + + ErrorMsg = '' + LotEventsUnsorted = '' + LotEventsSorted = '' + LotEventsToReturn = '' + If LotID NE '' then + // Get Operations + LotEvents = Xlate('LOT', LotId, LOT_LOT_EVENTS$, 'X') + for each LotEvent in LotEvents using @VM + ThisEventSequence = XLATE('LOT_EVENT', LotEvent, LOT_EVENT_SEQUENCE$, 'X') + LotEventsToReturn = LotEvent + Next LotOperation + end else + ErrorMsg = 'Error in ':Service:' service. Null LotID passed into service.' + end + + If ErrorMsg EQ '' then + Response = LotEventsToReturn + end else + Error_Services('Add', ErrorMsg) + end + end service + Service SetLatestLotEvent(LotId, LotEventId) - - ErrorMessage = '' - If RowExists('LOT', LotId) then - If RowExists('LOT_EVENT', LotEventId) then - LotRec = Database_Services('ReadDataRow', 'LOT', LotId, True$, 0, False$) - LotRec = LotEventId - Database_Services('WriteDataRow', 'LOT', LotId, LotRec) - If Error_Services('HasError') then - ErrorMessage = Error_Services('GetMessage') - end - end else - ErrorMessage = 'Lot event ' : LotEventId : ' for lot ' : LotId : ' not found in LOT_EVENT table' - end - end else - ErrorMessage = 'Lot Id ' : LotId : ' not found in LOT table.' - end - If ErrorMessage NE '' then - Error_Services('Add', ErrorMessage) - end + + ErrorMessage = '' + If RowExists('LOT', LotId) then + If RowExists('LOT_EVENT', LotEventId) then + LotRec = Database_Services('ReadDataRow', 'LOT', LotId, True$, 0, False$) + LotRec = LotEventId + Database_Services('WriteDataRow', 'LOT', LotId, LotRec) + If Error_Services('HasError') then + ErrorMessage = Error_Services('GetMessage') + end + end else + ErrorMessage = 'Lot event ' : LotEventId : ' for lot ' : LotId : ' not found in LOT_EVENT table' + end + end else + ErrorMessage = 'Lot Id ' : LotId : ' not found in LOT table.' + end + If ErrorMessage NE '' then Error_Services('Add', ErrorMessage) + end service -/* * * * * * * * * * -* INTERNAL GOSUBS -* * * * * * * * * */ + +//---------------------------------------------------------------------------------------------------------------------- +// Internal GoSubs +//---------------------------------------------------------------------------------------------------------------------- InitEventLog: - - LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\Lot' - LogDate = Oconv(Date(), 'D4/') - LogTime = Oconv(Time(), 'MTS') - LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM - LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' LotEvent.csv' - Headers = 'Logging DTM' : @FM : 'Lot Id' : @FM : 'Event Type' : @FM : 'Operator' : @FM : 'Begin Wafer Qty' : @FM : 'End Wafer Qty' : @FM : 'Bonus Wafer Qty' : @FM : 'Reduce Wafer Qty' : @FM : 'Message' - objLotEventLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ',', Headers, '', False$, False$) - + + LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\Lot' + LogDate = Oconv(Date(), 'D4/') + LogTime = Oconv(Time(), 'MTS') + LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM + LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' LotEvent.csv' + Headers = 'Logging DTM' : @FM : 'Lot Id' : @FM : 'Event Type' : @FM : 'Operator' : @FM : 'Begin Wafer Qty' : @FM : 'End Wafer Qty' : @FM : 'Bonus Wafer Qty' : @FM : 'Reduce Wafer Qty' : @FM : 'Message' + objLotEventLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ',', Headers, '', False$, False$) + return