Skip to main content

Feed

Connect with fellow Trailblazers. Ask and answer questions to build your skills and network.

HI, 

 

I have a couple flows that at the send out an email via the Send Email action at the end to a Account record Collection, the action is in a Loop. I want to check if this approach will hit an SOQL 101 error if the amount of emails the flow has to send is more than 100 in the loop? Or woud it be better if I can use "send email" action once outside of the loop and have it email a collection, if so How do I setup the Send Email action for that. I have to be able to relate all email the the Account or contact record. In my record Collection I ahve both the email and Account ID for example.  

 

If the Send Email Action doesn't have limits within a loop like a Create Record etc then I should be fine to leave it? 

 

In the Send Email Action, I have a text template for the body, Log Email on Send = True, Recipient Address List = Current Item in Loop > Business Email, Related Record ID > Current Itemt in Loop > AccountID, and all other essential field are filled. 

 

Thanks 

@Admin Trailblazers@Salesforce Flow Automation

 

 

#Flow  #Data Management  #Email  #Email Deliverability Issues  #Email Alerts

1 answer
  1. Divya Chauhan (Kcloud Technologies) Forum Ambassador
    Today, 9:37 AM

     If you're using the "Send Email"

    action inside a Flow loop that goes through a collection of Account records, here’s what you should know:  

    Will It Cause a SOQL 101 Error?

    • Not directly. The "Send Email" action doesn’t count toward the 101 SOQL query limit since it’s not actually running a SOQL query.
    • However, if you have other elements inside the loop—like "Get Records"—those could contribute to hitting the limit if not handled properly.
    • Also, remember that a Flow loop has a 2,000 iteration limit per transaction, so if you're working with a big record set, that’s something to watch out for.

    Email Limits-

    • Salesforce allows up to 5,000 emails per transaction when using Flow.
    • So if you're sending one email per record and staying under 2,000 records, you’re fine.
    • Sending emails in a loop is okay for smaller data sets (e.g., under 100–200 records).

    Is It Better to Move "Send Email" Outside the Loop?

    • Yes, definitely, especially if your record count might grow over time.
    • Instead of sending one email per iteration, you can build a list of email addresses during the loop.
    • Then send a single email outside the loop using that list. It’s cleaner, faster, and more efficient.
0/9000

Any way to pull the call transcript from conversation insights? I know the AI processes this data and wondering if there is a way to view it.  #Einstein Conversation Insights

2 answers
0/9000

Hi there, 

 

I'm running into a problem that I haven't found a solution for in our Salesforce org. 

We've never had problems with this until recently (+/- 2 weeks)  

 

When a user assigns an event to another user, it gets deleted sometimes. Not everytime, but just seemingly random. 

Of course I can put it back from the recycle bin, but that shouldn't be happening nor was it happening before.  

 

We have the connection with our Outlook, but we've always had that and there have been no changes with that recently as far as I know. 

 

Does anyone have an idea what I can do to fix this issue? 

I appreciate your time. 

 

 

#Event Object  #Delete Activity Event  #Delete Records

0/9000

I everyone, in the module

"

Amélioration d'Agentforce pour qu'il agisse sur les donn√©es avec un langage conversationnel" 

I don’t find the “agent” menu / agent Actions from my quick find box 

My Einstein and Sales Emails are turned ON.

Stage 

  1. “Dans la zone Quick Find (Recherche rapide), saisissez agent, puis cliquez sur Agent Actions (Actions d’agent)”.

Results when I'm searching for: “agent”:

Einstein

Agentforce Data Library

CollapseEinstein Generative AI

CollapseAgentforce Studio

Agentforce Agents

Agentforce Assets

Development

Agentforce for Developers 

 

Many thanks for your support... 

 

#Trailhead Challenges

