Compile function Lot_Operation_Services(@Service, @Params) #pragma precomp SRP_PreCompiler Declare function Lot_Services, Database_Services, Error_Services, Srp_Sort_Array, Lot_Operation_Services Declare function RTI_CreateGUID, MemberOf, SRP_JSON, Operation_Services, Datetime, Met_Test_Services, PSN_Services Declare function Date_Services, SRP_Stopwatch Declare subroutine Database_Services, Error_Services, SRP_JSON, Lot_Services, Lot_Event_Services, Lot_Operation_Services, SRP_Stopwatch $insert LOGICAL $insert LOT_EQUATES $Insert LOT_OPERATION_EQUATES $Insert OPERATION_EQUATES $Insert MET_TEST_EQUATES $Insert WAFER_COUNTER_EQUATES Options OPERATION_TYPE = 'CLEAN', 'THICK_METROLOGY', 'RES_METROLOGY', 'SURFACE_METROLOGY', 'VISUAL_INSPECTION', 'PACKAGING' GoToService Return Response or "" //----------------------------------------------------------------------------- // SERVICES //----------------------------------------------------------------------------- Service AddOperationToLot(LotId, OperationId, PrescribedSequence, UserId) Operation = '' ErrorMessage = '' If RowExists('LOT', LotId) then If RowExists('OPERATION', OperationId) then OperationActive = XLATE('OPERATION', OperationId, OPERATION_ACTIVE$, 'X') If OperationActive then If PrescribedSequence AND Num(PrescribedSequence) then If Lot_Services('CanUserModifyLot', UserId) then LotCurrOperation = Lot_Services('GetLotCurrOperationId', LotId) CurrOperationSequence = Xlate('LOT_OPERATION', LotCurrOperation, LOT_OPERATION_OPERATION_SEQUENCE$, 'X') If CurrOperationSequence LT PrescribedSequence then //Get Curr Operation Sequence Done = False$ LotCurrOperationSequence = Lot_Services('GetLotOperationSequence', LotId) for each Operation in LotCurrOperationSequence using @Fm setting OpPos ThisOperationRec = Database_Services('ReadDataRow', 'LOT_OPERATION', Operation) ThisOperationSequence = ThisOperationRec If ThisOperationSequence GE PrescribedSequence then NewOperationSequence = ThisOperationSequence + 1 ThisOperationRec = NewOperationSequence Database_Services('WriteDataRow', 'LOT_OPERATION', Operation, ThisOperationRec) If Error_Services('HasError') then Done = True$ ErrorMessage = Error_Services('GetMessage') end end Until Done Next Operation If ErrorMessage EQ '' then LotOperationRecID = RTI_CreateGUID() If Not(RowExists('LOT_OPERATION', LotOperationRecID)) then OperationRec = Database_Services('ReadDataRow', 'OPERATION', OperationId) Class = OperationRec Type = OperationRec Rework = OperationRec ThisNewOperationRec = Database_Services('ReadDataRow', 'OPERATION', OperationId) LotOperationRec = '' LotOperationRec = LotId LotOperationRec = OperationId LotOperationRec = PrescribedSequence LotOperationRec = Rework LotOperationRec = Type LotOperationRec = Class LotOperationRec = OperationRec LotOperationRec = OperationRec LotOperationRec = OperationRec LotOperationRec = OperationRec LotOperationRec = OperationRec IsOperationRework = Database_Services('ReadDataColumn', 'OPERATION', OperationId, OPERATION_REWORK$) Database_Services('WriteDataRow', 'LOT_OPERATION', LotOperationRecId, LotOperationRec) If Error_Services('NoError') then OperationDesc = XLATE('OPERATION', OperationId, OPERATION_OPERATION_DESCRIPTION$, 'X') Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'ADD_LOT_OPERATION', 'Added operation ' : Quote(OperationDesc) : ' to lot.', '', UserId) end else ErrorMessage = Error_Services('GetMessage') end end else ErrorMessage = 'Lot Operation already existed, cannot overwrite' end end end else ErrorMessage = 'Not allowed to add new operations prior to current operation' end end else ErrorMessage = 'User ' : UserId : ' does not have permission to modify lots.' end end else ErrorMessage = 'Invalid operation sequence entered.' end end else ErrorMessage = 'Operation is inactive. Unable to add.' end end else ErrorMessage = 'Operation ' : OperationId : 'not found in OPERATION table.' end end else ErrorMessage = 'Lot ' : LotId : ' not found in LOT table.' end If ErrorMessage EQ '' then Response = Operation end else Error_Services('Add', 'Error in ' : Service : '.' : ErrorMessage) end end service Service RemoveLotOperation(LotOperationId, UserId) //Todo User permission check ErrorMessage = '' Success = False$ If RowExists('LOT_OPERATION', LotOperationId) then If Lot_Services('CanUserModifyLot', UserId) then LotOperationRec = Database_Services('ReadDataRow', 'LOT_OPERATION', LotOperationId, True$, 0, False$) LotId = LotOperationRec MoveInTime = LotOperationRec MoveOutTime = LotOperationRec Sequence = LotOperationRec OperationId = LotOperationRec OperationClass = XLATE('OPERATION', OperationId, OPERATION_CLASS_ID$, 'X') If OperationClass NE 'RTF_DEFAULT' AND OperationClass NE 'RTF_DEFAULT_END' then If MoveInTime EQ '' AND MoveOutTime EQ '' then LotOperationRec = '';//Nulling this value out should disassociated the lot operation record from the lot. Database_Services('WriteDataRow', 'LOT_OPERATION', LotOperationId, LotOperationRec) If Error_Services('NoError') then Lot_Operation_Services('UpdateLotOperationSequence', LotId, Sequence) If Error_Services('NoError') then Success = True$ end else ErrorMessage = Error_Services('GetMessage') end OperationDesc = XLATE('OPERATION', OperationId, OPERATION_OPERATION_DESCRIPTION$, 'X') Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'REMOVE_LOT_OPERATION', 'Removed operation ' : Quote(OperationDesc) : ' from lot.', '', UserId) end else ErrorMessage = Error_Services('GetMessage') end end else ErrorMessage = 'Lot has already started processing on operation ' : OperationId end end else ErrorMessage = 'Unable to remove default operations.' end end else ErrorMessage = 'User ' : UserId : ' does not have permission modify lots.' end end else ErrorMessage = 'Lot Operation record not found' end If ErrorMessage NE '' then Error_Services('Add', ErrorMessage) end Response = Success end service Service UpdateLotOperationSequence(LotId, StartSequence) ErrorMessage = '' If StartSequence EQ '' then StartSequence = 1 end If RowExists('LOT', LotId) then LotOperationSequence = Lot_Services('GetLotOperationSequence', LotId) Offset = 0 for each LotOperationId in LotOperationSequence using @FM setting SeqPos If LotOperationId NE '' then ThisLotOperationRec = Database_Services('ReadDataRow', 'LOT_OPERATION', LotOperationId, True$, 0, False$) OrigSeq = ThisLotOperationRec NewSeq = OrigSeq - Offset ThisLotOperationRec = NewSeq Database_Services('WriteDataRow', 'LOT_OPERATION', LotOperationId, ThisLotOperationRec) If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage') end end else Offset += 1 end Until ErrorMessage NE '' Next LotOperation end else ErrorMessage = 'Lot Id not found' end If ErrorMessage NE '' then Error_Services('Add', 'Error in ' : Service : ' : ' : ErrorMessage) end end service Service GetAvailableSequences(LotId) AvailableSequences = '' If RowExists('LOT', LotId) then CurrentLotOperations = Lot_Services('GetLotOperationSequence', LotId) For each LotOperationId in CurrentLotOperations using @FM setting Sequence LotOperationRec = Database_Services('ReadDataRow', 'LOT_OPERATION', LotOperationId, True$, 0, False$) OperationId = LotOperationRec OperationClass = Database_Services('ReadDataColumn', 'OPERATION', OperationId, OPERATION_CLASS_ID$) StartDtm = LotOperationRec If StartDTM EQ '' then AvailableSequences<1, -1> = Sequence + 1 end Next LotOperationId end Response = AvailableSequences end service Service ConvertRecordToJson(LotOperationId) JsonString = '' objJSON = '' LotOperationRec = Database_Services('ReadDataRow', 'LOT_OPERATION', LotOperationId, True$, 0, False$) If SRP_JSON(objJSON, 'New', 'Object') then SRP_JSON(objJSON, 'SetValue', 'LotOperationId', LotOperationId) LotId = LotOperationRec LegacyLotId = Database_Services('ReadDataColumn', 'LOT', LotId, LOT_LEGACY_LOT_ID$, True$, 0, False$) SRP_JSON(objJSON, 'SetValue', 'LotOperationId', LotOperationId) SRP_JSON(objJSON, 'SetValue', 'LotId', LotId, 'String') SRP_JSON(objJSON, 'SetValue', 'LegacyLotId', LegacyLotId, 'String') SRP_JSON(objJSON, 'SetValue', 'OperationId', LotOperationRec, 'String') OperationDesc = XLATE('OPERATION', LotOperationRec, OPERATION_OPERATION_DESCRIPTION$, 'X') SRP_JSON(objJSON, 'SetValue', 'Description', OperationDesc, 'String') OperationClass = XLATE('OPERATION', LotOperationRec, OPERATION_CLASS_ID$, 'X') SRP_JSON(objJSON, 'SetValue', 'OperationClass', OperationClass) DatetimeIn = Date_Services('ConvertDateTimeToISO8601', LotOperationRec) SRP_JSON(objJSON, 'SetValue', 'DateTimeIn', DatetimeIn) DatetimeOut = Date_Services('ConvertDateTimeToISO8601', LotOperationRec) SRP_JSON(objJSON, 'SetValue', 'DateTimeOut', DatetimeOut) EquipmentId = LotOperationRec SRP_JSON(objJSON, 'SetValue', 'EquipmentId', EquipmentId) SRP_JSON(objJSON, 'SetValue', 'WaferInQty', LotOperationRec, 'Number') SRP_JSON(objJSON, 'SetValue', 'WaferOutQty', LotOperationRec, 'Number') SRP_JSON(objJSON, 'SetValue', 'OperatorInId', LotOperationRec) SRP_JSON(objJSON, 'SetValue', 'OperatorOutId', LotOperationRec) SRP_JSON(objJSON, 'SetValue', 'OperationSequence', LotOperationRec) DatetimeStart = Date_Services('ConvertDateTimeToISO8601', LotOperationRec) SRP_JSON(objJSON, 'SetValue', 'DateTimeStart', DatetimeStart) DatetimeStop = Date_Services('ConvertDateTimeToISO8601', LotOperationRec) SRP_JSON(objJSON, 'SetValue', 'DateTimeStop', DatetimeStop) SRP_JSON(objJSON, 'SetValue', 'MetTestId', LotOperationRec) SRP_JSON(objJSON, 'SetValue', 'CleanId', LotOperationRec) SRP_JSON(objJSON, 'SetValue', 'PackagingId', LotOperationRec) SRP_JSON(objJSON, 'SetValue', 'WaferCounterId', LotOperationRec) SRP_JSON(objJson, 'SetValue', 'MetTestTypeRequired', LotOperationRec, 'STRING') SRP_JSON(objJson, 'SetValue', 'MetTestRequired', LotOperationRec, 'Boolean') SRP_JSON(objJson, 'SetValue', 'PackagingRequired', LotOperationRec, 'Boolean') SRP_JSON(objJson, 'SetValue', 'CleanRequired', LotOperationRec, 'Boolean') SRP_JSON(objJson, 'SetValue', 'WaferCounterRequired', LotOperationRec, 'Boolean') PSNo = Xlate('LOT', LotId, LOT_PROD_SPEC_ID$, 'X') RecipeToolInfo = PSN_Services('GetAllMetrologyRecipes', PSNo, True$, True$, True$, True$) objRecipeInfo = '' If SRP_Json(objRecipeInfo, 'New', 'Array') then for each RecipeLine in RecipeToolInfo using @FM If SRP_Json(objRecipeLine, 'New', 'Object') then SRP_Json(objRecipeLine, 'SetValue', 'ToolClass', RecipeLine<1,1>, 'String') SRP_Json(objRecipeLine, 'SetValue', 'Recipe', RecipeLine<1,2>, 'String') SRP_Json(objRecipeLine, 'SetValue', 'Stage', RecipeLine<1,3>, 'String') SRP_Json(objRecipeInfo, 'Add', objRecipeLine) SRP_Json(objRecipeLine, 'Release') end Next RecipeLine SRP_Json(objJSON, 'Set', 'RecipeInfo', objRecipeInfo) SRP_Json(objRecipeInfo, 'Release') end SRP_JSON(objJSON, 'SetValue', 'OperationType', LotOperationRec) //Add OPERATION Object OperationJson = Operation_Services('ConvertRecordToJSON', LotOperationRec) If SRP_JSON(objOperationJson, 'Parse', OperationJson) EQ '' then SRP_Json(objJSON, 'Set', 'OperationInfo',objOperationJson) SRP_Json(objOperationJson, 'Release') end //Add Associated MET_TEST JSON Object AssocMetTestIds = LotOperationRec objAssocMetTest = '' If SRP_Json(objAssocMetTest, 'New', 'Array') then for each MetTestId in AssocMetTestIds using @VM MetTestJson = Met_Test_Services('ConvertRecordToJson', MetTestId) If SRP_Json(objMetTest, 'Parse', MetTestJson) EQ '' then SRP_Json(objAssocMetTest, 'Add', objMetTest) SRP_Json(objMetTest, 'Release') end Next MetTestId SRP_Json(objJSON, 'Set', 'AssociatedMetTests', objAssocMetTest) SRP_Json(objAssocMetTest, 'Release') end //Add Available Met Test Record RequiredClasses = LotOperationRec AvailMetTestIds = '' ThisOperationDTMIn = LotOperationRec ThisOperationDTMOut = LotOperationRec if RequiredClasses NE '' AND DatetimeIn NE '' AND DatetimeOut EQ '' then AvailMetTestIds = Met_Test_Services('GetMetTests', LotId, LegacyLotId, '', True$, RequiredClasses, ThisOperationDTMIn, ThisOperationDTMOut) end objAvailMetTest = '' If SRP_Json(objAvailMetTest, 'New', 'Array') then if AvailMetTestIds NE '' then for each MetTestId in AvailMetTestIds using @VM SRP_Stopwatch('Start', 'MetTestJson') MetTestJson = Met_Test_Services('ConvertRecordToJson', MetTestId) SRP_Stopwatch('Stop', 'MetTestJson') totalTime = SRP_Stopwatch('GetBenchmark', 'MetTestJson') If SRP_Json(objMetTest, 'Parse', MetTestJson) EQ '' then SRP_Json(objAvailMetTest, 'Add', objMetTest) SRP_Json(objMetTest, 'Release') end Next MetTestId end SRP_Json(objJSON, 'Set', 'AvailMetTests', objAvailMetTest) SRP_Json(objAvailMetTest, 'Release') end //Add in relevant recipes Recipes = '' ShowThickRecipes = False$ ShowResRecipes = False$ ShowCleanRecipes = False$ ShowSurfscanRecipes = False$ IsMetTestReqd = LotOperationRec IsCleanRequired = LotOperationRec If IsMetTestReqd then MetTestTypeRequired = LotOperationRec Begin Case Case MetTestTypeRequired EQ 'TENCOR' ShowSurfscanRecipes = True$ Case MetTestTypeRequired EQ 'THICK' ShowThickRecipes = True$ Case MetTestTypeRequired EQ 'RES' ShowResRecipes = True$ End Case end If IsCleanRequired then ShowCleanRecipes = True$ end ProdSpecNo = XLATE('LOT', LotId, LOT_PROD_SPEC_ID$, 'X') Recipes = PSN_Services('GetAllMetrologyRecipes', ProdSpecNo, ShowSurfscanRecipes, ShowCleanRecipes, ShowResRecipes, ShowThickRecipes) If SRP_JSON(objRecipes, 'New', 'Array') then for each Recipe in Recipes using @FM //ToolClass : @VM : Recipe : @VM : Stage ToolClass = Recipe<1,1> RecipeName = Recipe<1,2> Stage = Recipe<1,3> If SRP_JSON(objRecipe, 'New', 'Object') then SRP_JSON(objRecipe, 'SetValue', 'ToolClass', ToolClass, 'String') SRP_JSON(objRecipe, 'SetValue', 'RecipeName', RecipeName, 'String') SRP_JSON(objRecipe, 'SetValue', 'StageName', Stage, 'String') SRP_JSON(objRecipes, 'Add', objRecipe) SRP_JSON(objRecipe, 'Release') end Next Recipe SRP_JSON(objJSON, 'Set', 'RecipeParams', objRecipes) SRP_JSON(objRecipes, 'Release') end JsonString = SRP_JSON(objJSON, 'Stringify', 'Fast') SRP_JSON(objJSON, 'Release') end Response = JsonString end service Service StartLotOperation(LotOperationId, UserId) ErrorMessage = '' If RowExists('LOT_OPERATION', LotOperationId) then If RowExists('LSL_USERS', UserId) then //We can also add additional checks like security checks, training checks, etc here if needed. LotOperationRec = Database_Services('ReadDataRow', 'LOT_OPERATION', LotOperationId, True$, 0, False$) LotId = LotOperationRec LotCurrentLotOpId = Lot_Services('GetLotCurrOperationId', LotId) If LotOperationId EQ LotCurrentLotOpId then LotMovedIn = Lot_Services('IsLotMovedIn', LotId) If Not(LotMovedIn) then Lot_Services('MoveInLot', LotId, UserId) If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage') end end else ErrorMessage = 'Lot is already moved into this operation.' end end else end end else ErrorMessage = 'Invalid user passed to routine.' end end else ErrorMessage = 'Invalid Lot Operation passed to routine.' end If ErrorMessage EQ '' then Response = True$ end else Response = False$ Error_Services('Add', 'Error in ' : Service : '. ' : ErrorMessage) end end service Service CompleteLotOperation(LotOperationId, UserId) ErrorMessage = '' If RowExists('LOT_OPERATION', LotOperationId) then If RowExists('LSL_USERS', UserId) then //We can also add additional checks like security checks, training checks, etc here if needed. LotOperationRec = Database_Services('ReadDataRow', 'LOT_OPERATION', LotOperationId, True$, 0, False$) LotId = LotOperationRec LotCurrentLotOpId = Lot_Services('GetLotCurrOperationId', LotId) If LotOperationId EQ LotCurrentLotOpId then LotMovedIn = Lot_Services('IsLotMovedIn', LotId) If LotMovedIn then //Perform Validation for the particular operation here. OperationValid = Lot_Operation_Services('ValidateLotOperation', LotOperationId) If OperationValid then Lot_Services('MoveOutLot', LotId, UserId) If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage') end end else ErrorMessage = 'Lot Operation has not finished processing and cannot be moved out.' end end else ErrorMessage = 'Cannot complete operation because lot is not currently moved in.' end end else CurrOperationId = Xlate('LOT_OPERATION', LotCurrentLotOpId, LOT_OPERATION_OPERATION_ID$, 'X') CurrOperationDesc = Xlate('OPERATION', CurrOperationId, OPERATION_OPERATION_DESCRIPTION$, 'X') ErrorMessage = 'Cannot complete operation. Lot is currently at ' : CurrOperationDesc end end else ErrorMessage = 'Invalid user passed to routine.' end end else ErrorMessage = 'Invalid Lot Operation passed to routine.' end If ErrorMessage EQ '' then Response = True$ end else Response = False$ Error_Services('Add', ErrorMessage) end end service Service ValidateLotOperation(LotOperationId) ErrorMessage = '' IsValid = True$ If RowExists('LOT_OPERATION', LotOperationId) then LotOperationRec = Database_Services('ReadDataRow', 'LOT_OPERATION', LotOperationId, True$, 0, False$) OperationId = LotOperationRec MetTestRequired = LotOperationRec MetTestTypeRequired = LotOperationRec PackagingRequired = LotOperationRec CleanRequired = LotOperationRec WaferCountRequired = LotOperationRec OperationClass = XLATE('OPERATION', OperationId, OPERATION_CLASS_ID$, 'X') If MetTestRequired then MetTestsInSpec = True$ AssociatedMetTestIds = LotOperationRec If AssociatedMetTestIds NE '' then for each MetTestId in AssociatedMetTestIds using @VM MetTestOoS = Database_Services('ReadDataColumn', 'MET_TEST', MetTestId, MET_TEST.OUT_OF_SPEC$, True$, 0, False) If MetTestOoS AND OperationClass NE 'RTF' AND OperationClass NE 'RTF_DEFAULT' then MetTestsInSpec = False$ ErrorMessage = 'An associated Met test record is out of spec.' end Until MetTestsInSpec EQ False$ Next MetTestId end else IsValid = False$ ErrorMessage = 'Met tests are required and none are assigned.' end end If PackagingRequired AND IsValid then AssociatedPackagingIds = LotOperationRec If AssociatedPackagingIds NE '' then end else IsValid = False$ end end If CleanRequired AND IsValid then AssociatedCleanIds = LotOperationRec If AssociatedCleanIds NE '' then IsValid = True$ end else IsValid = False$ end end If WaferCountRequired AND IsValid then AssociatedWaferCountIds = LotOperationRec If AssociatedWaferCountIds NE '' then IsValid = True$ end else IsValid = False$ end end end else ErrorMessage = 'Lot Operation not found' end If ErrorMessage NE '' then IsValid = False$ Error_Services('Add', ErrorMessage) end Response = IsValid end service