open-insight/LSL2/STPROC/MATERIAL_SERVICES.txt

1594 lines
68 KiB
Plaintext

Function Material_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 : Material_Services
Description : Handler program for all module related services.
Notes : Service module to support environmental state issues. Environmental refers to the state of the
operating system, which includes version, client vs. server, and path to critical systems.
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)
04/16/18 dmb Original programmer.
04/24/18 dmb Modify GetAvailableMakeupWafers to avoid returning cassette with 0 wafers.
10/25/18 dmb Modify GetAvailableMakeupWafers to better support EpiPro.
09/07/23 djm Add GetLotHistory Service.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$insert LOGICAL
$insert SERVICE_SETUP
$insert WO_LOG_EQUATES
$insert WO_MAT_EQUATES
$insert WO_STEP_EQUATES
$insert PROD_SPEC_EQUATES
$insert RDS_EQUATES
$insert RLIST_EQUATES
$insert WO_MAT_QUEUE_EQUATES
$insert WM_OUT_QUEUE_EQUATES
$insert WO_STEP_QUEUE_EQUATES
$insert WM_OUT_EQUATES
$insert RDS_QUEUE_EQUATES
$insert REACT_RUN_EQUATES
$insert NOTIFICATION_EQUATES
$insert PROD_VER_EQUATES
$insert NCR_EQUATES
$insert CLEAN_INSP_EQUATES
$insert RDS_LAYER_EQUATES
$insert RDS_TEST_EQUATES
$insert TW_USE_EQUATES
$insert MAKEUP_WAFERS_EQUATES
Equ Tab$ to Char(9)
Equ Esc$ to \1B\
Equ CRLF$ to \0D0A\
Equ COMMA$ to ','
Common /EnvironmentServices/ Unused1@, Unused2@, Unused3@, Unused4@, Unused5@, Unused6@, Unused7@, Unused8@, Unused9@, Unused10@
Declare function Material_Services, Memory_Services, Database_Services, SRP_Array, obj_WO_Mat, obj_WM_Out
Declare function Logging_Services, Environment_Services, Datetime, obj_WO_Step, Database_Services, SQL_Services
Declare function SRP_Rotate_Array, SRP_DateTime, obj_WO_Log, obj_Shipment, SRP_Date
Declare subroutine Material_Services, Memory_Services, Database_Services, SRP_Array, Btree.Extract, Logging_Services
Declare subroutine SRP_Stopwatch, Set_Status, RList, Work_Order_Services, SQL_Services, obj_WO_Mat, obj_Notes
Declare subroutine SRP_Rotate_Array, SRP_DateTime, obj_WO_Log, Hold_Services
UseMakeupWafersTable = Database_Services('ReadDataRow', 'APP_INFO', 'USE_MAKEUP_WAFERS_TABLE')
If UseMakeupWafersTable EQ '' then UseMakeupWafersTable = False$
LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\MUBox'
LogDate = Oconv(Date(), 'D4/')
LogTime = Oconv(Time(), 'MTS')
LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' Makeup Auto Hold Log.csv'
Headers = 'Logging DTM' : @FM : 'WONo' : @FM : 'Notes'
objLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, Comma$, Headers, '', False$, False$)
LoggingDTM = LogDate : ' ' : LogTime
LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\WO_Mat'
LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' RDS Erase Attempt.csv'
Headers = 'Logging DTM' : @FM : 'User' : @FM : 'RDSNo' : @FM : 'WOMatKeyID' : @FM : 'Call Stack' : @FM : 'Error'
objLog3 = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, Comma$, Headers, '', False$, False$)
LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\WO_Mat'
LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' Curr Status Change.csv'
Headers = 'Logging DTM' : @FM : 'User' : @FM : 'WOMatKeyID' : @FM : 'Old Status' : @FM : 'New Status'
objStatusLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, Comma$, Headers, '', False$, False$)
GoToService else
Error_Services('Add', Service : ' is not a valid service request within the ' : ServiceModule : ' services module.')
end
Return Response OR ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN = True$, False$
Options IDType = 'RDS', 'WO_MAT'
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// GetLotHistory
//
// IDType - [Required] Either 'RDS' or 'WO_MAT'. Default is RDS
// LotID - [Required] RDS ID or WO_MAT ID, corresponding to IDType
// StartDate - (Optional)
// EndDate - (Optional)
//
// Returns a delimited array of Lot History Events and comments.
//
//----------------------------------------------------------------------------------------------------------------------
Service GetLotHistory(IDType=IDType, LotID, StartDate, EndDate)
LotList = ''
LotArray = ''
CommentList = ''
CommentArray = ''
ActionList = ''
ActionArray = ''
FinalLotArray = ''
// No Start/EndDate entered
If IDType = 'WO_MAT' then
// Open RDS and WO_MAT records
WOMatRow = Database_Services('ReadDataRow', 'WO_MAT', LotID)
RDSNo = WOMatRow<WO_MAT_RDS_NO$>
RDSRow = Database_Services('ReadDataRow', 'RDS', RDSNo)
// Get RDS Comments
CommentDates = RDSRow<RDS_COMMENT_DATE$>
CommentUsers = RDSRow<RDS_COMMENT_USER$>
Comments = RDSRow<RDS_COMMENT_NOTE$>
CommentList = CommentDates :@FM: CommentUsers :@FM:@FM: Comments
CommentArray = SRP_Rotate_Array(CommentList)
CommentCount = DCount(CommentArray, @FM)
For I = 1 to CommentCount
ThisComment = CommentArray<I, 4>
Begin Case
Case IndexC(ThisComment, 'Material Taken off Hold', 1)
CommentArray<I,3> = 'HOLD_OFF'
Case IndexC(ThisComment, 'Material Placed on Hold', 1)
CommentArray<I,3> = 'HOLD_ON'
Case IndexC(ThisComment, 'Packaging completed for', 1)
CommentArray<I,3> = 'PACK'
End Case
Next I
// WO_MAT Actions
INVDTMs = WOMatRow<WO_MAT_INV_DTM$>
INVUsers = WOMatRow<WO_MAT_INV_USER$>
INVActions = WOMatRow<WO_MAT_INV_ACTION$>
ActionList = INVDTMs :@FM: INVUsers :@FM: INVActions :@FM:@FM
ActionArray = SRP_Rotate_Array(ActionList)
// Remove Hold Inventory actions from array because they are populated from RDS commments.
HoldOffCount = Count(INVActions, 'HOLD_OFF')
HoldOnCount = Count(INVActions, 'HOLD_ON')
PackCount = Count(INVActions, 'PACK')
Locate 'HOLD_OFF' in InvActions Using @VM Setting POS then
ActionArray = Delete(ActionArray, POS, 0, 0)
end
Locate 'HOLD_ON' in InvActions Using @VM Setting POS then
ActionArray = Delete(ActionArray, POS, 0, 0)
end
For K = 1 to PackCount
Locate 'PACK' in InvActions Using @VM Setting POS then
ActionArray = Delete(ActionArray, POS, 0, 0)
end
Next K
end else
// RDS is default IDType
// Open RDS and WO_MAT records
RDSRow = Database_Services('ReadDataRow', 'RDS', LotID)
WOMatKey = Xlate('RDS', LotID, 'WO_MAT_KEY', 'X')
WOMatRow = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey)
// Get RDS Comments
CommentDates = RDSRow<RDS_COMMENT_DATE$>
CommentUsers = RDSRow<RDS_COMMENT_USER$>
Comments = RDSRow<RDS_COMMENT_NOTE$>
CommentList = CommentDates :@FM: CommentUsers :@FM:@FM: Comments
CommentArray = SRP_Rotate_Array(CommentList)
CommentCount = DCount(CommentArray, @FM)
For I = 1 to CommentCount
ThisComment = CommentArray<I, 4>
Begin Case
Case IndexC(ThisComment, 'Material Taken off Hold', 1)
CommentArray<I,3> = 'HOLD_OFF'
Case IndexC(ThisComment, 'Material Placed on Hold', 1)
CommentArray<I,3> = 'HOLD_ON'
Case IndexC(ThisComment, 'Packaging completed for', 1)
CommentArray<I,3> = 'PACK'
End Case
Next I
// WO_MAT Actions
INVDTMs = WOMatRow<WO_MAT_INV_DTM$>
INVUsers = WOMatRow<WO_MAT_INV_USER$>
INVActions = WOMatRow<WO_MAT_INV_ACTION$>
ActionList = INVDTMs :@FM: INVUsers :@FM: INVActions :@FM:@FM
ActionArray = SRP_Rotate_Array(ActionList)
HoldOffCount = Count(INVActions, 'HOLD_OFF')
HoldOnCount = Count(INVActions, 'HOLD_ON')
PackCount = Count(INVActions, 'PACK')
// Remove Hold Inventory actions from array because they are populated from RDS commments.
Locate 'HOLD_OFF' in InvActions Using @VM Setting POS then
ActionArray = Delete(ActionArray, POS, 0, 0)
end
Locate 'HOLD_ON' in InvActions Using @VM Setting POS then
ActionArray = Delete(ActionArray, POS, 0, 0)
end
For K = 1 to PackCount
Locate 'PACK' in InvActions Using @VM Setting POS then
ActionArray = Delete(ActionArray, POS, 0, 0)
end
Next K
end
// Add Comments if present
If CommentArray NE '' then
LotArray = CommentArray :@FM: ActionArray
end else
LotArray = ActionArray
end
// Sort by Date
SortedLotArray = SRP_Array('SortRows', LotArray, 'D1', 'LIST')
// Convert DateTimes to External
RowCount = Dcount(SortedLotArray, @FM)
If StartDate NE '' AND EndDate NE '' then
For index = 1 to RowCount
If SortedLotArray<index,1> LE EndDate and SortedLotArray<index,1> GE StartDate then
FinalLotArray<-1> = Oconv(SortedLotArray<index,1>, 'DT') :@vm: SortedLotArray<index,2> :@vm: SortedLotArray<index,3> :@vm: SortedLotArray<index,4>
end
Next Index
end else
For index = 1 to RowCount
FinalLotArray<-1> = Oconv(SortedLotArray<index,1>, 'DT') :@vm: SortedLotArray<index,2> :@vm: SortedLotArray<index,3> :@vm: SortedLotArray<index,4>
Next Index
end
Response = FinalLotArray
End Service
//----------------------------------------------------------------------------------------------------------------------
// ProcessAutoHold
//
// looks for MakeUp wafers older than 3 years old and then puts them on hold and sends notification.
//----------------------------------------------------------------------------------------------------------------------
Service ProcessAutoHold()
hSysLists = Database_Services('GetTableHandle', 'SYSLISTS')
Lock hSysLists, ServiceKeyID then
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = 'Begin ':Service
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
HoldList = ''
FailedHoldList = ''
CutoffDate = SRP_Date('AddYears', Date(), -3)
Query = 'SELECT MAKEUP_WAFERS WITH UNLOAD_DTM LT ':Quote(OConv(CutoffDate, 'DT2/^H'): ' AND WITH EXPIRED NE ':True$)
Flag = ''
RList(Query, TARGET_ACTIVELIST$, '', '', Flag)
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = 'RList Flag = ':Flag:'. @RecCount = ':@RecCount
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
EOF = False$
Loop
Readnext WOMatKey else EOF = True$
Until EOF
ErrorMsg = '' ; // Local loop error message tracking
ExpiredFlag = ''
HoldFlag = ''
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = 'Identified lot "':WOMatKey:'" as older than three years. Checking hold state...'
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
WONo = Field(WOMatKey, '*', 1)
ReactType = Xlate('WO_LOG', WONo, 'REACT_TYPE', 'X')
If ReactType EQ 'EPP' then
CassNo = Field(WOMatKey, '*', 2)
HoldEntity = 'WM_OUT'
HoldEntityID = WONo:'*1*':CassNo
end else
HoldEntity = 'RDS'
HoldEntityID = Xlate('WO_MAT', WOMatKey, 'RDS_NO', 'X')
end
WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey)
If Error_Services('NoError') then
HoldFlag = WOMatRec<WO_MAT_HOLD$>
If HoldFlag EQ True$ then
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = 'Lot "':WOMatKey:'" already on hold. Hold flag = ':HoldFlag:'.'
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
end else
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = 'Lot "':WOMatKey:'" not on hold. Hold flag = ':HoldFlag:'. Attempting to place lot on hold...'
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
// Toggle hold state
Hold_Services('ToggleHold', WOMatKey, HoldEntity, HoldEntityID, '', 'H', '', 'SYSTEM')
If Error_Services('NoError') then
// Verify hold state
// Re-read record to verify hold state
WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey)
If Error_Services('NoError') then
NewHoldFlag = WOMatRec<WO_MAT_HOLD$>
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = 'Lot "':WOMatKey:'" new hold flag = ':NewHoldFlag:'.'
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
If NewHoldFlag EQ HoldFlag then
// Something went wrong somewhere
ErrorMsg = 'New hold state, ':NewHoldFlag:', of lot "':WOMatKey:'" equals previous hold state, ':HoldFlag:'.'
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = ErrorMsg
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
end
end else
ErrorMsg = Error_Services('GetMessage')
LogMsg = 'Failed to verify lot "':WOMatKey:'" was placed on hold.'
LogMsg := 'Error message: ':ErrorMsg
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = LogMsg
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
end
end else
ErrorMsg = Error_Services('GetMessage')
LogMsg = 'Failed to toggle hold state of lot "':WOMatKey:'".'
LogMsg := 'Error message: ':ErrorMsg
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = LogMsg
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
end
end
If ErrorMsg EQ '' then
// Now mark cassette as expired
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = 'Attempting to mark lot "':WOMatKey:'" as expired.'
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
Material_Services('MarkMUCassExpired', WOMatKey)
If Error_Services('NoError') then
MWRec = Database_Services('ReadDataRow', 'MAKEUP_WAFERS', WOMatKey)
If Error_Services('NoError') then
ExpiredFlag = MWRec<MAKEUP_WAFERS.EXPIRED$>
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = 'Successfully marked lot "':WOMatKey:'" as expired. Expired flag = ':ExpiredFlag:'.'
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
end else
ErrorMsg = Error_Services('GetMessage')
LogMsg = 'Failed to verify lot "':WOMatKey:'" was marked as expired.'
LogMsg := 'Error message: ':ErrorMsg
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = LogMsg
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
end
end else
ErrorMsg = Error_Services('GetMessage')
LogMsg = 'Failed to mark lot "':WOMatKey:'" as expired.'
LogMsg := 'Error message: ':ErrorMsg
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = LogMsg
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
end
end else
ErrorMsg = Error_Services('GetMessage')
LogMsg = 'Failed to toggle hold state of lot "':WOMatKey:'".'
LogMsg := 'Error message: ':ErrorMsg
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = LogMsg
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
end
end else
ErrorMsg = Error_Services('GetMessage')
LogMsg = 'Failed to place lot "':WOMatKey:'" on hold. Error reading WO_MAT record to get hold state.'
LogMsg := 'Error message: ':ErrorMsg
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = LogMsg
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
end
If (ErrorMsg EQ '') then
HoldList<-1> = ReactType:TAB$:HoldEntityID
end else
FailedHoldList<-1> = ReactType:TAB$:HoldEntityID
end
Repeat
NotifyDtm = Datetime()
// Send initial notification of successful lots and failed lots
If (HoldList NE '') then
Recipients = ''
SentFrom = 'SYSTEM'
Subject = 'Makeup Wafer Auto-Hold Report'
AttachWindow = ''
AttachKey = ''
SendToGroup = 'AUTO_HOLD'
Message = 'The following makeup cassettes are older than three years and have been automatically '
Message := 'placed on hold.':CRLF$:'Reminder: EpiPro lots can contain multiple RDS lots.':CRLF$:CRLF$
Swap @FM with CRLF$ in HoldList
Message := HoldList
Parms = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
obj_Notes('Create',Parms)
For each WOMatKey in HoldList using @FM
WONo = Field(WOMatKey, '*', 1)
ReactType = Xlate('WO_LOG', WONo, 'REACT_TYPE', 'X')
If ReactType EQ 'EPP' then
CassNo = Field(WOMatKey, '*', 2)
HoldEntityID = WONo:'*1*':CassNo
end else
HoldEntityID = Xlate('WO_MAT', WOMatKey, 'RDS_NO', 'X')
end
MUWfrRec = Database_Services('ReadDataRow', 'MAKEUP_WAFERS', WOMatKey)
If Error_Services('NoError') then
HaveLock = Database_Services('GetKeyIDLock', 'MAKEUP_WAFERS', WOMatKey, True$)
If HaveLock then
MUWfrRec<MAKEUP_WAFERS.EXPIRY_LAST_NOTIFY_DTM$> = NotifyDtm
Database_Services('WriteDataRow', 'MAKEUP_WAFERS', WOMatKey, MUWfrRec, True$, False$, False$)
If Error_Services('NoError') then
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = 'Updated expiry notify dtm for expired lot "':WOMatKey:'".'
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
end else
ErrorMsg = Error_Services('GetMessage')
LogMsg = 'Failed to update expiry notify dtm for expired lot "':WOMatKey:'". Error updating MAKEUP_WAFERS record.'
LogMsg := 'Error message: ':ErrorMsg
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = LogMsg
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
SelfLocked = Database_Services('IsKeyIDSelfLocked', 'MAKEUP_WAFERS', WOMatKey)
If SelfLocked then Database_Services('ReleaseKeyIDLock', 'MAKEUP_WAFERS', WOMatKey)
end
end else
LogMsg = 'MAKEUP_WAFERS record for expired lot "':WOMatKey:'" is locked. Service will attempt again on next service call.'
LogMsg := 'Error message: ':ErrorMsg
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = LogMsg
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
end
end else
ErrorMsg = Error_Services('GetMessage')
LogMsg = 'Failed to send notification for expired lot "':WOMatKey:'". Error reading MAKEUP_WAFERS record.'
LogMsg := 'Error message: ':ErrorMsg
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = LogMsg
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
end
Next WOMatKey
end
If (FailedHoldList NE '') then
Recipients = ''
SentFrom = 'SYSTEM'
Subject = 'Makeup Wafer Auto-Hold Report'
AttachWindow = ''
AttachKey = ''
SendToGroup = 'AUTO_HOLD'
Message = 'The following makeup cassettes are older than three years and failed to be placed on hold by '
Message := 'the system.':CRLF$:'Reminder: EpiPro lots can contain multiple RDS lots.':CRLF$:CRLF$
Swap @FM with CRLF$ in FailedHoldList
Message := FailedHoldList
Parms = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
obj_Notes('Create',Parms)
end
// Send reminders of expired lots not yet NCR'd, which should trigger deletion of MAKEUP_WAFERS record when quantity reaches zero.
NotifyList = ''
ThresholdDtm = SRP_Datetime('AddHours', Datetime(), -12)
ThresholdDtm = OConv(ThresholdDtm, 'DT2/^H')
Query = 'SELECT MAKEUP_WAFERS WITH EXPIRED EQ ':True$:' AND WITH EXPIRY_LAST_NOTIFY_DTM LT ':Quote(ThresholdDtm)
Flag = ''
RList(Query, TARGET_ACTIVELIST$, '', '', Flag)
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = 'Notification RList Flag = ':Flag:'. @RecCount = ':@RecCount
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
EOF = False$
Loop
Readnext WOMatKey else EOF = True$
Until EOF
WONo = Field(WOMatKey, '*', 1)
ReactType = Xlate('WO_LOG', WONo, 'REACT_TYPE', 'X')
If ReactType EQ 'EPP' then
CassNo = Field(WOMatKey, '*', 2)
HoldEntityID = WONo:'*1*':CassNo
end else
HoldEntityID = Xlate('WO_MAT', WOMatKey, 'RDS_NO', 'X')
end
MUWfrRec = Database_Services('ReadDataRow', 'MAKEUP_WAFERS', WOMatKey)
If Error_Services('NoError') then
HaveLock = Database_Services('GetKeyIDLock', 'MAKEUP_WAFERS', WOMatKey, True$)
If HaveLock then
MUWfrRec<MAKEUP_WAFERS.EXPIRY_LAST_NOTIFY_DTM$> = NotifyDtm
Database_Services('WriteDataRow', 'MAKEUP_WAFERS', WOMatKey, MUWfrRec, True$, False$, False$)
If Error_Services('NoError') then
NotifyList<-1> = ReactType:TAB$:HoldEntityID
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = 'Updated expiry notify dtm for expired lot "':WOMatKey:'".'
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
end else
ErrorMsg = Error_Services('GetMessage')
LogMsg = 'Failed to send notification for expired lot "':WOMatKey:'". Error updating MAKEUP_WAFERS record.'
LogMsg := 'Error message: ':ErrorMsg
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = LogMsg
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
SelfLocked = Database_Services('IsKeyIDSelfLocked', 'MAKEUP_WAFERS', WOMatKey)
If SelfLocked then Database_Services('ReleaseKeyIDLock', 'MAKEUP_WAFERS', WOMatKey)
end
end else
LogMsg = 'MAKEUP_WAFERS record for expired lot "':WOMatKey:'" is locked. Service will attempt again on next service call.'
LogMsg := 'Error message: ':ErrorMsg
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = LogMsg
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
end
end else
ErrorMsg = Error_Services('GetMessage')
LogMsg = 'Failed to send notification for expired lot "':WOMatKey:'". Error reading MAKEUP_WAFERS record.'
LogMsg := 'Error message: ':ErrorMsg
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = LogMsg
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
end
Repeat
If (NotifyList NE '') then
Recipients = ''
SentFrom = 'SYSTEM'
Subject = 'Makeup Wafer Auto-Hold Report'
AttachWindow = ''
AttachKey = ''
SendToGroup = 'AUTO_HOLD'
Message = 'The following makeup cassettes are older than three years and have been automatically '
Message := 'placed on hold.':CRLF$:'Reminder: EpiPro lots can contain multiple RDS lots.':CRLF$:CRLF$
Swap @FM with CRLF$ in NotifyList
Message := NotifyList
Parms = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
obj_Notes('Create',Parms)
end
LogData = ''
LogData<1> = OConv(Datetime(), 'DT2/^H')
LogData<2> = 'End ':Service
Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
Unlock hSysLists, ServiceKeyID else Null
end
end service
//----------------------------------------------------------------------------------------------------------------------
// GetAvailableMakeupWafers
//
// Returns an array of available makeup wafers for the indicated work order.
//
// <1> = Cassettes with final RDS signature (i.e., available to use).
// <2> = Cassettes still missing final RDS signature.
//
// Data within each field mark will be @VM row and @SVM column limited.
//----------------------------------------------------------------------------------------------------------------------
Service GetAvailableMakeupWafers(WorkOrderNo, KeysOnly=BOOLEAN)
AvailableMakeupWafers = ''
If UseMakeupWafersTable EQ False$ then
If WorkOrderNo NE '' then
WorkOrderNo = WorkOrderNo[1, '*'] ; // This might be formatted as a WO_MAT Key ID, so strip off the Cassette No.
WOLogRow = Database_Services('ReadDataRow', 'WO_LOG', WorkOrderNo)
If Error_Services('NoError') then
WOStepKeys = WOLogRow<WO_LOG_WO_STEP_KEY$>
WOMatKeys = WOLogRow<WO_LOG_WO_MAT_KEY$>
FirstWOMatKey = WOMatKeys<0, 1>
WOMatRow = Database_Services('ReadDataRow', 'WO_MAT', FirstWOMatKey)
If Error_Services('NoError') then
PartNo = WOMatRow<WO_MAT_CUST_PART_NO$>
LastWOStepKey = WOStepKeys[-1, 'B' : @VM]
WOStepRow = Database_Services('ReadDataRow', 'WO_STEP', LastWOStepKey)
If Error_Services('NoError') then
WOStepPSN = WOStepRow<WO_STEP_PROD_SPEC_ID$>
WOStepRDSNos = WOStepRow<WO_STEP_RDS_KEY$>
WOStepWMOutNos = WOStepRow<WO_STEP_WM_OUT_KEYS$>
ProdSpecRow = Database_Services('ReadDataRow', 'PROD_SPEC', WOStepPSN)
If Error_Services('NoError') then
ReactorType = ProdSpecRow<PROD_SPEC_REACTOR_TYPE$>
SearchString = ''
If (ReactorType EQ 'EPP') OR (ReactorType EQ 'P') then
SearchTable = 'WM_OUT'
SearchString := 'MU_PART_NO' : @VM : PartNo : @FM
end else
SearchTable = 'WO_MAT'
SearchString := 'MAKEUP_BOX' : @VM : 1 : @FM
SearchString := 'CUST_PART_NO' : @VM : PartNo : @FM
end
hDictSearchTable = Database_Services('GetTableHandle', 'DICT.' : SearchTable)
If Error_Services('NoError') then
rv = Set_Status(0)
MakeupBoxes = ''
Flag = ''
StatusCode = ''
Btree.Extract(SearchString, SearchTable, hDictSearchTable, MakeupBoxes, '', Flag)
If Get_Status(StatusCode) then
Error_Services('Add', 'Error calling Btree.Extract in the ' : Service : ' service. StatusCode: ' : StatusCode)
end else
If MakeupBoxes NE '' then
// One or more makeup was found that matches the customer's part and has the status of 'Ready to Use'.
// Now loop through to find out which ones have the RDS final signature or not.
NumMakeupBoxes = DCount(MakeupBoxes, @VM)
For Each MakeupBoxID in MakeupBoxes using @VM
SRP_Stopwatch('Start', 'CurrStatus')
If (ReactorType EQ 'EPP') OR (ReactorType EQ 'P') then
WOMatKeyID = Field(MakeupBoxID, '*', 1) : '*' : Field(MakeupBoxID, '*', 3)
CurrStatus = obj_WM_Out('CurrStatus', MakeupBoxID)
end else
WOMatKeyID = MakeupBoxID
CurrStatus = obj_WO_Mat('CurrStatus', WOMatKeyID)
end
// DPC 7/21/20 added HOLD as excluded status type
Locate CurrStatus in 'MT,VOID,SHIP,REJ,HOLD' using ',' setting cPos else
CurrWaferCount = obj_WO_Mat('CurrWaferCnt', WOMatKeyID)
If CurrWaferCount GT 0 then
WOMatRow = Database_Services('ReadDataRow', 'WO_MAT', WOMatKeyID)
RDSKeyIDs = WOMatRow<WO_MAT_RDS_NO$>
SAPBatchNo = WOMatRow<WO_MAT_SAP_BATCH_NO$>
FirstRDSKeyID = RDSKeyIDs[1, @VM]
RDSRow = Database_Services('ReadDataRow', 'RDS', FirstRDSKeyID)
ThisWorkOrderNo = WOMatKeyID[1, '*']
ThisCassetteNo = WOMatKeyID[Col2() + 1, '*']
ThisWOLogRow = Database_Services('ReadDataRow', 'WO_LOG', ThisWorkOrderNo)
ThisWOStepKeyID = ThisWOLogRow<WO_LOG_WO_STEP_KEY$>[-1, 'B' : @VM]
ThisWOStepRow = Database_Services('ReadDataRow', 'WO_STEP', ThisWOStepKeyID)
WOStepRDSNos = ThisWoStepRow<WO_STEP_RDS_KEY$>
MakeupBoxDet = ThisWorkOrderNo : @SVM
MakeupBoxDet := ThisCassetteNo : @SVM
MakeupBoxDet := WOMatRow<WO_MAT_SAP_BATCH_NO$> : @SVM
MakeupBoxDet := ThisWOStepRow<WO_STEP_PROD_SPEC_ID$> : @SVM
MakeupBoxDet := PartNo : @SVM
MakeupBoxDet := CurrWaferCount : @SVM
MakeupBoxDet := FirstRDSKeyID
// JRO Added PROD_SPEC PARAMETERS 5/8/2020
If (ReactorType EQ 'EPP') OR (ReactorType EQ 'P') then
ProdSpecID = Xlate('RDS', WOStepRDSNos<1, 1>, 114, 'X')
end else
ProdSpecID = Xlate('RDS', RDSKeyIDs, 114, 'X')
end
ActiveStatus = XLATE('PROD_SPEC', ProdSpecID, 9, 'X')
// JRO Added the extra condition for Active Status 5/8/2020
If ActiveStatus EQ 'A' then
If (RDSRow<RDS_SUP_VER_SIG$> NE '') OR ((ReactorType EQ 'EPP') OR (ReactorType EQ 'P')) then
// Has a RDS final signature.
If KeysOnly EQ True$ then
If (ReactorType EQ 'EPP') OR (ReactorType EQ 'P') then
AvailableMakeupWafers = Insert(AvailableMakeupWafers, 1, -1, 0, MakeupBoxID)
end else
AvailableMakeupWafers = Insert(AvailableMakeupWafers, 1, -1, 0, WOMatKeyID)
end
end else
AvailableMakeupWafers = Insert(AvailableMakeupWafers, 1, -1, 0, MakeupBoxDet)
end
end else
// Does not have a RDS final signature.
If KeysOnly EQ True$ then
AvailableMakeupWafers = Insert(AvailableMakeupWafers, 2, -1, 0, WOMatKeyID)
end else
AvailableMakeupWafers = Insert(AvailableMakeupWafers, 2, -1, 0, MakeupBoxDet)
end
end
end
end
end
Next MakeupBoxID
end
end
end
end
end
end
end
end else
Error_Services('Add', 'WorkOrderNo argument was missing from the ' : Service : ' service.')
end
end else
If WorkOrderNo NE '' then
WorkOrderNo = WorkOrderNo[1, '*'] ; // This might be formatted as a WO_MAT Key ID, so strip off the Cassette No.
WOLogRow = Database_Services('ReadDataRow', 'WO_LOG', WorkOrderNo)
If Error_Services('NoError') then
WOStepKeys = WOLogRow<WO_LOG_WO_STEP_KEY$>
WOMatKeys = WOLogRow<WO_LOG_WO_MAT_KEY$>
FirstWOMatKey = WOMatKeys<0, 1>
WOMatRow = Database_Services('ReadDataRow', 'WO_MAT', FirstWOMatKey)
If Error_Services('NoError') then
PartNo = WOMatRow<WO_MAT_CUST_PART_NO$>
LastWOStepKey = WOStepKeys[-1, 'B' : @VM]
WOStepRow = Database_Services('ReadDataRow', 'WO_STEP', LastWOStepKey)
If Error_Services('NoError') then
WOStepPSN = WOStepRow<WO_STEP_PROD_SPEC_ID$>
WOStepRDSNos = WOStepRow<WO_STEP_RDS_KEY$>
WOStepWMOutNos = WOStepRow<WO_STEP_WM_OUT_KEYS$>
ProdSpecRow = Database_Services('ReadDataRow', 'PROD_SPEC', WOStepPSN)
If Error_Services('NoError') then
ReactorType = ProdSpecRow<PROD_SPEC_REACTOR_TYPE$>
SearchString = ''
SearchTable = 'MAKEUP_WAFERS'
If ReactorType EQ 'EPP' then
SearchString := 'EPI_PART_NO' : @VM : PartNo : @FM : 'REACT_TYPE' : @VM : 'EPP' : @FM
end else
SearchString := 'EPI_PART_NO' : @VM : PartNo : @FM : 'REACT_TYPE' : @VM : '#EPP' : @FM
end
hDictSearchTable = Database_Services('GetTableHandle', 'DICT.' : SearchTable)
If Error_Services('NoError') then
rv = Set_Status(0)
MakeupBoxes = ''
Flag = ''
StatusCode = ''
Btree.Extract(SearchString, SearchTable, hDictSearchTable, MakeupBoxes, '', Flag)
If Get_Status(StatusCode) then
Error_Services('Add', 'Error calling Btree.Extract in the ' : Service : ' service. StatusCode: ' : StatusCode)
end else
If MakeupBoxes NE '' then
// One or more makeup was found that matches the customer's part and has the status of 'Ready to Use'.
// Now loop through to find out which ones have the RDS final signature or not.
NumMakeupBoxes = DCount(MakeupBoxes, @VM)
For Each MakeupBoxID in MakeupBoxes using @VM
WOMatKeyID = MakeupBoxID
CurrStatus = Xlate('MAKEUP_WAFERS', MakeupBoxID, 'CURR_STATUS_STATIC', 'X')
// DPC 7/21/20 added HOLD as excluded status type
Locate CurrStatus in 'MT,VOID,SHIP,REJ,HOLD' using ',' setting cPos else
CurrWaferCount = obj_WO_Mat('CurrWaferCnt', WOMatKeyID)
If CurrWaferCount GT 0 then
WOMatRow = Database_Services('ReadDataRow', 'WO_MAT', WOMatKeyID)
RDSKeyIDs = WOMatRow<WO_MAT_RDS_NO$>
SAPBatchNo = WOMatRow<WO_MAT_SAP_BATCH_NO$>
FirstRDSKeyID = RDSKeyIDs[1, @VM]
RDSRow = Database_Services('ReadDataRow', 'RDS', FirstRDSKeyID)
WMOKey = WOMatRow<WO_MAT_WMO_KEY$>
If WMOKey NE '' then
WMOFQASig = Xlate('WM_OUT', WMOKey, 'SUP_VER_SIG', 'X')
end else
WMOFQASig = ''
end
ThisWorkOrderNo = WOMatKeyID[1, '*']
ThisCassetteNo = WOMatKeyID[Col2() + 1, '*']
ThisWOLogRow = Database_Services('ReadDataRow', 'WO_LOG', ThisWorkOrderNo)
ThisWOStepKeyID = ThisWOLogRow<WO_LOG_WO_STEP_KEY$>[-1, 'B' : @VM]
ThisWOStepRow = Database_Services('ReadDataRow', 'WO_STEP', ThisWOStepKeyID)
WOStepRDSNos = ThisWoStepRow<WO_STEP_RDS_KEY$>
MakeupBoxDet = ThisWorkOrderNo : @SVM
MakeupBoxDet := ThisCassetteNo : @SVM
MakeupBoxDet := WOMatRow<WO_MAT_SAP_BATCH_NO$> : @SVM
MakeupBoxDet := ThisWOStepRow<WO_STEP_PROD_SPEC_ID$> : @SVM
MakeupBoxDet := PartNo : @SVM
MakeupBoxDet := CurrWaferCount : @SVM
MakeupBoxDet := FirstRDSKeyID
// JRO Added PROD_SPEC PARAMETERS 5/8/2020
If (ReactorType EQ 'EPP') OR (ReactorType EQ 'P') then
ProdSpecID = Xlate('RDS', WOStepRDSNos<1, 1>, RDS_PROD_SPEC_ID$, 'X')
end else
ProdSpecID = Xlate('RDS', RDSKeyIDs, RDS_PROD_SPEC_ID$, 'X')
end
ActiveStatus = XLATE('PROD_SPEC', ProdSpecID, PROD_SPEC_STATUS$, 'X')
// JRO Added the extra condition for Active Status 5/8/2020
If ActiveStatus EQ 'A' then
Begin Case
Case SAPBatchNo EQ ''
// Cassette has not received a batch number from SAP, so it is not yet eligible to be used.
FieldPos = 3
Case ( (ReactorType NE 'EPP') and (RDSRow<RDS_SUP_VER_SIG$> NE '') ) OR ( (ReactorType EQ 'EPP') and (WMOFQASig NE '') )
// Cassette has a final signature, so it is eligible to be used.
FieldPos = 1
Case ( (ReactorType NE 'EPP') and (RDSRow<RDS_SUP_VER_SIG$> EQ '') ) OR ( (ReactorType EQ 'EPP') and (WMOFQASig EQ '') )
// Cassette does not yet have a final signature, so it is not yet eligible to be used.
FieldPos = 2
Case Otherwise$
// Log these cassettes as we should never end up here.
Null
End Case
If KeysOnly EQ True$ then
If (ReactorType EQ 'EPP') OR (ReactorType EQ 'P') then
WMOFormat = Field(MakeupBoxID, '*', 1):'*1*':Field(MakeupBoxID, '*', 2)
AvailableMakeupWafers = Insert(AvailableMakeupWafers, FieldPos, -1, 0, WMOFormat)
end else
AvailableMakeupWafers = Insert(AvailableMakeupWafers, FieldPos, -1, 0, WOMatKeyID)
end
end else
AvailableMakeupWafers = Insert(AvailableMakeupWafers, FieldPos, -1, 0, MakeupBoxDet)
end
end
end
end
Next MakeupBoxID
end
end
end
end
end
end
end
end else
Error_Services('Add', 'WorkOrderNo argument was missing from the ' : Service : ' service.')
end
end
Response = AvailableMakeupWafers
end service
Service UpdateWOMatStatus(WOMatKey)
If WOMatKey NE '' then
WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey)
WOMatCurrStatus = obj_WO_Mat('CurrStatus', WOMatKey:@RM:WOMatRec)
WOMatCurrStatus = WOMatCurrStatus[-1, 'B':@VM]
// Get a fresh copy of the record.
WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey)
WOMatCurrStatusStatic = WOMatRec<WO_MAT_CURR_STATUS_STATIC$>
If WOMatCurrStatus NE WOMatCurrStatusStatic then
WOMatRec<WO_MAT_CURR_STATUS_STATIC$> = WOMatCurrStatus
Database_Services('WriteDataRow', 'WO_MAT', WOMatKey, WOMatRec, True$, False$, True$)
LogData = ''
LogData<1> = LoggingDTM
LogData<2> = @User4
LogData<3> = WOMatKey
LogData<4> = WOMatCurrStatusStatic
LogData<5> = WOMatCurrStatus
Logging_Services('AppendLog', objStatusLog, LogData, @RM, @FM)
end
Database_Services('ReleaseKeyIDLock', 'WO_MAT', WOMatKey)
end
end service
Service PostWOMatUpdateRequest(WOMatKey)
If WOMatKey NE '' then
// Look for a pre-existing request in the queue
If (RowExists('WO_MAT_QUEUE', WOMatKey) EQ False$) then
// This is a new request
RequestKeyID = WOMatKey
RequestRow = ''
RequestRow<WO_MAT_QUEUE.REQUEST_DTM$> = Datetime()
Database_Services('WriteDataRow', 'WO_MAT_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 ProcessWOMatUpdateRequests()
hSysLists = Database_Services('GetTableHandle', 'SYSLISTS')
Lock hSysLists, ServiceKeyID then
Open 'WO_MAT_QUEUE' to hTable then
Select hTable
EOF = False$
Loop
ReadNext RequestKeyID else EOF = True$
Until EOF EQ True$
WOMatKey = RequestKeyID
Material_Services('UpdateWOMatStatus', WOMatKey)
If Error_Services('NoError') then
// Successfully updated the current status, so delete the request from the queue.
Database_Services('DeleteDataRow', 'WO_MAT_QUEUE', RequestKeyID, True$, True$)
end
Repeat
end else
ErrorMsg = 'Error opening WO_MAT_QUEUE in ':Service:' service.'
end
Unlock hSysLists, ServiceKeyID else Null
end
end service
Service UpdateWMOutStatus(WMOKey)
If WMOKey NE '' then
WMOutRec = Database_Services('ReadDataRow', 'WM_OUT', WMOKey)
WMOutCurrStatus = obj_WM_Out('CurrStatus', WMOKey:@RM:WMOutRec)
// Get a fresh copy of the record
WMOutRec = Database_Services('ReadDataRow', 'WM_OUT', WMOKey)
WMOutCurrStatusStatic = WMOutRec<WM_OUT_CURR_STATUS_STATIC$>
If WMOutCurrStatus NE WMOutCurrStatusStatic then
WMOutRec<WM_OUT_CURR_STATUS_STATIC$> = WMOutCurrStatus
Database_Services('WriteDataRow', 'WM_OUT', WMOKey, WMOutRec, True$, False$, True$)
end
Database_Services('ReleaseKeyIDLock', 'WM_OUT', WMOKey)
end
end service
Service UpdateRDSStatus(RDSNo)
If RDSNo NE '' then
RDSCombStatus = Xlate('RDS', RDSNo, 'COMB_STATUS', 'X')
// Get a fresh copy of the record
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
RDSCombStatusStatic = RDSRec<RDS_COMB_STATUS_STATIC$>
If RDSCombStatus NE RDSCombStatusStatic then
RDSRec<RDS_COMB_STATUS_STATIC$> = RDSCombStatus
Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, True$, True$)
end
end
end service
Service PostRDSUpdateRequest(RDSNo)
If RDSNo NE '' then
// Look for a pre-existing request in the queue
If (RowExists('WM_OUT_QUEUE', RDSNo) EQ False$) then
// This is a new request
RequestKeyID = RDSNo
RequestRow = ''
RequestRow<RDS_QUEUE.REQUEST_DTM$> = Datetime()
Database_Services('WriteDataRow', 'RDS_QUEUE', RequestKeyID, RequestRow, False$, False$, False$)
end else
// Duplicate request - ignore it.
Null
end
end else
Error_Services('Add', 'Null parameter passed into service call. All parameters are required.')
end
end service
Service ProcessRDSUpdateRequests()
hSysLists = Database_Services('GetTableHandle', 'SYSLISTS')
Lock hSysLists, ServiceKeyID then
Open 'RDS_QUEUE' to hTable then
Select hTable
EOF = False$
Loop
ReadNext RequestKeyID else EOF = True$
Until EOF EQ True$
RDSNo = RequestKeyID
Material_Services('UpdateRDSStatus', RDSNo)
If Error_Services('NoError') then
// Successfully updated the current status, so delete the request from the queue.
Database_Services('DeleteDataRow', 'RDS_QUEUE', RequestKeyID, True$, True$)
end
Repeat
end else
ErrorMsg = 'Error opening RDS_QUEUE in ':Service:' service.'
end
Unlock hSysLists, ServiceKeyID else Null
end
end service
Service PostWMOutUpdateRequest(WMOKey)
If WMOKey NE '' then
// Look for a pre-existing request in the queue
If (RowExists('WM_OUT_QUEUE', WMOKey) EQ False$) then
// This is a new request
RequestKeyID = WMOKey
RequestRow = ''
RequestRow<WM_OUT_QUEUE.REQUEST_DTM$> = Datetime()
Database_Services('WriteDataRow', 'WM_OUT_QUEUE', RequestKeyID, RequestRow, False$, False$, False$)
end else
// Duplicate request - ignore it.
Null
end
end else
Error_Services('Add', 'Null parameter passed into service call. All parameters are required.')
end
end service
Service ProcessWMOutUpdateRequests()
hSysLists = Database_Services('GetTableHandle', 'SYSLISTS')
Lock hSysLists, ServiceKeyID then
Open 'WM_OUT_QUEUE' to hTable then
Select hTable
EOF = False$
Loop
ReadNext RequestKeyID else EOF = True$
Until EOF EQ True$
WMOKey = RequestKeyID
Material_Services('UpdateWMOutStatus', WMOKey)
If Error_Services('NoError') then
// Successfully updated the current status, so delete the request from the queue.
Database_Services('DeleteDataRow', 'WM_OUT_QUEUE', RequestKeyID, True$, True$)
end
Repeat
end else
ErrorMsg = 'Error opening WM_OUT_QUEUE in ':Service:' service.'
end
Unlock hSysLists, ServiceKeyID else Null
end
end service
Service PostWfrLocUpdate(WMOKey)
Swap '.' with '*' in WMOKey
WONo = Field(WMOKey, '*', 1)
CassNo = Field(WMOKey, '*', 2)
WOMatKey = WONo:'*':CassNo
If RowExists('WO_MAT', WOMatKey) then
WfrList = Xlate('WO_MAT_WFR', WOMatKey, 'OUT_WFR_ID', 'X')
GaNWfrIDs = Xlate('WO_WFR', WfrList, 'GAN_WFR_ID', 'X')
WfrLocs = Xlate('WO_WFR', WfrList, 'CUST_NAME', 'X')
For each Wfr in GaNWfrIDs using @VM setting vPos
LocationName = WfrLocs<0, vPos>
GaNWfrID = GaNWfrIDs<0, vPos>
SQLStatement = 'UPDATE [G4Wafers_01].[dbo].[Wafer Location] '
SQLStatement := "SET Main_Location = '":LocationName:"', Main_Form = 'FULL' "
SQLStatement := "WHERE Wafer_ID = '":GaNWfrID:"'"
SQL_Services('PostSQLStatement', 'IQSDMS1', SQLStatement)
Next Wfr
end
end service
Service UpdateWaferLocation(WMOKey)
Swap '.' with '*' in WMOKey
WONo = Field(WMOKey, '*', 1)
CassNo = Field(WMOKey, '*', 2)
WOMatKey = WONo:'*':CassNo
If RowExists('WO_MAT', WOMatKey) then
WfrList = Xlate('WO_MAT_WFR', WOMatKey, 'OUT_WFR_ID', 'X')
GaNWfrIDs = Xlate('WO_WFR', WfrList, 'GAN_WFR_ID', 'X')
WfrLocs = Xlate('WO_WFR', WfrList, 'CUST_NAME', 'X')
objConn = Sql_Services('GetConnectionObject', 'IQSDMS1')
For each Wfr in GaNWfrIDs using @VM setting vPos
LocationName = WfrLocs<0, vPos>
GaNWfrID = GaNWfrIDs<0, vPos>
SQLStatement = 'UPDATE [G4Wafers_01].[dbo].[Wafer Location] '
SQLStatement := "SET Main_Location = '":LocationName:"', Main_Form = 'FULL' "
SQLStatement := "WHERE Wafer_ID = '":GaNWfrID:"'"
SQL_Services('ExecuteQuery', objConn, SQLStatement, 0, 1)
Next Wfr
end
end service
Service VerifyEPPUnload(RDSNo)
ErrorMsg = ''
If RDSNo NE '' then
// Verify RDS and REACT_RUN outbound cassette data matches.
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
RDSOutCassNos = RDSRec<RDS_OUT_CASS_NO$>
RDSOutSlotNos = RDSRec<RDS_OUT_SLOT_NO$>
RRRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo)
RROutCassNos = RRRec<REACT_RUN_OUT_CASS_NO$>
RROutSlotNos = RRRec<REACT_RUN_OUT_SLOT_NO$>
If ( (RDSOutCassNos NE RROutCassNos) or (RDSOutSlotNos NE RROutSlotNos) ) then
ErrorMsg = 'Error in ':Service:' service. RDS and REACT_RUN mismatch for key ':RDSNo:'!'
end else
WONo = RDSRec<RDS_WO$>
// Verify WM_OUT outbound cassette data matches
RDSInCassNos = RDSRec<RDS_IN_CASS_NO$>
RDSInSlotNos = RDSRec<RDS_IN_SLOT_NO$>
If RDSOutCassNos NE '' then
For each OutCassNo in RDSOutCassNos using @VM setting vPos
// TEST wafers are not placed in outbound cassettes.
If OutCassNo NE '' then
// Open WM_OUT record, go to the out slot and verify that the IN_CASS_NO and IN_SLOT_NO match.
WMOutKey = WONo:'*1*':OutCassNo
WMOutRec = Database_Services('ReadDataRow', 'WM_OUT', WMOutKey)
OutSlotNo = RDSOutSlotNos<0, vPos>
WMOInCassNo = WMOutRec<WM_OUT_IN_CASS_NO$, OutSlotNo>
WMOInSlotNo = WMOutRec<WM_OUT_IN_SLOT_NO$, OutSlotNo>
RDSInCassNo = RDSInCassNos<0, vPos>
RDSInSlotNo = RDSInSlotNos<0, vPos>
If (WMOInCassNo EQ RDSInCassNo) and (WMOInSlotNo EQ RDSInSlotNo) then
// Data matches
Null
end else
// Data mismatch - throw error
ErrorMsg = 'Error in ':Service:' service. RDS and WM_OUT mismatch for inbound wafer ':RDSInCassNo:'*':RDSInSlotNo:'!'
end
end
Until ErrorMsg NE ''
Next OutCassNo
end else
ErrorMsg = 'Error in ':Service:' service. RDS out cassettes numbers are null!'
end
end
end else
ErrorMsg = 'Error in ':Service:' service. Null RDSNo passed in!'
end
If ErrorMsg NE '' then
Error_Services('Add', 'Error in ':Service:' service. Error message: ':ErrorMsg)
Response = False$
end else
Response = True$
end
end service
Service ConvertMaterial(WONo, CassNos, NewPVNo)
NewWONo = ''
ErrorMsg = ''
If RowExists('WO_LOG', WONo) then
If CassNos NE '' then
Swap @FM with @VM in CassNos
WOMatKeys = ''
For each CassNo in CassNos using @VM setting vPos
WOMatKeys<0, vPos> = WONo:'*':CassNo
MakeupFlag = Xlate('WO_MAT', WONo:'*':CassNo, WO_MAT_MAKEUP_BOX$, 'X')
If MakeupFlag then
ErrorMsg = 'Error in ':Service:' service. Cassette ':WONo:'*':CassNo:' is a makeup box and cannot be converted to a different part number.'
end
If ( (ErrorMsg EQ '') and (Not(RowExists('WO_MAT', WONo:'*':CassNo) ) ) ) then
ErrorMsg = 'Error in ':Service:' service. Cassette ':WONo:'*':CassNo:' does not exist.'
end
Until ErrorMsg NE ''
Next CassNo
If ErrorMsg EQ '' then
If RowExists('PROD_VER', NewPVNo) then
* 1. Create new WO with coresponding Part no, PSN, EpiPartNo, Cust Epi Part, Sub Part No, Revised Quantity(Peeled off amount coming back)
* -Subtract MU wafer quantity(original amount that is apart of a MU lot, 1 MU lot = 25 wafers)
// Generate new internal production order number to associate with the new work order.
NumAttempts = 0
HaveLock = False$
Loop
NumAttempts += 1
HaveLock = Database_Services('GetKeyIDLock', 'APP_INFO', 'CURR_INT_PROD_ORD_NO')
Until HaveLock or NumAttempts EQ 10
Repeat
If HaveLock then
CurrIntProdOrdNo = Database_Services('ReadDataRow', 'APP_INFO', 'CURR_INT_PROD_ORD_NO')
NextIntProdOrdNo = CurrIntProdOrdNo + 1
NewIntProdOrdNo = 'IFX' : Fmt(NextIntProdOrdNo, 'R(0)#4') : '.1'
NewEpiPartNo = Xlate('PROD_VER', NewPVNo, PROD_VER_EPI_PART_NO$, 'X')
SubPartNo = Xlate('PROD_VER', NewPVNo, PROD_VER_SUB_PART_NO$, 'X')
SubPartRev = Xlate('WO_LOG', WONo, WO_LOG_ORD_SUB_PART_REV$, 'X')
NewWOQty = Sum(Xlate('WO_MAT', WOMatKeys, WO_MAT_WAFER_QTY$, 'X'))
VendCd = Xlate('WO_LOG', WONo, WO_LOG_EXP_VEND_CD$, 'X')
NewCustNo = Xlate('PROD_VER', NewPVNo, PROD_VER_CUST_NO$, 'X')
NewPSNo = Xlate('PROD_VER', NewPVNo, PROD_VER_PROC_STEP_PSN$, 'X')
If ( (NewIntProdOrdNo NE '') and (NewEpiPartNo NE '') and (SubPartNo NE '') and (NewWOQty NE '') and (VendCd NE '') and (NewCustNo NE '') and (NewPSNo NE '') ) then
MockSAPFile = ''
MockSAPFile<0, 1> = NewIntProdOrdNo ; // Prod Ord No - Must match "'M'6N'.1'" OR "7X'.1'" and not conflict with SAP
MockSAPFile<0, 2> = 'NA' ; // CustPONo - Not Applicable
MockSAPFile<0, 3> = Date() + 365 ; // Promise Ship Date - Hard coded to a year from today
MockSAPFile<0, 4> = NewEpiPartNo ; // EpiPartNo - Changing from original work order
MockSAPFile<0, 5> = SubPartNo ; // SubPartNo - Not changing from original work order
MockSAPFile<0, 6> = SubPartRev ; // SubRevNo - Not changing from original work order
MockSAPFile<0, 7> = NewWOQty ; // WOQty - Quantity of material moving to new work order
MockSAPFile<0, 8> = VendCd ; // VendCd - Not changing from original work order
Success = obj_WO_Log('SAPCreate', MockSAPFile)
If Success then
// obj_WO_Log('SAPCreate') does not return new work order number, so look it up instead.
SearchString = 'PROD_ORD_NO':@VM:NewIntProdOrdNo:@FM
Open 'DICT.WO_LOG' to hDict then
Flag = ''
Btree.Extract(SearchString, 'WO_LOG', hDict, NewWONo, 'E', Flag)
// Check for successful query
If Flag EQ 0 then
// There should only be one work order associated with our unique internal production order number.
If (DCount(NewWONo, @VM) EQ 1) then
// Associate new work order with the part number passed in.
obj_WO_Log('Route', NewWONo:@RM:NewPVNo)
ErrCode = ''
If Not(Get_Status(ErrCode)) then
// Start "migrating" WO_MAT, RDS, etc. entities from previous work order to new work order.
NewWOStepKey = NewWONo:'*1'
NewCassNo = 0
NewWOMatKeys = ''
RDSKeys = Xlate('WO_MAT', WOMatKeys, 'RDS_NO', 'X')
For each WOMatKey in WOMatKeys using @VM setting vPos
NewCassNo += 1
RDSKey = RDSKeys<0, vPos>
CassNo = Field(WOMatKey, '*', 2)
WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey)
If Error_Services('NoError') then
NewWOMatKey = NewWONo:'*':NewCassNo
NewWOMatKeys<0, -1> = NewWOMatKey
NewWOMatRec = WOMatRec
// Modify WO_MAT fields INV_... (6-10, 31, 103, 142), Cust Part No(3), Part No(22)
// Clear material log starting at 1QA
InvActions = WOMatRec<WO_MAT_INV_ACTION$>
Locate '1QA' in InvActions using @VM setting aPos then
NewWOMatRec<WO_MAT_INV_WH$> = Field(WOMatRec<WO_MAT_INV_WH$>, @VM, 1, aPos - 1)
NewWOMatRec<WO_MAT_INV_LOCATION$> = Field(WOMatRec<WO_MAT_INV_LOCATION$>, @VM, 1, aPos - 1)
NewWOMatRec<WO_MAT_INV_ACTION$> = Field(WOMatRec<WO_MAT_INV_ACTION$>, @VM, 1, aPos - 1)
NewWOMatRec<WO_MAT_INV_DTM$> = Field(WOMatRec<WO_MAT_INV_DTM$>, @VM, 1, aPos - 1)
NewWOMatRec<WO_MAT_INV_USER$> = Field(WOMatRec<WO_MAT_INV_USER$>, @VM, 1, aPos - 1)
NewWOMatRec<WO_MAT_INV_TAG$> = Field(WOMatRec<WO_MAT_INV_TAG$>, @VM, 1, aPos - 1)
NewWOMatRec<WO_MAT_INV_SCAN_ENTRY$> = Field(WOMatRec<WO_MAT_INV_SCAN_ENTRY$>, @VM, 1, aPos - 1)
NewWOMatRec<WO_MAT_INV_TOOL_ID$> = Field(WOMatRec<WO_MAT_INV_TOOL_ID$>, @VM, 1, aPos - 1)
end
NewWOMatRec<WO_MAT_CUST_PART_NO$> = NewEpiPartNo
NewWOMatRec<WO_MAT_PROD_VER_NO$> = NewPVNo
NewWOMatRec<WO_MAT_SHIP_NO$> = '' ; // Clear ship number to prevent status of "Shipped" and to allow for re-ship.
NewWOMatRec<WO_MAT_CONVERTED_MATERIAL$> = True$ ; // This flag is used to override INSP_REQ calculated column in CLEAN_INSP.
Database_Services('WriteDataRow', 'WO_MAT', NewWOMatKey, NewWOMatRec)
If Error_Services('NoError') then
NCRKeys = WOMatRec<WO_MAT_NCR_KEYS$>
If NCRKeys NE '' then
For each NCRKey in NCRKeys using @VM setting nPos
NCRRec = Database_Services('ReadDataRow', 'NCR', NCRKey)
If Error_Services('NoError') then
// Modify NCR fields WO_NO(62), WO_MAT_CASS_NO(64), REJ_WAFER_ID(Change first two fields, third will stay the same(Probably MV))(67)
NewNCRRec = NCRRec
NewNCRRec<NCR_WO_NO$> = NewWONo
NewNCRRec<NCR_WO_MAT_CASS_NO$> = NewCassNo
WfrIDs = NCRRec<NCR_REJ_WAFER_ID$>
If WfrIDs NE '' then
For each WfrID in WfrIDs using @VM setting wPos
NewNCRRec<0, wPos> = NewWONo:'.':NewCassNo:'.':Field(WfrID, '.', 3)
Next WfrID
end
Database_Services('WriteDataRow', 'NCR', NCRKey, NewNCRRec, True$, False$, True$)
end else
ErrorMsg = Error_Services('GetMessage')
end
Until ErrorMsg NE ''
Next NCRKey
end
If ErrorMsg EQ '' then
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSKey)
If Error_Services('NoError') then
// Modify RDS fields Epi Part No(10), WO(6), Cust No(9), Prod_Spec_Id(114), WO_STEP_KEY(256), CASS_NO(260)
NewRDSRec = RDSRec
NewRDSRec<RDS_WO$> = NewWONo
NewRDSRec<RDS_CUST_NO$> = NewCustNo
NewRDSRec<RDS_PART_NUM$> = NewEpiPartNo
NewRDSRec<RDS_PROD_SPEC_ID$> = NewPSNo
NewRDSRec<RDS_WO_STEP_KEY$> = NewWOStepKey
NewRDSRec<RDS_CASS_NO$> = NewCassNo
NewRDSRec<RDS_SUP_VER_SIG$> = '' ; // Clear FQA signature to prevent MFS from blocking write and to re-require FQA
NewRDSRec<RDS_SUP_VER_SIG_DATE$> = ''
NewRDSRec<RDS_SUP_VER_SIG_TIME$> = ''
Database_Services('WriteDataRow', 'RDS', RDSKey, NewRDSRec, True$, False$, True$)
If Error_Services('NoError') then
// Copy WO_MAT_QA record (no changes necessary)
WOMatQARec = Database_Services('ReadDataRow', 'WO_MAT_QA', WOMatKey)
Database_Services('WriteDataRow', 'WO_MAT_QA', NewWOMatKey, WOMatQARec)
If Error_Services('NoError') then
// Modify REACT_RUN fields WO_NO(1), CASS_NO(3), CI_NO(Dont remove, but capture value, may be MV. Field 6)
ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSKey)
If Error_Services('NoError') then
NewReactRunRec = ReactRunRec
NewReactRunRec<REACT_RUN_WO_NO$> = NewWONo
NewReactRunRec<REACT_RUN_CASS_NO$> = NewCassNo
Database_Services('WriteDataRow', 'REACT_RUN', RDSKey, NewReactRunRec, True$, False$, True$)
If Error_Services('NoError') then
CINos = ReactRunRec<REACT_RUN_CI_NO$>
If CINos NE '' then
For each CINo in CINos using @VM setting cPos
// Modify CLEAN_INSP fields WO_NO(1), CASS_NO(3)
CIRec = Database_Services('ReadDataRow', 'CLEAN_INSP', CINo)
If Error_Services('NoError') then
NewCIRec = CIRec
NewCIRec<CLEAN_INSP_WO_NO$> = NewWONo
NewCIRec<CLEAN_INSP_CASS_NO$> = NewCassNo
Database_Services('WriteDataRow', 'CLEAN_INSP', CINo, NewCIRec, True$, False$, True$)
If Error_Services('HasError') then
ErrorMsg = Error_Services('GetMessage')
end
end else
ErrorMsg = Error_Services('GetMessage')
end
Until ErrorMsg NE ''
Next CINo
end
RDSLayerKeys = ReactRunRec<REACT_RUN_RDS_LAYER_KEYS$>
If RDSLayerKeys NE '' then
For each RDSLayerKey in RDSLayerKeys using @VM
RDSTestKeys = Xlate('RDS_LAYER', RDSLayerKey, RDS_LAYER_RDS_TEST_KEYS$, 'X')
If RDSTestKeys NE '' then
For each RDSTestKey in RDSTestKeys using @VM
TWUseKeys = Xlate('RDS_TEST', RDSTestKey, RDS_TEST_TW_USE_ID$, 'X')
If TWUseKeys NE '' then
For each TWUseKey in TWUseKeys using @VM
TWUseRec = Database_Services('ReadDataRow', 'TW_USE', TWUseKey)
If Error_Services('NoError') then
// Modify TW_USE fields WAFER_ID(19)(Can be multivalue) Change first two fields(WO)(CASS_NO) Third will stay the same.
NewTWUseRec = TWUseRec
TWUseWfrIDs = TWUseRec<TW_USE_WAFER_ID$>
If TWUseWfrIDs NE '' then
For each TWUseWfrID in TWUseWfrIDs using @VM setting tPos
NewTWUseRec<TW_USE_WAFER_ID$, tPos> = NewWONo:'*':NewCassNo:'*':Field(TWUseWfrID, '*', 3)
Next TWUseWfrID
end
Database_Services('WriteDataRow', 'TW_USE', TWUseKey, NewTWUseRec, True$, False$, True$)
end else
ErrorMsg = Error_Services('GetMessage')
end
Until ErrorMsg NE ''
Next TWUseKey
end
Until ErrorMsg NE ''
Next RDSTestKey
end
Until ErrorMsg NE ''
Next RDSLayerKey
end
end else
ErrorMsg = Error_Services('GetMessage')
end
end else
ErrorMsg = Error_Services('GetMessage')
end
end else
ErrorMsg = Error_Services('GetMessage')
end
end else
ErrorMsg = Error_Services('GetMessage')
end
end
end else
ErrorMsg = Error_Services('GetMessage')
end
end else
ErrorMsg = Error_Services('GetMessage')
end
end else
ErrorMsg = Error_Services('GetMessage')
end
Until ErrorMsg NE ''
// Delete old records
Database_Services('DeleteDataRow', 'WO_MAT', WOMatKey, True$, False$)
Database_Services('DeleteDataRow', 'WO_MAT_QA', WOMatKey, True$, False$)
Next WOMatKey
If ErrorMsg EQ '' then
// Update new work order record to contain list of new WO_MAT keys.
NewWORec = Database_Services('ReadDataRow', 'WO_LOG', NewWONo)
If Error_Services('NoError') then
NewWORec<WO_LOG_WO_MAT_KEY$> = NewWOMatKeys
Database_Services('WriteDataRow', 'WO_LOG', NewWONo, NewWORec, True$, False$, True$)
If Error_Services('HasError') then
ErrorMsg = Error_Services('GetMessage')
end
end else
ErrorMsg = Error_Services('GetMessage')
end
If ErrorMsg EQ '' then
// Reduce source work order quantity by new work order quantity
WORec = Database_Services('ReadDataRow', 'WO_LOG', WONo)
WORec<WO_LOG_WO_QTY$> = WORec<WO_LOG_WO_QTY$> - NewWOQty
Database_Services('WriteDataRow', 'WO_LOG', WONo, WORec, True$, False$, True$)
If Error_Services('HasError') then
ErrorMsg = Error_Services('GetMessage')
end
end
end
end else
ErrorMsg = 'Error in ':Service:' service. Error routing work order ':NewWONo:'. Error message: ':ErrCode:'.'
end
end else
ErrorMsg = 'Error in ':Service:' service. Error retrieving new work order number. Btree.Extract result: "':NewWONo:'".'
end
end else
ErrorMsg = 'Error in ':Service:' service. Error calling Btree.Extract.'
end
end else
ErrorMsg = 'Error in ':Service:' service. Failed to open DICT.WO_LOG table.'
end
end else
ErrorMsg = 'Error in ':Service:' service. obj_WO_Log("SAPCreate") failed. Check SAP_LOG table for details.'
end
If ErrorMsg EQ '' then
// Increment internal production order number
Database_Services('WriteDataRow', 'APP_INFO', 'CURR_INT_PROD_ORD_NO', NextIntProdOrdNo, True$, False$, False$)
If Error_Services('HasError') then ErrorMsg = Error_Services('GetMessage')
end else
Locked = Database_Services('IsKeyIDLocked', 'APP_INFO', 'CURR_INT_PROD_ORD_NO')
If Locked then Database_Services('ReleaseKeyIDLock', 'APP_INFO', 'CURR_INT_PROD_ORD_NO')
end
end else
ErrorMsg = 'Error in ':Service:' service. Failed to determine SAP parameters for new work order.'
end
end else
ErrorMsg = 'Error in ':Service:' service. Failed to get new internal prod order number.'
end
end else
ErrorMsg = 'Error in ':Service:' service. PROD_VER "':NewPVNo:'" does not exist.'
end
end
end else
ErrorMsg = 'Error in ':Service:' service. Null CassNos passed into service.'
end
end else
ErrorMsg = 'Error in ':Service:' service. WO_LOG "':WONo:'" does not exist.'
end
If ErrorMsg EQ '' then
Response = NewWONo
end else
Error_Services('Add', ErrorMsg)
Response = ''
end
end service
Service ShipConvertedMaterial(ProdOrdNo, CassNos)
ErrorMsg = ''
NewShipmentNo = ''
If ProdOrdNo NE '' then
If CassNos NE '' then
SearchString = 'PROD_ORD_NO':@VM:ProdOrdNo:@FM
Open 'DICT.WO_LOG' to hDict then
Flag = ''
WONo = ''
Btree.Extract(SearchString, 'WO_LOG', hDict, WONo, 'E', Flag)
// Check for successful query
If Flag EQ 0 then
// There should only be one work order associated with our unique internal production order number.
If (DCount(WONo, @VM) EQ 1) then
MockShipData = ''
For each CassNo in CassNos using @VM setting vPos
WOMatKey = WONo:'*':CassNo
If RowExists('WO_MAT', WOMatKey) then
SAPBatchNo = Xlate('WO_MAT', WOMatKey, 'SAP_BATCH_NO', 'X')
If SAPBatchNo NE '' then
MockShipData<vPos, 1> = ProdOrdNo ; // SAP Delivery Number - Just use internal IFX generated SAP production order number.
MockShipData<vPos, 2> = ProdOrdNo ; // Internal IFX generated SAP production order number.
MockShipData<vPos, 3> = SAPBatchNo ; // Original SAP batch number associated with cassette.
end else
ErrorMsg = 'Error in ':Service:' service. No SAP batch number found for WO_MAT record ':WOMatKey:'.'
end
end else
ErrorMsg = 'Error in ':Service:' service. WO_MAT record ':WOMatKey:' does not exist.'
end
Until ErrorMsg NE ''
Next CassNo
If ErrorMsg EQ '' then
If MockShipData NE '' then
Success = obj_Shipment('SAPCreate', MockShipData)
If Not(Success) then
ErrorMsg = Error_Services('GetMessage')
end
end else
ErrorMsg = 'Error in ':Service:' service. Failed to generate mock ship data file for obj_Shipment("SAPCreate").'
end
end
end else
ErrorMsg = 'Error in ':Service:' service. Error retrieving work order number. Btree.Extract result: "':WONo:'".'
end
end else
ErrorMsg = 'Error in ':Service:' service. Error calling Btree.Extract.'
end
end else
ErrorMsg = 'Error in ':Service:' service. Failed to open DICT.WO_LOG table.'
end
end else
ErrorMsg = 'Error in ':Service:' service. Null CassNos passed into service.'
end
end else
ErrorMsg = 'Error in ':Service:' service. Null ProdOrdNo passed into service.'
end
If ErrorMsg EQ '' then
Response = NewShipmentNo
end else
Error_Services('Add', ErrorMsg)
Response = ''
end
end service
Service MarkMUCassExpired(WoMatKey)
ErrorMsg = ''
If WoMatKey NE '' then
If RowExists('MAKEUP_WAFERS', WoMatKey) then
Open 'MAKEUP_WAFERS' to hMuTable then
WriteV True$ to hMuTable, WoMatKey, MAKEUP_WAFERS.EXPIRED$ else
ErrorMsg = 'Error in ':Service:' service. Error writing MAKEUP_WAFERS record "':WoMatKey:'".'
end
end else
ErrorMsg = 'Error in ':Service:' service. Failed to open MAKEUP_WAFERS table.'
end
end else
ErrorMsg = 'Error in ':Service:' service. MAKEUP_WAFERS record "':WoMatKey:'" does not exist!'
end
end else
ErrorMsg = 'Error in ':Service:' service. Null WoMatKey passed in.'
end
If ErrorMsg NE '' then
Error_Services('Add', ErrorMsg)
Response = False$
end else
Response = True$
end
end service
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ClearCursors:
For counter = 0 to 8
ClearSelect counter
Next counter
return