2 answers
  1. Today, 9:31 AM

    Many thanks for your answer @Tushar Jadav

    I’ve created a Check-in Guest Event following your recommandations

    Create Check-in Guest Event - Custom - Flow  - Jean-Claude Fourny

    But once again at step 14, I can’t find Einstein Copilot to move forward 

    1. Toujours avec la saisie agent dans la zone Quick Find (Recherche rapide), cliquez sur Agents.
    2. Cliquez sur Einstein Copilot. I've no access to this option

    Nb: No agentforce sub menu under Einstein in Setup=

     

    Einstein  

    Agentforce Data Library

     

    Collapse 

    Einstein Assessors 

    Einstein Bots Assessor

     

    Einstein Conversation Insights Assessor

     

    Sales Cloud Einstein Assessor

     

    Service Cloud Einstein Assessor

     

    Collapse 

    Einstein Generative AI 

    Collapse 

    Agentforce Studio  

    Agentforce Agents

     

    Agentforce Assets

     

    Einstein Feedback and Monitoring Setup

     

    Einstein Setup

     

    Einstein Trust Layer

     

    Prompt Builder

     

    Collapse 

    Einstein Platform 

    Einstein Bots

     

    Einstein Intent Sets

     

    Einstein.ai

     

    Collapse 

    Einstein Sales 

    Collapse 

    Einstein Activity Capture  

    Settings

     

    Einstein for Sales

     

    Collapse 

    Einstein Search 

    Thank you once again

0/9000

