Skip to content
This repository was archived by the owner on Apr 4, 2026. It is now read-only.

Latest commit

 

History

History
602 lines (481 loc) · 21.6 KB

File metadata and controls

602 lines (481 loc) · 21.6 KB

SPSGP-35421-Salesforce-Developer-Catalyst-Self-Learning-Super-Badges

##Salesforce Developer Catalyst Self-Learning & Super Badges #Lightning Web Components Basics Deploy Lightning Web Component Files ##Challenge : Create an app page for the bike card component bikeCard.html

Name: {name}
Description: {description}
Price: {price}

bikeCard.js import { LightningElement } from 'lwc'; export default class BikeCard extends LightningElement { name = 'Electra X4'; description = 'A sweet bike built for comfort.'; category = 'Mountain'; material = 'Steel'; price = '$2,700'; pictureUrl = 'https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/electrax4.jpg'; }

bikeCard.js-meta.xml

52.0 true Product Card lightning__AppPage lightning__RecordPage lightning__HomePage

##Handle Events in Lightning Web Components

tile.html

{product.fields.Name.value}

tile.js

import { LightningElement, api } from 'lwc';

export default class Tile extends LightningElement { @api product;

tileClick() {
    const event = new CustomEvent('tileclick', {
        // detail contains only primitives
        detail: this.product.fields.Id.value
    });
    // Fire the event from c-tile
    this.dispatchEvent(event);
}

}

list.html

list.js

import { LightningElement } from 'lwc'; import { bikes } from 'c/data';

export default class List extends LightningElement { bikes = bikes;

handleTileClick(evt) {
    // This component wants to emit a productselected event to its parent
    const event = new CustomEvent('productselected', {
        detail: evt.detail
    });
    // Fire the event from c-list
    this.dispatchEvent(event);
}

}

selector.html

Available Bikes
{name}

selector.js

import { LightningElement, wire } from 'lwc'; import { getRecord, getFieldValue } from 'lightning/uiRecordApi'; import Id from '@salesforce/user/Id'; import NAME_FIELD from '@salesforce/schema/User.Name'; const fields = [NAME_FIELD]; export default class Selector extends LightningElement { selectedProductId; handleProductSelected(evt) { this.selectedProductId = evt.detail; } userId = Id; @wire(getRecord, { recordId: '$userId', fields }) user; get name() { return getFieldValue(this.user.data, NAME_FIELD); } }

detail.html

{product.fields.Name.value}
{product.fields.MSRP__c.displayValue}
{product.fields.Description__c.value}

Select a bike

detail.js import { LightningElement, api } from 'lwc'; import { bikes } from 'c/data';

export default class Detail extends LightningElement {

// Ensure changes are reactive when product is updated
product;

// Private var to track @api productId
_productId = undefined;

// Use set and get to process the value every time it's
// requested while switching between products
set productId(value) {
    this._productId = value;
    this.product = bikes.find(bike => bike.fields.Id.value === value);
}

// getter for productId
@api get productId(){
    return this._productId;
}

}

Apex Specialist superbadge

Challenge 1 Automated Record Creation

MaintenanceRequestHelper.apxc public with sharing class MaintenanceRequestHelper { public static void updateworkOrders(List updWorkOrders, Map<Id,Case> nonUpdCaseMap) { Set validIds = new Set();

    For (Case c : updWorkOrders){
        if (nonUpdCaseMap.get(c.Id).Status != 'Closed' && c.Status == 'Closed'){
            if (c.Type == 'Repair' || c.Type == 'Routine Maintenance'){
                validIds.add(c.Id);
                
         
            }
        }
    }
    
    if (!validIds.isEmpty()){
        List<Case> newCases = new List<Case>();
        Map<Id,Case> closedCasesM = new Map<Id,Case>([SELECT Id, Vehicle__c, Equipment__c, Equipment__r.Maintenance_Cycle__c,(SELECT Id,Equipment__c,Quantity__c FROM Equipment_Maintenance_Items__r) 
                                                     FROM Case WHERE Id IN :validIds]);
        Map<Id,Decimal> maintenanceCycles = new Map<ID,Decimal>();
        AggregateResult[] results = [SELECT Maintenance_Request__c, MIN(Equipment__r.Maintenance_Cycle__c)cycle FROM Equipment_Maintenance_Item__c WHERE Maintenance_Request__c IN :ValidIds GROUP BY Maintenance_Request__c];
    
    for (AggregateResult ar : results){ 
        maintenanceCycles.put((Id) ar.get('Maintenance_Request__c'), (Decimal) ar.get('cycle'));
    }
        
        for(Case cc : closedCasesM.values()){
            Case nc = new Case (
                ParentId = cc.Id,
            Status = 'New',
                Subject = 'Routine Maintenance',
                Type = 'Routine Maintenance',
                Vehicle__c = cc.Vehicle__c,
                Equipment__c =cc.Equipment__c,
                Origin = 'Web',
                Date_Reported__c = Date.Today()
                
            );
            
            If (maintenanceCycles.containskey(cc.Id)){
                nc.Date_Due__c = Date.today().addDays((Integer) maintenanceCycles.get(cc.Id));
            } else {
                nc.Date_Due__c = Date.today().addDays((Integer) cc.Equipment__r.maintenance_Cycle__c);
            }
            
            newCases.add(nc);
        }
        
       insert newCases;
        
       List<Equipment_Maintenance_Item__c> clonedWPs = new List<Equipment_Maintenance_Item__c>();
       for (Case nc : newCases){
            for (Equipment_Maintenance_Item__c wp : closedCasesM.get(nc.ParentId).Equipment_Maintenance_Items__r){
                Equipment_Maintenance_Item__c wpClone = wp.clone();
                wpClone.Maintenance_Request__c = nc.Id;
                ClonedWPs.add(wpClone);
                
            }
        }
        insert ClonedWPs;
    }
}

}

