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);
        }

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .