0

I encountered this error while deploying my code enter image description here

Looking at the issue, it seems everything is pointed at one particular class. I am currently unsure of where it is going wrong or what causes the issue. Attached the code below

ProductRequiredTrigger:

trigger ProductRequiredTrigger on ProductRequired (before update, before Insert, after Insert, after update, after delete) {

//Retrieving Custom Metadata to activate/deactivate trigger
List<LTNG_TriggerControl__mdt> triggerControl = [Select DeveloperName, MasterLabel, LTNG_AfterDelete__c,LTNG_AfterInsert__c,
                                                 LTNG_AfterUndelete__c,LTNG_AfterUpdate__c,LTNG_BeforeDelete__c,
                                                 LTNG_BeforeInsert__c,LTNG_BeforeUpdate__c from LTNG_TriggerControl__mdt 
                                                 where DeveloperName='ProductRequiredTrigger' LIMIT 1];

// Trigger on before Insert
if(trigger.isBefore && trigger.isInsert && triggerControl[0].LTNG_BeforeInsert__c == true){ 
    ProductRequiredTriggerHandler.onBeforeInsert(Trigger.New);
}

// Trigger on before update
if(trigger.isBefore && trigger.isUpdate && triggerControl[0].LTNG_BeforeUpdate__c == true){ 
    ProductRequiredTriggerHandler.onBeforeUpdate(Trigger.New, Trigger.oldMap);
}    


// Trigger on After Insert
if(trigger.isAfter && trigger.isInsert && triggerControl[0].LTNG_AfterInsert__c == true){ 
    ProductRequiredTriggerHandler.onAfterInsert(Trigger.New);
}

// Trigger on After Update
if(trigger.isAfter && trigger.isUpdate && triggerControl[0].LTNG_AfterUpdate__c == true){ 
    ProductRequiredTriggerHandler.onAfterUpdate(Trigger.New, Trigger.oldMap);
}

// Trigger on After Update
if(trigger.isAfter && trigger.isDelete && triggerControl[0].LTNG_AfterDelete__c == true){ 
    ProductRequiredTriggerHandler.onAfterDelete(Trigger.Old);
} }

ProductRequiredTriggerHandler:

public without sharing class ProductRequiredTriggerHandler {
public static void onBeforeInsert(List <ProductRequired> productRequiredList) {
    
    Set<Id> productIds = new Set<Id>();
    for (ProductRequired prodReq: productRequiredList) {
        productIds.add(prodReq.Product2Id);
    }
    
    if(! productIds.isEmpty())
        calculateTotalPrice(productIds, productRequiredList);
}

public static void onBeforeUpdate(List<ProductRequired> newProductRequiredList, Map<Id, ProductRequired> oldProductRequiredMap) {
    
    Set<Id> productIds = new Set<Id>();
    for (ProductRequired prodReq: newProductRequiredList) {
        if(prodReq.Product2Id != oldProductRequiredMap.get(prodReq.Id).Product2Id)
            productIds.add(prodReq.Product2Id);
    }
    
    if(! productIds.isEmpty())
        calculateTotalPrice(productIds, newProductRequiredList);
}

public static void calculateTotalPrice(Set<Id> productIds, List<ProductRequired> productRequiredList) {
    
    List<PricebookEntry> pricebookEntries = new List<PricebookEntry>();
    pricebookEntries = [SELECT Id, Product2Id, UnitPrice FROM PricebookEntry WHERE Product2Id IN :productIds];
    
    Map<Id, PricebookEntry> pricebookEntryMap = new Map<Id, PricebookEntry>();
    for(PricebookEntry pbe : pricebookEntries){
        pricebookEntryMap.put(pbe.Product2Id, pbe);
    }
    
    for(ProductRequired prodReq : productRequiredList){
        if(pricebookEntryMap.containsKey(prodReq.Product2Id)){
            prodReq.LTNG_UnitPrice__c = pricebookEntryMap.get(prodReq.Product2Id).UnitPrice;
        }
    }       
}

public static void onAfterInsert(List<ProductRequired> productRequiredList) {
    Set<Id> saIds = new Set<Id>();        
    for (ProductRequired prodReq: productRequiredList) {
        saIds.add(prodReq.LTNG_ServiceAppointment__c);            
    }
    
    if(!saIds.isEmpty())
        calculateNetPayableAmount(saIds);
}

/**
 * @description : method for all After Update Actions
 * @param productRequiredList : list of new productRequired records
 **/
public static void onAfterUpdate(List<ProductRequired> productRequiredList, Map<Id, ProductRequired> oldProductRequiredMap) {
    
    Set<Id> saIds = new Set<Id>();
    for (ProductRequired preq : productRequiredList){
        if(preq.LTNG_ServiceAppointment__c != oldProductRequiredMap.get(preq.Id).LTNG_ServiceAppointment__c || preq.LTNG_TotalPrice__c != oldProductRequiredMap.get(preq.Id).LTNG_TotalPrice__c)  
            saIds.add(preq.LTNG_ServiceAppointment__c);
    }    
    
    if(!saIds.isEmpty())
        calculateNetPayableAmount(saIds);
}

public static void onAfterDelete(List<ProductRequired> oldProductRequiredList) {
    
    Set<Id> saIds = new Set<Id>();        
    for (ProductRequired prodReq: oldProductRequiredList) {
        saIds.add(prodReq.LTNG_ServiceAppointment__c);            
    }
    
    if(!saIds.isEmpty())
        calculateNetPayableAmount(saIds);
}

public static void calculateNetPayableAmount(Set<Id> saIds) {
    
    Map<Id, List<ProductRequired>> prodReqMap = new Map<Id, List<ProductRequired>>();
    for (ProductRequired prodReq: [SELECT Id, LTNG_TotalPrice__c, LTNG_ServiceAppointment__c FROM ProductRequired WHERE LTNG_ServiceAppointment__c IN :saIds AND isDeleted = FALSE]) {
        if(!prodReqMap.containsKey(prodReq.LTNG_ServiceAppointment__c)){
            prodReqMap.put(prodReq.LTNG_ServiceAppointment__c, new List<ProductRequired>());
        }
        prodReqMap.get(prodReq.LTNG_ServiceAppointment__c).add(prodReq);
        System.debug('prodReqMap::' +prodReqMap +'prodReqMap::' +prodReq);
    }
    
    List<ServiceAppointment> serviceAppointmentList = [SELECT Id, Net_Payable_Amount__c FROM ServiceAppointment WHERE Id IN :saIds];
    for(ServiceAppointment sa : serviceAppointmentList){
        sa.Net_Payable_Amount__c = 0.00;     
        if(prodReqMap.containsKey(sa.Id)){
            for(ProductRequired prodReq : prodReqMap.get(sa.Id)){
                sa.Net_Payable_Amount__c = sa.Net_Payable_Amount__c + prodReq.LTNG_TotalPrice__c;
            }   
        }
    }
    
    if(! serviceAppointmentList.isEmpty()){
        update serviceAppointmentList;
    }
} }

