Merged PR 21598: Refactored receive and release codebase.

Refactored receive and release codebase.

bug fixes and performance improvements

modified WO_REC form to use the same receive and same release dtm for all cassettes released in a given batch

Related work items: #259878
This commit is contained in:
Stieber Daniel (CSC FI SPS MESLEO)
2025-07-23 15:40:25 +00:00
parent 84da66ccd5
commit de2e6af5f7
26 changed files with 53999 additions and 14791 deletions

View File

@ -48,15 +48,18 @@ $Insert WM_IN_EQUATES
$Insert WM_OUT_EQUATES
$Insert VOIDED_LOT_EQUATES
$Insert IFX_EQUATES
$Insert CUST_EPI_PART_EQUATES
Declare subroutine Error_Services, Work_Order_Services, Memory_Services, RList, Database_Services, SRP_JSON
Declare subroutine Btree.Extract, Set_Status, obj_WO_Log, obj_Notes, Print_Wo_Mat_In_Labels, Print_Wo_Mat_Out_Labels
Declare subroutine Print_Wmi_Labels, Print_Wmo_Labels, ErrMsg, Print_Cass_Labels, Logging_Services, Service_Services
Declare subroutine obj_WO_Mat_Log, WO_Mat_Services, Work_Order_Services, Transaction_Services, Extract_Si_Keys
Declare subroutine Mona_Services, Lot_Event_Services, RDS_Services, Lot_Services, WM_In_Services, WM_Out_Services
Declare subroutine obj_WO_Mat, obj_Post_Log
Declare function SRP_Array, Work_Order_Services, Memory_Services, Database_Services, SRP_Sort_Array, SRP_JSON
Declare function Company_Services, obj_Prod_Spec, Schedule_Services, Datetime, obj_WO_Log, obj_WO_Step, Memberof
Declare function Environment_Services, Logging_Services, Hold_Services, Signature_Services, Lot_Services, RTI_CreateGUID
Declare function Company_Services, obj_Prod_Spec, Schedule_Services, obj_WO_Log, obj_WO_Step, Memberof, Datetime
Declare function Environment_Services, Logging_Services, Hold_Services, Signature_Services, Lot_Services
Declare function SRP_Datetime, RTI_CreateGUID
LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\WO_LOG'
LogDate = Oconv(Date(), 'D4/')
@ -589,120 +592,283 @@ Service UpdateUnscheduledQuantities(WOList)
end service
Service ReleaseCassettes(WONo)
Service ReceiveCassette(WONo, ReceiveUser, LotNo, CassQty, SubPartNo, SubVendorCode, RecDtm)
NumRelCass = 0
ErrorMsg = ''
If WONo NE '' then
WOMatKey = ''
ErrorMsg = ''
Begin Case
Case ( (WONo EQ '') or Not( RowExists('WO_LOG', WONo) ) )
ErrorMsg = 'Error in ':Service:' service. Invalid WONo ':Quote(WONo):'.'
Case ( (ReceiveUser EQ '') or Not(RowExists('LSL_USERS', ReceiveUser) ) )
ErrorMsg = 'Error in ':Service:' service. Invalid ReceiveUser ':Quote(ReceiveUser):'.'
Case (LotNo EQ '')
ErrorMsg = 'Error in ':Service:' service. Invalid LotNo ':Quote(LotNo):'.'
Case ( (CassQty EQ '') or Not( Num(CassQty) ) )
ErrorMsg = 'Error in ':Service:' service. Invalid CassQty ':Quote(CassQty):'.'
Case (SubPartNo EQ '')
ErrorMsg = 'Error in ':Service:' service. Invalid SubPartNo ':Quote(SubPartNo):'.'
Case (SubVendorCode EQ '')
ErrorMsg = 'Error in ':Service:' service. Invalid SubVendorCode ':Quote(SubVendorCode):'.'
End Case
If (ErrorMsg EQ '') then
If RecDtm EQ '' then RecDtm = Datetime()
WORec = Database_Services('ReadDataRow', 'WO_LOG', WONo)
If Error_Services('NoError') then
OrderItemNo = 1
CustPartNo = WORec<WO_LOG_CUST_PART_NO$>
ProdOrderNo = WORec<WO_LOG_PROD_ORD_NO$>
ProdVerNo = WORec<WO_LOG_PROD_VER_NO$>
CustNo = WORec<WO_LOG_CUST_NO$>
ProdVerRec = Xlate('PROD_VER',ProdVerNo,'','X')
ProcStepPSNs = ProdVerRec<PROD_VER_PROC_STEP_PSN$>
ReactType = ProdVerRec<PROD_VER_REACT_TYPE$>
SpecType = Xlate('PROD_SPEC',ProcStepPSNs[-1,'B':@VM],'SPEC_TYPE','X')
EpiPartNo = WORec<WO_LOG_EPI_PART_NO$>
CustEpiPartRec = Xlate('CUST_EPI_PART',CustNo:'*':EpiPartNo,'','X')
MUWaferFlag = CustEpiPartRec<CUST_EPI_PART_MAKEUP_WAFERS$>
RetRejects = CustEpiPartRec<CUST_EPI_PART_RET_REJECTS$>
If SpecType EQ 'Q' then
CassShipQty = ''
end else
CassShipQty = CustEpiPartRec<CUST_EPI_PART_CASS_SHIP_QTY$>
end
MinCassShipQty = CustEpiPartRec<CUST_EPI_PART_MIN_CASS_SHIP_QTY$>
ShipShort = CustEpiPartRec<CUST_EPI_PART_EPI_PRO_SHIP_SHORT$>
Reprocessed = ''
EpiPartRec = Database_Services('ReadDataRow', 'EPI_PART', EpiPartNo)
If Error_Services('NoError') then
SubSuppBy = EpiPartRec<EPI_PART_SUB_SUPP_BY$> ;* L - EpiSvcs supplied, C - Customer Supplied
WOMatKeys = WORec<WO_LOG_WO_MAT_KEY$>
WOMatKeys = SRP_Array('SortRows', WOMatKeys, 'AR2', 'LIST', @VM, '*')
If WOMatKeys NE '' then
WOMatKeys = SRP_Array('SortRows', WOMatKeys, 'AR2', 'LIST', @VM, '*')
LastCassNo = WOMatKeys[-1, 'B*']
end else
LastCassNo = 0
end
hSysLists = Database_Services('GetTableHandle', 'SYSLISTS')
CassNo = ''
CandidateCassNo = LastCassNo + 1
Loop
CandidateWOMatKey = WONo:'*':CandidateCassNo
If Not(RowExists('WO_MAT', CandidateWOMatKey)) then
Lock hSysLists, CandidateWOMatKey then
CassNo = CandidateCassNo
end
end
Until (CassNo NE '')
CandidateCassNo = CandidateCassNo + 1
Repeat
Parms = WONo:@RM
Parms := CassNo:@RM
Parms := ProdVerNo:@RM
Parms := LotNo:@RM
Parms := CassQty:@RM
Parms := CustPartNo:@RM
Parms := OrderItemNo:@RM
Parms := ReactType:@RM
Parms := SubPartNo:@RM
Parms := 'SR':@RM ;* Warehouse = 'SR' - Shipping/Receiving Area
Parms := 'RB':@RM ;* Location = 'RB' - Receiving Bench
Parms := OConv(RecDtm, 'DT2/^H'):@RM
Parms := ReceiveUser:@RM
Parms := SubSuppBy:@RM
Parms := MUWaferFlag:@RM
Parms := RetRejects :@RM
Parms := Reprocessed:@RM
Parms := CassShipQty:@RM
Parms := ShipShort:@RM
Parms := SubVendorCode:@RM
Parms := MinCassShipQty
obj_WO_Mat('Create',Parms)
ErrCode = ''
If Not(Get_Status(ErrCode)) then
WOMatKey = WONo:'*':CassNo
Locate WOMatKey in WOMatKeys by 'AR' using @VM setting NewPos else
WOMatKeys<0, CassNo> = WOMatKey
Transaction_Services('PostWriteFieldTransaction', 'WO_LOG', WONo, WO_LOG_WO_MAT_KEY$, WOMatKey, CassNo)
ErrCode = ''
If Get_Status(ErrCode) then
ErrorMsg = 'Error in ':Service:' service. Error message: ':ErrCode
end
end
If (ErrorMsg EQ '') then
Recipients = ''
SentFrom = ReceiveUser
Subject = 'Cassette ':CassNo:' Received for Work Order ':WONo
Message ='Cassette ':CassNo:' Received for Work Order ':WONo
AttachWindow = 'NDW_WO_LOG'
AttachKey = WONo
SendToGroup = 'MATERIAL_RECEIPT'
Parms = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
obj_Notes('Create',Parms)
If Error_Services('HasError') then
ErrorMsg = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage')
end
end
end
Unlock hSysLists, CandidateWOMatKey else Null
end else
ErrorMsg = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage')
end
end else
ErrorMsg = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage')
end
end
If (ErrorMsg EQ '') then
Response = WOMatKey
end else
Response = False$
Error_Services('Add', ErrorMsg)
end
end service
//----------------------------------------------------------------------------------------------------------------------
// ReleaseCassette
//
// Input:
// WOMatKey [Required] - Cassette to be released
// ReleaseUser [Required] - User to be recorded in REL transaction
// RelDtm [Optional] - Will be used as the REL dtm if provided, otherwise it will use the current dtm.
//
// Output:
// Returns true if successful, false otherwise. If false, the error will be added to Error_Services.
//
// Releases a given cassette. This will create all child records for a given WO_MAT record and record a REL transaction
// in the material log.
//----------------------------------------------------------------------------------------------------------------------
Service ReleaseCassette(WOMatKey, ReleaseUser, RelDtm)
ErrorMsg = ''
Begin Case
Case (WOMatKey EQ '')
ErrorMsg = 'Error in ':Service:' service. Null WOMatKey passed into service.'
Case Not( RowExists('WO_MAT', WOMatKey) )
ErrorMsg = 'Error in ':Service:' service. WO_MAT ':Quote(WOMatKey):' does not exist.'
Case (ReleaseUser EQ '')
ErrorMsg = 'Error in ':Service:' service. Null ReleaseUser passed into service.'
Case Not( RowExists('LSL_USERS', ReleaseUser) )
ErrorMsg = 'Error in ':Service:' service. User ':ReleaseUser:' does not exist.'
End Case
If (ErrorMsg EQ '') then
PSNo = Xlate('WO_LOG', WONo, 'PS_NO', 'X')
PSMode = Xlate('PROD_SPEC',PSNo,'SPEC_TYPE','X')
If PSMode = 'Q' OR PSMode = 'U' then
ReactType = Xlate('WO_LOG', WONo, 'REACT_TYPE', 'X')
If ReactType = 'EPP' OR ReactType = 'EpiPro' then
OutLoadQty = Xlate('WO_LOG', WONo, 'CUST_EPI_PART_WMO_LOAD_CNT', 'X')
If OutLoadQty = '' then
ErrorMsg = 'Outbound Load Cnt is required for ':OCONV(PSMode,'[PROD_SPEC_MODE_CONV]'):' Work Orders.'
end
end else
OutLoadQty = Xlate('WO_LOG', WONo, 'CUST_EPI_PART_SHIP_QTY', 'X')
If OutLoadQty = '' then
ErrorMsg = 'Cass Ship Qty is required for ':OCONV(PSMode,'[PROD_SPEC_MODE_CONV]'):' Work Orders.'
end
end
end
end
If ErrorMsg EQ '' then
CassList = Xlate('WO_LOG', WONo, 'WO_MAT_CASS_NO', 'X')
RelDTMs = Xlate('WO_LOG', WONo, 'WO_MAT_REL_DTM', 'X')
SAPCassIDs = Xlate('WO_LOG', WONo, 'WO_MAT_CASS_ID_SAP', 'X')
CassStatus = Xlate('WO_LOG', WONo, 'WO_MAT_CURR_STATUS', 'X')
CassRelDtm = Xlate('WO_MAT', WOMatKey, 'REL_DTM', 'X')
CassRxDtm = Xlate('WO_MAT', WOMatKey, 'RX_DTM', 'X')
Loop
LastLine = CassList[-1,'B':@VM]
Until LastLine<1,1> NE '' OR LastLine = ''
CassList[COL1(),COL2()] = ''
Repeat
CassCnt = DCount(CassList, @VM)
UnReleasedCassNos = ''
For I = 1 to CassCnt
If ( (RelDTMs<0, I> = '') and (CassStatus<0, I> EQ '') ) then
ErrorMsg = 'Error in obj_WO_Log("ReleaseCassettes"). Cass status is null for ':CassList<0, I>:'!'
LogData = ''
LogData<1> = LoggingDTM
LogData<2> = @USER4
LogData<3> = ErrorMsg
Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM, False$)
end
If ErrorMsg EQ '' then
// Log work order, cassette number, status, and release DTM in the event that a release
// issue occurs again.
LogData = ''
LogData<1> = LoggingDTM
LogData<2> = @User4
LogData<3> = WONo
LogData<4> = CassList<0, I> ; // CassNo
LogData<5> = CassStatus<0, I> ; // Cass Status
LogData<6> = Quote(RelDTMs<0, I>) ; // Release DTM
Logging_Services('AppendLog', objReleaseLog, LogData, @RM, @FM, False$)
If ( (RelDTMs<0, I> = '') and ( (CassStatus<0, I> = 'RX') or (CassStatus<0, I> = 'MT'))) then
UnReleasedCassNos<1,-1> = CassList<0, I>
end
end
Until ErrorMsg NE ''
Next I
If ErrorMsg EQ '' then
TempWONo = WONo
If ( (CassRelDtm EQ '') and ( CassRxDtm NE '' ) ) then
RelWONo = Field(WOMatKey, '*', 1, 1)
RelCassNo = Field(WOMatKey, '*', 2, 1)
Set_Status(0)
obj_WO_Log('ReleaseCassettes',TempWONo:@RM:UnReleasedCassNos) ;* This variable gets changed down the line
errCode = ''
obj_WO_Log('ReleaseCassettes',RelWONo:@RM:RelCassNo:@RM:ReleaseUser:@RM:RelDtm)
errCode = ''
If Get_Status(errCode) then
ErrorMsg = 'Error in obj_WO_Log("ReleaseCassettes"). Error code ':errCode:'.'
Database_Services('ReleaseKeyIDLock', 'WO_LOG', WONo)
end else
NumRelCass = CassCnt
OrderNo = Get_Property(@WINDOW:'.ORD_NO','TEXT')
Recipients = XLATE('NOTIFICATION','WO_ENTRY',NOTIFICATION_USER_ID$,'X')
SentFrom = @USER4
Subject = 'Work Order Released ':WONo
Message = 'Work Order Released to Production.'
NewForm = Xlate('APP_INFO', 'NEW_WO_FORM', '', 'X')
If NewForm then
AttachWindow = 'NDW_WO_LOG'
end else
AttachWindow = 'WO_LOG2'
ErrorMsg = 'Error in ':Service:' service. Error code ':errCode:'.'
If Database_Services('IsKeyIDLocked', 'WO_LOG', RelWONo) then
Database_Services('ReleaseKeyIDLock', 'WO_LOG', RelWONo)
end
AttachKey = WONo
SendToGroup = ''
end else
Recipients = ''
SentFrom = ReleaseUser
Subject = 'Cassette ':WOMatKey:' released for work order ':RelWONo
Message = 'Cassette ':WOMatKey:' released for work order ':RelWONo
AttachWindow = 'WO_MAT'
AttachKey = WOMatKey
SendToGroup = 'WO_ENTRY'
Parms = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
obj_Notes('Create',Parms)
end
end else
ErrorMsg = 'Error in ':Service:' service. WO_MAT ':WOMatKey:' is ineligible to be released.'
end
end
end
Work_Order_Services('UpdateReleasedQty', WONo)
If ErrorMsg EQ '' then
Response = True$
end else
Response = False$
Error_Services('Add', ErrorMsg)
end
If ErrorMsg NE '' then Error_Services('Add', ErrorMsg)
Response = DCount(UnReleasedCassNos, @VM)
end service
Service ReceiveReleaseCassette(WONo, ReceiveUser, LotNo, CassQty, SubPartNo, SubVendorCode, RecDtm)
WOMatKey = ''
ErrorMsg = ''
Begin Case
Case ( (WONo EQ '') or Not( RowExists('WO_LOG', WONo) ) )
ErrorMsg = 'Error in ':Service:' service. Invalid WONo ':Quote(WONo):'.'
Case ( (ReceiveUser EQ '') or Not(RowExists('LSL_USERS', ReceiveUser) ) )
ErrorMsg = 'Error in ':Service:' service. Invalid ReceiveUser ':Quote(ReceiveUser):'.'
Case (LotNo EQ '')
ErrorMsg = 'Error in ':Service:' service. Invalid LotNo ':Quote(LotNo):'.'
Case ( (CassQty EQ '') or Not( Num(CassQty) ) )
ErrorMsg = 'Error in ':Service:' service. Invalid CassQty ':Quote(CassQty):'.'
Case (SubPartNo EQ '')
ErrorMsg = 'Error in ':Service:' service. Invalid SubPartNo ':Quote(SubPartNo):'.'
Case (SubVendorCode EQ '')
ErrorMsg = 'Error in ':Service:' service. Invalid SubVendorCode ':Quote(SubVendorCode):'.'
End Case
If (ErrorMsg EQ '') then
If RecDtm EQ '' then RecDtm = Datetime()
WOMatKey = Work_Order_Services('ReceiveCassette', WONo, ReceiveUser, LotNo, CassQty, SubPartNo, SubVendorCode, RecDtm)
If Error_Services('NoError') then
If RowExists('WO_MAT', WOMatKey) then
RelDtm = SRP_Datetime('AddSeconds', RecDtm, 30)
If Not(Work_Order_Services('ReleaseCassette', WOMatKey, ReceiveUser, RelDtm)) then
ErrorMsg = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage')
end
end else
ErrorMsg = 'Error in ':Service:' service. Error receiving cassette. WO_MAT ':WOMatKey:' does not exist.'
end
end else
ErrorMsg = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage')
end
end
If (ErrorMsg EQ '') then
Response = WOMatKey
end else
Response = False$
Error_Services('Add', ErrorMsg)
end
end service
@ -1329,15 +1495,15 @@ Service CreateVoidedLotRecord(LotId, LegacyLotId, LegacyLotType, WoMatKey, UserI
If ErrorMessage NE '' then
If RowExists('LOT', LotId) then
NewVoidedLotId = RTI_CreateGUID()
NewVoidedLotRec = ''
NewVoidedLotId = RTI_CreateGUID()
NewVoidedLotRec = ''
NewVoidedLotRec<VOIDED_LOT_WORK_ORDER_LOG_ID$> = Field(WoMatKey, '*', 1)
NewVoidedLotRec<VOIDED_LOT_VOID_BY$> = UserId
NewVoidedLotRec<VOIDED_LOT_VOID_DTM$> = Datetime()
NewVoidedLotRec<VOIDED_LOT_ENTITY_TYPE$> = LegacyLotType
NewVoidedLotRec<VOIDED_LOT_LOT_ID$> = LotId
NewVoidedLotRec<VOIDED_LOT_LEGACY_LOT_ID$> = LegacyLotId
NewVoidedLotRec<VOIDED_LOT_WO_MAT_KEY$> = WoMatKey
NewVoidedLotRec<VOIDED_LOT_VOID_BY$> = UserId
NewVoidedLotRec<VOIDED_LOT_VOID_DTM$> = Datetime()
NewVoidedLotRec<VOIDED_LOT_ENTITY_TYPE$> = LegacyLotType
NewVoidedLotRec<VOIDED_LOT_LOT_ID$> = LotId
NewVoidedLotRec<VOIDED_LOT_LEGACY_LOT_ID$> = LegacyLotId
NewVoidedLotRec<VOIDED_LOT_WO_MAT_KEY$> = WoMatKey
Database_Services('WriteDataRow', 'VOIDED_LOT', NewVoidedLotId, NewVoidedLotRec)
If Error_Services('HasError') then
ErrorMessage = Error_Services('GetMessage')
@ -1399,7 +1565,7 @@ Service SignVoidNonEpp(WOMatKeys, WONo, Username)
If Error_Services('NoError') then
//Create a voided LOT record then record an event.
Work_Order_Services('CreateVoidedLotRecord', '', RDSNo, 'RDS', WoMatKey, Username)
Lot_Event_Services('CreateLotEvent', RDSNo, DateTime, 'VOID', 'Lot voided by ' : Username, '', Username, True$, 'RDS')
Lot_Event_Services('CreateLotEvent', RDSNo, Datetime(), 'VOID', 'Lot voided by ' : Username, '', Username, True$, 'RDS')
end else
ErrorMessage = Error_Services('GetMessage')
end