Function Work_Order_Services(@Service, @Params) /*********************************************************************************************************************** This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written permission from SRP Computer Solutions, Inc. Name : Work_Order_Services Description : Handler program for all module related services. Notes : The generic parameters should contain all the necessary information to process the services. Often this will be information like the data Record and Key ID. 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) 06/16/17 dmb Original programmer. - [EPIOI-8] 11/23/20 djs Added CreateOutbound service. ***********************************************************************************************************************/ #pragma precomp SRP_PreCompiler $insert APP_INSERTS $insert SERVICE_SETUP $insert WO_LOG_EQUATES $insert EPI_PART_EQUATES $insert WO_MAT_EQUATES $insert WO_STEP_EQUATES $insert WO_SCHEDULE_EQUATES $insert WO_SCHEDULE_NG_EQUATES $insert RDS_EQUATES $insert PROD_SPEC_EQUATES $insert PRS_LAYER_EQU $insert PROD_VER_EQUATES $insert WO_MAT_WFR_EQUATES $insert MSG_EQUATES $insert POPUP_EQUATES $insert LOGICAL $insert RLIST_EQUATES $insert COMPANY_EQUATES $Insert NOTIFICATION_EQUATES $Insert WM_IN_EQUATES $Insert WM_OUT_EQUATES Declare subroutine Error_Services, Work_Order_Services, Memory_Services, RList, Database_Services, SRP_JSON Declare subroutine Btree.Extract, Set_Status, obj_WO_Log, obj_Notes, Print_Wo_Mat_In_Labels, Print_Wo_Mat_Out_Labels Declare subroutine Print_Wmi_Labels, Print_Wmo_Labels, ErrMsg, Print_Cass_Labels, Logging_Services, Service_Services Declare subroutine obj_WO_Mat_Log, WO_Mat_Services, Work_Order_Services Declare function SRP_Array, Work_Order_Services, Memory_Services, Database_Services, SRP_Sort_Array, SRP_JSON Declare function Company_Services, obj_Prod_Spec, Schedule_Services, Datetime, obj_WO_Log, obj_WO_Step, Memberof Declare function Environment_Services, Logging_Services, Hold_Services, Signature_Services 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] : ' Release Log.csv' Headers = 'Logging DTM' : @FM : 'User' : @FM : 'Notes' objReleaseLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$,',', Headers, '', False$, False$) 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] : ' Void Log.csv' Headers = 'Logging DTM' : @FM : 'User' : @FM : 'CassetteId' : @FM : 'Notes' objVoidLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$,',', Headers, '', False$, False$) LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM GoToService else Error_Services('Set', Service : ' is not a valid service request within the ' : ServiceModule : ' services module.') end Return Response else '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Service Parameter Options //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Options BOOLEAN = True$, False$ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Services //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------------------------------------------- // GetUnscheduledWorkOrders // // Returns an array of unscheduled work order details based on the arguments provided. //---------------------------------------------------------------------------------------------------------------------- Service GetUnscheduledWorkOrders(ReactorType, SusceptorSize, ReactorNo) WorkOrders = '' // Select WO_LOG rows that do not have a closed date. OpenWOLogKeyIDs = Database_Services('SearchIndex', 'WO_LOG', 'CLOSE_DATE', '=', True$) // Check each WO_LOG Key ID against the WO_SCHEDULE table. If the row does not exist or if the row does not have any // SCED_DET Key IDs, exists then it is not scheduled an should be included. WOLogKeyIDs = Str(\00\, 100000) If OpenWOLogKeyIDs NE '' then hWOSchedule = Database_Services('GetTableHandle', 'WO_SCHEDULE') If Error_Services('NoError') then cPos = 1 For Each WOLogKeyID in OpenWOLogKeyIDs using @FM Read WOScheduleRow from hWOSchedule, WOLogKeyID then If WOScheduleRow EQ '' then WOLogKeyIDs[cPos, Len(WOLogKeyID) + 1] = WOLogKeyID : @FM cPos += Len(WOLogKeyID) + 1 end end else WOLogKeyIDs[cPos, Len(WOLogKeyID) + 1] = WOLogKeyID : @FM cPos += Len(WOLogKeyID) + 1 end Next WOLogKeyID end end Convert \00\ to '' in WOLogKeyIDs WOLogKeyIDs[-1, 1] = '' If Error_Services('NoError') then For Each WOLogKeyID in WOLogKeyIDs using @FM setting fPos WOLogRow = Database_Services('ReadDataRow', 'WO_LOG', WOLogKeyID) EpiPartNo = WOLogRow ProdVerNo = WOLogRow ProdVerRow = Database_Services('ReadDataRow', 'PROD_VER', ProdVerNo) PSN = ProdVerRow ProdSpecRow = Database_Services('ReadDataRow', 'PROD_SPEC', PSN) BlockedReactors = ProdSpecRow PSNBlock = False$ If EpiPartNo NE '' then AcceptWorkOrder = True$ ; // Assume this work order is acceptable for now. ReactType = WOLogRow // The following two lines of code are temporary but necessary to allows work orders // for ASM to be scheduled on ASM+ and vice-versa. If ReactType _EQC 'ASM+' then ReactType = 'ASM' If ReactorType _EQC 'ASM+' then ReactorType = 'ASM' If (ReactorType NE '') AND (ReactType NE ReactorType) then // The reactor type for this work order does not match the required reactor type. AcceptWorkOrder = False$ end If AcceptWorkOrder AND SusceptorSize NE '' then EpiPart = Database_Services('ReadDataRow', 'EPI_PART', EpiPartNo) SuscSize = EpiPart If SuscSize NE SusceptorSize then // The susceptor size for this work order does not match the required susceptor size. AcceptWorkOrder = False$ end end If (BlockedReactors NE '') AND (ReactorNo NE '') then // This work order uses a part spec that is blocked on the current reactor. Locate ReactorNo in BlockedReactors using @VM setting vPos then PSNBlock = True$ end If AcceptWorkOrder then CustNo = WOLogRow CompanyRow = Database_Services('ReadDataRow', 'COMPANY', CustNo) CustName = CompanyRow<42> Swap True$ with 'Yes' in PSNBlock Swap False$ with '' in PSNBlock WorkOrders := WOLogKeyID : @VM : EpiPartNo : @VM : CustName : @VM : ReactType : @VM : PSNBlock : @FM end end Next WOLogKeyID WorkOrders[-1, 1] = '' WorkOrders = SRP_Array('SortRows', WorkOrders, 'AR1' : @FM : 'AR2', 'LIST', @FM, @VM) end Response = WorkOrders end service //---------------------------------------------------------------------------------------------------------------------- // GetWorkOrderLogDetail // // Returns the WO_LOG row for the indicated Key ID. //---------------------------------------------------------------------------------------------------------------------- Service GetWorkOrderLogDetail(WorkOrderLogID) WorkOrderDetail = '' TableName = 'WO_LOG' If WorkOrderLogID NE '' then WorkOrderDetail = Database_Services('ReadDataRow', Tablename, WorkOrderLogID) end else Error_Services('Add', 'WorkOrderLogID argument was missing from the ' : Service : ' service.') end Response = WorkOrderDetail end service //---------------------------------------------------------------------------------------------------------------------- // GetWorkOrder // // Returns a JSON formatted object of information related to the indicated work order number. The ExtendedData argument // determines if extended data related to wafers, product versions, and recipe should be included. The default is false. //---------------------------------------------------------------------------------------------------------------------- Service GetWorkOrder(WorkOrderNo, ExtendedData) SRP_Stopwatch('Start', Service) If ExtendedData NE True$ then ExtendedData = False$ ServiceKeyID := '*' : WorkOrderNo WorkOrder = '' If Memory_Services('IsValueCurrent', ServiceKeyID, 15, True$) then WorkOrder = Memory_Services('GetValue', ServiceKeyID) end else If WorkOrderNo NE '' then WorkOrderRow = Database_Services('ReadDataRow', 'WO_LOG', WorkOrderNo, True$, 15) objWorkOrder = '' If SRP_JSON(objWorkOrder, 'NEW', 'OBJECT') then SRP_JSON(objWorkOrder, 'SETVALUE', 'WorkOrderNumber', WorkOrderNo, 'STRING') SRP_JSON(objWorkOrder, 'SETVALUE', 'EpiPartNumber', WorkOrderRow, 'STRING') SRP_JSON(objWorkOrder, 'SETVALUE', 'ReactorType', WorkOrderRow, 'STRING') ProdVerNo = WorkOrderRow SRP_JSON(objWorkOrder, 'SETVALUE', 'ProdVerNumber', ProdVerNo, 'STRING') TotalWafers = WorkOrderRow SRP_JSON(objWorkOrder, 'SETVALUE', 'TotalWafers', TotalWafers, 'STRING') SRP_JSON(objWorkOrder, 'SETVALUE', 'Closed', Oconv(WorkOrderRow NE '', 'BYes,No'), 'STRING') SRP_JSON(objWorkOrder, 'SETVALUE', 'ClosedDate', Oconv(WorkOrderRow, 'D4/'), 'STRING') SRP_JSON(objWorkOrder, 'SETVALUE', 'HotLot', Oconv(WorkOrderRow NE '', 'BYes,No'), 'STRING') CustomerNo = WorkOrderRow Company = Company_Services('GetCompany', CustomerNo) objCompany = '' If SRP_JSON(objCompany, 'PARSE', Company) EQ '' then SRP_JSON(objWorkOrder, 'SET', 'Company', objCompany) SRP_JSON(objCompany, 'RELEASE') end If ExtendedData EQ True$ then WafersRemaining = Work_Order_Services('GetRemainingWafers', WorkOrderNo) SRP_JSON(objWorkOrder, 'SETVALUE', 'WafersRemaining', WafersRemaining, 'STRING') If TotalWafers GT 0 then PercentComplete = (TotalWafers - WafersRemaining) / TotalWafers * 100 end else PercentComplete = 0 end PercentComplete = Oconv(Iconv(PercentComplete, 'MD2'), 'MD2%S') SRP_JSON(objWorkOrder, 'SETVALUE', 'PercentComplete', PercentComplete, 'STRING') ProdVerRow = Database_Services('ReadDataRow', 'PROD_VER', ProdVerNo, True$, 15) PSN = ProdVerRow SRP_JSON(objWorkOrder, 'SETVALUE', 'PSN', PSN, 'STRING') LayerSpecs = obj_Prod_Spec('GetLayerProp', PSN : @RM : @RM : 1) ; // Returns specs for all layers in internal format. LayerSpec = Field(LayerSpecs, @RM, 1) ; // Take the first Layer LayerSet = Field(LayerSpec, @FM, 1) ; // Not used here but shown for clarity LayerSpec = Field(LayerSpec, @FM, 2, 99) ; // LayerSpec without the LayerSet Recipe = LayerSpec SRP_JSON(objWorkOrder, 'SETVALUE', 'Recipe', Recipe, 'STRING') end WorkOrder = SRP_JSON(objWorkOrder, 'STRINGIFY', 'FAST') Memory_Services('SetValue', ServiceKeyID, WorkOrder) SRP_JSON(objWorkOrder, 'RELEASE') end else Error_Services('Add', 'Error creating objWorkOrder in the ' : Service : ' service.') end end else Error_Services('Add', 'WorkOrder argument was missing from the ' : Service : ' service.') end end Response = WorkOrder SRP_Stopwatch('Stop', Service) end service //---------------------------------------------------------------------------------------------------------------------- // GetRemainingWafers // // Returns the number of remaining wafers needed to be scheduled for the indicated work order. //---------------------------------------------------------------------------------------------------------------------- Service GetRemainingWafers(WorkOrderNo) RemainingWafers = '' If WorkOrderNo NE '' then WOLogRow = Database_Services('ReadDataRow', 'WO_LOG', WorkOrderNo) If Error_Services('NoError') then // Get the total number of unreleased work orders. TotalWafers = WOLogRow TotalReleased = 0 WOMatKeys = WOLogRow For Each WOMatKey in WOMatKeys using @VM WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey) TotalReleased += WOMatRec Next WOMatKey TotalUnreleased = TotalWafers - TotalReleased WOStepKeys = WOLogRow TotalUnprocessed = 0 If WOStepKeys NE '' then ReactorType = WOLogRow For Each WOStepKey in WOStepKeys using @VM WOStepRec = Database_Services('ReadDataRow', 'WO_STEP', WOStepKey) If Error_Services('NoError') then // Get the total released but unprocessed. If ReactorType EQ 'EPP' then // EpiPro work orders have their own way of calculating. StatusCodes = Xlate('WM_IN', WOStepRec, 'CURR_STATUS', 'X') RFWCnt = Count(StatusCodes, 'RFW') TotalUnprocessed = RFWCnt * 25 end else // All other reactor types use this method. RDSKeys = WOStepRec If RDSKeys NE '' then For Each RDSKey in RDSKeys using @VM RDSRec = Database_Services('ReadDataRow', 'RDS', RDSKey) If RDSRec EQ '' then TotalUnprocessed += 25 end Next RDSKey end end end Next WOStepKey end // Add the two. RemainingWafers = TotalUnreleased + TotalUnprocessed end end else Error_Services('Add', 'WorkOrderNo argument was missing from the ' : Service : ' service.') end Response = RemainingWafers end service ! This service should be deprecated as it returns inaccurate information for EpiPro. ! Use GetRemainingWafers service insead. //---------------------------------------------------------------------------------------------------------------------- // GetUnprocessedWafers // // Returns the number of released wafers that have not yet been processed. //---------------------------------------------------------------------------------------------------------------------- Service GetUnprocessedWafers(WorkOrderNo) RemainingWafers = '' If WorkOrderNo NE '' then WOLogRow = Database_Services('ReadDataRow', 'WO_LOG', WorkOrderNo) If Error_Services('NoError') then // Get the total number of unreleased work orders. TotalWafers = WOLogRow TotalReleased = 0 WOMatKeys = WOLogRow For Each WOMatKey in WOMatKeys using @VM WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey) TotalReleased += WOMatRec Next WOMatKey TotalUnreleased = TotalWafers - TotalReleased WOStepKeys = WOLogRow TotalUnprocessed = 0 If WOStepKeys NE '' then ReactorType = WOLogRow For Each WOStepKey in WOStepKeys using @VM WOStepRec = Database_Services('ReadDataRow', 'WO_STEP', WOStepKey) If Error_Services('NoError') then // Get the total released but unprocessed. RDSKeys = WOStepRec If RDSKeys NE '' then For Each RDSKey in RDSKeys using @VM RDSRec = Database_Services('ReadDataRow', 'RDS', RDSKey) WOMatKey = Xlate('RDS', RDSKey, 'WO_MAT_KEY', 'X') CurrStatus = Xlate('WO_MAT', WOMatKey, 'CURR_STATUS', 'X') If ( (RDSRec EQ '') and (CurrStatus NE 'REJ') and (CurrStatus NE 'MT') ) then TotalUnprocessed += RDSRec end Next RDSKey end end Next WOStepKey end // Add the two. RemainingWafers = TotalUnreleased + TotalUnprocessed end end else Error_Services('Add', 'WorkOrderNo argument was missing from the ' : Service : ' service.') end Response = RemainingWafers end service //---------------------------------------------------------------------------------------------------------------------- // GetCurrCassNo // // Returns the next cassette number to be unloaded. //---------------------------------------------------------------------------------------------------------------------- Service GetCurrCassNo(WorkOrderNo) If RowExists('WO_LOG', WorkOrderNo) then CurrCassNo = '' DateIn = '' RDSKeys = Xlate('WO_STEP', WorkOrderNo:'*1', 'RDS_KEY', 'X') NumKeys = DCount(RDSKeys, @VM) For KeyIndex = NumKeys to 1 Step -1 RDSKey = RDSKeys<0, KeyIndex> DateIn = Xlate('RDS', RDSKey, 'DATE_IN', 'X') Until DateIn NE '' Next KeyIndex If DateIn NE '' then CurrCassNo = Xlate('RDS', RDSKey, 'CASS_NO', 'X') Response = CurrCassNo end end service //---------------------------------------------------------------------------------------------------------------------- // GetLastCassOut // // Returns the last cassette number unloaded. //---------------------------------------------------------------------------------------------------------------------- Service GetLastCassOut(WorkOrderNo) If RowExists('WO_LOG', WorkOrderNo) then LastCassOut = '' DateOut = '' RDSKeys = Xlate('WO_STEP', WorkOrderNo:'*1', 'RDS_KEY', 'X') NumKeys = DCount(RDSKeys, @VM) For KeyIndex = NumKeys to 1 Step -1 RDSKey = RDSKeys<0, KeyIndex> DateOut = Xlate('RDS', RDSKey, 'DATE_OUT', 'X') Until DateOut NE '' Next KeyIndex If DateOut NE '' then LastCassOut = Xlate('RDS', RDSKey, 'CASS_NO', 'X') Response = LastCassOut end end service //---------------------------------------------------------------------------------------------------------------------- // GetNextRunNo // // Returns the next run number in the work order. //---------------------------------------------------------------------------------------------------------------------- Service GetNextRunNo(WorkOrderNo, WorkOrderStep) hSysLists = Database_Services('GetTableHandle', 'SYSLISTS') HaveLock = False$ TimeElapsed = 0 RequestTime = Time() If WorkOrderNo NE '' then Loop Lock hSysLists, ServiceKeyID then HaveLock = True$ If WorkOrderStep = '' then WorkOrderStep = 1 StepRDSNos = XLATE('WO_STEP', WorkOrderNo:'*':WorkOrderStep, 'RDS_KEY', 'X') CurrRuns = 0 NumRDS = DCount(StepRDSNos, @VM) For I = 1 to NumRDS If RowExists('RDS', StepRDSNos<1,I>) then CurrRuns += 1 end next I NextRunNo = CurrRuns + 1 Response = NextRunNo Unlock hSysLists, ServiceKeyID else Null end TimeElapsed = Time() - RequestTime Until HaveLock EQ True$ or TimeElapsed GT 60 Repeat end If TimeElapsed GT 60 then Error_Services('Add', 'Error occurred within the ':Service:' service module') end end service //---------------------------------------------------------------------------------------------------------------------- // CreateOutbound // // Creates an empty outbound cassette for a GaN work order. //---------------------------------------------------------------------------------------------------------------------- Service CreateOutbound(WONo) If WONo NE '' then WORec = Database_Services('ReadDataRow', 'WO_LOG', WONo) CassNos = WORec LastCassNo = DCount(CassNos, @VM) NextCassNo = LastCassNo + 1 LastCassID = WONo : '*' : LastCassNo NewCassID = WONo : '*' : NextCassNo SchedCassQty = Xlate('WO_MAT', LastCassID, 'SCHED_QTY', 'X') WOMatWfrRec = Database_Services('ReadDataRow', 'WO_MAT_WFR', NewCassID) If WOMatWfrRec EQ '' then for WfrCount = 1 to SchedCassQty WOMatWfrRec = NewCassID : '*' : WfrCount Next WfrCount Database_Services('WriteDataRow', 'WO_MAT_WFR', NewCassID, WOMatWfrRec) WOMatRecToCopy = Database_Services('ReadDataRow', 'WO_MAT', LastCassID) WOMatRecToCopy = '' WOMatRecToCopy = '' Database_Services('WriteDataRow', 'WO_MAT', NewCassID, WOMatRecToCopy) WORec = Insert(WORec, WO_LOG_WO_MAT_KEY$, -1, 0, NewCassID) Database_Services('WriteDataRow', 'WO_LOG', WONo, WORec) end else ErrorMessage = 'Error in service ':Service:'. WO_MAT_WFR record ':NewCassID:' already exists!' Error_Services('Add', ErrorMessage) end end end service Service UpdateUnscheduledQuantities(WOList) hSysLists = Database_Services('GetTableHandle', 'SYSLISTS') Lock hSysLists, ServiceKeyID then SchedList = Database_Services('ReadDataRow', 'APP_INFO', 'SCHED_WO_LIST') // Select WO_LOG rows that do not have a closed date. OpenWOLogKeyIDs = '' If WOList NE '' then OpenWOLogKeyIDs = WOList If OpenWOLogKeyIDs EQ '' then Open 'DICT.WO_LOG' to hWOLogDict then Set_Status(0) Flag = '' Btree.Extract('CLOSE_DATE' : @VM : '' : @FM, 'WO_LOG', hWOLogDict, OpenWOLogKeyIDs, 'S', Flag) If Flag NE 0 then Status = Get_Status(errCode) Error_Services('Add', 'Error in ':Service:' service. Error code ':errCode:'.') end end end If ( Error_Services('NoError') and (OpenWOLogKeyIDs NE '') ) then SchedList = SRP_Array('Rotate', SchedList, @FM, @VM) For Each WONo in OpenWOLogKeyIDs using @VM setting fPos UnscheduledWfrQty = Schedule_Services('GetUnscheduledWfrQty', WONo) WONos = SchedList<1> If UnscheduledWfrQty GT 0 then Locate WONo in WONos using @VM setting vPos else vPos = -1 WOLogRow = Database_Services('ReadDataRow', 'WO_LOG', WONo) EpiPartNo = WOLogRow CustNo = WOLogRow CompanyRow = Database_Services('ReadDataRow', 'COMPANY', CustNo) CustName = CompanyRow ReactorType = WOLogRow SchedList<1, vPos> = WONo SchedList<2, vPos> = EpiPartNo SchedList<3, vPos> = CustName SchedList<4, vPos> = ReactorType WOSchedRec = Database_Services('ReadDataRow', 'WO_SCHEDULE_NG', WONo) CurrVal = WOSchedRec If CurrVal NE UnscheduledWfrQty then WOSchedRec = UnscheduledWfrQty Database_Services('WriteDataRow', 'WO_SCHEDULE_NG', WONo, WOSchedRec, True$, False$, True$) end end else Locate WONo in WONos using @VM setting vPos then SchedList = Delete(SchedList, 1, vPos, 0) SchedList = Delete(SchedList, 2, vPos, 0) SchedList = Delete(SchedList, 3, vPos, 0) SchedList = Delete(SchedList, 4, vPos, 0) Database_Services('DeleteDataRow', 'WO_SCHEDULE_NG', WONo) end end Next WONo end SchedList = SRP_Array('Rotate', SchedList, @FM, @VM) If WOList EQ '' then // Clear out WO_SCHEDULE_NG table of work orders that no longer have any wafers left to schedule. EOF = False$ Query = 'SELECT WO_SCHEDULE_NG WITH UNSCHED_QTY EQ 0' RList(Query, TARGET_ACTIVELIST$, '', '', '') Loop Readnext WOLogKeyID else EOF = True$ Until EOF = True$ Database_Services('DeleteDataRow', 'WO_SCHEDULE_NG', WOLogKeyID) Repeat end SchedList = SRP_Array('SortSimpleList', SchedList, 'DescendingNumbers', @FM) Database_Services('WriteDataRow', 'APP_INFO', 'SCHED_WO_LIST', SchedList) Unlock hSysLists, ServiceKeyID else Null end end service Service ReleaseCassettes(WONo) NumRelCass = 0 ErrorMsg = '' If WONo NE '' then PSNo = Xlate('WO_LOG', WONo, 'PS_NO', 'X') PSMode = Xlate('PROD_SPEC',PSNo,'SPEC_TYPE','X') If PSMode = 'Q' OR PSMode = 'U' then ReactType = Xlate('WO_LOG', WONo, 'REACT_TYPE', 'X') If ReactType = 'EPP' OR ReactType = 'EpiPro' then OutLoadQty = Xlate('WO_LOG', WONo, 'CUST_EPI_PART_WMO_LOAD_CNT', 'X') If OutLoadQty = '' then ErrorMsg = 'Outbound Load Cnt is required for ':OCONV(PSMode,'[PROD_SPEC_MODE_CONV]'):' Work Orders.' end end else OutLoadQty = Xlate('WO_LOG', WONo, 'CUST_EPI_PART_SHIP_QTY', 'X') If OutLoadQty = '' then ErrorMsg = 'Cass Ship Qty is required for ':OCONV(PSMode,'[PROD_SPEC_MODE_CONV]'):' Work Orders.' end end end If ErrorMsg EQ '' then CassList = Xlate('WO_LOG', WONo, 'WO_MAT_CASS_NO', 'X') RelDTMs = Xlate('WO_LOG', WONo, 'WO_MAT_REL_DTM', 'X') SAPCassIDs = Xlate('WO_LOG', WONo, 'WO_MAT_CASS_ID_SAP', 'X') CassStatus = Xlate('WO_LOG', WONo, 'WO_MAT_CURR_STATUS', 'X') Loop LastLine = CassList[-1,'B':@VM] Until LastLine<1,1> NE '' OR LastLine = '' CassList[COL1(),COL2()] = '' Repeat CassCnt = DCount(CassList, @VM) UnReleasedCassNos = '' For I = 1 to CassCnt If ( (RelDTMs<0, I> = '') and (CassStatus<0, I> EQ '') ) then ErrorMsg = 'Error in obj_WO_Log("ReleaseCassettes"). Cass status is null for ':CassList<0, I>:'!' LogData = '' LogData<1> = LoggingDTM LogData<2> = @USER4 LogData<3> = ErrorMsg Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM, False$) end If ErrorMsg EQ '' then // Log work order, cassette number, status, and release DTM in the event that a release // issue occurs again. LogData = '' LogData<1> = LoggingDTM LogData<2> = @User4 LogData<3> = WONo LogData<4> = CassList<0, I> ; // CassNo LogData<5> = CassStatus<0, I> ; // Cass Status LogData<6> = Quote(RelDTMs<0, I>) ; // Release DTM Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM, False$) If ( (RelDTMs<0, I> = '') and ( (CassStatus<0, I> = 'RX') or (CassStatus<0, I> = 'MT'))) then UnReleasedCassNos<1,-1> = CassList<0, I> end end Until ErrorMsg NE '' Next I If ErrorMsg EQ '' then TempWONo = WONo Set_Status(0) obj_WO_Log('ReleaseCassettes',TempWONo:@RM:UnReleasedCassNos) ;* This variable gets changed down the line errCode = '' If Get_Status(errCode) then ErrorMsg = 'Error in obj_WO_Log("ReleaseCassettes"). Error code ':errCode:'.' Database_Services('ReleaseKeyIDLock', 'WO_LOG', WONo) end else NumRelCass = CassCnt OrderNo = Get_Property(@WINDOW:'.ORD_NO','TEXT') Recipients = XLATE('NOTIFICATION','WO_ENTRY',NOTIFICATION_USER_ID$,'X') SentFrom = @USER4 Subject = 'Work Order Released ':WONo Message = 'Work Order Released to Production.' NewForm = Xlate('APP_INFO', 'NEW_WO_FORM', '', 'X') If NewForm then AttachWindow = 'NDW_WO_LOG' end else AttachWindow = 'WO_LOG2' end AttachKey = WONo SendToGroup = '' Parms = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup obj_Notes('Create',Parms) end end end end Work_Order_Services('UpdateReleasedQty', WONo) If ErrorMsg NE '' then Error_Services('Add', ErrorMsg) Response = DCount(UnReleasedCassNos, @VM) end service Service PrintLabels(WONo) If WONo NE '' then WOSteps = XLATE('WO_LOG', WONo, WO_LOG_WO_STEP_KEY$, 'X') If INDEX(WOSteps,@VM,1) then Buttons = '' FOR I = 1 TO COUNT(WOSteps,@VM) + (WOSteps NE '') Buttons = 'Step ':I NEXT I SWAP @FM WITH ',' IN Buttons Buttons = 'B':Buttons TypeOver = '' TypeOver = 'Which Work Order step do you wish to print labels for?' TypeOver = Buttons TypeOver = '?' TypeOver = 'MultiStep WorkOrder Selection' WOStep = Msg(@window, TypeOver) MultiStepFlag = WOStep end ELSE WOStep = 1 MultiStepFlag = 0 end If WOStep = 1 then PSNo = XLATE('WO_STEP',WONo:'*1',WO_STEP_PROD_SPEC_ID$,'X') ReactorType = XLATE('PROD_SPEC',PSNo,PROD_SPEC_REACTOR_TYPE$,'X') If ReactorType = 'GAN' then Print_WO_Mat_In_Labels(WONo,'') Print_WO_Mat_Out_Labels(WONo,'') end If ReactorType = 'EPP' OR ReactorType = 'P' then Print_WMI_Labels(WONo,1) Print_WMO_Labels(WONo,1) end end NonEpiPro = ( (ReactorType NE 'GAN') and (ReactorType NE 'EPP') and (ReactorType NE 'P') ) If NonEpiPro then If WOStep > 1 then Def = "" Def = "Adjusting Step ":WOStep:" Scheduled Quantities..." Def = "U" MsgUp = Msg(@window, Def) RDSNos = obj_WO_Step('AdjStepRDSQtys', WOStep:@RM:WOSteps) If Get_Status(errCode) then ErrMsg(errCode) ;* Display error from the update Msg(@WINDOW,MsgUp) ;* Take down the processing message RETURN end Msg(@WINDOW,MsgUp) end ELSE RDSNos = XLATE('WO_STEP',WOSteps<1,1>,WO_STEP_RDS_KEY$,'X') end If MemberOf(@USER4,'OI_ADMIN') then WOMatKeys = XLATE('WO_LOG',WONo,WO_LOG_WO_MAT_KEY$,'X') CONVERT @VM TO @FM IN WOMatKeys AllRDSNos = XLATE('WO_MAT',WOMatKeys,WO_MAT_RDS_NO$,'X') RDSNos = '' LOOP CassRDSNos = AllRDSNos[1,@FM] AllRDSNos[1,COL2()] = '' UNTIL CassRdsNos = '' RDSNos := CassRdsNos<1,WOStep>:@VM REPEAT RDSNos[-1,1] = '' end If INDEX(RDSNos,@VM,1) then TypeOver = '' TypeOver = RDSNos TypeOver = 2 TypeOver = 'K' RDSKeys = Popup(@WINDOW,TypeOver,'WO_LOG_RTS') end ELSE RDSKeys = RDSNos end If RDSKeys = '' then ErrMsg('No RDS Numbers Selected or Work Order Not Yet Released to Production.') end ELSE CONVERT @VM TO @FM IN RDSKeys Print_Cass_Labels(RDSKeys,MultiStepFlag) ;* Updated labels with Akrion Bar Codes end end end end service Service UpdateWOStepStatus(WONo) If WONo NE '' then WOStepKey = WONo:'*':1 WOStepRec = Database_Services('ReadDataRow', 'WO_STEP', WOStepKey) WOStepCurrStatus = obj_WO_Step('CurrStatus', WOStepKey:@RM:WOStepRec) // Get a fresh copy of the record WOStepRec = Database_Services('ReadDataRow', 'WO_STEP', WOStepKey) WOStepCurrStatusStatic = WOStepRec If WOStepCurrStatus NE WOStepCurrStatusStatic then WOStepRec = WOStepCurrStatus Database_Services('WriteDataRow', 'WO_STEP', WOStepKey, WOStepRec, True$, False$, True$) end Database_Services('ReleaseKeyIDLock', 'WO_STEP', WOStepKey) end end service Service PostWOStepUpdateRequest(WONo) If WONo NE '' then StepNo = 1 WOStepKey = WONo:'*':StepNo // Look for a pre-existing request in the queue If (RowExists('WO_STEP', WOStepKey) EQ False$) then // This is a new request RequestKeyID = WOStepKey RequestRow = '' RequestRow = Datetime() Database_Services('WriteDataRow', 'WO_STEP_QUEUE', RequestKeyID, RequestRow, False$, False$, False$) end else // Duplicate request Null end end else Error_Services('Add', 'Null parameter passed into service call. All parameters are required.') end end service Service ProcessWOStepUpdateRequests() hSysLists = Database_Services('GetTableHandle', 'SYSLISTS') Lock hSysLists, ServiceKeyID then Open 'WO_STEP_QUEUE' to hTable then Select hTable EOF = False$ Loop ReadNext RequestKeyID else EOF = True$ Until EOF EQ True$ WONo = Field(RequestKeyID, '*', 1) Work_Order_Services('UpdateWOStepStatus', WONo) If Error_Services('NoError') then // Successfully updated the current status, so delete the request from the queue. Database_Services('DeleteDataRow', 'WO_STEP_QUEUE', RequestKeyID, True$, True$) end Repeat end else ErrorMsg = 'Error opening WO_STEP_QUEUE in ':Service:' service.' end Unlock hSysLists, ServiceKeyID else Null end end service Service SetHotFlag(WONo, HotFlag=BOOLEAN) If ( ( RowExists('WO_LOG', WONo) and ( (HotFlag EQ True$) or (HotFlag EQ False$) ) ) ) then Open 'WO_LOG' to hTable then WriteV HotFlag on hTable, WONo, WO_LOG_HOT_FLAG$ else Error_Services('Add', 'Error in ':Service:' service. File error: ':@File_Error) end end end else Error_Services('Add', 'Error in ':Service:' service. Invalid parameters passed into service.') end end service Service GetHotFlag(WONo) HotFlag = '' If RowExists('WO_LOG', WONo) then Open 'WO_LOG' to hTable then ReadV HotFlag from hTable, WONo, WO_LOG_HOT_FLAG$ else Error_Services('Add', 'Error in ':Service:' service. File error: ':@File_Error) end end end else Error_Services('Add', 'Error in ':Service:' service. Invalid parameters passed into service.') end Response = HotFlag end service Service UpdateReleasedQty(WONo) 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] : ' Update Released Qty Log.csv' Headers = 'Logging DTM' : @FM : 'WONo' : @FM : 'Notes' objUpRelLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$,',', Headers, '', False$, False$) LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM ErrorMsg = '' If WONo NE '' then If RowExists('WO_LOG', WONo) then WORec = Database_Services('ReadDataRow', 'WO_LOG', WONo) If Error_Services('NoError') then RelQty = obj_WO_Log('RelQty', WONo:@RM:WORec) WOQty = WORec If RelQty GT WOQty then UnRelQty = 0 end else UnRelQty = WOQty - RelQty end Open 'WO_LOG' to hTable then WriteV RelQty on hTable, WONo, WO_LOG_REL_QTY_STATIC$ then WriteV UnRelQty on hTable, WONo, WO_LOG_UNREL_QTY_STATIC$ else ErrorMsg = 'Error in ':Service:' service. Failed to write unreleased quantity ':UnRelQty ErrorMsg := ' to the UNREL_QTY_STATIC field of WO_LOG record ':WONo:'.' ErrorMsg := '@FILE_ERROR: ':@FILE_ERROR end end else ErrorMsg = 'Error in ':Service:' service. Failed to write released quantity ':RelQty ErrorMsg := ' to the REL_QTY_STATIC field of WO_LOG record ':WONo:'.' ErrorMsg := '@FILE_ERROR: ':@FILE_ERROR end end else ErrorMsg = 'Error in ':Service:' service. Failed to open the WO_LOG table.' end end else ErrorMsg = 'Error in ':Service:' service. Failed to read record ':WONo:' from the WO_LOG table. ' ErrorMsg := 'Error message: ':Error_Services('GetMessage') end end else ErrorMsg = 'Error in ':Service:' service. ':WONo:' does not exist in the WO_LOG table.' end end else ErrorMsg = 'Error in ':Service:' service. Null WONo passed into service' end LogData = '' LogData<1> = LoggingDtm LogData<2> = WONo If ErrorMsg EQ '' then LogResult = 'Successfully updated WO_LOG record ':WONo:' field REL_QTY_STATIC with released quantity ':RelQty LogResult := ' and field UNREL_QTY_STATIC with unreleased quantity ':UnRelQty:'.' LogData<3> = LogResult Logging_Services('AppendLog', objUpRelLog, LogData, @RM, @FM) end else LogResult = 'Failed to update WO_LOG record ':WONo:' field REL_QTY_STATIC with released quantity ':RelQty LogResult := ' or field UNREL_QTY_STATIC with unreleased quantity ':UnRelQty:'. Error message: ':ErrorMsg LogData<3> = LogResult Logging_Services('AppendLog', objUpRelLog, LogData, @RM, @FM) Error_Services('Add', ErrorMsg) end end service Service UpdateReceivedQty(WONo) 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] : ' Update Received Qty Log.csv' Headers = 'Logging DTM' : @FM : 'WONo' : @FM : 'Notes' objUpRecLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$,',', Headers, '', False$, False$) LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM ErrorMsg = '' If WONo NE '' then If RowExists('WO_LOG', WONo) then WORec = Database_Services('ReadDataRow', 'WO_LOG', WONo) If Error_Services('NoError') then RXQty = obj_WO_Log('RxQty', WONo:@RM:WORec) Open 'WO_LOG' to hTable then WriteV RXQty on hTable, WONo, WO_LOG_RX_QTY_STATIC$ else ErrorMsg = 'Error in ':Service:' service. Failed to write received quantity ':RXQty ErrorMsg := ' to the RX_QTY_STATIC field of WO_LOG record ':WONo:'.' ErrorMsg := '@FILE_ERROR: ':@FILE_ERROR end end else ErrorMsg = 'Error in ':Service:' service. Failed to open the WO_LOG table.' end end else ErrorMsg = 'Error in ':Service:' service. Failed to read record ':WONo:' from the WO_LOG table. ' ErrorMsg := 'Error message: ':Error_Services('GetMessage') end end else ErrorMsg = 'Error in ':Service:' service. ':WONo:' does not exist in the WO_LOG table.' end end else ErrorMsg = 'Error in ':Service:' service. Null WONo passed into service' end LogData = '' LogData<1> = LoggingDtm LogData<2> = WONo If ErrorMsg EQ '' then LogData<3> = 'Successfully updated WO_LOG record ':WONo:' field RX_QTY_STATIC with received quantity ':RXQty:'.' Logging_Services('AppendLog', objUpRecLog, LogData, @RM, @FM) end else LogResult = 'Failed to update WO_LOG record ':WONo:' field RX_QTY_STATIC with received quantity ':RXQty LogResult := '. Error message: ':ErrorMsg LogData<3> = LogResult Logging_Services('AppendLog', objUpRecLog, LogData, @RM, @FM) Error_Services('Add', ErrorMsg) end end service Service UpdateShippedQty(WONo) 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] : ' Update Shipped Qty Log.csv' Headers = 'Logging DTM' : @FM : 'WONo' : @FM : 'Notes' objUpShipLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$,',', Headers, '', False$, False$) LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM ErrorMsg = '' If WONo NE '' then If RowExists('WO_LOG', WONo) then WORec = Database_Services('ReadDataRow', 'WO_LOG', WONo) If Error_Services('NoError') then ShipQty = obj_WO_Log('ShipQty', WONo:@RM:WORec) Open 'WO_LOG' to hTable then WriteV ShipQty on hTable, WONo, WO_LOG_SHIP_QTY_STATIC$ else ErrorMsg = 'Error in ':Service:' service. Failed to write ':ShipQty ErrorMsg := ' to the SHIP_QTY_STATIC field of WO_LOG record ':WONo:'.' ErrorMsg := '@FILE_ERROR: ':@FILE_ERROR end end else ErrorMsg = 'Error in ':Service:' service. Failed to open the WO_LOG table.' end end else ErrorMsg = 'Error in ':Service:' service. Failed to read record ':WONo:' from the WO_LOG table. ' ErrorMsg := 'Error message: ':Error_Services('GetMessage') end end else ErrorMsg = 'Error in ':Service:' service. ':WONo:' does not exist in the WO_LOG table.' end end else ErrorMsg = 'Error in ':Service:' service. Null WONo passed into service' end LogData = '' LogData<1> = LoggingDtm LogData<2> = WONo If ErrorMsg EQ '' then LogResult = 'Successfully updated WO_LOG record ':WONo:' field SHIP_QTY_STATIC ' LogResult := 'with shipped quantity ':ShipQty:'.' LogData<3> = LogResult Logging_Services('AppendLog', objUpShipLog, LogData, @RM, @FM) end else LogResult = 'Failed to update WO_LOG record ':WONo:' field SHIP_QTY_STATIC with shipped quantity ' LogResult := ShipQty:'. Error message: ':ErrorMsg LogData<3> = LogResult Logging_Services('AppendLog', objUpShipLog, LogData, @RM, @FM) Error_Services('Add', ErrorMsg) end end service Service ConvertRecordToJSON(WONo, Record, ItemURL) jsonRecord = '' IF WONo NE '' then If Record EQ '' then Record = Database_Services('ReadDataRow', 'WO_LOG', WONo) If Error_Services('NoError') then @DICT = Database_Services('GetTableHandle', 'DICT.WO_LOG') @ID = WONo @RECORD = Record objJSON = '' If SRP_JSON(objJSON, 'New', 'Object') then objWOLog = '' If SRP_JSON(objWOLog, 'New', 'Object') then SRP_JSON(objWOLog, 'SetValue', 'KeyId', @ID) SRP_JSON(objWOLog, 'SetValue', 'ProdOrdNo', {PROD_ORD_NO}) SRP_JSON(objWOLog, 'SetValue', 'PSN', {PROD_SPEC_ID}) SRP_JSON(objWOLog, 'SetValue', 'EpiPartNo', {EPI_PART_NO}) SRP_JSON(objWOLog, 'SetValue', 'HOT_FLAG', {HOT_FLAG}) //Create a list of cassettes CassIDs = {WO_MAT_KEY} objChildCassettes = '' If SRP_JSON(objChildCassettes, 'New', 'Array') then If CassIDs NE '' then for each Cass in CassIDs using @VM setting vPos SAPBatchNo = XLATE('WO_MAT', Cass, WO_MAT_SAP_BATCH_NO$, 'X') SAPTXDtm = XLATE('WO_MAT', Cass, WO_MAT_SAP_TX_DTM$, 'X') RDSNo = XLATE('WO_MAT', Cass, WO_MAT_RDS_NO$, 'X') ShipNo = XLATE('WO_MAT', Cass, WO_MAT_SHIP_NO$, 'X') //Add in each indv. cassette object objChildCassette = '' If SRP_JSON(objChildCassette, 'New', 'Object') then SRP_JSON(objChildCassette, 'SetValue', 'KeyId', Cass) SRP_JSON(objChildCassette, 'SetValue', 'SAPBatchNo', SAPBatchNo) SRP_JSON(objChildCassette, 'SetValue', 'SAPTXDtm', OCONV(SAPTXDtm, 'DT')) SRP_JSON(objChildCassette, 'SetValue', 'RDSNo', RDSNo) SRP_JSON(objChildCassette, 'SetValue', 'ShipNo', ShipNo) SRP_JSON(objChildCassettes, 'Add', objChildCassette) SRP_JSON(objChildCassette, 'Release') end Next Cass end else SRP_JSON(objWOLog, 'SetValue', 'ChildCassettes', '') end SRP_JSON(objWOLog, 'Set', 'ChildCassettes', objChildCassettes) SRP_JSON(objChildCassettes, 'Release') end SRP_JSON(objJSON, 'Set', 'WO_Log', objWOLog) SRP_JSON(objWOLog, 'Release') end If itemURL NE '' then // The itemURL was passed in so add HAL+JSON properties. // Create the _links property and then all link objects needed for this resource. objLinks = '' If SRP_JSON(objLinks, 'New', 'Object') then // Create a self link. objLink = '' If SRP_JSON(objLink, 'New', 'Object') then SRP_JSON(objLink, 'SetValue', 'href', ItemURL, 'String') SRP_JSON(objLink, 'SetValue', 'title', 'Self', 'String') SRP_JSON(objLinks, 'Set', 'self', objLink) SRP_JSON(objLink, 'Release') end SRP_JSON(objJSON, 'Set', '_links', objLinks) SRP_JSON(objLinks, 'Release') end // Create the _class property for this resource. SRP_JSON(objJSON, 'SetValue', '_class', 'resource') end jsonRecord = SRP_JSON(objJSON, 'Stringify', 'Styled') SRP_JSON(objJSON, 'Release') end else Error_Services('Add', 'Unable to create JSON representation in the ' : Service : ' service.') end end end else Error_Services('Add', 'KeyID argument was missing in the ' : Service : ' service.') end Response = jsonRecord end service Service RemoveWoMatCassetteFromWO(WoMatKey, Username) ErrorMessage = '' If RowExists('WO_MAT', WoMatKey) then WoNo = Field(WoMatKey, '*', 1) WOLogRecord = Database_Services('ReadDataRow', 'WO_LOG', WoNo, True$, 0, False$) If Error_Services('NoError') then WoMatKeys = WOLogRecord Locate WoMatKey in WoMatKeys using @VM setting CassPos then WoLogRecord = Delete(WOLogRecord, 1, CassPos, 0) Database_Services('WriteDataRow', 'WO_LOG', WoNo, WoLogRecord) If Error_Services('NoError') then Work_Order_Services('UpdateReceivedQty', WONo) Work_Order_Services('UpdateReleasedQty', WONo) Work_Order_Services('UpdateUnscheduledQuantities') end else ErrorMessage = Error_Services('GetMessage') end end else ErrorMessage = "Unable to locate cass no " : WoMatKey : ' in the WO_LOG ' : WoNo : ' Record.' end end else ErrorMessage = Error_Services('GetMessage') end end else ErrorMessage = 'Invalid WoMat Key ' : WoMatKey : ' passed to RemoveWoMatCassetteFromWO routine.' end If ErrorMessage NE '' then Error_Services('Add', ErrorMessage) end end service Service SignVoidNonEpp(WOMatKey, Username) ErrorMessage = '' WONo = Field(WOMatKey, '*', 1) CassNo = Field(WoMatKey, '*', 2) ReactType = XLATE('WO_LOG', WONo, WO_LOG_REACT_TYPE$, 'X') If ReactType EQ 'ASM' OR ReactType EQ 'ASM+' OR ReactType EQ 'HTR' then RDSNo = Database_Services('ReadDataColumn', 'WO_MAT', WoMatKey, WO_MAT_RDS_NO$, True$, 0, False$) If Error_Services('NoError') then WoMatRec = Database_Services('ReadDataRow', 'WO_MAT', WoMatKey, True$, 0, False$) IsVoided = WoMatRec If Not(IsVoided) then IsOnHold = Hold_Services('CheckForHold', WoMatKey) If Not(IsOnHold) then Service_Services('PostProcedure', 'WORK_ORDER_SERVICES', 'RemoveWoMatCassetteFromWO':@vm:WOMatKey:@vm:Username) If Error_Services('NoError') then Service_Services('PostProcedure', 'WO_MAT_SERVICES', 'SetWoMatVoidFlag':@vm:WOMatKey:@VM:Username) if Error_Services('NoError') then Service_Services('PostProcedure', 'RDS_SERVICES', 'DetachRDSFromWO':@vm:RDSNo) If Error_Services('NoError') then LotEventParams = '' LotEventParams<1,1> = 'CreateLotEvent' LotEventParams<1,4> = DateTime() LotEventParams<1,5> = 'VOID' LotEventParams<1,6> = 'Lot voided by ' : Username LotEventParams<1,11> = Username If RDSNo NE '' then LotEventParams<1,2> = RDSNo LotEventParams<1,3> = 'RDS' Service_Services('PostProcedure', 'LOT_SERVICES', LotEventParams) end else LotEventParams<1,2> = WoMatKey LotEventParams<1,3> = 'WO_MAT' Service_Services('PostProcedure', 'LOT_SERVICES', LotEventParams) end If Error_Services('NoError') then //Add inventory transaction end else ErrorMessage = Error_Services('GetMessage') end end else ErrorMessage = Error_Services('GetMessage') end end else ErrorMessage = Error_Services('GetMessage') end end else ErrorMessage = Error_Services('GetMessage') end end end else ErrorMessage = 'Unable to void lot as it is already voided.' end end else ErrorMessage = Error_Services('GetMessage') end end else ErrorMessage = 'Cannot use this routine to void EpiPro lots.' end If ErrorMessage NE '' then LogData = '' LogData<1> = LoggingDTM LogData<2> = Username LogData<3> = WOMatKey LogData<4> = ErrorMessage Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM, False$) Error_Services('Add', ErrorMessage) end else LogData = '' LogData<1> = LoggingDTM LogData<2> = Username LogData<3> = WOMatKey LogData<4> = 'Void queued successfully.' Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM, False$) Error_Services('Add', ErrorMessage) end end service Service SignVoidWMI(WMInKey, Username) ErrorMessage = '' WONo = Field(WMInKey, '*', 1) CassNo = Field(WMInKey, '*', 3) WoStepKey = Xlate('WO_LOG', WONo, WO_LOG_WO_STEP_KEY$, 'X') WoMatKey = WONo : '*' : CassNo ReactType = XLATE('WO_LOG', WONo, WO_LOG_REACT_TYPE$, 'X') If ReactType EQ 'EPP' then WMInRec = Database_Services('ReadDataRow', 'WM_IN', WMInKey, True$, 0, False$) IsVoided = WMInRec If Not(IsVoided) then IsOnHold = Hold_Services('CheckForHold', WoMatKey) If Not(IsOnHold) then Service_Services('PostProcedure', 'WM_IN_SERVICES', 'SetVoidFlag':@vm:WMInKey:@VM:Username) If Error_Services('NoError') then LotEventParams = '' LotEventParams<1,1> = 'CreateLotEvent' LotEventParams<1,4> = DateTime() LotEventParams<1,5> = 'VOID' LotEventParams<1,6> = 'Lot voided by ' : Username LotEventParams<1,11> = Username LotEventParams<1,2> = WMInKey LotEventParams<1,3> = 'WM_IN' Service_Services('PostProcedure', 'LOT_SERVICES', LotEventParams) If Error_Services('NoError') then //Check if WMO is also voided. If it is, remove it from the WO_MAT_KEY field in WO_LOG, and void the WO_MAT record WMOKey = WMInKey; //the paired WMO key is the same as the WMIKey IsWMOVoided = Database_Services('ReadDataColumn', 'WM_OUT', WMOKey, WM_OUT_VOID$) If IsWMOVoided then Service_Services('PostProcedure', 'WO_MAT_SERVICES', 'SetWoMatVoidFlag':@VM:WoMatKey:@VM:Username) If Error_Services('NoError') then Service_Services('PostProcedure', 'WORK_ORDER_SERVICES','RemoveWoMatCassetteFromWO':@VM:WoMatKey:@VM:Username) If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage') end end else ErrorMessage = Error_Services('GetMessage') end end end else ErrorMessage = Error_Services('GetMessage') end end else ErrorMessage = Error_Services('GetMessage') end end end else ErrorMessage = 'Unable to void lot as it is already voided.' end end else ErrorMessage = 'Cannot use this routine to void EpiPro lots.' end If ErrorMessage NE '' then LogData = '' LogData<1> = LoggingDTM LogData<2> = Username LogData<3> = WMInKey LogData<4> = ErrorMessage Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM, False$) Error_Services('Add', ErrorMessage) end else LogData = '' LogData<1> = LoggingDTM LogData<2> = Username LogData<3> = WMInKey LogData<4> = 'Void queued successfully.' Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM, False$) Error_Services('Add', ErrorMessage) end end service Service SignVoidWMO(WMOutKey, Username) ErrorMessage = '' WONo = Field(WMOutKey, '*', 1) CassNo = Field(WMOutKey, '*', 3) WoStepKey = Xlate('WO_LOG', WONo, WO_LOG_WO_STEP_KEY$, 'X') WoMatKey = WONo : '*' : CassNo ReactType = XLATE('WO_LOG', WONo, WO_LOG_REACT_TYPE$, 'X') If ReactType EQ 'EPP' then WMOutRec = Database_Services('ReadDataRow', 'WM_OUT', WMOutKey, True$, 0, False$) IsVoided = WMOutRec If Not(IsVoided) then IsOnHold = Hold_Services('CheckForHold', WoMatKey) If Not(IsOnHold) then Service_Services('PostProcedure', 'WM_OUT_SERVICES', 'SetVoidFlag':@vm:WMOutKey:@VM:Username) If Error_Services('NoError') then LotEventParams = '' LotEventParams<1,1> = 'CreateLotEvent' LotEventParams<1,4> = DateTime() LotEventParams<1,5> = 'VOID' LotEventParams<1,6> = 'Lot voided by ' : Username LotEventParams<1,11> = Username LotEventParams<1,2> = WMOutKey LotEventParams<1,3> = 'WM_OUT' Service_Services('PostProcedure', 'LOT_SERVICES', LotEventParams) If Error_Services('NoError') then //Check if WMI is also voided. If it is, remove it from the WO_MAT_KEY field in WO_LOG, and void the WO_MAT record WMIKey = WMOutKey; //the paired WMO key is the same as the WMIKey IsWMIVoided = Database_Services('ReadDataColumn', 'WM_IN', WMIKey, WM_IN_VOID$) If IsWMIVoided then Service_Services('PostProcedure', 'WO_MAT_SERVICES', 'SetWoMatVoidFlag':@VM:WoMatKey:@VM:Username) If Error_Services('NoError') then Service_Services('PostProcedure', 'WORK_ORDER_SERVICES','RemoveWoMatCassetteFromWO':@VM:WoMatKey:@VM:Username) If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage') end end else ErrorMessage = Error_Services('GetMessage') end end end else ErrorMessage = Error_Services('GetMessage') end end else ErrorMessage = Error_Services('GetMessage') end end end else ErrorMessage = 'Unable to void lot as it is already voided.' end end else ErrorMessage = 'Cannot use this routine to void EpiPro lots.' end If ErrorMessage NE '' then LogData = '' LogData<1> = LoggingDTM LogData<2> = Username LogData<3> = WMOutKey LogData<4> = ErrorMessage Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM, False$) Error_Services('Add', ErrorMessage) end else LogData = '' LogData<1> = LoggingDTM LogData<2> = Username LogData<3> = WMOutKey LogData<4> = 'Void queued successfully.' Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM, False$) Error_Services('Add', ErrorMessage) end end service Service GetEligiblePeelOffLotsByWOAndEntityType(WONo, EntityType) ErrorMessage = '' EligibleCassIds = '' If RowExists('WO_LOG', WONo) then Begin Case Case EntityType EQ 'RDS' CassIds = Database_Services('ReadDataColumn', 'WO_LOG', WONo, WO_LOG_WO_MAT_KEY$, True$, 0, False$) for each CassId in CassIds using @VM RDSNo = XLATE('WO_MAT', CassId, WO_MAT_RDS_NO$, 'X') Signatures = Signature_Services('GetSigProfile', CassId, 0, RDSNo) Eligible = True$ for each Signature in Signatures<1> using @VM setting SigPos SignatureDtm = Signatures<3, SigPos> If SignatureDtm NE '' then Eligible = False$ end Until Eligible EQ False$ Next Signature If Eligible then EligibleCassIds<1, -1> = CassId Next CassId Case EntityType EQ 'WM_OUT' //WM_OUTS can be voided when //1. There are no RDS Nos associated //2. There have never been any wafers in them WOStepKey = XLATE('WO_LOG', WONo, WO_LOG_WO_STEP_KEY$, 'X') CassIds = Database_Services('ReadDataColumn', 'WO_STEP', WOStepKey, WO_STEP_WM_OUT_KEYS$, True$, 0, False$) for each CassId in CassIds using @VM WMORec = Database_Services('ReadDataRow', 'WM_OUT', CassId, True$, 0, False);//XLATE('WM_OUT',WMOutKeys<1,I>,'','X') WMO_RdsNos = WMORec WMO_NCRNos = WMORec WMO_UMWCassIDs = WMORec Eligible = True$ //Loop through RDS list to see if there is an RDS attached. If there are any RDS No's attached it is not eligible. for each RDSNo in WMO_RDSNos using @VM If RDSNo NE '' then Eligible = False$ end Until Eligible EQ False$ Next RDSNo //Loop through NCR list to see if there are any NCR's associated. If there are any NCR No's attached it is not eligible. If Eligible then For Each NCRNo in WMO_NCRNos using @VM If NCRNo NE '' then Eligible = False$ end Until Eligible EQ False$ Next NCR end //Loop through MU Wafer Usage list to see if there are any MU wafer's taken from this lot. If there are any Makeup Wafers attached it is not eligible. If Eligible then For Each UMWCass in WMO_UMWCassIDs using @VM If UMWCass NE '' then Eligible = False$ end Until Eligible EQ False$ Next UMWCass end If Eligible then EligibleCassIds<1, -1> = CassId Next CassId Case EntityType EQ 'WM_IN' WOStepKey = XLATE('WO_LOG', WONo, WO_LOG_WO_STEP_KEY$, 'X') CassIds = Database_Services('ReadDataColumn', 'WO_STEP', WOStepKey, WO_STEP_WM_IN_KEYS$, True$, 0, False$) for each CassId in CassIds using @VM Eligible = True$ WMIRec = Database_Services('ReadDataRow', 'WM_IN', CassId, True$, 0, False);//XLATE('WM_OUT',WMOutKeys<1,I>,'','X') WMI_RdsNos = WMIRec WMI_NCRNos = WMIRec Eligible = True$ //Loop through RDS list to see if there is an RDS attached. If there are any RDS No's attached it is not eligible. for each RDSNo in WMI_RDSNos using @VM If RDSNo NE '' then Eligible = False$ end Until Eligible EQ False$ Next RDSNo //Loop through NCR list to see if there are any NCR's associated. If there are any NCR No's attached it is not eligible. If Eligible then For Each NCRNo in WMI_NCRNos using @VM If NCRNo NE '' then Eligible = False$ end Until Eligible EQ False$ Next NCR end If Eligible then EligibleCassIds<1, -1> = CassId Next CassId Case EntityType EQ '' ErrorMessage = 'Entity type parameter was invalid.' Case Otherwise$ ErrorMessage = 'Entity type parameter was null.' End Case end else ErrorMessage = 'WO# ' : WONo : ' not found in WO_LOG table.' end If ErrorMessage NE '' then Error_Services('Add', 'Error in ' : Service : '. ' : ErrorMessage) end Response = EligibleCassIds end service //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Internal GoSubs //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ClearCursors: For counter = 0 to 8 ClearSelect counter Next counter return