1594 lines
68 KiB
Plaintext
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
|
|
|
|
|
|
|