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 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 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 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$) 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) //(SAPCassIDs<0, I> = '') 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 Machine = Environment_Services('GetServer') If Machine NE 'MESSA01EC' then EmailAddr = 'dstieber@srpcs.com,6613649828@txt.att.net' Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM, False$, EmailAddr, ErrorMsg) end else Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM, False$) end 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) * HaveLock = Database_Services('GetKeyIDLock', 'WO_STEP', WOStepKey) * If HaveLock then // 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 else * // Failed to lock record for update. Throw an error to keep the request in the queue. * Error_Services('Add', 'Failed to lock WO_STEP record ':WOStepKey:' in ':Service:' service.') * end 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) WORec = Database_Services('ReadDataRow', 'WO_LOG', WONo) If Error_Services('NoError') then RelQty = obj_WO_Log('RelQty', WONo:@RM:WORec) WORec = RelQty WOQty = WORec If RelQty GT WOQty then UnRelQty = 0 end else UnRelQty = WOQty - RelQty end WORec = UnRelQty Database_Services('WriteDataRow', 'WO_LOG', WONo, WORec, True$, False$, False$) end end service Service UpdateReceivedQty(WONo) WORec = Database_Services('ReadDataRow', 'WO_LOG', WONo) If Error_Services('NoError') then RXQty = obj_WO_Log('RxQty', WONo:@RM:WORec) WORec = RXQty Database_Services('WriteDataRow', 'WO_LOG', WONo, WORec, True$, False$, False$) end end service Service UpdateShippedQty(WONo) WORec = Database_Services('ReadDataRow', 'WO_LOG', WONo) If Error_Services('NoError') then ShipQty = obj_WO_Log('ShipQty', WONo:@RM:WORec) WORec = ShipQty Database_Services('WriteDataRow', 'WO_LOG', WONo, WORec) 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 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Internal GoSubs //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ClearCursors: For counter = 0 to 8 ClearSelect counter Next counter return