Function NCR_Actions(Action, CalcColName, FSList, Handle, Name, FMC, Record, Status, OrigRecord, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)
/***********************************************************************************************************************

    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 Infineon.

    Name        :   NCR_Actions

    Description :   Handles calculated columns and MFS calls for the current table.

    Notes       :   This function uses @ID, @RECORD, and @DICT to make sure {ColumnName} references work correctly.
                    If called from outside of a calculated column these will need to be set and restored.

    Parameters  :
        Action          [in] -- Name of the action to be taken
        CalcColName     [in] -- Name of the calculated column that needs to be processed. Normally this should only be
                                populated when the CalcField action is being used.
        FSList          [in] -- The list of MFSs and the BFS name for the current file or volume. This is an @SVM
                                delimited array, with the current MFS name as the first value in the array, and the BFS
                                name as the last value. Normally set by a calling MFS.
        Handle          [in] -- The file handle of the file or media map being accessed. Note, this does contain the
                                entire handle structure that the Basic+ Open statement would provide. Normally set by a
                                calling MFS.
        Name            [in] -- The name (key) of the record or file being accessed. Normally set by a calling MFS.
        FMC             [in] -- Various functions. Normally set by a calling MFS.
        Record          [in] -- The entire record (for record-oriented functions) or a newly-created handle (for
                                "get handle" functions). Normally set by a calling MFS.
        Status      [in/out] -- Indicator of the success or failure of an action. Normally set by the calling MFS but
                                for some actions can be set by the action handler to indicate failure.
        OrigRecord      [in] -- Original content of the record being processed by the current action. This is
                                automatically being assigned by the WRITE_RECORD and DELETE_RECORD actions within
                                BASE_MFS.
        Param1-10   [in/out] -- Additional request parameter holders
        ActionFlow     [out] -- Used to control the action chain (see the ACTION_SETUP insert for more information.)
                                Can also be used to return a special value, such as the results of the CalcField
                                method.

    History     :   (Date, Initials, Notes)
        06/05/18    djs     Original programmer.
        03/07/19    djs     Updated WRITE_RECORD and DELETE_RECORD actions such that calls to obj_NCR('RejQty') are
                            now wrapped in a Sum() function call because EpiPro wafers return @VM delimited reject
                            quantity values for each distinct RDS in the NCR record. This Sum() function call will not
                            affect Non-EpiPro NCR records or EpiPro NCRs with only a single reject quanitity (i.e. the
                            NCR only contains one distinct RDS).


***********************************************************************************************************************/

#pragma precomp SRP_PreCompiler

$insert LOGICAL
$insert FILE.SYSTEM.EQUATES
$insert ACTION_SETUP
$insert RDS_TEST_EQUATES
$insert RDS_EQUATES
$insert WO_LOG_EQUATES
$insert WM_OUT_EQUATES
$insert WM_IN_EQUATES
$insert WO_MAT_EQUATES
$insert NCR_EQUATES
$insert IFX_EQUATES

EQU CRLF$        TO \0D0A\
EQU Comma$       TO ','

EQU COL$LOG_FILE TO 1
EQU COL$LOG_DTM  TO 2
EQU COL$ACTION   TO 3
EQU COL$WH_CD    TO 4
EQU COL$LOC_CD   TO 5
EQU COL$WO_NOS   TO 6
EQU COL$CASS_NOS TO 7
EQU COL$USER_ID  TO 8
EQU COL$TAGS     TO 9
EQU COL$TOOL_ID  TO 10

Declare function    Database_Services, obj_NCR, obj_SAP, Environment_Services, Logging_Services, obj_Tables
Declare function    obj_WO_Mat, obj_RDS, Error_Services, MemberOf, SRP_Array
Declare subroutine  Error_Services, Database_Services, obj_NCR, obj_SAP, Material_Services, Work_Order_Services
Declare subroutine  Logging_Services, Set_Status, obj_WO_Mat, obj_WO_Mat_Log, Schedule_Services, obj_Tables
Declare subroutine  obj_RDS, SAP_Services, Pass_To_SQL, NCR_Services, Service_Services

LogPath     = Environment_Services('GetApplicationRootPath') : '\LogFiles\NCR'
LogDate     = Oconv(Date(), 'D4/')
LogTime     = Oconv(Time(), 'MTS')
LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' NCR Delete Log.csv'
Headers     = 'Logging DTM' : @FM : 'User' : @FM : 'KeyID' : @FM : 'Record'
objLog      = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, Comma$, Headers, '', False$, False$)

LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' NCR Negative Scrap Log.csv'
Headers     = 'Logging DTM' : @FM : 'User' : @FM : 'KeyID' : @FM : 'SAP Scrap Qty'
objSAPLog   = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, Comma$, Headers, '', False$, False$)

LoggingDTM  = LogDate : ' ' : LogTime   ; // Logging DTM

If KeyID then GoSub Initialize_System_Variables

Begin Case
	
	Case Action _EQC 'CalcField'            ;   GoSub Calc_Field
	Case Action _EQC 'READ_RECORD_PRE'      ;   GoSub READ_RECORD_PRE
	Case Action _EQC 'READ_RECORD'          ;   GoSub READ_RECORD
	Case Action _EQC 'READONLY_RECORD_PRE'  ;   GoSub READONLY_RECORD_PRE
	Case Action _EQC 'READONLY_RECORD'      ;   GoSub READONLY_RECORD
	Case Action _EQC 'WRITE_RECORD_PRE'     ;   GoSub WRITE_RECORD_PRE
	Case Action _EQC 'WRITE_RECORD'         ;   GoSub WRITE_RECORD
	Case Action _EQC 'DELETE_RECORD_PRE'    ;   GoSub DELETE_RECORD_PRE
	Case Action _EQC 'DELETE_RECORD'        ;   GoSub DELETE_RECORD
	Case Otherwise$                         ;   Status = 'Invalid Action'
		
End Case

If KeyID then GoSub Restore_System_Variables

If Assigned(ActionFlow) else ActionFlow = ACTION_CONTINUE$

Return ActionFlow


// ----- Calculated Columns --------------------------------------------------------------------------------------------
//
// The typical structure of a calculated column will look like this:
//
// Declare function TableName_Actions
//
// A = {COL1} ; * Reference as many data columns in this way to ensure the dictionary dependency is generated.
//
// @ANS = TableName_Actions('CalcField', 'CalcColName')
//
// ---------------------------------------------------------------------------------------------------------------------

Calc_Field:
	// Make sure the ActionFlow return variable is cleared in case nothing is calculated.
	ActionFlow = ''
	
return


// ----- MFS calls -----------------------------------------------------------------------------------------------------

READ_RECORD_PRE:
	// In order to stop a record from being read in this action these lines of code must be used:
	//
	//    OrigFileError   = 100 : @FM : KeyID
	//    Status          = 0
	//    Record          = ''
	//    ActionFlow      = ACTION_STOP$
return

READ_RECORD:
	// In order to stop a record from being read in this action these lines of code must be used:
	//
	//    OrigFileError   = 100 : @FM : KeyID
	//    Status          = 0
	//    Record          = ''
	
	Shift = Record<NCR_SHIFT$>	
	If Num(Shift) then
	    Begin Case
	        Case Shift EQ 1
	            Record<NCR_SHIFT$> = 'A'
	        Case Shift EQ 2
	            Record<NCR_SHIFT$> = 'B'
	        Case Shift EQ 3
	            Record<NCR_SHIFT$> = 'C'
	        Case Shift EQ 4
	            Record<NCR_SHIFT$> = 'D'
	        Case Shift EQ 5
	            Record<NCR_SHIFT$> = '5'
	        Case Otherwise$
	            Null
	    End Case
	end
	
return

READONLY_RECORD_PRE:
	// In order to stop a record from being read in this action these lines of code must be used:
	//
	//    OrigFileError   = 100 : @FM : KeyID
	//    Status          = 0
	//    Record          = ''
	//    ActionFlow      = ACTION_STOP$
return

READONLY_RECORD:
	// In order to stop a record from being read in this action these lines of code must be used:
	//
	//    OrigFileError   = 100 : @FM : KeyID
	//    Status          = 0
	//    Record          = ''

	Shift = Record<NCR_SHIFT$>
	If Num(Shift) then
	    Begin Case
	        Case Shift EQ 1
	            Record<NCR_SHIFT$> = 'A'
	        Case Shift EQ 2
	            Record<NCR_SHIFT$> = 'B'
	        Case Shift EQ 3
	            Record<NCR_SHIFT$> = 'C'
	        Case Shift EQ 4
	            Record<NCR_SHIFT$> = 'D'
	        Case Shift EQ 5
	            Record<NCR_SHIFT$> = '5'
	        Case Otherwise$
	            Null
	    End Case
	end
	
return

