Hot answers tagged

5

Ideally for such kind of requirements, it would be better if you can build the logic in before update event rather than after update event, in which case, there won't be any need to handle the recursion and you won't need to write the DML (update) statement as well which would make this the safest approach. If you still want to go with after update event, ...


5

Using boolean flags is often something of a bodge. As well as stopping the undesired unlimited recursion, it can stop the logic from settling to the correct values. Best to first think through the sequence of inserts and updates and aim to eliminate the recursive cases. A simple cause of the recursion limit problem is updating the object - making a DML ...


5

If you adopt the Enterprise Patterns as defined by Andrew Fawcett, VP at SFDC and formerly CTO of FinancialForce, you will quickly realize the advantage of the underlying principle of separation of concerns into: Service layer Domain layer Selector layer Unit of Work A trigger is merely an entry point to the domain layer and typically is coded as a single ...


4

There is a simpler solution to this problem. Just do this: if (String.isNotEmpty(pr.Description__c) { pr.Description__c = pr.Description__c.abbreviate(lengthOfField); } Complete Code (I added my snippet to what Pranay had already written for you): trigger ProductTrigger on Product__c (before insert, before update) { Schema.DescribeFieldResult F ...


4

Note that floating point numeric values correctly define equals to ignore the scale, but the hashCode function considers scale part of the mix. As such, because Maps use hashCode when selecting a bucket for the key, you have to ensure that you set the scale on your values consistently when inserting and querying the map. If you don't, you get this sort of ...


4

count is a reserved word and cannot be your alias. Change it to somenthing like recordCount and your query will work Example: AggregateResult[] aggOpptyIdLineCount = [SELECT OpportunityId, COUNT(Id) recordCount FROM OpportunityLineItem GROUP BY OpportunityId];


4

This is because you are using an aggregate query on Contact: for (AggregateResult ar: [Select Count(Id) ContactCount, AccountId from Contact where AccountId IN: AccountIds GROUP BY AccountId]) Once the final Contact is deleted, there's nothing to aggregate, so you will not see an AggregateResult with that Contact's AccountId and ...


3

The Change Data Capture feature targets synchronization of changes to some persistent store. Because of this fact, each event only contains enough information to apply a specific change to a stored record. As a result, Change Data Capture events contain neither old values prior to a change nor a complete snapshot of an sObject at any point in time besides ...


3

You cannot use dot notation to access field values when accessing values from sObject. As objList is a List<sObject>, you will have to use the sObject's method to get the value of field Instead of using objList[0].Name you should be using (String)objList[0].get('Name'); Note : If you want to use the dot notation to access field values, then you ...


3

By far the easiest and least error-prone approach is to base the logic on an auto-number field and then do further Apex processing (if that is needed) in an after trigger that applies its logic to the auto-number value and then updates a separate field with the final value. There will be gaps in the numbering, but while you might be able to construct a ...


3

The Object viewer UI does not show actual API Names for certian fields on certain standard object. Lead being one of them, If you want to see actual API names, Open Developer Console->Open -> Lead.obj , it displays a table for APINames of the field that you can use in your code. A field has 2 main Attributes, 1 Label , and 1 API Name. Label can have ...


3

Yes, you can consider your code bulkified. You have only 1 SOQL outside of loop. You don't have any DMLs I don't see any method invocations with potentials DML/SOQL. You iterate over trigger.new collection But I would give a few pieces of advice on how you can improve your code. I'll mostly reference Salesforce docs, but still. Rename your Trigger to ...


3

As oposed to BEFORE triggers, changes made to trigger.new don't persist in Database. That's because in before context, there's still a dml operation to be made, before doing it, we alter the contents of the records in trigger.new and when the dml operation is done the new values are already there. But after the dml is done, there no dml to be made so you ...


3

Yes, in an after update trigger, you'd need a DML operation. However, this will cause an infinite loop. Instead, do this logic in a before update trigger: trigger Call_Report_AfterUpdate on Call_Report__c (before update) { Map<Id, AggregateResult> tasks = new Map<Id, AggregateResult>([ SELECT COUNT(Id) sum, WhatId Id FROM Task WHERE WhatId ...


3

I think you have some large data sets in prod which are exposing some issues. In your case, I think you're querying for all accounts, and on 3 occasions querying for all your contacts and opps as well. Also, you have 3 nested for loops. Cubes like that take time. Having said that, it seems like the goal of your code is to check which accounts are ...


3

Yes this feature is available for managed package . In order to test this i created a simple package with the below code Trigger code trigger AccountChangeAsyncTrigger on AccountChangeEvent (after insert) { List<AccountChangeEvent> changes = Trigger.new; Set<String> accIds = new Set<String>(); List<Contact> lstcontacts = new List&...


3

let's assume, you have only one Support_Settings__c record per each Case RecordTypeId field value. In this case, in order to avoid nested loops, you can group Support_Settings__c records by RecordTypeId__c field. After that on iterating Case records in the trigger, just get value from Map by Case RecortdTypeId field value. //grouping support settings by ...


3

Salesforce provides context variables that are available during an execution context. As mentioned in the comment above, the Trigger.old variable is only available in update and delete triggers. The current trigger that you posted is running on before insert operations. In that case, it would be necessary to do a SOQL query to fetch existing Work_Item__c ...


3

You can use queueable apex. If the callout fails then chain the same job by using system.enqueueJob method. Below is the way how you can do a callout from queuable apex, you have to implement Database.AllowCallouts interface. public class myClass implements Queueable, Database.AllowsCallouts { public void execute(QueueableContext context) { //your ...


2

Limitation Sadly, there is no apex email support from platform events. Per the documentation: Sending an email message from a platform event trigger using the Messaging.SingleEmailMessage class is not supported. The email can’t be sent because the sender is the Automated Process entity, which has no email address. Workaround You can, however, send ...


2

You have to perform update crList DML in order to persist your changes when (a) working outside of a before context or (b) working on queried sObjects, rather than those accessed directly via Trigger.new. Both are the case here. Additional notes: You do not need this loop at all: for(Call_Report__c cr : trigger.new){ It's costing you needless, ...


2

You need to add the error to a record in Trigger.old or Trigger.oldMap in order to prevent deletion. You can write your code like this: trigger delAccountWithoutOpportunity on Account (before delete) { Map<Id, Account> accounts = new Map<Id, Account>([ SELECT Id FROM Account WHERE AND Id IN (SELECT AccountId FROM Opportunity WHERE ...


2

Your this piece of code is causing the error:- if( (accCont.Name != account_i.Name) || (account_i.Name != accOpp.Name) ) You are trying to access the value from list directly using accCont.Name or accOpp.Name but you cannot as Name exist on single instance of Account but List is group of accounts. To access the value from a list, Use Get method like ...


2

You have to check if the description field is not null and its length is more than lengthOfField, then you have to substring the description till last 3 chars and append ... trigger ProductTrigger on Product__c (before insert, before update) { Schema.DescribeFieldResult F = Product__c.Description__c.getDescribe(); Integer lengthOfField = F....


2

As a trigger, you should be using the aggregate-query-update pattern. Also, you need to add the error message to the Trigger.new records. You cannot use addError on a record retrieved from a query, as it will have no effect on the transaction. The trigger should look more like this: trigger accttrigger on Account (before insert) { // Get list of names ...


2

You aren't performing any DML here - and you can't, because your aggregate query doesn't return any Ids as you've aggregated them: SELECT Name, Prospect_Code__c , COUNT(Id) ids ... You'll have to perform a second query based on the Name and Prospect_Code__c of each AggregateResult to find the Accounts you're considering duplicated and update them. Your ...


2

Your signature for onBeforeInsert in base class and child class does not match. That is the reason you are getting the error which you are getting. Changing the below line in base class public virtual void onBeforeInsert(){} to public virtual void onBeforeInsert(List<sObject> newRecords){} should do the trick. Also, one more thing you need to ...


2

Personally, I'd use the Database methods with allOrNone set to false. You can check if the record failed because of this reason (or any general failure): Opportunity[] records = new Opportunity[0]; // populate records here // Database.SaveResult[] results = Database.update(records, false); for(Integer i = 0, s = results.size(); i < s; i++) { if(!...


2

You need to create a callout mock and use Test.startTest/Test.stopTest around the code that invokes the callout. See the documentation for details. Fundamentally, tests cannot use real callouts. Using a mock, your tests can check that the code calling the callout behaves correctly for the details it gets back. This lets you simulate "happy path" and failure ...


2

In addition to Phil's points, when you do DML that causes automation to run, and then you want to test that the automation worked (or in production code, get the results of that automation), you need to re-query the record(s). Until you do, the object only has what you've set on it (except the record Id, which does get added to the in-memory object when you ...


Only top voted, non community-wiki answers of a minimum length are eligible