0

I wrote this schedulable B2B Commerce Product Index Builder class based on documentation from Salesforce and consulting a custom rep.

global class ccScheduledProductIndexBuilder  implements Schedulable {
       global void execute(SchedulableContext SC) {

        Map<Integer, Map<String, String>> batchScopeValues =  ccrz.ccProductIndexBuilder.getBatchScopeValues(new Map<String, Object> {
            ccrz.ccProductIndexBuilder.NUMBER_OF_SCOPE_KEY_PAIRS => 5,
            ccrz.ccProductIndexBuilder.IS_FULL_REFRESH => FALSE
        });

        for (Integer key : batchScopeValues.keySet()){
            ccrz.ccProductIndexBuilder.cleanAndBuild(new Map<String, Object> {
                ccrz.ccProductIndexBuilder.BATCH_JOB_PRODUCT_SCOPE => batchScopeValues.get(key),
                ccrz.ccApiProductIndex.CLEAN_ONLY => TRUE,
                ccrz.ccAPIProductIndex.LOCALES => new Set<String>{'en_US','en'}
            });
        }
     }
}

I then wrote a tester class for it

@isTest
private class ccScheduledProductIndexBuilderTest {
    @isTest
    static void TestScheduledJob() {

      /*

  from https://help.salesforce.com/articleView?id=sf.b2b_commerce_product_index.htm&type=5

A single product index record references a corresponding CC Product record. 
The product index record also reflects data from a single instance of the following types of 
records related to that product:

- CC Product Category
- CC Price List Item
- CC Product Item I18N

To create an index record for a particular product, the product must meet the following criteria:

- The value of the Product Status field on the product record is Released or Not Orderable.
- The product has a price list item assigned to an entitled price list.
- The price list that the price list item belongs to has the Enabled field selected.
- The value of the End Date field for the product, price list, and price list item records are greater than the current date.
- If you’re using B2B Commerce for Visualforce Spring ’20 (version 4.12), the Exclude from Product Index field on the product isn't selected.

*/ 
      
             ccrz__E_Category__c c1 = new ccrz__E_Category__c();
            c1.Name = 'Test category';
            c1.ccrz__CategoryID__c = 'CAT-123';
            c1.ccrz__StartDate__c = date.ValueOf('2021-01-01');
            c1.ccrz__EndDate__c = date.ValueOf('2100-01-01');
            insert c1;

            ccrz__E_PriceList__c pl1 = new ccrz__E_PriceList__c();
            pl1.Name = 'Test price list';
            pl1.ccrz__StartDate__c = date.ValueOf('2021-01-01');
            pl1.ccrz__EndDate__c = date.ValueOf('2100-01-01');
            pl1.ccrz__Enabled__c = true;
            insert pl1;
           
            ccrz__E_Product__c  p1 = new ccrz__E_Product__c();
            p1.Name = 'Test product 1';
            p1.ccrz__SKU__c = 'SKU-1234';
            p1.ccrz__ProductStatus__c = 'Released';
            p1.ccrz__EndDate__c = date.ValueOf('2100-01-01');
            p1.ccrz__ExcludeFromProductIndex__c = false;
            insert p1;

            ccrz__E_PriceListItem__c pLI1 = new ccrz__E_PriceListItem__c();
            plI1.ccrz__Pricelist__c =  pl1.Id;
            plI1.ccrz__StartDate__c = date.ValueOf('2021-01-01');
            plI1.ccrz__EndDate__c = date.ValueOf('2100-01-01');
            plI1.ccrz__Price__c = 10.00;
            plI1.ccrz__Product__c = p1.Id;
            plI1.ccrz__ItemType__c = 'test price line item type';
            plI1.ccrz__PricelistItemId__c = 'external price list item id';
            plI1.ccrz__MaxQty__c = 15;
            plI1.ccrz__MinQty__c = 10;
            plI1.ccrz__PricingTiers__c = 'Pricing tier 1';
            plI1.ccrz__RecurringPrice__c = false;
            pLI1.ccrz__UnitOfMeasure__c = 'Measure 1';
            plI1.ccrz__AttributePricing__c = 'Atr pricing 1';
            insert plI1;  
            //  System.debug('plI1.Id = ' + plI1.Id);
        
        

            ccrz__E_ProductCategory__c pc1 = new ccrz__E_ProductCategory__c();
            pc1.ccrz__Category__c = c1.Id;
            pc1.ccrz__Product__c = p1.Id;
            pc1.ccrz__StartDate__c = date.ValueOf('2021-01-01');
            pc1.ccrz__EndDate__c = date.ValueOf('2100-01-01');
            insert pc1;
            ccrz__E_ProductItemI18N__c pI1 = new ccrz__E_ProductItemI18N__c();
            pI1.Name = 'Test product item name';
            pI1.ccrz__Product__c = p1.Id;
            insert pI1;


            ccrz__E_Product__c  p2 = new ccrz__E_Product__c(ccrz__SKU__c = 'SKU-3456');
            p2.Name = 'Test product 2';
            p2.ccrz__SKU__c = 'SKU-3456';
            p2.ccrz__ProductStatus__c = 'Released';
            p2.ccrz__EndDate__c = date.ValueOf('2100-01-01');
            p2.ccrz__ExcludeFromProductIndex__c = false;
            insert p2;

            ccrz__E_PriceListItem__c pLI2 = new ccrz__E_PriceListItem__c();
            plI2.ccrz__Pricelist__c =  pl1.Id;
            plI2.ccrz__StartDate__c = date.ValueOf('2021-01-01');
            plI2.ccrz__EndDate__c =  date.ValueOf('2100-01-01');
            plI2.ccrz__Price__c = 10.00;
            plI2.ccrz__Product__c = p2.Id;
            plI2.ccrz__ItemType__c = 'test price line item type 2';
            plI2.ccrz__PricelistItemId__c = 'external price list item id 2';
            plI2.ccrz__MaxQty__c = 15;
            plI2.ccrz__MinQty__c = 10;
            plI2.ccrz__PricingTiers__c = 'Pricing tier 2';
            plI2.ccrz__RecurringPrice__c = false;
            plI2.ccrz__UnitOfMeasure__c = 'Measure 2';
            plI2.ccrz__AttributePricing__c = 'Atr pricing 2';
            insert plI2;
           // System.debug('plI2.Id = ' + plI2.Id);

            ccrz__E_ProductCategory__c pc2 = new ccrz__E_ProductCategory__c();
            pc2.ccrz__Category__c = c1.Id;
            pc2.ccrz__Product__c = p2.Id;
            pc2.ccrz__StartDate__c = date.ValueOf('2021-01-01');
            pc2.ccrz__EndDate__c = date.ValueOf('2100-01-01');
            insert pc2;
            ccrz__E_ProductItemI18N__c pI2 = new ccrz__E_ProductItemI18N__c();
            pI2.Name = 'Test product item name';
            pI2.ccrz__Product__c = p2.Id;
            insert pI2;



            String sch = '0 0 23 * * ?';  
            Crontrigger ct;
            
            ccScheduledProductIndexBuilder myClass = new ccScheduledProductIndexBuilder();
            String jobId = System.Schedule('Test Sched', sch, myClass);
             ct = [SELECT Id, CronExpression, TimesTriggered, NextFireTime FROM CronTrigger WHERE id = :jobId];
        
          System.assertEquals(sch, ct.CronExpression);
         System.assertEquals(0, ct.TimesTriggered);
         
         
        // System.assertEquals(true, true);
    }
 }

