You need to sign in to do that
Don't have an account?

Apex Trigger updating all records in batch with the same value
I have a trigger on opportunites that will add a field from a custom object (TSG__c) if a match is found on .P21_Customer_ID. The issue is that when multiple records are being updated through an upsert (Informatica Cloud) all of those opportunites are getting updated with the same field value.
Below is my trigger, please let me know where I went wrong.
Thanks again.
TRIGGER populate_TSG on Opportunity (before insert,before update) {
Set<string> ss = New Set<string>();
List<TSG__c> TheTSG=new LIST<TSG__c>();
//Loop through all records in the Trigger.new collection
FOR(Opportunity O: Trigger.new)
{
ss.Add(O.P21_Customer_ID__c );
}
TheTSG = [SELECT ID from TSG__c WHERE P21_CompanyCustomer_ID__c IN: ss];
System.debug('@@@@--'+TheTSG.size());
IF (TheTSG.size() >0)
{
For (Opportunity O: Trigger.new)
{
For(TSG__c tsg:TheTSG)
{
O.p21_account_number__c = tsg.ID;
System.debug('@@@@--'+tsg.ID);
}
}
}
}
Below is my trigger, please let me know where I went wrong.
Thanks again.
TRIGGER populate_TSG on Opportunity (before insert,before update) {
Set<string> ss = New Set<string>();
List<TSG__c> TheTSG=new LIST<TSG__c>();
//Loop through all records in the Trigger.new collection
FOR(Opportunity O: Trigger.new)
{
ss.Add(O.P21_Customer_ID__c );
}
TheTSG = [SELECT ID from TSG__c WHERE P21_CompanyCustomer_ID__c IN: ss];
System.debug('@@@@--'+TheTSG.size());
IF (TheTSG.size() >0)
{
For (Opportunity O: Trigger.new)
{
For(TSG__c tsg:TheTSG)
{
O.p21_account_number__c = tsg.ID;
System.debug('@@@@--'+tsg.ID);
}
}
}
}
I've also made some assumptions, like how the related object for both Opp and TSG is Account, and that p21_account_number__c is a lookup to TSG and not a text.
You need to addapt this to your structure
Thank you,
Adrian
All Answers
Where exactly are you matching the oppty.P21_Customer_ID__c with the tsg.P21_CompanyCustomer_ID__c?
You are extracting the TSG using the set of P21_Customer_ID__c from oppties but when parsing the oppties from the trigger.new you just overwrite the p21_account_number__c with the tsg.Id for all of them instead of just the one that matches...
Try to add this and tell me how it goes...
Also you should have a mass opportunity insert/update test in your test class for your trigger. Just create in a loop 200 oppties(or how many Informatica can updtate at a time) + ther TSG correspondent records and do an update on them to see how the trigger behaves
Ty,
Adrian
TheTSG = [SELECT ID from TSG__c WHERE P21_CompanyCustomer_ID__c IN: ss];
I am getting an error now with the changes you recommended.
Error: Invalid Data.
Review all error messages below to correct your data.
Apex trigger popTSG_2 caused an unexpected exception, contact your administrator: popTSG_2: execution of BeforeUpdate caused by: System.SObjectException: SObject row was retrieved via SOQL without querying the requested field: TSG__c.P21_CompanyCustomer_ID__c: Trigger.popTSG_2: line 22, column 1
Since O.p21_account_number__c is a lookup field to the TSG__c object I am populating the TSG__c to link these two objects. Is seems as though when the trigger files for multiple opps at the same time it is updating all of them with the same value.
Some how I need to reference them individually but still make the trigger bulk friendly.
I am at a loss.
There are 2 opportunities: Opp1 with P21_Customer_ID__c = '1' and Opp2 with P21_Customer_ID__c = '2'.
There are 2 TSG: TSG1 with P21_CompanyCustomer_ID__c = '1' and TSG2 with P21_CompanyCustomer_ID__c ='2'.
It should be a straight match Opp1 gets the Id from TSG1 and Opp2 gets the Id from TSG2.
You get the list of TSG__c and since it is not empty you start the first for, going through the 2 opportunities. The second for starts for the Opp1 and it will first set the p21_Account to TSG1 then to TSG2. SAME for Opp2.
The second for without any if will ALWAYS set p21_account_number__c to the Id of the last TSG__c record in the TheTSG list.
It is a trivial logic error (I hope). To see it for yourself add a debug to see the value of the TheTSG list after you SELECT it, plus another System.debug to the for that cycles the opportunities in trigger.new and a final debug after the two for statements to see the value of trigger.new. The p21_account_number__c will always have the Id of the last TSG record in list
As for the Exception that you are getting pls add the P21_CompanyCustomer_ID__c to the SELECT
Tell me how it works
Ty,
Adrian
Thanks again.
I've also made some assumptions, like how the related object for both Opp and TSG is Account, and that p21_account_number__c is a lookup to TSG and not a text.
You need to addapt this to your structure
Thank you,
Adrian
Currently I am only getting 54% (6/11) on the trigger coverage.
Here is the modified class, let me know if there are any changes we can make to get better coverage.
@isTest
private class StuffClass {
@isTest
static void test_checkTSGPopulateOnOpportunityInsert() {
// create the accounts(or whatever are the related objects for the oppty
// P21_Customer_ID__c field)
List<Account> accList = new List<Account>();
for (Integer i = 0; i < 200; i++) {
Account newAcc = new Account(P21_CompanyCustomer_ID__c = '1-10009' + i , Name='TestAcc' + i);
accList.add(newAcc);
}
insert accList;
// create the TSGs
List<TSG__c> tsgList = new List<TSG__c>();
for (Integer i=0; i < 200; i++) {
TSG__c newTSG = new TSG__c(Name='Test' + i,
P21_CompanyCustomer_ID__c = '1-10009' + i);
tsgList.add(newTSG);
}
insert tsgList;
// create the Opportunities
List<Opportunity> oppList = new List<Opportunity>();
for (Integer i=0; i<200; i++) {
// observe the same name for Opp and TSG
Opportunity newOpp = new Opportunity(CloseDate = date.parse('08/26/2014'), Stagename = 'Won', Name = 'Test' + i,
p21_account_number__c = tsgList[i].ID);
oppList.add(newOpp);
}
insert oppList;
// the trigger has matched the opportunities with their TSGs
// we check that the p21_account_number__c has been correctly set
oppList = [SELECT Id, Name, p21_account_number__c,
p21_account_number__r.Name
FROM Opportunity];
for (Opportunity opp: oppList) {
System.assertEquals(opp.Name, opp.p21_account_number__r.Name);
}
}
}
@isTest
private class StuffClass {
@isTest
static void test_checkTSGPopulateOnOpportunityInsert() {
// create the accounts(or whatever are the related objects for the oppty
// P21_Customer_ID__c field)
List<Account> accList = new List<Account>();
for (Integer i = 0; i < 200; i++) {
Account newAcc = new Account(Name='TestAcc' + i);
accList.add(newAcc);
}
insert accList;
// create the TSGs
List<TSG__c> tsgList = new List<TSG__c>();
for (Integer i=0; i < 200; i++) {
TSG__c newTSG = new TSG__c(Name='Test' + i,
P21_CompanyCustomer_ID__c = accList[i].Id);
tsgList.add(newTSG);
}
insert tsgList;
// create the Opportunities
List<Opportunity> oppList = new List<Opportunity>();
for (Integer i=0; i<200; i++) {
// observe the same name for Opp and TSG
Opportunity newOpp = new Opportunity(CloseDate = date.parse('09/26/2014'), Stagename = 'Won', Name = 'Test' + i,
p21_account_number__c = tsgList[i].Id);
oppList.add(newOpp);
}
insert oppList;
// the trigger has matched the opportunities with their TSGs
// we check that the p21_account_number__c has been correctly set
oppList = [SELECT Id, Name, p21_account_number__c,P21_Customer_ID__c,
p21_account_number__r.Name
FROM Opportunity];
for (Opportunity opp: oppList) {
System.assertEquals(opp.Name, opp.p21_account_number__r.Name);
}
}
}
Thank you so much for your help with all of this.
@isTest
private class StuffClass {
@isTest
static void test_checkTSGPopulateOnOpportunityInsert() {
// create the accounts(or whatever are the related objects for the oppty
// P21_Customer_ID__c field)
List<Account> accList = new List<Account>();
for (Integer i = 0; i < 200; i++) {
Account newAcc = new Account(Name='Test' + i,P21_CompanyCustomer_ID__c = '1-10009' + i );
accList.add(newAcc);
}
insert accList;
// create the TSGs
List<TSG__c> tsgList = new List<TSG__c>();
for (Integer i = 0; i < 200; i++) {
TSG__c newTSG = new TSG__c(Name='Test' + i,
P21_CompanyCustomer_ID__c = accList[i].P21_CompanyCustomer_ID__c);
tsgList.add(newTSG);
}
insert tsgList;
// create the Opportunities
List<Opportunity> oppList = new List<Opportunity>();
for (Integer i = 0; i< 200; i++) {
// observe the same name for Opp and TSG
Opportunity newOpp = new Opportunity(CloseDate = date.parse('09/26/2014'), Stagename = 'Won', Name = 'Test' + i,
AccountID = accList[i].Id);
oppList.add(newOpp);
}
insert oppList;
// the trigger has matched the opportunities with their TSGs
// we check that the p21_account_number__c has been correctly set
oppList = [SELECT Id, Name, p21_account_number__c,
p21_account_number__r.Name
FROM Opportunity];
for (Opportunity opp: oppList) {
System.assertEquals(opp.Name, opp.p21_account_number__r.Name);
}
}
}