You need to sign in to do that
Don't have an account?
Deployment Error - MISSING_ARGUMENT, Id not specified in an update call:
I'm brand new to triggers and apex so I'm tending to borrow code snippets from blogs and websites and trying to appropriate them for my org. I found two classes that help me easily add lookup roll up summary fields to objects. The classes are listed here: https://github.com/abhinavguptas/Salesforce-Lookup-Rollup-Summaries/tree/master/classes
I then used the example on that site to create a lookup roll up summary field trigger in my sandbox which worked perfectly. The problem is I'm unable to deploy it to my production environment as I keep receiving 17 or so instances of the below error:
"Failure Message: "System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, OppRollup: execution of AfterInsert caused by: System.DmlException: Update failed. First exception on row 0; first error: MISSING_ARGUMENT, Id not specified in an update call: [] Trigger.OppRollup:..."
The OppRollup Trigger is as follows:
"trigger OppRollup on Opportunity (after insert, after update,
after delete, after undelete) {
// modified objects whose parent records should be updated
Opportunity[] objects = null;
if (Trigger.isDelete) {
objects = Trigger.old;
} else {
/*
Handle any filtering required, specially on Trigger.isUpdate event. If the rolled up fields
are not changed, then please make sure you skip the rollup operation.
We are not adding that for sake of similicity of this illustration.
*/
objects = Trigger.new;
}
/*
First step is to create a context for LREngine, by specifying parent and child objects and
lookup relationship field name
*/
LREngine.Context ctx = new LREngine.Context(Contact.SobjectType, // parent object
Opportunity.SobjectType, // child object
Schema.SObjectType.Opportunity.fields.key_broker_contact__c // relationship field name
);
/*
Next, one can add multiple rollup fields on the above relationship.
Here specify
1. The field to aggregate in child object
2. The field to which aggregated value will be saved in master/parent object
3. The aggregate operation to be done i.e. SUM, AVG, COUNT, MIN/MAX
*/
ctx.add(
new LREngine.RollupSummaryField(
Schema.SObjectType.Contact.fields.OppCount__c,
Schema.SObjectType.Opportunity.fields.Amount,
LREngine.RollupOperation.Count
));
/*
Calling rollup method returns in memory master objects with aggregated values in them.
Please note these master records are not persisted back, so that client gets a chance
to post process them after rollup
*/
Sobject[] masters = LREngine.rollUp(ctx, objects);
// Persiste the changes in master
update masters;"
As I said I'm brand new to Apex although I do have some education in Java and C++. Any ideas? I think I have to put something in the first ELSE statement although I've no idea where to start. Hopefully a solution here will help me fix many of my deployment issues as I've seen this error message a lot.
Thanks in advance!
Sorry looks like I lead you into a hole you didn't need to go. Based off the code it just takes the records with the Master Record Id field, if that happens to be null (in your lookup) than that method will end up giving you a SObject without an Id resulting in the update call to fail.
Try this for the trigger:
All Answers
Hi slipton,
In above trigger you have to put one if condition as like below. and then make deployment
Important :
Hit Kudos if this provides you with useful information and if this is what you where looking for then please mark it as a solution for other benefits.
Thanks,
Hitesh Patel
Hi Hitesh90,
That didn't work unfortunately. Still getting the same 17 errors.
I would take a look at this method:
Sobject[] masters = LREngine.rollUp(ctx, objects);
Specifically see if anything happening in that particular method is creating a new record and not updating an existing record. If so you'll either want to trap those cases or change your update call to an upsert call.
/**
Key driver method that rolls up lookup fields based on the context. This is specially useful in Trigger context.
@param ctx Context the complete context required to rollup
@param detailRecordsFromTrigger child/detail records which are modified/created/deleted during the Trigger
@returns Array of in memory master objects. These objects are not updated back to the database
because we want client or calling code to have this freedom to do some post processing and update when required.
*/
public static Sobject[] rollUp(Context ctx, Sobject[] detailRecordsFromTrigger) {
// API name of the lookup field on detail sobject
String lookUpFieldName = ctx.lookupField.getName();
Set<Id> masterRecordIds = new Set<Id>();
for (Sobject kid : detailRecordsFromTrigger) {
masterRecordIds.add((Id)kid.get(lookUpFieldName));
}
return rollUp(ctx, masterRecordIds);
}
You'll need to go a step further and look at this:
return rollUp(ctx, masterRecordIds);
Which is an overload of the previous method but it seems to take the master record Id's instead of the objects being processed in the trigger.
OK. I'm a bit lost with this one now.
public static Sobject[] rollUp(Context ctx, Set<Id> masterIds) {
// K: Id of master record
// V: Empty sobject with ID field, this will be used for updating the masters
Map<Id, Sobject> masterRecordsMap = new Map<Id, Sobject>();
for (Id mId : masterIds) {
masterRecordsMap.put(mId, ctx.master.newSobject(mId));
}
// #0 token : SOQL projection
String soqlProjection = ctx.lookupField.getName();
// k: detail field name, v: master field name
Map<String, String> detail2MasterFldMap = new Map<String, String>();
for (RollupSummaryField rsf : ctx.fieldsToRoll) {
// create aggreate projection with alias for easy fetching via AggregateResult class
// i.e. SUM(Amount) Amount
soqlProjection += ', ' + rsf.operation + '(' + rsf.detail.getName() + ') ' + rsf.detail.getName();
detail2MasterFldMap.put(rsf.detail.getName(), rsf.master.getName());
}
// #1 token for SOQL_TEMPLATE
String detailTblName = ctx.detail.getDescribe().getName();
// #2 Where clause
String whereClause = '';
if (ctx.detailWhereClause != null && ctx.detailWhereClause.trim().length() > 0) {
whereClause = 'WHERE ' + ctx.detailWhereClause ;
}
// #3 Group by field
String grpByFld = ctx.lookupField.getName();
String soql = String.format(SOQL_TEMPLATE, new String[]{soqlProjection, detailTblName, whereClause, grpByFld});
// aggregated results
List<AggregateResult> results = Database.query(soql);
for (AggregateResult res : results){
Id masterRecId = (Id)res.get(grpByFld);
Sobject masterObj = masterRecordsMap.get(masterRecId);
if (masterObj == null) {
System.debug(Logginglevel.WARN, 'No master record found for ID :' + masterRecId);
continue;
}
for (String detailFld : detail2MasterFldMap.keySet()) {
Object aggregatedDetailVal = res.get(detailFld);
masterObj.put(detail2MasterFldMap.get(detailFld), aggregatedDetailVal);
}
}
return masterRecordsMap.values();
}
Sorry looks like I lead you into a hole you didn't need to go. Based off the code it just takes the records with the Master Record Id field, if that happens to be null (in your lookup) than that method will end up giving you a SObject without an Id resulting in the update call to fail.
Try this for the trigger:
I'm just getting an error at line 4 - Error: Compile Error: expecting a semi-colon, found '[' at line 4 column 40.
Does it need a "new" after the equals sign?
Yes sorry, I don't get a chance to test compile since I write a lot of this on the fly.
It seems that fixed it. Thank you so much!
I am getting below error when ever I am trying to use the below syntax
"LREngine.Context ctx = new LREngine.Context(Parent_API.SobjectType, // parent object
Child_API.SobjectType, // child object
Schema.SObjectType.Child.fields.Relationship_Field_API // relationship field name
);"
Error: Compile Error: Invalid type: LREngine.Context at line 18 column 32
Can you please help me fix this?
I tried in many blogs but I didnt receive any reply from others.
Thanks,
MR