Compile function Automated_Workflow_Services(@Service, @Params)

/*
Initial Author: Jonathan Ouellette
This service module has a catalogued list of functions to quickly and easily perform certain functions related to lot
processing.

1. CreateAWO - Imitates the process of getting data from SAP and processing the WO start in OI.
2. RouteWO - Imitates routing of a WO, AKA selecting a ProdVer and Assigning the WO to a reactor Type
3. PrescribeWafers - Imitates creating the child lots for a WO, AKA creating WO_MAT records
4. ReleaseCassettes - Assigns raw substrates to the WO_MAT records. RDS for non-epipro is created at this point.
5. PerformPTI - Imitates Receiving operator moving the lot into the fab.
6. Perform1VER - Performs the 1VER operation for an RDS.
7. PerformLoad - Performs the load operation for an RDS.
8. PerformUnload - Performs the unload operation for a non-epipro RDS.
9. EnterRecipeParms - Used in conjunction with PerformLoad. Used to enter the parameters for the Reactor Recipe upon load
typically this is the first load of a Work Order.
10. VerifyRecipeParms - Used in conjunction with PerformLoad. Used to verify the current recipe setpoints for an RDS load.


*/
#pragma precomp SRP_PreCompiler
Declare function Gan_Services, Obj_Notes_Sent, msg, Check_Notes, Jonathan_Services, Database_Services, SRP_Datetime
Declare function Lsl_Users_Services, SRP_Time, RList, Error_Services, Obj_Wo_Mat, Pm_Services, Date_Services, Test_Run_Services
Declare function Reactor_Services, Reactor_Log_Services, obj_react_item, Utility, Environment_Services, obj_wo_log, Qa_Services
Declare subroutine Start_Window, RList, Set_Status, Database_Services, Obj_Sap, Sap_Services, Btree.Extract, Qa_Services
Declare subroutine Reactor_Services, Obj_Wo_Log, obj_wo_mat, Work_Order_Services, Material_Movement_Services, Automated_Workflow_Services
Declare subroutine Override_Services, Obj_Wo_Mat_Log, obj_post_log, Obj_Sap 

$insert LOGICAL
$insert NOTE_PTRS_EQU
$insert MSG_EQUATES
$Insert APP_INSERTS
$Insert RLIST_EQUATES
$Insert	WO_LOG_EQUATES
$Insert RDS_EQUATES
$Insert WO_STEP_EQUATES
$Insert WO_MAT_QA_EQUATES
$Insert REACT_RUN_EQUATES
$Insert RDS_LAYER_EQUATES
$Insert RDS_TEST_EQUATES
$Insert PM_EQUATES
$Insert PM_SPEC_EQUATES
$Insert WO_MAT_EQUATES
$Insert WM_OUT_EQUATES
$Insert TEST_RUN_EQUATES
$Insert TEST_RUN_WAFER_EQUATES
$Insert TEST_WAFER_PROD_EQUATES
$Insert TEST_RUN_TYPE_EQUATES
$Insert EPI_PART_EQUATES
$Insert POPUP_EQUATES
$Insert REACTOR_EQUATES

GoToService

Return Response or ""

//-----------------------------------------------------------------------------
// SERVICES
//-----------------------------------------------------------------------------

Service CreatAWO()

    //Step 1: Start a WO WOLogFileIn variable emulates what an SAP file would have
    /*
            ProdOrdNo     = FileIn<1,1>
            CustPONo      = FileIn<1,2>
            PromiseShipDt = FileIn<1,3>
            EpiPartNo     = FileIn<1,4>
            SubPartNo     = FileIn<1,5>
            SubRevNo      = FileIn<1,6>
            WOQty         = FileIn<1,7>
            VendCd        = FileIn<1,8>
            */
            debug
    WOLogFileIn = 'M999930.1':@VM:'NA':@VM:'02/29/2024':@VM:'U053':@VM:'931968':@VM:'1.0':@VM:'2400':@VM:'NA'
    RetVal      = obj_WO_LOG('SAPCreate',WOLogFileIn)
    Response    = RetVal