Challenge 2 Synchronize Salesforce data with an external system

WarehouseCalloutService.apxc
public with sharing class WarehouseCalloutService implements Queueable {
private static final String WAREHOUSE_URL = 'https://th-superbadge-apex.herokuapp.com/equipment';

//class that makes a REST callout to an external warehouse system to get a list of equipment that needs to be updated.
//The callout’s JSON response returns the equipment records that you upsert in Salesforce. 

@future(callout=true)
public static void runWarehouseEquipmentSync(){
    Http http = new Http();
    HttpRequest request = new HttpRequest();
    
    request.setEndpoint(WAREHOUSE_URL);
    request.setMethod('GET');
    HttpResponse response = http.send(request);
    
    List<Product2> warehouseEq = new List<Product2>();
    
    if (response.getStatusCode() == 200){
        List<Object> jsonResponse = (List<Object>)JSON.deserializeUntyped(response.getBody());
        System.debug(response.getBody());
        
        //class maps the following fields: replacement part (always true), cost, current inventory, lifespan, maintenance cycle, and warehouse SKU
        //warehouse SKU will be external ID for identifying which equipment records to update within Salesforce
        for (Object eq : jsonResponse){
            Map<String,Object> mapJson = (Map<String,Object>)eq;
            Product2 myEq = new Product2();
            myEq.Replacement_Part__c = (Boolean) mapJson.get('replacement');
            myEq.Name = (String) mapJson.get('name');
            myEq.Maintenance_Cycle__c = (Integer) mapJson.get('maintenanceperiod');
            myEq.Lifespan_Months__c = (Integer) mapJson.get('lifespan');
            myEq.Cost__c = (Integer) mapJson.get('cost');
            myEq.Warehouse_SKU__c = (String) mapJson.get('sku');
            myEq.Current_Inventory__c = (Double) mapJson.get('quantity');
            myEq.ProductCode = (String) mapJson.get('_id');
            warehouseEq.add(myEq);
        }
        
        if (warehouseEq.size() > 0){
            upsert warehouseEq;
            System.debug('Your equipment was synced with the warehouse one');
        }
    }
}

public static void execute (QueueableContext context){
    runWarehouseEquipmentSync();
}

}

Challenge 3 Schedule synchronization using Apex code

WarehouseSyncShedule.apxc :-

global with sharing class WarehouseSyncSchedule implements Schedulable{ global void execute(SchedulableContext ctx){ System.enqueueJob(new WarehouseCalloutService()); } }

Challenge 4 Test automation logic

MaintenanceRequestHelperTest.apxc :-

