• Jeremiah Cochran
  • NEWBIE
  • 80 Points
  • Member since 2016

  • Chatter
    Feed
  • 1
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 8
    Questions
  • 13
    Replies
Hi everyone, I have been working on the OrderTest apex test class and have been getting good coverage so far on much of my code. However, one area I seem to be stuck on is writing the test class for the OrderUpdate_UnitTest in relation to the AnnouncementsQueueable class, which sends off announcements to the chatter group when a message has been posted. 

As I run all tests, the OrderUpdate_UnitTest fails with the message.
System.AsyncException: Maximum stack depth has been reached.​

Class.AnnouncementQueueable.PostAnnouncements: line 30, column 1
Class.AnnouncementQueueable.execute: line 14, column 1​

My code for the OrderUpdate is below followed by AnnouncementsQueueable 
static testmethod void OrderUpdate_UnitTest (){
        test.startTest();
        Order rec = [select id, Status from Order limit 1];
        Product2 prod = [SELECT Family,Id,Name,Quantity_Ordered__c,Quantity_Remaining__c FROM Product2 limit 1];
        system.debug('kkk '+prod.Quantity_Ordered__c);
        rec.status = constants.ACTIVATED_ORDER_STATUS;
        Update rec;
        Product2 updatedprod = [SELECT Family,Id,Name,Quantity_Ordered__c,Quantity_Remaining__c FROM Product2 limit 1];
        
        system.debug('kkk '+updatedprod.Quantity_Ordered__c);
        TestDataFactory.VerifyQuantityOrdered(prod,updatedprod,constants.DEFAULT_ROWS);
         test.stopTest();
    }
 
/**
 * @name AnnouncementQueueable
 * @description This class posts Chatter Announcements
**/
public class AnnouncementQueueable implements system.Queueable{

     public List<ConnectApi.AnnouncementInput> toPost;
    
    public AnnouncementQueueable(List<ConnectApi.AnnouncementInput> toPost){
        this.toPost = toPost;
    }

    public void execute(QueueableContext context){
          PostAnnouncements(toPost);
     }


    /**
     * @name postAnnouncements
     * @description This method is provided for you to facilitate the Super Badge
    **/
     public static void PostAnnouncements(List<ConnectApi.AnnouncementInput> announcements){
        while ( announcements.size() > 0 ){
            if ( Limits.getDMLStatements() < Limits.getLimitDMLStatements() && !test.isRunningTest()){ 
                ConnectApi.AnnouncementInput a = announcements.remove(0);
                ConnectApi.Announcements.postAnnouncement('Internal', a);
            } else {
                AnnouncementQueueable announcementQueuable = new AnnouncementQueueable(announcements);
//        		announcementQueuable.toPost = announcements;
                System.enqueueJob(announcementQueuable);
                break;
            }
        }
        if ( announcements.size() > 0 && !test.isRunningTest() ){
            AnnouncementQueueable q = new AnnouncementQueueable(announcements);
//            q.toPost = announcements;
			System.enqueueJob(q);
            //ToDo: Enqueue the above instance of announcementQueueable
            
        }
    }
}

 

Hi and thank you in advance.

I have a lighting component that serves as a custom related list for a custom object, we'll call testObject__c. The lighting component lives on a standard object, Opportuniy. Here is what i am trying to prevent: when a user that has access to the Opporuntity object views an Opportunity record, but they don't have access to the custom object (testObject__c) they get an error on their screen which I have determined is because the Lighting Component related list for the custom object (testObject__c) is still trying to load.
 

I have added an attribute which gets set based on this:

Boolean userCATMAccess = Schema.sObjectType.testObject__c.isAccessible();

However, even though that check comes back false the Lighting Component related list still tries to render and throws the error.

My question is how do I prevent the Lighting Component related list from trying to render if the user does not have access to the testObject__c but does have access to Opportunity records?

Here is the context of what I'm trying to do. I have a lightning component that I want to be able to use on any object so I have added an attribute to the design file that allows a user to enter the API Name of the field that data should be retrieved from. I have a dynamic SOQL query that takes in variables for the sobject type and the field the user indicated. However, the returned result is the ID for the object record, not the data stored in the field. How do I get the actual data from the field?