I have this class:  public class CandidateFetcherQueueable implements Queueable {      private List<Id> serviceAppointmentIds;      private Boolean withDelay; // Flag to introduce delay        public CandidateFetcherQueueable(List<Id> serviceAppointmentIds, Boolean withDelay) {          this.serviceAppointmentIds = serviceAppointmentIds;          this.withDelay = withDelay; // Initialize delay flag      }        public void execute(QueueableContext context) {          System.debug('CandidateFetcherQueueable executed for SAs: ' + serviceAppointmentIds);            if (withDelay) {              Long startTime = System.now().getTime();              while (System.now().getTime() - startTime < 5000) {                               }          }          List<ServiceAppointment> serviceApps = [              SELECT Id, ServiceTerritoryId, Work_Order__c, Sub_Customer__r.Send_Potential_Tech__c,                     Active_Technician__c, Active_Technician_Details__c              FROM ServiceAppointment               WHERE Id IN :serviceAppointmentIds                 AND Do_Not_Use_SA__c = true          ];          for (ServiceAppointment sa : serviceApps) {              if (sa.ServiceTerritoryId == null) {                  System.debug('ServiceTerritoryId not populated for SA: ' + sa.Id);                  continue;              }              FSL__Scheduling_Policy__c schedulingPolicy = [                  SELECT Id, Name                   FROM FSL__Scheduling_Policy__c                   WHERE Name = 'Resource Capability'                   LIMIT 1              ];                if (schedulingPolicy == null) {                  System.debug('Scheduling policy "Resource Capability" not found.');                  continue;              }              FSL.GradeSlotsService slotService = new FSL.GradeSlotsService(schedulingPolicy.Id, sa.Id);              FSL.AdvancedGapMatrix resultMatrix = slotService.getGradedMatrix(true);              Map<Id, FSL.ResourceScheduleData> resourceData = resultMatrix.ResourceIDToScheduleData;              System.debug('Resource Data: ' + resourceData);              Set<Id> resourceIdsToQuery = new Set<Id>();              for (Id resourceId : resourceData.keySet()) {                  if (!resourceData.get(resourceId).SchedulingOptions.isEmpty()) {                      resourceIdsToQuery.add(resourceId);                  }              }              System.debug('Resource IDs to Query: ' + resourceIdsToQuery);              Map<Id, ServiceResource> serviceResources = new Map<Id, ServiceResource>([                  SELECT Id, Name, MobilePhone__c, Email__c                   FROM ServiceResource                   WHERE Id IN :resourceIdsToQuery              ]);              List<String> resourceIds = new List<String>();              List<String> technicianDetails = new List<String>();              for (Id resourceId : resourceData.keySet()) {                  if (serviceResources.containsKey(resourceId)) {                      ServiceResource sr = serviceResources.get(resourceId);                      resourceIds.add(resourceId);                      technicianDetails.add(sr.Name + ' , ' + sr.MobilePhone__c + ' , ' + sr.Email__c);                  }              }              System.debug('Resource IDs: ' + resourceIds);              System.debug('Technician Details: ' + technicianDetails);              if (!resourceIds.isEmpty()) {                  sa.Active_Technician__c = String.join(resourceIds, '; ');                  sa.Active_Technician_Details__c = String.join(technicianDetails, '; ');                  update sa; // Ensure the SA is updated                  System.debug('Updated SA with candidate data: ' + sa.Id);              } else {                  System.debug('No candidates found for SA: ' + sa.Id);              }          }            if (!Test.isRunningTest() ) {                System.enqueueJob(new ResourcePreferenceCreatorQueueable(serviceAppointmentIds));  }          }  }        

 

@* Salesforce Developers *  @* Salesforce Field Service * 

7 answers
  1. Today, 9:31 AM

    Mixing data access/dml and business logic is always hard to test and hard to maintain.

     

    I would suggest moving the data access into some other class that implements a well defined interface, this queueable can then be constructed with that other interface. Call it what you want, for the rest of this post I will call it IServiceSelector.

     

    I would also suggest moving DML into some form of (well tested) DML handling class, so that you can also divorce all testing from DML issues and focus on what any class itself does. 

     

    public CandidateFetcherQueueable(IServiceSelector selector, List<Id> serviceAppointmentIds, Boolean withDelay)

    {

    this.serviceAppointmentIds = serviceAppointmentIds;

    this.withDelay = withDelay; // Initialize delay flag

    this.serviceSelector = selector;

    }

     

    The code in the execute just uses the selector, and not directly does the SOQL itself.

    List<ServiceAppointment> serviceApps = this.serviceSelector.getServiceAppointments(serviceAppointmentIds);

    [...]

    Map<Id, ServiceResource> serviceResources = this.serviceSelector.getServiceResources(resourceIdsToQuery);

     

    Once you have done this you will have 2 test classes, one for the class that implements the interface. Testing these types of classes is usually fairly easy - juts insert the test data and check you get the correct records/fields back.

     

    Then you test this class, however, now that you have put the SOQL behind an interface you can Mock that out for the test. Your Mock version can just be coded to return what ever you need for the test without having to insert any actual data (and run into all sorts of validation issues with that).

     

    @isTest

    static void someTest()

    {

    MockSelector mockSelector = new MockSelector();

    mockSelector.appointments = new List<ServiceAppointment>{

    new ServiceAppointment(

    Name = 'Test SA ' + i,

    Do_Not_Use_SA__c = true,

    ServiceTerritoryId = 'a0A000000000001')

    };

    mockSelector.resources = new Map<Id, ServiceResource>{

    'someId' => new ServiceResource(

    Name = 'Test Resource ' + i,

    MobilePhone__c = '123-456-7890',

    Email__c = 'test' + i + '@example.com')

    }

    [...] //other setup

    new CandidateFetcherQueueable(mockSelector, serviceAppointmentIds, false);

    }

     

    you can now put together many different tests very quickly, as you do not have to worry about the rest of the logic in the system. These tests will also run very fast without all that setup DML.

     

    I would also strongly suggest TDD. If you follow TDD then you will always have near enough 100% coverage at all points in development.

0/9000

I created a static resource and I want to use it as the icon for my Salesforce indicator. I'm just not sure how to get the URL or how to reference it within the indicator item!   

 

Here is my indicator item:

How to use static resource for my indicator

 

And here is my static resource:

Screenshot 2025-04-02 at 12.16.26 PM.png

 

 

 

4 answers
0/9000

I am working with this package in a sandbox and struggling with the reporting side: https://www.beaufort12.com/mailchimp

 

 

Ideally we'd need to report on Contact > Mailchimp Membership *and* Opportunities (i.e. opportunities on a granular level, opposed to rollup opportunity values on the contact object). Suggestions very welcome! Am aware of third-party multistep reporting offerings but would prefer a more cost effective solution.

0/9000