When I run the test, I'm always getting this error "System.NullPointerException: Attempt to de-reference a null object Class.ccScheduledProductIndexBuilder.execute: line 9, column 1"

I created all the objects necessary for Indexing a Product so I do not know what else I need to add. Do you have any ideas how I can fix this?

1 Answer 1

0

I changed this section of the code

 String sch = '0 0 23 * * ?';  
            Crontrigger ct;
            
ccScheduledProductIndexBuilder myClass = new ccScheduledProductIndexBuilder();
String jobId = System.Schedule('Test Sched', sch, myClass);
ct = [SELECT Id, CronExpression, TimesTriggered, NextFireTime FROM CronTrigger WHERE id = :jobId];
 System.assertEquals(sch, ct.CronExpression);
     System.assertEquals(0, ct.TimesTriggered);
    

with this

 Map<Integer, Map<String, String>> batchScopeValues = new Map<Integer, Map<String, String>> ();
        batchScopeValues.put(1, new Map<String, String>{
            ccrz.ccProductIndexBuilder.START_KEY => p1.Id,
            ccrz.ccProductIndexBuilder.END_KEY => p2.Id
            });

        try {
            for (Integer key : batchScopeValues.keySet()){
                ccrz.ccProductIndexBuilder.cleanAndBuild(new Map<String, Object> {
                    ccrz.ccProductIndexBuilder.BATCH_JOB_PRODUCT_SCOPE => batchScopeValues.get(key),
                    ccrz.ccApiProductIndex.CLEAN_ONLY => TRUE,
                    ccrz.ccAPIProductIndex.LOCALES => new Set<String>{'en_US','en'}
                });
                System.assert(true);
            } 
        } catch (Exception ex) {
            System.debug('exception = ' + ex.getMessage());
            System.assert(false);
        }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.