end service

Service RouteWO(WO_No)
    //Step 2: Route a WO with a Product Version

    WOLogRec      = Database_Services('ReadDataRow', 'WO_LOG', WO_No)
    EpiPartNo     = WOLogRec<WO_LOG_EPI_PART_NO$>
    If EpiPartNo NE '' then
        AllProdVerNos = XLATE('EPI_PART',EpiPartNo,EPI_PART_PROD_VER_NO$,'X')
        TypeOver            = ''
        TypeOver<PDISPLAY$> = AllProdVerNos
        TypeOver<PSELECT$>  = 1
        TypeOver<PMODE$>    = 'K'
        SelectedProdVerNo = Popup(@WINDOW,TypeOver,'PROD_VER')
        If SelectedProdVerNo NE '' then
            obj_WO_Log('Route',WO_No:@RM:SelectedProdVerNo)
        end
    end
end service

Service PrescribeWafers(WONo, AmountToRX)
    //Step 3: prescribe wafers. This is the same as assigning lot numbers to individual lots of raw material. AKA creating WO_MAT records
    /*
            a. User clicks the PUB_RX button on the WO_LOG form.
            b. Opens WO Receipt form
            c. Users clicks on WO's Due in
            d. User selects or enters a WO.
            e. User clicks scan codes, opens 
            */
debug
    ProdVerNo         = XLATE('WO_LOG', WONo, 'PROD_VER_NO', 'X')
    ReactType         = XLATE('WO_LOG', WONo, 'REACT_TYPE', 'X')
    CassLotNo         = '123456789'
    CustPartNo        = XLATE('WO_LOG', WONo, 'CUST_PART_NO', 'X')
    CassQty           = 25
    NumCassToRX       = AmountToRX / 25
    ExistingWOMatList = XLATE('WO_LOG', WONo, 'WO_MAT_KEY', 'X')
    LastCassNo        = 0
    for each cass in ExistingWOMatList using @VM setting iPos
        thisCassNo = FIELD(cass, '*', 2)
        if thisCassNo GT LastCassNo then LastCassNo =  thisCassNo
    Next cass
    for i = 1 to NumCassToRX
        NextCassNo                        = LastCassNo + 1
        LastCassNo                        = nextCassNo
        Parms                             = WONo:@RM
        Parms                            := NextCassNo:@RM
        Parms                            := ProdVerNo:@RM
        Parms                            := CassLotNo:@RM
        Parms                            := CassQty:@RM
        Parms                            := CustPartNo:@RM		;* This is the CUSTOMER part No
        Parms                            := 1:@RM
        Parms                            := ReactType:@RM									;* 3 character Reactor Type Code
        Parms                            := '':@RM
        Parms                            := 'SR':@RM									;* Warehouse = 'SR' - Shipping/Receiving Area
        Parms                            := 'RB':@RM									;* Location = 'RB' - Receiving Bench
        Parms                            := OCONV(SRP_Datetime('Now'), 'DT/4'):@RM
        Parms                            := 'JONATHAN_O':@RM
        Parms                            := '':@RM
        Parms                            := '':@RM
        Parms                            := '':@RM							;* Added 8/18/2009 JCH
        Parms                            := '':@RM							;* Added 12/16/2009 JCH
        Parms                            := 25:@RM							;* Added 11/4/2009 JCH
        Parms                            := 0:@RM								;* Added 05/14/2010 JCH
        Parms                            := '':@RM							    ;* Added 07/14/2011 for SAP Project JCH
        Parms                            := 25                             ; // Added 02/01/2018 dmb
        obj_WO_Mat('Create',Parms)
        If Error_Services('NoError') then
            WOLogRec                         = Database_Services('ReadDataRow', 'WO_LOG', WONo)
            WOLogRec<WO_LOG_WO_MAT_KEY$, -1> = WONo : '*' : LastCassNo
            Database_Services('WriteDataRow', 'WO_LOG', WONo, WOLogRec, 1, 0, 1)
        end
    Next i
    Work_Order_Services('UpdateReceivedQty', WONo)
    
    
end service

Service ReleaseCassettes(WONo)

    //Step 4: User clicks release cassettes(PUB_RELEASE) from WO_LOG form
    Work_Order_Services('ReleaseCassettes', WONo)
    //Can get RDS number at this point
end service

Service PerformPTI(CassID)
    debug
    //Step 5: User performs a PTI scan to tag lot into the fab.
    Warehouse = '1K'
    Location  = 'PTI'
    Material_Movement_Services('SaveRecord', CassID, Warehouse, Location, @USER4)
end service

* Service BatchProcessLotList()
*    RDSList    = ''
*
*    RDSList<1> = 627134
*    RDSList<2> = 627135
*    RDSList<3> = 627136
*    RDSList<4> = 627132
*    RDSList<5> = 627133
*    
*    for each rds in RDSList using @FM
*        //Automated_Workflow_Services('Perform1VER', rds, 63, 25)
*        Automated_Workflow_Services('PerformUnload', rds)
*    Next rds
* end service

Service Perform1VER(CassID, ReactorID, WfrQty)
    
    //Step 6
    If RowExists('RDS', CassID) AND ReactorID NE '' then
        ReadyToSign = QA_Services('PreEpiSignatureReady', CassID, @User4, WfrQty, ReactorID)
        If (ReadyToSign EQ True$) then
            QA_Services('SignPreEpiStage', CassID, @USER4, WfrQty, ReactorID) 
        end
    end
    
end service

Service PerformLoad(CassID, WfrInQty, LorRLL)

    //Step 7
    If RowExists('RDS', CassID) then
        ReadyToSign = Qa_Services('LoadSignatureReady', CassID, @User4, WfrInQty, LorRLL, 0)
        If ReadyToSign then
            Qa_Services('SignLoadStage', CassID, @User4, WfrInQty, LorRLL, 0)
        end else
            ErrorReason = Error_Services('GetMessage')
            Begin Case
                Case ErrorReason EQ 'Process Error: Recipe parameters have not been entered.'
                    //Get the expected parameters and enter them. This is in the RDS_Layer Record
                    //First lets get limits from the RDS Layer Record(s)
                    RDSLayerKeys = XLATE('RDS', CassID, RDS_RDS_LAYER_KEYS$, 'X')
                    for each RDSLayerKey in RDSLayerKeys using @VM setting rlPos
                        Automated_Workflow_Services('EnterRecipeParams', RDSLayerKey)
                        If Error_Services('NoError') then
                            Automated_Workflow_Services('PerformLoad', CassID, WfrInQty, LorRLL)
                        end else
                            //Die
                            Return
                        end
                    Next RDSLayerKey
                Case ErrorReason EQ 'RDS layer parameters must be reviewed for accuracy and acknowledged before the load operation can be signed.'
                    Automated_Workflow_Services('VerifyRecipeParams', CassID)
                    If Error_Services('NoError') then
                            Automated_Workflow_Services('PerformLoad', CassID, WfrInQty, LorRLL)
                        end else
                            //Die
                            Return
                        end
            End Case
        end
    end
end service

Service PerformUnload(RDSNo)
    //Step 8

    If RDSNo NE '' then
        Reactor     = XLATE('RDS', RDSNo, 'REACTOR', 'X')
        If Reactor NE ''  then
            ReadyToSign = QA_Services('UnloadSignatureReady', RDSNo, @User4, Reactor)
            If Error_Services('HasError') then
                If ErrorMsg EQ 'Cassette runtime exceeds three days! An override by a LEAD or SUPERVISOR is required.' then
                    Override_Services('SetOverride', 'RDS', RDSNo, 'UNLOAD_DTM', @USER4)
                    ReadyToSign = True$
                end
            end
            If ReadyToSign then
                QA_Services('SignUnloadStage', RDSNo, @User4)
            end
        end else
            Error_Services('Add', 'No Reactor assigned to RDS!') 
        end
    end else
        Error_Services('Add', 'No RDS No. Supplied!')
    end
end service