WRITE_RECORD_PRE:
	
	WorkOrderNo = {WO_NO}
	CassNo      = {WO_MAT_CASS_NO}
	WoMatKey    = WorkOrderNo : '*' : CassNo
	SAPBatchNo  = Xlate('WO_MAT', WOMatKey, 'SAP_BATCH_NO', 'X')
	Shift       = Record<NCR_SHIFT$>
	If Num(Shift) then
	    Begin Case
	        Case Shift EQ 1
	            Record<NCR_SHIFT$> = 'A'
	        Case Shift EQ 2
	            Record<NCR_SHIFT$> = 'B'
	        Case Shift EQ 3
	            Record<NCR_SHIFT$> = 'C'
	        Case Shift EQ 4
	            Record<NCR_SHIFT$> = 'D'
	        Case Shift EQ 5
	            Record<NCR_SHIFT$> = '5'
	        Case Otherwise$
	            Null
	    End Case
	end
	SaveRecord = Record
	
	If SAPBatchNo NE '' then
		NCRNo      = Name
		OrigRejQty = Sum(obj_NCR('RejQty',NCRNo:@RM:OrigRecord))
		NewRejQty  = Sum(obj_NCR('RejQty',NCRNo:@RM:Record))
		If ( (NewRejQty LT OrigRejQty) and Not(MemberOf(@User4, 'OI_ADMIN') ) ) then
			// Log reduction attempt
			LogData    = ''
			LogData<1> = LoggingDTM
			LogData<2> = @User4
			LogData<3> = Name
			LogData<4> = SAPBatchNo
			LogData<5> = (OrigRejQty - NewRejQty)
			LogData<6> = 'Blocking scrap qty reduction due to SAP batch number present.'
			Logging_Services('AppendLog', objSAPLog, LogData, @RM, @FM)     
			
			// Block write!
			// FS275: The record "%2%" cannot be saved because it is write/delete-protected in the "%1%" table.
			OrigFileError = 279 : @FM : Name : @FM : 'NCR'
			Status        = 0
			ActionFlow    = ACTION_STOP$
		end
	end
	
return

