superbadge apex specialist

Salesforce Trailhead Superbadge: Apex Specialist Solution

Challenge 1: Automate record creation

STEP 1:

  1. Create a new Trailhead Playground
  2. Install the unmanaged Package
  3. Rename Case to Maintenance Request and Product to Equipment

STEP 2: Automate record creation using Apex Trigger

Update the trigger MaintenanceRequest:

trigger MaintenanceRequest on Case (before update, after update) {
    // call MaintenanceRequestHelper.updateWorkOrders  
    Map<Id,Case> caseList = new Map<Id,Case>();
    if(Trigger.isUpdate  && Trigger.isAfter){
        for(Case oCase: Trigger.new){
            if (oCase.IsClosed && (oCase.Type.equals('Repair') || oCase.Type.equals('Routine Maintenance'))){
                caseList.put(oCase.Id, oCase);
            }
        }
        if(caseList.size() > 0){
            System.debug('Calling updateWorkOrders from MaintenanceRequestHelper Class');
            MaintenanceRequestHelper.updateWorkOrders(caseList);    
        }        
    } 
}

dont miss out iconDon't forget to check out: Schema Class in Salesforce Apex | The Developer Guide

Update the class MaintenanceRequestHelper:

public with sharing class MaintenanceRequestHelper {
    public static void updateWorkOrders(Map<Id,Case>applicableCases) {
        // TODO: Complete the method to update workorders
        System.debug('*******Inside MaintenanceRequestHelper Class*******');
        Map<Id, Integer> mapProduct = new Map<Id, Integer>(); 
        List<Case> newCaseList = new List<Case>();
        List<Product2> listProduct = [select Id, Maintenance_Cycle__c from Product2];       							
        for (Product2 p : listProduct) {
            if (p != null) {
                if(p.Maintenance_Cycle__c != null){
                    mapProduct.put(p.Id, Integer.valueOf(p.Maintenance_Cycle__c));
                }               
            }
        }
        for(Case a: applicableCases.values()){
            Case newCase = new Case();
            newCase.Vehicle__c = a.Vehicle__c;
            newCase.Equipment__c = a.Equipment__c;
            newCase.Type = 'Routine Maintenance';
            newCase.Subject = String.isBlank(a.Subject) ? 'Routine Maintenance Request' : a.Subject;
            newCase.Date_Reported__c = Date.today();
            newCase.Status = 'New';
            newCase.Product__c = a.Product__c;
            newCase.AccountId = a.AccountId;
            newCase.ContactId = a.ContactId;
            newCase.AssetId = a.AssetId;
            newCase.Origin = a.Origin;
            newCase.Reason = a.Reason;
            newCase.Date_Due__c =  (mapProduct.get(a.Id) != null) ? (Date.today().addDays(Integer.valueOf(mapProduct.get(a.Id)))) : (Date.today());
                newCaseList.add(newCase);
        }
        if(newCaseList.size() > 0){
            insert newCaseList;
        }    
    }        
}

Challenge 2: Synchronize Salesforce data with an external system

Update the class WarehouseCalloutService to handle the REST callout:

public with sharing class WarehouseCalloutService {   
    private static final String WAREHOUSE_URL = 'https://th-superbadge-apex.herokuapp.com/equipment';    
    // complete this method to make the callout (using @future) to the
    // REST endpoint and update equipment on hand.
    @future(callout=true)
    public static void runWarehouseEquipmentSync(){
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setMethod('GET');
        request.setEndpoint(WAREHOUSE_URL);
        HttpResponse response = http.send(request);
        if(response.getStatusCode() == 200) {
            List<Object> jsonResponse = (List<Object>)JSON.deserializeUntyped(response.getBody());
            system.debug('~~ '+jsonResponse);
            List<Product2> productList = new List<Product2>();
            for(Object ob : jsonResponse) {
                Map<String,Object> mapJson = (Map<String,Object>)ob;
                Product2 pr = new Product2();
                pr.Replacement_Part__c = (Boolean)mapJson.get('replacement');
                pr.Name = (String)mapJson.get('name');
                pr.Maintenance_Cycle__c = (Integer)mapJson.get('maintenanceperiod');
                pr.Lifespan_Months__c = (Integer)mapJson.get('lifespan');
                pr.Cost__c = (Decimal) mapJson.get('lifespan');
                pr.Warehouse_SKU__c = (String)mapJson.get('sku');
                pr.Current_Inventory__c = (Double) mapJson.get('quantity');
                productList.add(pr);
            }            
            if(productList.size()>0)
                upsert productList;
        }        
    }    
}

Challenge 3: Schedule synchronization

Update the Schedule Apexclass WarehouseSyncSchedule:

global class WarehouseSyncSchedule implements Schedulable{
    global void execute(System.SchedulableContext context){
        WarehouseCalloutService.runWarehouseEquipmentSync();
    }
}

Create Schedule Apex from the Salesforce UI

Challenge 4: Test automation logic

@isTest
public class MaintenanceRequestTest {
    static  List<Case> caseList1 = new List<Case>();
    static List<Product2> prodList = new List<Product2>();
    static List<Work_Part__c> wpList = new List<Work_Part__c>();
    @testSetup
    static void getData(){
        caseList1= CreateData( 300,3,3,'Repair');
    }    
    public static List<Case>
    CreateData( Integer numOfcase, Integer numofProd, Integer numofVehicle,
    String type){
        List<Case> caseList = new List<Case>();
        //Create Vehicle       
        Vehicle__c vc = new Vehicle__c();
        vc.name='Test Vehicle';
        upsert vc;
        //Create Equipment
        for(Integer i=0;i<numofProd;i++){
            Product2 prod = new Product2();
            prod.Name='Test Product'+i;
            if(i!=0)
            prod.Maintenance_Cycle__c=i;
            prod.Replacement_Part__c=true;
            prodList.add(prod);
        }
        upsert prodlist;
        //Create Case
        for(Integer i=0;i< numOfcase;i++){
            Case newCase = new Case();
            newCase.Status='New';
            newCase.Origin='web';
            if( math.mod(i, 2) ==0)
            newCase.Type='Routine Maintenance';
            else
            newCase.Type='Repair'; 
            newCase.Subject='Routine Maintenance of Vehicle' +i;
            newCase.Vehicle__c=vc.Id;
            if(i<numofProd)
            newCase.Equipment__c=prodList.get(i).ID;
            else 
            newCase.Equipment__c=prodList.get(0).ID;
            caseList.add(newCase);
        }
        upsert caseList;       
        //create work part                               
        for(Integer i=0;i<numofProd;i++){                           
            Work_Part__c wp = new Work_Part__c();
            wp.Equipment__c   =prodlist.get(i).Id   ; 
            wp.Maintenance_Request__c=caseList.get(i).id;
            wplist.add(wp) ;
        }
        upsert wplist;
        return caseList;              
    }      
    public static testmethod void testMaintenanceHelper(){        
        Test.startTest();
        getData();
        for(Case cas: caseList1)   
        cas.Status ='Closed';      
        update caseList1;  
        Test.stopTest();
    }
}

dont miss out iconCheck out another amazing blog by Aditya here: Data Mapping and Merge Mapping in Salesforce - Everything you Need to Know

Challenge 5: Test callout logic

Update the class WarehouseCalloutServiceMock to generate a fake response:

public class WarehouseCalloutServiceMock implements HTTPCalloutMock {
    // implement http mock callout
    public HTTPResponse respond (HttpRequest request){
        HttpResponse response = new HTTPResponse();
        response.setHeader('Content-type','application/json');
        response.setBody('[{"_id":"55d66226726b611100aaf741","replacement":false,"quantity":5,"name":"Generator 1000 kW","maintenanceperiod":365,"lifespan":120,"cost":5000,"sku":"100003"},{"_id":"55d66226726b611100aaf742","replacement":true,"quantity":183,"name":"Cooling Fan","maintenanceperiod":0,"lifespan":0,"cost":300,"sku":"100004"},{"_id":"55d66226726b611100aaf743","replacement":true,"quantity":143,"name":"Fuse 20A","maintenanceperiod":0,"lifespan":0,"cost":22,"sku":"100005"}]');
        response.setStatusCode(200);
        return response;
    }    
}

Create the class WarehouseCalloutServiceTest

@isTest
private class WarehouseCalloutServiceTest {   
    @isTest  
    static void testWareHouseCallout(){
        Test.startTest();
        // implement mock callout test here
        Test.setMock(HTTPCalloutMock.class, new WarehouseCalloutServiceMock());
        WarehouseCalloutService.runWarehouseEquipmentSync();
        Test.stopTest();
    }     
}

Challenge 6: Test scheduling logic

@isTest
private class WarehouseSyncScheduleTest {
    //Dummy CRON expression
    public static String CRON_EXP = '0 0 0 15 3 ? 2022';
    @isTest 
    static void testScheduledJob(){
        //call the MaintenanceRequestTest class with method CreateData
         MaintenanceRequestTest.CreateData( 5,2,2,'Repair');
        Test.startTest();
        //implements the mock callout 
        Test.setMock(HttpCalloutMock.class, new WarehouseCalloutServiceMock());
        String joBID= System.schedule('TestScheduleJob', CRON_EXP, new WarehouseSyncSchedule());
       // List<Case> caselist = [Select count(id) from case where case]        
        Test.stopTest();
    }
}

Popular Salesforce Blogs