Service PerformFQA(RDSNo)

    ToolID = ''
    WHCd   = 'CR'
    LocCD  = 'QA'
    Tag    = ''
    SigDt  = Date()
    SigTm  = Time()
    WONo   = XLATE('RDS', RDSNo, RDS_WO$, 'X')
    CassNo = XLATE('RDS', RDSNo, RDS_CASS_NO$, 'X')

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
EventParms        = ''
    EventParms<COL$LOG_FILE> = 'WO_MAT'
    EventParms<COL$LOG_DTM>  = SigDt:' ':SigTm
    EventParms<COL$ACTION>   = 1:'QA'
    EventParms<COL$WH_CD>    = 'CR'
    EventParms<COL$LOC_CD>   = 'QA'
    EventParms<COL$WO_NOS>   = WONo
    EventParms<COL$CASS_NOS> = CassNo
    EventParms<COL$USER_ID>  = @USER4
    EventParms<COL$TAGS>     = ''
    EventParms<COL$TOOL_ID>  = ''
    
    CONVERT @FM TO @RM IN EventParms
    
    obj_WO_Mat_Log('Create',EventParms)        ;* * * * * INV EVENT LOG * * * * *
    Obj_Post_Log('POST')
    
    Qa_Services('SignFQAStage', RDSNo, @USER4)
end service