WRITE_RECORD:
	
	NCRNo  = @ID        
	NewQty = Sum(obj_NCR('RejQty',NCRNo:@RM:Record))
	OrgQty = Sum(obj_NCR('RejQty',NCRNo:@RM:OrigRecord))
	WorkOrderNo = {WO_NO}
	// NCR quantity may have changed, so update RDS data in SCRAPE DB as well as the total scrap qty in the work order.
	RDSNos = {RDS_ID}
	For each RDSNo in RDSNos using @VM setting vPos
		Pass_To_SQL('WRITE', 'RDS', RDSNo)
	Next RDSNo
	
	If (OrgQty NE NewQty) then
		ScrapAdj = NewQty - OrgQty
		Work_Order_Services('AdjustScrappedQty', WorkOrderNo, ScrapAdj)
	end
	
	// On the write of the record, read then write associated WM_IN and WM_OUT records to trigger the WM_MFS.
	// This will update their current status within the associated WO_MAT record.
	ReactorType = XLATE('WO_LOG', WorkOrderNo, 'REACT_TYPE', 'X')
	ReactorType = Field(ReactorType, @VM, 1)
	CassNo      = {WO_MAT_CASS_NO}
	WoMatKey    = WorkOrderNo : '*' : CassNo
	WoMatRec    = Database_Services('ReadDataRow', 'WO_MAT', WoMatKey)
	WMIKey      = WoMatRec<WO_MAT_WMI_KEY$>
	WMOKey      = WoMatRec<WO_MAT_WMO_KEY$>
	If WMIKey NE '' then
		WMIRec  = Database_Services('ReadDataRow', 'WM_IN', WMIKey)
		Database_Services('WriteDataRow', 'WM_IN', WMIKey, WMIRec, True$, True$, False$)
	end
	If WMOKey NE '' then
		WMORec  = Database_Services('ReadDataRow', 'WM_OUT', WMOKey)
		Database_Services('WriteDataRow', 'WM_OUT', WMOKey, WMORec, True$, True$, False$)
	end
	
    // If NCR created after cassette has received a batch number, then inform SAP of new quantities
    SAPBatchNo  = Xlate('WO_MAT', WOMatKey, 'SAP_BATCH_NO', 'X')
    IF SAPBatchNo NE '' THEN
        
        IF (ReactorType = 'EPP') OR (ReactorType = 'EpiPro') THEN
            WMOutKey    = Xlate('WO_MAT', WOMatKey, 'WMO_KEY', 'X')
            CassStatus  = Xlate('WM_OUT', WMOutKey, 'CURR_STATUS', 'X')
            
        END ELSE
            // Non-EpiPro
            RDSNo      = Xlate('WO_MAT', WoMatKey, 'RDS_NO', 'X')
            CassStatus = Xlate('RDS', RDSNo, 'CURR_STATUS', 'X')
        END
        
        // Add SAP transaction
        IF OrigRecord = '' THEN
            TransQty = NewQty
        END ELSE
            TransQty = NewQty - OrgQty
        END 
        IF TransQty NE 0 THEN       
            obj_SAP('AddTransaction','SCRAP_IN':@RM:WorkOrderNo:@RM:CassNo:@RM:TransQty)
            
            If TransQty LT 0 then
                // Log negative SAP scrap transaction to capture metrics to submit for SAP change request
                LogData    = ''
                LogData<1> = LoggingDTM
                LogData<2> = @User4
                LogData<3> = Name
                LogData<4> = SAPBatchNo
                LogData<5> = TransQty
                Logging_Services('AppendLog', objSAPLog, LogData, @RM, @FM)    
            end
        end
    end
	
	OrigStatus = OrigRecord<NCR_STATUS$>
	NewStatus  = Record<NCR_STATUS$>
	
	If ( (OrigStatus NE NewStatus) and (NewStatus EQ 'C') ) then
		
		********************
		* Auto send to SPC *
		********************
		If Record<NCR_SPC_DTM$> EQ '' then
			NCRNo = @ID
			RDSList = ''
			RDSList<1> = {RDS_ID}
			RDSList<2> = {REACTOR}
			RDSList<3> = {REJ_CNT}
			PSNo = {PROD_SPEC_NO}
			DeptResp = {DEPT_RESP}
			LossCode = {LOSS_CODE}
			LossDesc = {LOSS_DESC}
			LossStage = {LOSS_STAGE}
			LossBy = {LOSS_BY}
			ACCode = {AC_CODE}
			ACDesc = {AC_DESC}
			
			TempID   = @ID
			TempRec  = @Record
			TempDict = @Dict
			
			NCR_Services('SendToSPC', NCRNo, RDSList, ReactorType, PSNo, DeptResp, LossCode, LossDesc, LossStage, LossBy, ACCode, ACDesc)
			
			@ID     = TempID
			@Record = TempRec
			@Dict   = TempDict
			
			If Error_Services('HasError') NE True$ then
				Record<NCR_SPC_DTM$> = Date()
			end
		end			
		
		// NCR has been closed. Check if it is a full box reject.
		WONo     = {WO_NO}
		CassNo   = {WO_MAT_CASS_NO}
		WOStep   = {WO_STEP}
		WOStepNo = WOStep
		WOMatKey = WONo:'*':CassNo
		
		If (ReactorType EQ 'EPP') then
			
			InCassNos = {CASS_NO}
		
			****************************************************************************
			* Verify the need to "Auto-Sign" the box after returning from the NCR form *
			****************************************************************************
			
            CassetteQty  = XLATE('WO_MAT', WOMatKey, 'WAFER_QTY', 'X')
            CurrWfrCount = Xlate('WM_OUT', WMOKey, 'WAFER_CNT', 'X')
            If CurrWfrCount EQ '' then CurrWfrCount = 0
            WMOKey       = WONo:'*':WOStep:'*':CassNo
			NCRNos       = Xlate('WM_OUT', WMOKey, 'SLOT_NCR', 'X')
			RejectedQty  = 0
			If NCRNos NE '' then 
				For each NCRNo in NCRNos using @VM
					RejectedQty += (NCRNo NE '')
				Next NCRNo
			end
			
			If ( (CurrWfrCount EQ 0) and (RejectedQty GE CassetteQty) ) then
            	
                // Full box reject
                *****************************
                * Set SAP Batch as Rejected *
                *****************************
                WOMatKey = WONo:'*':CassNo
                WoMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey)
                ProdOrdNo = XLATE('WO_LOG',WONo,WO_LOG_PROD_ORD_NO$,'X')
                ProdOrdNo[-1,1] = 'R'
                SAPBatchNo = ProdOrdNo      
                WOMatRec<WO_MAT_SAP_BATCH_NO$> = SAPBatchNo
                Database_Services('WriteDataRow', 'WO_MAT', WOMatKey, WoMatRec, True$, False$, True$)
                   
                *****************
                * Auto-Sign FQA *
                *****************
                SigDate		 = Date()
                SigTime		 = Time()
                SigDt   	 = OCONV(SigDate, 'D2/')
                SigTm 		 = OConv(SigTime, 'MTS')
                SigTmPlusOne = OCONV(SigTime + 1, 'MTS' )
                SigTmPlusTwo = OCONV(SigTime + 2, 'MTS' )
                SigDTM       = SigDate + (SigTime / 86400) ; // 86400 = 24 hours * 60 minutes * 60 seconds
                SignedBy     = 'AUTO_FQA'
                ToolID       = ''
                WHCode       = 'CR'  /* Warehouse Code = Cleanroom */
                LocCode      = 'QA'  /* Location  Code = QA   	 */
                ActionCode   = 'REJ' /* Action    Code = Rejected  */
                Tag          = ''
                
                // Sign WM_OUT<SIG_SUP_VER>		
                StatusStage = 'MO_QA'
                WMOKey = Xlate('WO_MAT', WOMatKey, 'WMO_KEY', 'X')
                WMORec = Database_Services('ReadDataRow', 'WM_OUT', WMOKey)
                WMORec<WM_OUT_SUP_VER_SIG$>     = SignedBy
                WMORec<WM_OUT_SUP_VER_SIG_DTM$> = IConv(SigDt:' ':SigTm, 'DT')
                Database_Services('WriteDataRow', 'WM_OUT', WMOKey, WMORec, True$, False$, True$)
                
                ***************************
                * Log the signature event *
                ***************************
                Set_Status(0)				
                EventParms               = ''
                EventParms<COL$LOG_FILE> = 'WO_MAT'
                EventParms<COL$LOG_DTM>  = SigDt:' ':SigTm
                EventParms<COL$ACTION>   = WOStepNo:'QA'
                EventParms<COL$WH_CD>    = WHCode
                EventParms<COL$LOC_CD>   = LocCode
                EventParms<COL$WO_NOS>   = WONo
                EventParms<COL$CASS_NOS> = CassNo
                EventParms<COL$USER_ID>  = SignedBy
                EventParms<COL$TAGS>     = ''
                EventParms<COL$TOOL_ID>  = ''
                CONVERT @FM TO @RM IN EventParms
                obj_WO_Mat_Log('Create', EventParms)
                errCode                  = ''
                IF Get_Status(errCode) THEN
                    Error_Services('Add', 'Error in NCR_ACTIONS. Error code: ':ErrCode)
                END

                *********************************
                * Log the full box reject event *
                *********************************
                Set_Status(0)				
                EventParms = ''
                EventParms<COL$LOG_FILE>	  = 'WO_MAT'
                EventParms<COL$LOG_DTM>		  = SigDt:' ':SigTmPlusTwo
                EventParms<COL$ACTION>  	  = ActionCode
                EventParms<COL$WH_CD>		  = WHCode
                EventParms<COL$LOC_CD>		  = LocCode
                EventParms<COL$WO_NOS>		  = WONo
                EventParms<COL$CASS_NOS>	  = CassNo
                EventParms<COL$USER_ID>		  = SignedBy
                EventParms<COL$TAGS>		  = ''
                EventParms<COL$TOOL_ID>		  = ''
                CONVERT @FM TO @RM IN EventParms
                obj_WO_Mat_Log('Create',EventParms)
                IF Get_Status(errCode) THEN
                    Error_Services('Add', 'Error in NCR_ACTIONS. Error code: ':ErrCode)
                END

                **********************************************************************
                * Synchonize the WO_MAT schedule wafers quatity with the RDS records *
                **********************************************************************
                IF (Not(ReactorType = 'EPP') and Not(ReactorType = 'EpiPro')) THEN
                    IF (RDSNo NE '') THEN
                        RDSRec = obj_Tables('ReadOnlyRec','RDS':@RM:RDSNo)
                        RDSRec<RDS_SUP_VER_SIG$>	  = SignedBy
                        RDSRec<RDS_SUP_VER_SIG_DATE$> = SigDate
                        RDSRec<RDS_SUP_VER_SIG_TIME$> = SigTime
                        obj_Tables('WriteOnlyRec','RDS':@RM:RDSNo:@RM:@RM:RDSRec)
                        
                        WOMatRec = XLATE('WO_MAT',WOMatKey,'','X')
                        WMRDSNos = WOMatRec<WO_MAT_RDS_NO$>
                        LOCATE RDSNo IN WMRDSNos USING @VM SETTING Pos THEN
                            NextRDSNo = WMRDSNos<1,Pos+1>
                            IF (NextRDSNo NE '') THEN
                                CurrWfrQty = obj_WO_Mat('CurrWaferCnt', WOMatKey:@RM:WOMatRec)
                                Set_Status(0)
                                obj_RDS('SetSchedWfrQty', NextRDSNo:@RM:CurrWfrQty)
                                IF Get_Status(errCode) THEN
                                    Error_Services('Add', 'Error in NCR_ACTIONS. Error code: ':ErrCode)
                                END
                            END
                        END
                    END
                END                       
                
                ***********************************************************************
                * Send CASS_COMP transaction to SAP to inform SAP of the rejected box *
                ***********************************************************************
                SAP_Services('AddCassCompTransaction', WOMatKey)
            END
			
		end else
			
			// Non-EpiPro
			****************************************************************************
			* Verify the need to "Auto-Sign" the box after returning from the NCR form *
			****************************************************************************
			
			RejectedWafers   = 0
			RejectedMUWafers = 0
			ProdTestWafers   = 0
			
			If ( (WONo NE '') and (CassNo NE '') ) then
				WOMatKey = WONo:'*':CassNo
				Set_Status(0)
				CassetteQty      = XLATE('WO_MAT', WOMatKey, 'WAFER_QTY', 'X')
				RejectedWafers   = XLATE('WO_MAT', WOMatKey, 'TOT_REJ_WFRS', 'X')
				RejectedMUWafers = XLATE('WO_MAT', WOMatKey, 'TOT_REJ_MU_WFRS', 'X')
				ProdTestWafers   = XLATE('WO_MAT', WOMatKey, 'TW_PROD','X')
				CurrWfrCount     = XLATE('WO_MAT', WOMatKey, 'CURR_WFR_CNT', 'X')
				
				IF (RejectedWafers = '') then
					RejectedWafers = 0
				END
				IF (RejectedMUWafers = '') then
					RejectedMUWafers = 0
				END
				IF (ProdTestWafers = '') then
					ProdTestWafers = 0
				END
				
				IF ((ReactorType = 'EPP') OR (ReactorType = 'EpiPro')) THEN
					RejectedQty = RejectedWafers + RejectedMUWafers
				END ELSE
					RejectedQty = RejectedWafers + RejectedMUWafers + ProdTestWafers
				END
				
				If ( (CurrWfrCount EQ 0) and (RejectedQty GE CassetteQty) ) then
					****************************************************
					* Set SAP Batch as Rejected - full cassette reject *
					****************************************************
					WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey)
					ProdOrdNo = XLATE('WO_LOG', WONo, WO_LOG_PROD_ORD_NO$, 'X')
					ProdOrdNo[-1,1] = 'R'
					SAPBatchNo = ProdOrdNo      
					WOMatRec<WO_MAT_SAP_BATCH_NO$> = SAPBatchNo
					Database_Services('WriteDataRow', 'WO_MAT', WOMatKey, WoMatRec, True$, False$, True$)
					
					*****************
					* Auto-Sign FQA *
					*****************
					SigDate		 = Date()
					SigTime		 = Time()
					SigDt   	 = OCONV(SigDate, 'D2/')
					SigTm 		 = SigTime
					SigTmPlusOne = OCONV(SigTm + 1, 'MTS' )
					SigTmPlusTwo = OCONV(SigTm + 2, 'MTS' )
					SigTm		 = OCONV(SigTm,'MTS')
					SigDTM       = SigDate + (SigTime / 86400) ; // 86400 = 24 hours * 60 minutes * 60 seconds
					SignedBy     = 'AUTO_FQA'
					ToolID       = ''
					WHCode       = 'CR'  /* Warehouse Code = Cleanroom */
					LocCode      = 'QA'  /* Location  Code = QA   	 */
					ActionCode   = 'REJ' /* Action    Code = Rejected  */
					Tag          = ''
					
					// Sign RDS FQA Signature
					StatusStage = 'QA'
					RDSNo = Xlate('WO_MAT', WOMatKey, 'RDS_NO', 'X')
					RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
					RDSRec<RDS_SUP_VER_SIG$>      = SignedBy
					RDSRec<RDS_SUP_VER_SIG_DATE$> = SigDate
					RDSRec<RDS_SUP_VER_SIG_TIME$> = SigTime
					Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, False$, True$)
					
					***************************
					* Log the signature event *
					***************************
					Set_Status(0)				
					EventParms = ''
					EventParms<COL$LOG_FILE>	  = 'WO_MAT'
					EventParms<COL$LOG_DTM>		  = SigDt:' ':SigTm
					EventParms<COL$ACTION>  	  = WOStepNo:'QA'
					EventParms<COL$WH_CD>		  = WHCode
					EventParms<COL$LOC_CD>		  = LocCode
					EventParms<COL$WO_NOS>		  = WONo
					EventParms<COL$CASS_NOS>	  = CassNo
					EventParms<COL$USER_ID>		  = SignedBy
					EventParms<COL$TAGS>		  = ''
					EventParms<COL$TOOL_ID>		  = ''
					CONVERT @FM TO @RM IN EventParms
					obj_WO_Mat_Log('Create', EventParms)
					errCode = ''
					IF Get_Status(errCode) THEN
						Error_Services('Add', 'Error in NCR_ACTIONS. Error code: ':errCode)
					END
					
					*********************************
					* Log the full box reject event *
					*********************************
					Set_Status(0)				
					EventParms = ''
					EventParms<COL$LOG_FILE>	  = 'WO_MAT'
					EventParms<COL$LOG_DTM>		  = SigDt:' ':SigTmPlusTwo
					EventParms<COL$ACTION>  	  = ActionCode
					EventParms<COL$WH_CD>		  = WHCode
					EventParms<COL$LOC_CD>		  = LocCode
					EventParms<COL$WO_NOS>		  = WONo
					EventParms<COL$CASS_NOS>	  = CassNo
					EventParms<COL$USER_ID>		  = SignedBy
					EventParms<COL$TAGS>		  = ''
					EventParms<COL$TOOL_ID>		  = ''
					CONVERT @FM TO @RM IN EventParms
					obj_WO_Mat_Log('Create',EventParms)
					IF Get_Status(errCode) THEN
						Error_Services('Add', 'Error in NCR_ACTIONS. Error code: ':ErrCode)
					END
					
					**********************************************************************
					* Synchonize the WO_MAT schedule wafers quatity with the RDS records *
					**********************************************************************
					IF (RDSNo NE '') THEN
						RDSRec = obj_Tables('ReadOnlyRec','RDS':@RM:RDSNo)
						RDSRec<RDS_SUP_VER_SIG$>	  = SignedBy
						RDSRec<RDS_SUP_VER_SIG_DATE$> = SigDate
						RDSRec<RDS_SUP_VER_SIG_TIME$> = SigTime
						obj_Tables('WriteOnlyRec','RDS':@RM:RDSNo:@RM:@RM:RDSRec)
						
						WOMatRec = XLATE('WO_MAT',WOMatKey,'','X')
						WMRDSNos = WOMatRec<WO_MAT_RDS_NO$>
						LOCATE RDSNo IN WMRDSNos USING @VM SETTING Pos THEN
							NextRDSNo = WMRDSNos<1,Pos+1>
							IF (NextRDSNo NE '') THEN
								CurrWfrQty = obj_WO_Mat('CurrWaferCnt', WOMatKey:@RM:WOMatRec)
								Set_Status(0)
								obj_RDS('SetSchedWfrQty', NextRDSNo:@RM:CurrWfrQty)
								IF Get_Status(errCode) THEN
									Error_Services('Add', 'Error in NCR_ACTIONS. Error code: ':ErrCode)
								END
							END
						END
					END					
					
					***********************************************************************
					* Send CASS_COMP transaction to SAP to inform SAP of the rejected box *
					***********************************************************************
					SAP_Services('AddCassCompTransaction', WOMatKey)
				END
				
			end else
				Error_Services('Add', 'Error in NCR_ACTIONS. WONo and/or CassNo are null!.')
			end
		end
	end
	