@istest public with sharing class MaintenanceRequestHelperTest {

private static final string STATUS_NEW = 'New';
private static final string WORKING = 'Working';
private static final string CLOSED = 'Closed';
private static final string REPAIR = 'Repair';
private static final string REQUEST_ORIGIN = 'Web';
private static final string REQUEST_TYPE = 'Routine Maintenance';
private static final string REQUEST_SUBJECT = 'Testing subject';

PRIVATE STATIC Vehicle__c createVehicle(){
    Vehicle__c Vehicle = new Vehicle__C(name = 'SuperTruck');
    return Vehicle;
}

PRIVATE STATIC Product2 createEq(){
    product2 equipment = new product2(name = 'SuperEquipment',
                                     lifespan_months__C = 10,
                                     maintenance_cycle__C = 10,
                                     replacement_part__c = true);
    return equipment;
}

PRIVATE STATIC Case createMaintenanceRequest(id vehicleId, id equipmentId){
    case cs = new case(Type=REPAIR,
                      Status=STATUS_NEW,
                      Origin=REQUEST_ORIGIN,
                      Subject=REQUEST_SUBJECT,
                      Equipment__c=equipmentId,
                      Vehicle__c=vehicleId);
    return cs;
}

PRIVATE STATIC Equipment_Maintenance_Item__c createWorkPart(id equipmentId,id requestId){
    Equipment_Maintenance_Item__c wp = new Equipment_Maintenance_Item__c(Equipment__c = equipmentId,
                                                                        Maintenance_Request__c = requestId);
    return wp;
}


@istest
private static void testMaintenanceRequestPositive(){
    Vehicle__c vehicle = createVehicle();
    insert vehicle;
    id vehicleId = vehicle.Id;
    
    Product2 equipment = createEq();
    insert equipment;
    id equipmentId = equipment.Id;
    
    case somethingToUpdate = createMaintenanceRequest(vehicleId,equipmentId);
    insert somethingToUpdate;
    
    Equipment_Maintenance_Item__c workP = createWorkPart(equipmentId,somethingToUpdate.id);
    insert workP;
    
    test.startTest();
    somethingToUpdate.status = CLOSED;
    update somethingToUpdate;
    test.stopTest();
    
    Case newReq = [Select id, subject, type, Equipment__c, Date_Reported__c, Vehicle__c, Date_Due__c
                  from case
                  where status =:STATUS_NEW];
    
    Equipment_Maintenance_Item__c workPart = [select id
                                             from Equipment_Maintenance_Item__c
                                             where Maintenance_Request__c =:newReq.Id];
    
    system.assert(workPart != null);
    system.assert(newReq.Subject != null);
    system.assertEquals(newReq.Type, REQUEST_TYPE);
    SYSTEM.assertEquals(newReq.Equipment__c, equipmentId);
    SYSTEM.assertEquals(newReq.Vehicle__c, vehicleId);
    SYSTEM.assertEquals(newReq.Date_Reported__c, system.today());
}

@istest
private static void testMaintenanceRequestNegative(){
    Vehicle__C vehicle = createVehicle();
    insert vehicle;
    id vehicleId = vehicle.Id;
    
    product2 equipment = createEq();
    insert equipment;
    id equipmentId = equipment.Id;
    
    case emptyReq = createMaintenanceRequest(vehicleId,equipmentId);
    insert emptyReq;
    
    Equipment_Maintenance_Item__c workP = createWorkPart(equipmentId, emptyReq.Id);
    insert workP;
    
    test.startTest();
    emptyReq.Status = WORKING;
    update emptyReq;
    test.stopTest();
    
    list<case> allRequest = [select id 
                             from case];
    
    Equipment_Maintenance_Item__c workPart = [select id 
                                              from Equipment_Maintenance_Item__c 
                                              where Maintenance_Request__c = :emptyReq.Id];
    
    system.assert(workPart != null);
    system.assert(allRequest.size() == 1);
}

@istest
private static void testMaintenanceRequestBulk(){
    list<Vehicle__C> vehicleList = new list<Vehicle__C>();
    list<Product2> equipmentList = new list<Product2>();
    list<Equipment_Maintenance_Item__c> workPartList = new list<Equipment_Maintenance_Item__c>();
    list<case> requestList = new list<case>();
    list<id> oldRequestIds = new list<id>();
    
    for(integer i = 0; i < 300; i++){
       vehicleList.add(createVehicle());
        equipmentList.add(createEq());
    }
    insert vehicleList;
    insert equipmentList;
    
    for(integer i = 0; i < 300; i++){
        requestList.add(createMaintenanceRequest(vehicleList.get(i).id, equipmentList.get(i).id));
    }
    insert requestList;
    
    for(integer i = 0; i < 300; i++){
        workPartList.add(createWorkPart(equipmentList.get(i).id, requestList.get(i).id));
    }
    insert workPartList;
    
    test.startTest();
    for(case req : requestList){
        req.Status = CLOSED;
        oldRequestIds.add(req.Id);
    }
    update requestList;
    test.stopTest();
    
    list<case> allRequests = [select id
                             from case
                             where status =: STATUS_NEW];
    
    list<Equipment_Maintenance_Item__c> workParts = [select id
                                                    from Equipment_Maintenance_Item__c
                                                    where Maintenance_Request__c in: oldRequestIds];
    
    system.assert(allRequests.size() == 300);
}

}

