更新 Apex 代码中的层次结构自定义设置

你可能希望在执行代码期间更新自定义设置,以关闭验证或工作流程规则。

在下面的代码中,我创建了一个可调度 Apex 类 ,它将更新其关闭日期小于或等于当前日期 6 天的任何商机的关闭日期,将日期更改为 20 天。

我将使用我的自定义设置 Val_Rule_Cntrlr__c 来停用任何验证规则,这将阻止我更新符合我的条件的商机。

global class Scheduled_OppCloseDateUpdate implements Schedulable {

    global void execute(SchedulableContext SC) {
        updOpportunityCloseDates();
    }

    global void updOpportunityCloseDates() {
        
        Id userId;
        Val_Rule_Cntrlr__c setting;
        Boolean validationRulesAlreadyDisabled;
        List<Opportunity> processedOpps = new List<Opportunity>();
        Date d;
        
        // get running user's Id
        userId = userinfo.getUserId();
        // retrieve Custom Setting status, for running user
        setting = Val_Rule_Cntrlr__c.getInstance(userId);
        
        // if the setting field is false, update it to disable validation rules
        if (setting.All_Opportunity_Disabled__c == false) {
            setting.All_Opportunity_Disabled__c = true;
            upsert setting;
        }
        // if the setting field was already true, there's no need to disable it
        // but it shouldn't be switched to false by this class once the process has been completed
        else {
            validationRulesAlreadyDisabled = true;
        }
        
        // execute code to manage business process
   
        d = system.today().addDays(6);
        
        for(Opportunity o : [SELECT Id, CloseDate
                               FROM Opportunity
                              WHERE CloseDate <= :d
                                // class only updates open Opportunities
                                AND Probability > 0 AND Probability < 100])
        {
            o.CloseDate = System.today().addDays(20);
            processedOpps.add(o);
        }
        
        if (processedOpps.size() > 0) {
            update processedOpps;
        }
        
        // reactivate validation rules
        if (validationRulesAlreadyDisabled == false) {
            setting.All_Opportunity_Disabled__c = false;
            upsert setting;
        }
        
    }
    
}

为了确保我的类中的自定义设置更改停用了我的验证规则,我创建了一个复选框字段 Trigger_Validation_Rule__c(用户无法看到或添加到页面布局中)和带有此条件的验证规则:

AND(
  $Setup.Val_Rule_Cntrlr__c.All_Opportunity_Disabled__c = FALSE,
  Trigger_Validation_Rule__c = TRUE,

  /* allow the above criteria to be met while inserting the Opportunities, without triggering the rule, in the @testSetup portion of the test */
  NOT(ISNEW())
)

然后,在创建机会时,我将复选框字段设置为 true,以便在我的代码不编辑自定义设置字段时满足规则标准。

@isTest
private class WE_ScheduledCloseDateUpdateTest {

    @testSetup
    static void dataSetup() {

        Profile p = [SELECT Id FROM Profile WHERE Name = 'System Administrator' LIMIT 1];
        
        User u = new User(LastName = 'Test',Alias = 't1',Email = 'example@gmail.com',Username = 'sotest@gmail.com',ProfileId = p.Id,TimeZoneSidKey = 'America/Denver',LocaleSidKey = 'en_US',EmailEncodingKey = 'UTF-8',LanguageLocaleKey = 'en_US');
        insert u;

        Val_Rule_Cntrlr__c valRuleCntrlr = new Val_Rule_Cntrlr__c(SetupOwnerId = u.Id,All_Opportunity_Disabled__c = false);
        upsert valRuleCntrlr;
            
        List<Opportunity> testOpps = new List<Opportunity>();
            
        // create the Opportunities that will be updated by the class
        for(integer i = 0; i < 200; i++) {
            testOpps.add(new Opportunity(
                Name          = 'Test Opp Update' + i,
                OwnerId       = u.Id,
                StageName     = 'Prospecting',
                CloseDate     = date.today().addDays(1),
                Amount        = 100,
                // set checkbox field to true, to trigger validation rules if they've not been deactivated by class
                Trigger_Validation_Rule__c = true));
        }
        // create the Opportunities that won't be updated by the class
        for(integer i = 0; i < 200; i++) {
            testOpps.add(new Opportunity(
                Name          = 'Test Opp Skip' + i,
                OwnerId       = u.Id,
                StageName     = 'Prospecting',
                CloseDate     = date.today().addDays(15),
                Amount        = 100,
                Trigger_Validation_Rule__c = true));
        }           
        insert testOpps;

    }
    
    // code required to test a scheduled class, see https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_scheduler.htm for more details
    public static String CRON_EXP = '0 0 0 15 3 ? 2022';

    static testmethod void testCloseDateUpdates() {

        // execute scheduled class
        
        Test.startTest();
        
        String jobId = System.schedule('ScheduleApexClassTest',
                                       CRON_EXP,
                                       new Scheduled_OppCloseDateUpdate());
        
        CronTrigger ct = [SELECT Id, CronExpression, TimesTriggered, NextFireTime
                            FROM CronTrigger
                           WHERE id = :jobId];
        
        System.assertEquals(CRON_EXP, ct.CronExpression);
        System.assertEquals(0, ct.TimesTriggered);
        System.assertEquals('2022-03-15 00:00:00', String.valueOf(ct.NextFireTime));
        
        Test.stopTest();

        // test results
        
        Integer updateCount = 0;
        Integer skipCount   = 0;

        List <Opportunity> opportunitys = [SELECT Id, Name, CloseDate FROM Opportunity];

        for(Opportunity o : opportunitys) {
            if (o.Name.contains('Update') &&
                updateCount == 0)
            {
                System.assertEquals(date.today().addDays(20), o.CloseDate, 'Opportunity\'s Close Date should have been updated as it was less than 7 days away');
                updateCount = 1;
            }
            if (o.Name.contains('Skip') &&
                skipCount == 0)
            {
                System.assertEquals(date.today().addDays(15), o.CloseDate, 'Opportunity should not have been updated as it\'s Close Date is more than 7 days away');
                skipCount = 1;
            }
        }
        // check that both lists of Opportunities have been tested
        System.assertEquals(2, updateCount + skipCount, 'Count should be 2 once all assertions have been executed');
    
    }
    
    // check that the class does not change the custom setting's field to false, if it was true before class was executed
    static testmethod void testSettingUpdates() {
        
        User u = [SELECT Id FROM User WHERE UserName = 'sotest@gmail.com'];
        
        // switch the custom setting field to true before the scheduled job executes
        Val_Rule_Cntrlr__c setting;
        setting = Val_Rule_Cntrlr__c.getInstance(u.Id);
        setting.All_Opportunity_Disabled__c = true;
        upsert setting;
        
        System.runAs(u) {
            
            Test.startTest();
            
            String jobId = System.schedule('ScheduleApexClassTest',
                                           CRON_EXP,
                                           new Scheduled_OppCloseDateUpdate());
            
            CronTrigger ct = [SELECT Id, CronExpression, TimesTriggered, NextFireTime
                                FROM CronTrigger
                               WHERE id = :jobId];
            
            System.assertEquals(CRON_EXP, ct.CronExpression);
            System.assertEquals(0, ct.TimesTriggered);
            System.assertEquals('2022-03-15 00:00:00', String.valueOf(ct.NextFireTime));
            
            Test.stopTest();
        }
        setting = Val_Rule_Cntrlr__c.getInstance(u.Id);
        
        // check that the class did not change the All_Opportunity_Disabled__c field to false
        System.assertEquals(true, setting.All_Opportunity_Disabled__c);
    }

}