Here is my code:

public with sharing class ProgressBarControler{
    
    @AuraEnabled
    public static List<String> getProgress(Id recordId, String fieldName)
    {
        List<String> progress = new List<String>();
           
        Id myId = recordId;
        system.debug('the record Id is '+myId);
        
        String objfieldName = fieldName;
        system.debug('the fieldName is '+objfieldName);
        

        String sObjName = myId.getSObjectType().getDescribe().getName();
        system.debug('the sObjectName is '+sObjName);
		
         SObjectType sObjType = Schema.getGlobalDescribe().get(sObjName);
        
        // Create Dynamic Query Start ..
        String theQuery = 'SELECT ';
        // Insert field name variable into Query
        theQuery += objfieldName + ',' ;
               system.debug('the field name is '+objfieldName); 
        
        // Trim last comma
        theQuery = theQuery.subString(0, theQuery.length() - 1);
        // Finalize query string
        theQuery += ' FROM '+sObjType+' LIMIT 1';
        // Query End ..
        System.debug('theQuery = '+theQuery);            
            
            Object o = Database.Query(theQuery);
            
        String returnValue = String.valueOf(o);
               
                progress.add(returnValue);
            	System.debug('the return value = '+returnValue);
        
        return progress;
    }
}

 


0down votefavorite
I have 2 custom objects we will call ObjectOne__c and ObjectTwo__c, these 2 objects DO NOT have a direct relationship to each other. However, I have a business need that requires fields on ObjectTwo__c to be updated to match the fields on ObjectOne__c when ObjectOne__c is updated. Here is a sample of the Trigger that handles this process. My issues is I need to move the SOQL out of the loop to properly handle mass updates, but I can’t figure out how to do that and still get the trigger to properly update all the records in the trigger.
Here is a sample of the code in my trigger:
trigger COSyncTrigger on ObjectOne__c (after update) { 
//Create list to store the ObjectTwo__c records that will be Updated 
List < ObjectTwo__c> upObTwo = new List < ObjectTwo__c >(); 

//Look at records being Updated 
if(trigger.isUpdate){ for(ObjectOne__c ObjOne : trigger.new){ 

//Create a list of existing ObjectTwo__c records that match the ObjectOne__c record being updated 
List < ObjectTwo__c > checkupObjTwo = [Select Id from ObjectTwo__c Where (Account__c = :ObjOne.Account__c And Owner = : ObjOne.Owner And Client__c = : ObjOne. Client__c) ]; 

//If the Above List is NOT Empty Update the ObjectTwo__c records 
If(!checkupObjTwo.isEmpty()) { 

ObjectTwo__c upobjtwo = [Select Id from ObjectTwo__c Where (Account__c = : ObjOne.Account__c And Owner = : ObjOne.Owner And Client__c = : ObjOne. Client__c)]; 

upobjtwo.Client_Role__c = ObjOne. Client_Role__c; 
upobjtwo.Client_Status__c = ObjOne. Client_Status__c; 

//Add the ATM record to the list to be updated later 
upObTwo.add(upobjtwo); } 
} 

//If the List of records to update is NOT Empty update the ObjectTwo__c records 
if(upObTwo.size() > 0){ 
system.debug('Count of ObjectTwo__c records to update = '+ upObTwo.size()); 

update upObTwo; } 
}
I have done some research and understand I need to create a list outside my loop but I can't seem to get it to update ObjectTwo__c records to Match the ObjectOne__c records in the trigger. Please explain how I can accomplish this and provide an example if possible. Thank you in advance.
Is it possible to determine what sobject a lightning component is being used on and store that value in a variable and then pass that variable to an APEX controller so that information is returned for that object?

I have built a lightning component that is used to provide rating information and overall quality evaluation for a custom object, but the same functionality could also be helpful on another object. Do I have to recreate the component for each specific object or is it possible to determine what object is using it?

Secondly, I am considering another approach that would allow a system admin to create a record on a custom object where they specify the object api name and the field api name the component should use, but again I'm not sure how to achieve this. Any help would be greatly appreciated.
Hi, I'm getting some errors later in this super badge, which is causing my component to not work properly, I believe this is related to poor code and I need some help cleaning it up. Here is what I have so far.

BoatSearch.cmp
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes" access="global" >
    <aura:handler name="formsubmit"
                  event="c:formsubmit"
                  action="{!c.onFormSubmit}"
                  phase="capture"/>
    
    <lightning:card title="Find a Boat" class="slds-m-top_10px" >
     <c:BoatSearchForm />
</lightning:card>    
<lightning:card title="Matching Boats" >
     <c:BoatSearchResults aura:id="BSRcmp"/>
</lightning:card>
</aura:component>
BoatSearchController.js
({
    onFormSubmit : function(component, event, helper){
        console.log("event received by BoatSearchController.js");
        var formData = event.getParam("formData");
        var boatTypeId = formData.boatTypeId;
        var BSRcmp = component.find("BSRcmp");
        var auraMethodResult = BSRcmp.search(boatTypeId);
        console.log("auraMethodResult: " + auraMethodResult);
    }

})
BoatTypeController.apex
public class BoatTypeController {
@AuraEnabled
    public static List<String> getpickval() {
        List<String> options = new List<String>();

        Schema.DescribeFieldResult fieldResult = BoatType__c.Name.getDescribe();

        List<Schema.PicklistEntry> ple = fieldResult.getPicklistValues();

        for (Schema.PicklistEntry f: ple) {
            options.add(f.getLabel());
        }       
        return options;
    }
}









 
I have built the reports and dashboards as outlined in the requirements, but I'm getting the following error "Challenge Not yet complete... here's what's wrong: Couldn't find a component with the title 'My Top Accounts'."  
User-added image

However, I have the component on the dashboard as you can see below.
User-added image
What am I missing?
I'm trying to generate random geolocation codes and assign them to a record when it is created, These records are simply dummy data to use for testing purposes but for my test to work properly I need to set random geolocation codes. Here is what I have so far, but I can't get the geocode to generate:
 
List<Location__c> locat = new List<Location__c>();
for (Integer a = 0; a <5; a++) {
  locat.add(new Location__c(Location_Name__c = 'Location ' + a ));
   
	locat.GeoCode__Latitude__s = getRandomInteger();
    locat.GeoCode__Longitude__s = getRandomLong();
}

insert locat;

 
Hi, I'm new to writing triggers and need some assistance with the following code, I have it work for the most part, what is giving me trouble is trying to figure out how to prevent it from creating multiple child cases for the same parent case. For example, if the parent case that fires the trigger has 2 secret keywords, then 2 child cases are created when I only want 1. Thanks in advance.

Here is the trigger code:

trigger CheckSecretInformation on Case (after insert, before update) 
{
    String childCaseSubject = 'Warning this case may contain secret info';

//Step 1: Create a collection containing each secret keyword
    Set<String> secretKeywords = new Set<String>();
    secretKeywords.add('Credit Card');
    secretKeywords.add('Social Security');
    secretKeywords.add('SSN');
    secretKeywords.add('Passport');
    secretKeywords.add('Body Weight');

    //Step 2: Check to see if a case contains any of the secret keywords
    List<Case> casesWithSecretInfo = new List<Case>();
    List<String> secretKeywordsFound = new List<String>();
    
    for (Case myCase : Trigger.new) 
    {
        if (myCase.Subject != childCaseSubject) 
        {
            for (String keyword : secretKeywords) 
            {
                 if (myCase.Description !=null && myCase.Description.containsIgnoreCase(keyword)) 
                {
                    casesWithSecretInfo.add(myCase);
                    secretKeywordsFound.add(keyword);
                    
                    System.debug ('Case ' +myCase.ID + ' includes secret keyword ' +keyword);
                  }
            }
        }

    }
        //Step 3: If a case contains secret keywords, create a child case
        List<Case> caseToCreate = new List<Case>();
        for (Case caseWithSecretInfo : casesWithSecretInfo) 
        {
            if (caseWithSecretInfo.Cases.Size()<1) 
             {
                       
            Case childCase = new Case();
            childCase.Subject = childCaseSubject;
            childCase.ParentId = caseWithSecretInfo.Id;
            childCase.Priority = 'High';
            childCase.IsEscalated = true;
            childCase.Description = 'At least one of the following keywords were found ' + secretKeywordsfound;
            caseToCreate.add(childCase);
             }
        }

        insert caseToCreate;
}

Hi and thank you in advance.

I have a lighting component that serves as a custom related list for a custom object, we'll call testObject__c. The lighting component lives on a standard object, Opportuniy. Here is what i am trying to prevent: when a user that has access to the Opporuntity object views an Opportunity record, but they don't have access to the custom object (testObject__c) they get an error on their screen which I have determined is because the Lighting Component related list for the custom object (testObject__c) is still trying to load.
 

I have added an attribute which gets set based on this:

Boolean userCATMAccess = Schema.sObjectType.testObject__c.isAccessible();

However, even though that check comes back false the Lighting Component related list still tries to render and throws the error.

My question is how do I prevent the Lighting Component related list from trying to render if the user does not have access to the testObject__c but does have access to Opportunity records?

Here is the context of what I'm trying to do. I have a lightning component that I want to be able to use on any object so I have added an attribute to the design file that allows a user to enter the API Name of the field that data should be retrieved from. I have a dynamic SOQL query that takes in variables for the sobject type and the field the user indicated. However, the returned result is the ID for the object record, not the data stored in the field. How do I get the actual data from the field?

Here is my code:

public with sharing class ProgressBarControler{
    
    @AuraEnabled
    public static List<String> getProgress(Id recordId, String fieldName)
    {
        List<String> progress = new List<String>();
           
        Id myId = recordId;
        system.debug('the record Id is '+myId);
        
        String objfieldName = fieldName;
        system.debug('the fieldName is '+objfieldName);
        

        String sObjName = myId.getSObjectType().getDescribe().getName();
        system.debug('the sObjectName is '+sObjName);
		
         SObjectType sObjType = Schema.getGlobalDescribe().get(sObjName);
        
        // Create Dynamic Query Start ..
        String theQuery = 'SELECT ';
        // Insert field name variable into Query
        theQuery += objfieldName + ',' ;
               system.debug('the field name is '+objfieldName); 
        
        // Trim last comma
        theQuery = theQuery.subString(0, theQuery.length() - 1);
        // Finalize query string
        theQuery += ' FROM '+sObjType+' LIMIT 1';
        // Query End ..
        System.debug('theQuery = '+theQuery);            
            
            Object o = Database.Query(theQuery);
            
        String returnValue = String.valueOf(o);
               
                progress.add(returnValue);
            	System.debug('the return value = '+returnValue);
        
        return progress;
    }
}

 


0down votefavorite
I have 2 custom objects we will call ObjectOne__c and ObjectTwo__c, these 2 objects DO NOT have a direct relationship to each other. However, I have a business need that requires fields on ObjectTwo__c to be updated to match the fields on ObjectOne__c when ObjectOne__c is updated. Here is a sample of the Trigger that handles this process. My issues is I need to move the SOQL out of the loop to properly handle mass updates, but I can’t figure out how to do that and still get the trigger to properly update all the records in the trigger.
Here is a sample of the code in my trigger:
trigger COSyncTrigger on ObjectOne__c (after update) { 
//Create list to store the ObjectTwo__c records that will be Updated 
List < ObjectTwo__c> upObTwo = new List < ObjectTwo__c >(); 

//Look at records being Updated 
if(trigger.isUpdate){ for(ObjectOne__c ObjOne : trigger.new){ 

//Create a list of existing ObjectTwo__c records that match the ObjectOne__c record being updated 
List < ObjectTwo__c > checkupObjTwo = [Select Id from ObjectTwo__c Where (Account__c = :ObjOne.Account__c And Owner = : ObjOne.Owner And Client__c = : ObjOne. Client__c) ]; 

//If the Above List is NOT Empty Update the ObjectTwo__c records 
If(!checkupObjTwo.isEmpty()) { 

ObjectTwo__c upobjtwo = [Select Id from ObjectTwo__c Where (Account__c = : ObjOne.Account__c And Owner = : ObjOne.Owner And Client__c = : ObjOne. Client__c)]; 

upobjtwo.Client_Role__c = ObjOne. Client_Role__c; 
upobjtwo.Client_Status__c = ObjOne. Client_Status__c; 

//Add the ATM record to the list to be updated later 
upObTwo.add(upobjtwo); } 
} 

//If the List of records to update is NOT Empty update the ObjectTwo__c records 
if(upObTwo.size() > 0){ 
system.debug('Count of ObjectTwo__c records to update = '+ upObTwo.size()); 

update upObTwo; } 
}
I have done some research and understand I need to create a list outside my loop but I can't seem to get it to update ObjectTwo__c records to Match the ObjectOne__c records in the trigger. Please explain how I can accomplish this and provide an example if possible. Thank you in advance.
Hi everyone, I have been working on the OrderTest apex test class and have been getting good coverage so far on much of my code. However, one area I seem to be stuck on is writing the test class for the OrderUpdate_UnitTest in relation to the AnnouncementsQueueable class, which sends off announcements to the chatter group when a message has been posted. 

As I run all tests, the OrderUpdate_UnitTest fails with the message.
System.AsyncException: Maximum stack depth has been reached.​

Class.AnnouncementQueueable.PostAnnouncements: line 30, column 1
Class.AnnouncementQueueable.execute: line 14, column 1​

My code for the OrderUpdate is below followed by AnnouncementsQueueable 
static testmethod void OrderUpdate_UnitTest (){
        test.startTest();
        Order rec = [select id, Status from Order limit 1];
        Product2 prod = [SELECT Family,Id,Name,Quantity_Ordered__c,Quantity_Remaining__c FROM Product2 limit 1];
        system.debug('kkk '+prod.Quantity_Ordered__c);
        rec.status = constants.ACTIVATED_ORDER_STATUS;
        Update rec;
        Product2 updatedprod = [SELECT Family,Id,Name,Quantity_Ordered__c,Quantity_Remaining__c FROM Product2 limit 1];
        
        system.debug('kkk '+updatedprod.Quantity_Ordered__c);
        TestDataFactory.VerifyQuantityOrdered(prod,updatedprod,constants.DEFAULT_ROWS);
         test.stopTest();
    }
 
/**
 * @name AnnouncementQueueable
 * @description This class posts Chatter Announcements
**/
public class AnnouncementQueueable implements system.Queueable{

     public List<ConnectApi.AnnouncementInput> toPost;
    
    public AnnouncementQueueable(List<ConnectApi.AnnouncementInput> toPost){
        this.toPost = toPost;
    }

    public void execute(QueueableContext context){
          PostAnnouncements(toPost);
     }


    /**
     * @name postAnnouncements
     * @description This method is provided for you to facilitate the Super Badge
    **/
     public static void PostAnnouncements(List<ConnectApi.AnnouncementInput> announcements){
        while ( announcements.size() > 0 ){
            if ( Limits.getDMLStatements() < Limits.getLimitDMLStatements() && !test.isRunningTest()){ 
                ConnectApi.AnnouncementInput a = announcements.remove(0);
                ConnectApi.Announcements.postAnnouncement('Internal', a);
            } else {
                AnnouncementQueueable announcementQueuable = new AnnouncementQueueable(announcements);
//        		announcementQueuable.toPost = announcements;
                System.enqueueJob(announcementQueuable);
                break;
            }
        }
        if ( announcements.size() > 0 && !test.isRunningTest() ){
            AnnouncementQueueable q = new AnnouncementQueueable(announcements);
//            q.toPost = announcements;
			System.enqueueJob(q);
            //ToDo: Enqueue the above instance of announcementQueueable
            
        }
    }
}

 
I am getting the error:

Ensure that you modify the constructCollaborationGroup method so that it has the correct return type and is not an instance method

Here is that method:
public CollaborationGroup ConstructCollaborationGroup(){
        //ToDo: Ensure this method returns a single Chatter CollaborationGroup
        //    whose Name starts with 'TEST' followed by the INVENTORY_ANNOUNCEMENTS constant
        //    and configured so anyone can join, see and post updates.
        //    
        CollaborationGroup ChatterGroup = new CollaborationGroup(
              Name = 'TEST'+Constants.INVENTORY_ANNOUNCEMENTS,  
              CollaborationType = 'Public',
              CanHaveGuests = true,
              IsArchived = false,
              IsAutoArchiveDisabled = true
        );
        insert ChatterGroup;
        return ChatterGroup;
        
    }
Any ideas on what is wrong. If I run
public void SetupTestData(Integer cnt){
        //ToDo: Ensure this method calls each of the construct methods
        //  and inserts the results for use as test data.
        //  
        CollaborationGroup g = this.ConstructCollaborationGroup();
        List<Account> accounts = this.ConstructAccounts(10);
        List<Contact> contacts = this.ConstructContacts(10,accounts);
        List<Product2> products = this.ConstructProducts(10);
        List<PricebookEntry> pes = this.ConstructPricebookEntries(products);
        List<Order>orders = this.ConstructOrders(10,accounts);
        List<OrderItem> ois = this.ConstructOrderItems(10,pes,orders);
            
    }
All works as expected. I am not sure what I am missing in the ConstructCollaborationGroup method. It is returing a CollaborationGroup and is not static.

Thanks!
I have built the reports and dashboards as outlined in the requirements, but I'm getting the following error "Challenge Not yet complete... here's what's wrong: Couldn't find a component with the title 'My Top Accounts'."  
User-added image

However, I have the component on the dashboard as you can see below.
User-added image
What am I missing?
Hi, I'm new to writing triggers and need some assistance with the following code, I have it work for the most part, what is giving me trouble is trying to figure out how to prevent it from creating multiple child cases for the same parent case. For example, if the parent case that fires the trigger has 2 secret keywords, then 2 child cases are created when I only want 1. Thanks in advance.

Here is the trigger code:

trigger CheckSecretInformation on Case (after insert, before update) 
{
    String childCaseSubject = 'Warning this case may contain secret info';

//Step 1: Create a collection containing each secret keyword
    Set<String> secretKeywords = new Set<String>();
    secretKeywords.add('Credit Card');
    secretKeywords.add('Social Security');
    secretKeywords.add('SSN');
    secretKeywords.add('Passport');
    secretKeywords.add('Body Weight');

    //Step 2: Check to see if a case contains any of the secret keywords
    List<Case> casesWithSecretInfo = new List<Case>();
    List<String> secretKeywordsFound = new List<String>();
    
    for (Case myCase : Trigger.new) 
    {
        if (myCase.Subject != childCaseSubject) 
        {
            for (String keyword : secretKeywords) 
            {
                 if (myCase.Description !=null && myCase.Description.containsIgnoreCase(keyword)) 
                {
                    casesWithSecretInfo.add(myCase);
                    secretKeywordsFound.add(keyword);
                    
                    System.debug ('Case ' +myCase.ID + ' includes secret keyword ' +keyword);
                  }
            }
        }

    }
        //Step 3: If a case contains secret keywords, create a child case
        List<Case> caseToCreate = new List<Case>();
        for (Case caseWithSecretInfo : casesWithSecretInfo) 
        {
            if (caseWithSecretInfo.Cases.Size()<1) 
             {
                       
            Case childCase = new Case();
            childCase.Subject = childCaseSubject;
            childCase.ParentId = caseWithSecretInfo.Id;
            childCase.Priority = 'High';
            childCase.IsEscalated = true;
            childCase.Description = 'At least one of the following keywords were found ' + secretKeywordsfound;
            caseToCreate.add(childCase);
             }
        }

        insert caseToCreate;
}