Service EnterRecipeParams(RDSLayerKey)

    RDSLayerRec = Database_Services('ReadDataRow', 'RDS_LAYER', RDSLayerKey)
    If RDSLayerRec NE '' then
        If RDSLayerRec<RDS_LAYER_EPI_TIME_MIN$> NE '' AND RDSLayerRec<RDS_LAYER_EPI_TIME_MAX$> NE '' then
            //Epi Deposit Time
            RDSLayerRec<RDS_LAYER_EPI_TIME$> = ((RDSLayerRec<RDS_LAYER_EPI_TIME_MAX$> - RDSLayerRec<RDS_LAYER_EPI_TIME_MIN$>) / 2) + RDSLayerRec<RDS_LAYER_EPI_TIME_MIN$>
        end
        
        If RDSLayerRec<RDS_LAYER_DILUENT_MIN$> NE '' AND RDSLayerRec<RDS_LAYER_DILUENT_MAX$> NE '' then
            //Diluent
            RDSLayerRec<RDS_LAYER_DILUENT_ADJ_PARAM$> = ((RDSLayerRec<RDS_LAYER_DILUENT_MAX$> - RDSLayerRec<RDS_LAYER_DILUENT_MIN$>) / 2) + RDSLayerRec<RDS_LAYER_DILUENT_MIN$>
        end
        
        If RDSLayerRec<RDS_LAYER_DOPANT_FLOW_MIN$> NE '' AND RDSLayerRec<RDS_LAYER_DOPANT_FLOW_MAX$> NE '' then
            //Dopant Flow
            RDSLayerRec<RDS_LAYER_DOPANT_FLOW$> = ((RDSLayerRec<RDS_LAYER_DOPANT_FLOW_MAX$> - RDSLayerRec<RDS_LAYER_DOPANT_FLOW_MIN$>) / 2) + RDSLayerRec<RDS_LAYER_DOPANT_FLOW_MIN$>
        end
        
        If RDSLayerRec<RDS_LAYER_HCL_FLOW_MIN$> NE '' AND RDSLayerRec<RDS_LAYER_HCL_FLOW_MAX$> NE '' then
            //HCL Flow
            RDSLayerRec<RDS_LAYER_HCL_FLOW$> = ((RDSLayerRec<RDS_LAYER_HCL_FLOW_MAX$> - RDSLayerRec<RDS_LAYER_HCL_FLOW_MIN$>) / 2) + RDSLayerRec<RDS_LAYER_HCL_FLOW_MIN$>
        end
        
        If RDSLayerRec<RDS_LAYER_BAKE_TIME_MIN$> NE '' AND RDSLayerRec<RDS_LAYER_BAKE_TIME_MAX$> NE '' then
            //Bake Time
            RDSLayerRec<RDS_LAYER_BAKE_TIME$> = ((RDSLayerRec<RDS_LAYER_BAKE_TIME_MAX$> - RDSLayerRec<RDS_LAYER_BAKE_TIME_MIN$>) / 2) + RDSLayerRec<RDS_LAYER_BAKE_TIME_MIN$>
        end
        
        If RDSLayerRec<RDS_LAYER_EPI_H2_FLOW_MIN$> NE '' AND RDSLayerRec<RDS_LAYER_EPI_H2_FLOW_MAX$> NE '' then
            //H2 Flow
            RDSLayerRec<RDS_LAYER_EPI_H2_FLOW$> = ((RDSLayerRec<RDS_LAYER_EPI_H2_FLOW_MAX$> - RDSLayerRec<RDS_LAYER_EPI_H2_FLOW_MIN$>) / 2) + RDSLayerRec<RDS_LAYER_EPI_H2_FLOW_MIN$>
        end
        
        If RDSLayerRec<RDS_LAYER_TCS_FLOW_MIN$> NE '' AND RDSLayerRec<RDS_LAYER_TCS_FLOW_MAX$> NE '' then
            //TCS Flow
            RDSLayerRec<RDS_LAYER_TCS_FLOW$> = ((RDSLayerRec<RDS_LAYER_TCS_FLOW_MAX$> - RDSLayerRec<RDS_LAYER_TCS_FLOW_MIN$>) / 2) + RDSLayerRec<RDS_LAYER_TCS_FLOW_MIN$>
        end
        
        If RDSLayerRec<RDS_LAYER_DCS_FLOW_MIN$> NE '' AND RDSLayerRec<RDS_LAYER_DCS_FLOW_MAX$> NE '' then
            //DCS Flow
            RDSLayerRec<RDS_LAYER_DCS_FLOW$> = ((RDSLayerRec<RDS_LAYER_DCS_FLOW_MAX$> - RDSLayerRec<RDS_LAYER_DCS_FLOW_MIN$>) / 2) + RDSLayerRec<RDS_LAYER_DCS_FLOW_MIN$>
        end
        
        If RDSLayerRec<RDS_LAYER_AUX1_MIN$> NE '' AND RDSLayerRec<RDS_LAYER_AUX1_MAX$> NE '' then
            //AUX 1
            RDSLayerRec<RDS_LAYER_AUX1$> = ((RDSLayerRec<RDS_LAYER_AUX1_MAX$> - RDSLayerRec<RDS_LAYER_AUX1_MIN$>) / 2) + RDSLayerRec<RDS_LAYER_AUX1_MIN$>
        end
        
        If RDSLayerRec<RDS_LAYER_AUX2_MIN$> NE '' AND RDSLayerRec<RDS_LAYER_AUX2_MAX$> NE '' then
            //AUX2
            RDSLayerRec<RDS_LAYER_AUX2$> = ((RDSLayerRec<RDS_LAYER_AUX2_MAX$> - RDSLayerRec<RDS_LAYER_AUX2_MIN$>) / 2) + RDSLayerRec<RDS_LAYER_AUX2_MIN$>
        end
        
        If RDSLayerRec<RDS_LAYER_F_OFFSET_MIN$> NE '' AND RDSLayerRec<RDS_LAYER_F_OFFSET_MAX$> NE '' then
            //F_OFFSET
            RDSLayerRec<RDS_LAYER_F_OFFSET$> = ((RDSLayerRec<RDS_LAYER_F_OFFSET_MAX$> - RDSLayerRec<RDS_LAYER_F_OFFSET_MIN$>) / 2) + RDSLayerRec<RDS_LAYER_F_OFFSET_MIN$>
        end
        
        If RDSLayerRec<RDS_LAYER_S_OFFSET_MIN$> NE '' AND RDSLayerRec<RDS_LAYER_S_OFFSET_MAX$> NE '' then
            //S_OFFSET
            RDSLayerRec<RDS_LAYER_S_OFFSET$> = ((RDSLayerRec<RDS_LAYER_S_OFFSET_MAX$> - RDSLayerRec<RDS_LAYER_S_OFFSET_MIN$>) / 2) + RDSLayerRec<RDS_LAYER_S_OFFSET_MIN$>
        end
        
        If RDSLayerRec<RDS_LAYER_R_OFFSET_MIN$> NE '' AND RDSLayerRec<RDS_LAYER_R_OFFSET_MAX$> NE '' then
            //R OFFSET
            RDSLayerRec<RDS_LAYER_R_OFFSET$> = ((RDSLayerRec<RDS_LAYER_R_OFFSET_MAX$> - RDSLayerRec<RDS_LAYER_R_OFFSET_MIN$>) / 2) + RDSLayerRec<RDS_LAYER_R_OFFSET_MIN$>
        end
        
        If RDSLayerRec<RDS_LAYER_ETCH1_MIN$> NE '' AND RDSLayerRec<RDS_LAYER_ETCH1_MAX$> NE '' then
            //ETCH 1
            RDSLayerRec<RDS_LAYER_ETCH1$> = ((RDSLayerRec<RDS_LAYER_ETCH1_MAX$> - RDSLayerRec<RDS_LAYER_ETCH1_MIN$>) / 2) + RDSLayerRec<RDS_LAYER_ETCH1_MIN$>
        end
        
        If RDSLayerRec<RDS_LAYER_ETCH2_MIN$> NE '' AND RDSLayerRec<RDS_LAYER_ETCH2_MAX$> NE '' then
            //ETCH 2
            RDSLayerRec<RDS_LAYER_ETCH2$> = ((RDSLayerRec<RDS_LAYER_ETCH2_MAX$> - RDSLayerRec<RDS_LAYER_ETCH2_MIN$>) / 2) + RDSLayerRec<RDS_LAYER_ETCH2_MIN$>
        end
        
        If RDSLayerRec<RDS_LAYER_ETCH3_MIN$> NE '' AND RDSLayerRec<RDS_LAYER_ETCH3_MAX$> NE '' then
            //ETCH 3
            RDSLayerRec<RDS_LAYER_ETCH3$> = ((RDSLayerRec<RDS_LAYER_ETCH3_MAX$> - RDSLayerRec<RDS_LAYER_ETCH3_MIN$>) / 2) + RDSLayerRec<RDS_LAYER_ETCH3_MIN$>
        end
        
        If RDSLayerRec<RDS_LAYER_UL_TEMP_MIN$> NE '' AND RDSLayerRec<RDS_LAYER_UL_TEMP_MAX$> NE '' then
            //UL_TEMP
            RDSLayerRec<RDS_LAYER_UL_TEMP$> = ((RDSLayerRec<RDS_LAYER_UL_TEMP_MAX$> - RDSLayerRec<RDS_LAYER_UL_TEMP_MIN$>) / 2) + RDSLayerRec<RDS_LAYER_UL_TEMP_MIN$>
        end
        
        If RDSLayerRec<RDS_LAYER_SUSC_ETCH_MIN$> NE '' AND RDSLayerRec<RDS_LAYER_SUSC_ETCH_MAX$> NE '' then
            //Susceptor Etch
            RDSLayerRec<RDS_LAYER_SUSC_ETCH$> = ((RDSLayerRec<RDS_LAYER_SUSC_ETCH_MAX$> - RDSLayerRec<RDS_LAYER_SUSC_ETCH_MIN$>) / 2) + RDSLayerRec<RDS_LAYER_SUSC_ETCH_MIN$>
        end
        Database_Services('WriteDataRow', 'RDS_LAYER', RDSLayerKey, RDSLayerRec, True$, False$, True$)
    end
    
end service

Service VerifyRecipeParams(RDSNo)
    //Used to verify exisiting recipe params. This is if they are already set.
    IF RDSNo NE '' then
        RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
        RDSRec<RDS_RDS_LAYER_ACK$> = True$
        Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, False$, True$)
    end else
        Error_Services('Add', 'RDS No was blank!!!')
    end
end service

Service SendCassComp(WoMatKey)
    debug
    Sap_Services('RetransmitCassComp', WoMatKey)
	obj_sap('SendOutbound')
end service