return

DELETE_RECORD_PRE:
	
	WorkOrderNo = {WO_NO}
	CassNo      = {WO_MAT_CASS_NO}
	WoMatKey    = WorkOrderNo : '*' : CassNo
	SAPBatchNo  = Xlate('WO_MAT', WOMatKey, 'SAP_BATCH_NO', 'X')
	If SAPBatchNo NE '' then
		NCRNo    = Name        
		RejQty   = Sum(obj_NCR('RejQty',NCRNo:@RM:Record))
		If ( (RejQty GT 0) and Not(MemberOf(@User4, 'OI_ADMIN') ) ) then
			
			// Log delete attempt
			LogData    = ''
			LogData<1> = LoggingDTM
			LogData<2> = @User4
			LogData<3> = Name
			LogData<4> = SAPBatchNo
			LogData<5> = RejQty
			LogData<6> = 'Blocking delete due to SAP batch number present.'
			Logging_Services('AppendLog', objSAPLog, LogData, @RM, @FM)     
			
			// Block deletion!
			// FS279: The record "%1%" cannot be deleted because it is delete-protected in the "%2%" table.
			OrigFileError = 279 : @FM : Name : @FM : 'NCR'
			Status        = 0
			ActionFlow    = ACTION_STOP$
		end
	end
	