MaintenanceRequestHelper.apxc :-

public with sharing class MaintenanceRequestHelper { public static void updateworkOrders(List updWorkOrders, Map<Id,Case> nonUpdCaseMap) { Set validIds = new Set();

    For (Case c : updWorkOrders){
        if (nonUpdCaseMap.get(c.Id).Status != 'Closed' && c.Status == 'Closed'){
            if (c.Type == 'Repair' || c.Type == 'Routine Maintenance'){
                validIds.add(c.Id);
                
         
            }
        }
    }
    
    if (!validIds.isEmpty()){
        List<Case> newCases = new List<Case>();
        Map<Id,Case> closedCasesM = new Map<Id,Case>([SELECT Id, Vehicle__c, Equipment__c, Equipment__r.Maintenance_Cycle__c,(SELECT Id,Equipment__c,Quantity__c FROM Equipment_Maintenance_Items__r) 
                                                     FROM Case WHERE Id IN :validIds]);
        Map<Id,Decimal> maintenanceCycles = new Map<ID,Decimal>();
        AggregateResult[] results = [SELECT Maintenance_Request__c, MIN(Equipment__r.Maintenance_Cycle__c)cycle FROM Equipment_Maintenance_Item__c WHERE Maintenance_Request__c IN :ValidIds GROUP BY Maintenance_Request__c];
    
    for (AggregateResult ar : results){ 
        maintenanceCycles.put((Id) ar.get('Maintenance_Request__c'), (Decimal) ar.get('cycle'));
    }
        
        for(Case cc : closedCasesM.values()){
            Case nc = new Case (
                ParentId = cc.Id,
            Status = 'New',
                Subject = 'Routine Maintenance',
                Type = 'Routine Maintenance',
                Vehicle__c = cc.Vehicle__c,
                Equipment__c =cc.Equipment__c,
                Origin = 'Web',
                Date_Reported__c = Date.Today()
                
            );
            
            If (maintenanceCycles.containskey(cc.Id)){
                nc.Date_Due__c = Date.today().addDays((Integer) maintenanceCycles.get(cc.Id));
            }
            
            newCases.add(nc);
        }
        
       insert newCases;
        
       List<Equipment_Maintenance_Item__c> clonedWPs = new List<Equipment_Maintenance_Item__c>();
       for (Case nc : newCases){
            for (Equipment_Maintenance_Item__c wp : closedCasesM.get(nc.ParentId).Equipment_Maintenance_Items__r){
                Equipment_Maintenance_Item__c wpClone = wp.clone();
                wpClone.Maintenance_Request__c = nc.Id;
                ClonedWPs.add(wpClone);
                
            }
        }
        insert ClonedWPs;
    }
}

}

Challenge 5 Test callout logicWarehouseCalloutService.apxc :-

public with sharing class WarehouseCalloutService {

private static final String WAREHOUSE_URL = 'https://th-superbadge-apex.herokuapp.com/equipment';

//@future(callout=true)
public static void runWarehouseEquipmentSync(){
    
    Http http = new Http();
    HttpRequest request = new HttpRequest();
    
    request.setEndpoint(WAREHOUSE_URL);
    request.setMethod('GET');
    HttpResponse response = http.send(request);
    
    
    List<Product2> warehouseEq = new List<Product2>();
    
    if (response.getStatusCode() == 200){
        List<Object> jsonResponse = (List<Object>)JSON.deserializeUntyped(response.getBody());
        System.debug(response.getBody());
        
        for (Object eq : jsonResponse){
            Map<String,Object> mapJson = (Map<String,Object>)eq;
            Product2 myEq = new Product2();
            myEq.Replacement_Part__c = (Boolean) mapJson.get('replacement');
            myEq.Name = (String) mapJson.get('name');
            myEq.Maintenance_Cycle__c = (Integer) mapJson.get('maintenanceperiod');
            myEq.Lifespan_Months__c = (Integer) mapJson.get('lifespan');
            myEq.Cost__c = (Decimal) mapJson.get('lifespan');
            myEq.Warehouse_SKU__c = (String) mapJson.get('sku');
            myEq.Current_Inventory__c = (Double) mapJson.get('quantity');
            warehouseEq.add(myEq);
        }
        
        if (warehouseEq.size() > 0){
            upsert warehouseEq;
            System.debug('Your equipment was synced with the warehouse one');
            System.debug(warehouseEq);
        }
        
    }
}

}

Challenge 6 Test scheduling logic

WarehouseSyncSchedule.apxc :-

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

}