productRequiredTestTrigger:

@isTest(seeAllData=false)
public class ProductRequiredTriggerTest {

static testMethod void productRequiredTestTrigger() {
    
   WorkType workTypeRecord = LTNG_TestDataFactory.createWorkType(true);
    FSL__Scheduling_Policy__c policy = LTNG_TestDataFactory.createSchedulingPolicy(true);
    OperatingHours operatingHourRecord = LTNG_TestDataFactory.createOperatingHours(true);
    ServiceTerritory territoryRecord = LTNG_TestDataFactory.createServiceTerritory(true, 'Launceston', 'Footscray', '7250', 'Australia', operatingHourRecord.Id);
    WorkOrder testWorkOrderRecord = LTNG_TestDataFactory.createWorkOrders(1, true, workTypeRecord.Id, territoryRecord.Id)[1];
    
    DateTime earliestStartTime = DateTime.now();
    DateTime dueDateTime = earliestStartTime.addDays(7);
    
    ServiceAppointment newSA = new ServiceAppointment();
    newSA.ParentRecordId = testWorkOrderRecord.id;
    newSA.Status = 'None';
    newSA.EarliestStartTime = earliestStartTime;
    newSA.DueDate = dueDateTime;
    newSA.Net_Payable_Amount__c = 1020;
    
    insert newSA;
    
    Product2 product = new Product2();
    product.Name = 'Product X';
    product.Duration__c = 30;    
    product.ProductCode = 'productX';
    product.LTNG_ProductType__c = 'Equipment';
    insert product;
    
    Product2 product1 = new Product2();
    product1.Name = 'Product Y';
    product1.Duration__c = 30;    
    product1.ProductCode = 'productY';
    product1.LTNG_ProductType__c = 'Equipment';
    insert product1;
    
    ProductRequired newProductRequired = new ProductRequired();
    newProductRequired.LTNG_ServiceAppointment__c = newSA.id;
    newProductRequired.Product2Id = product.id;
    newProductRequired.QuantityRequired = 1;
    newProductRequired.ParentRecordId = testWorkOrderRecord.id;
    insert newProductRequired;
    
    Pricebook2 customPricebook = new Pricebook2(
        Name = 'Price Book',
        IsActive = true
    );
    insert customPricebook;
    
    PricebookEntry pbe1 = new PricebookEntry(
        Pricebook2Id = Test.getStandardPricebookId(),
        Product2Id = product.Id,
        UnitPrice = 1020,
        IsActive = true
    );
    Insert pbe1;
    
    PricebookEntry pbe = new PricebookEntry(
        Pricebook2Id = customPricebook.Id,
        Product2Id = product.Id,
        UnitPrice = 1020,
        IsActive = true
    );
    Insert pbe;
    
    newProductRequired.Product2Id = product1.Id;
    update newProductRequired;
    
    newProductRequired.QuantityRequired = 2;
    update newProductRequired;     
    
    delete newProductRequired;
} }

1 Answer 1

0

It seems to me that the trigger isn't part of the deployment, and the old trigger logic is still being run. In that code, you query a CMDT, then select the first item out of that list [0]. If this CMDT doesn't exist in the target environment, this would cause this ListException to occur. As far as I can tell, this is the only possible explanation, as there are no other List being used by index anywhere in the code you've presented.

Make sure that the trigger is included as part of the deployment.

1
  • Thanks for this I missed that one, but it still displayed the same errors however, I believe I have resolved the issue, will be posting the Answer if it works. Thanks Dec 11, 2023 at 6:39

You must log in to answer this question.

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