return

DELETE_RECORD:
	
	WorkOrderNo = {WO_NO}
	CassNo      = {WO_MAT_CASS_NO}
	WoMatKey    = WorkOrderNo : '*' : CassNo
	WoMatRec    = Database_Services('ReadDataRow', 'WO_MAT', WoMatKey)
	WMIKey      = WoMatRec<WO_MAT_WMI_KEY$>
	WMOKey      = WoMatRec<WO_MAT_WMO_KEY$>
	If WMIKey NE '' then
		WMIRec  = Database_Services('ReadDataRow', 'WM_IN', WMIKey)
		Database_Services('WriteDataRow', 'WM_IN', WMIKey, WMIRec, True$, True$, False$)
	end
	If WMOKey NE '' then
		WMORec  = Database_Services('ReadDataRow', 'WM_OUT', WMOKey)
		Database_Services('WriteDataRow', 'WM_OUT', WMOKey, WMORec, True$, True$, False$)
	end
	
	// Log record delete action
	LogData    = ''
	LogData<1> = LoggingDTM
	LogData<2> = @User4
	LogData<3> = Name
	LogData<4> = Record
	Logging_Services('AppendLog', objLog, LogData, @RM, @FM)
	
	SAPBatchNo = Xlate('WO_MAT', WOMatKey, 'SAP_BATCH_NO', 'X')
	If SAPBatchNo NE '' then
		NCRNo    = Name        
		TransQty = Sum(obj_NCR('RejQty',NCRNo:@RM:Record))
		TransQty = TransQty * '-1'
		
		// Log negative SAP scrap transaction to capture metrics to submit for SAP change request
		LogData    = ''
		LogData<1> = LoggingDTM
		LogData<2> = @User4
		LogData<3> = Name
		LogData<4> = SAPBatchNo
		LogData<5> = TransQty
		Logging_Services('AppendLog', objSAPLog, LogData, @RM, @FM)               
	end
	
	// NCR quantity may have changed, so update RDS data in SCRAPE.
	RDSNos = {RDS_ID}
	For each RDSNo in RDSNos using @VM setting vPos
		Pass_To_SQL('WRITE', 'RDS', RDSNo)
	Next RDSNo
	
	OrgQty    = Sum(obj_NCR('RejQty',NCRNo:@RM:OrigRecord))
	NewQty    = 0
	AdjustQty = NewQty - OrgQty
	Work_Order_Services('AdjustScrappedQty', WorkOrderNo, AdjustQty)
	
return

// ----- Internal Methods ----------------------------------------------------------------------------------------------


Initialize_System_Variables:
	// Save these for restoration later
	SaveDict        = @DICT
	SaveID          = @ID
	SaveRecord      = @RECORD
	OrigFileError   = @FILE.ERROR
	
	// Now make sure @DICT, ID, and @RECORD are populated
	CurrentDictName = ''
	If @DICT then
		DictHandle = @DICT<1, 2>
		Locate DictHandle in @TABLES(5) Using @FM Setting fPos then
			CurrentDictName = Field(@TABLES(0), @FM, fPos, 1)
		end
	end
	
	If CurrentDictName NE DictName then
		Open DictName to @DICT else Status = 'Unable to initialize @DICT'
	end    
	
	@ID = KeyID
	If Record else
		// Record might not have been passed in. Read the record from the database table just to make sure.
		@FILE.ERROR     = ''
		Open TableName to hTable then
			FullFSList  = hTable[1, 'F' : @VM]
			BFS         = FullFSList[-1, 'B' : @SVM]
			LastHandle  = hTable[-1, 'B' : \0D\]
			FileHandle  = \0D\ : LastHandle[1, @VM]
			
			Call @BFS(READO.RECORD, BFS, FileHandle, KeyID, FMC, Record, ReadOStatus)
		end
	end
	@RECORD = Record
return


Restore_System_Variables:
	Transfer SaveDict   to @DICT
	Transfer SaveID     to @ID
	Transfer SaveRecord to @RECORD
	@FILE.ERROR = OrigFileError
return


LogRecord:
	
	WOMatRecCopy = WOMatRec
	Swap @FM with CRLF$ in WOMatRecCopy
	LogData     = ''
	LogData<1>  = LoggingDTM
	LogData<2>  = @USER4
	LogData<3>  = WOMatKey
	LogData<4>  = WOMatRecCopy
	LogData<5>  = RetStack()
	Logging_Services('AppendLog', ObjLog, LogData, @RM, @FM, False$)
	
return

