You need to sign in to do that
Don't have an account?
INVALID_FIELD_FOR_INSERT_UPDATE, Business Account may not use Person Account field PersonEmail:
Hi All.
i want When opportunity is updated & Email or Fax fields are changed
trigger UpdateEmailFax on Opportunity (after update)
{
List<Account> acc = new List<Account>();
List<Contact> con = new List<Contact>();
List<Id> aid = new List<Id>();
Map<Id,Opportunity> accMap = new Map<Id,Opportunity>();
Integer i = 0;
for(Opportunity o : trigger.new)
{
system.debug('Inside For loop : ' + i + ' Account id : ' + o.AccountId);
if(o.AccountId!=null)
{
system.debug('Old value - Email : ' + trigger.old[i].Email__c + ', Fax : ' + trigger.old[i].Fax__c);
if((trigger.old[i].Email__c!=o.Email__c) || (trigger.old[i].Fax__c!=o.Fax__c))
{
if(o.Account.RecordType.Name == 'Business_Account')
{
system.debug('Business_Account - Record Type : ' + o.Account.RecordType.Name);
accMap.put(o.AccountId,o);
aid.add(o.Account.id);
}
else
{
system.debug('Person_Account - Record Type : ' + o.Account.RecordType.Name);
Account a = new Account();
//o.Account.PersonEmail = o.Email__c;
//o.Account.Fax = o.Fax__c;
a.id = o.AccountId;
a.PersonEmail = o.Email__c;
a.Fax = o.Fax__c;
acc.add(a);
}
}
}
i++;
}
update acc; // ERROR IS HERE
//con = [select id,name,Account.id, Email , Fax from Contact where Account.id in :aid];
for(Contact c : [select id,name,Account.id, Email , Fax from Contact where Account.id in :aid])
{
if(c.Account!=null)
{
c.Email = accMap.get(c.Account.id).Email__c;
c.Fax = accMap.get(c.Account.id).Fax__c;
con.add(c);
}
}
update con;
}
You're not querying for the account at all, so when you try to access that information, the if statement is false (o.Account.RecordType is unknown, as you haven't queried for it), so it branches to the ELSE statement, which assumes that it is a person account (which, it apparently is not). I would recommend the following changes:
1) Notice how I use queries to find the record type. As a bonus, I use the IsPersonType flag instead of depending on the name of the record type being a specific value.
2) Notice the use of maps so we don't need to iterate over items unnecessarily. And, we don't need an index counter, either now.
3) Changed the need for if-then statements by optimising queries, reducing the database rows returned and script statements executed. I do this by specifically making sure I removed the need to query for contacts with blank accountids.
Hi sfdcfox,
Thanks for replying me it solved the problem with small changes but now i'm getting another problem because i have another trigger on contact which will fire when a contact is updated .i need to perform
trigger updateemailfax on opportunity (after update) {
map<id,account> acc = new map<id,account>(), upacc = new map<id,account>();
map<id,opportunity> opp = new map<id,opportunity>();
contact[] con = new contact[0];
set<id> busacc = new set<id>();
for(opportunity o:trigger.new) {
acc.put(o.accountid,null);
opp.put(o.accountid,o); }
acc.remove(null);
opp.remove(null);
acc.putall([select id,recordtype.ispersontype from account where id in :acc.keyset()]);
for(opportunity o:trigger.new) {
if(o.accountid!=null && (o.email__c!=trigger.oldmap.get(o.id).email__c || o.fax__c!=trigger.oldmap.get(o.id).fax__c)) {
if(acc.get(o.accountid).recordtype.ispersontype) {
upacc.put(o.accountid,new account(id=o.accountid,personemail=o.email__c,fax=o.fax__c)); }
else {
busacc.add(o.accountid); } } }
if(!busacc.isempty()) {
con.addall([select id,accountid from contact where accountid in :busacc]);
System.debug('busacc set size is'+busacc.size()); }
for(contact c:con) {
c.email = opp.get(c.accountid).email__c;
c.fax = opp.get(c.accountid).fax__c; }
update upacc.values();
update con;
}
Here is my contact trigger
trigger Contacttoopp on Contact (after update) {
// map tracks records on ContactID
Map<String, Contact> ContactMap = new Map<String, Contact>();
List<Opportunity> lstToUpdate = new List<Opportunity>();
for( Contact con : Trigger.new ) {
if( (Trigger.oldMap.get(con.id).Email != con.Email ) || (Trigger.oldMap.get(con.id).Fax != con.Fax ) )
{ ContactMap.put( Con.ID, con );
}
if( ContactMap.keySet().size() > 0 ) {
//map to keep track of the opportunity contact roles
map<Id, Id> oppycontactroles = new map<Id, Id>();
//select OpportunityContactRoles for the contacts with contact role required
List<OpportunityContactRole> ContactRoles = [select OpportunityID, ContactID from OpportunityContactRole where contactID in :ContactMap.keySet() ];
for (OpportunityContactRole ocr : ContactRoles) {
//puts the contact roles in the map with the opportunity ID as the key
oppycontactroles.put(ocr.OpportunityId,ocr.ContactID);
}
// update opportunity Prior Email,Fax field from the matching record
for( Opportunity opp : [Select Email__c, Fax__c, Id From Opportunity Where ID IN : oppycontactroles.keySet()]) {
opp.Email__c = ContactMap.get(oppycontactroles.get(opp.id)).Email;
opp.Fax__c = ContactMap.get(oppycontactroles.get(opp.id)).Fax;
lstToUpdate.add(opp); }
} }
update lstToupdate;
}
You've got a recursive trigger problem: updateEmailFax updates contacts, so when ContactToOpp is called as a result, the opportunities are updated again, which will call updateEmailFax again. You'll need a static variable to prevent the recursion:
With this in place, on line 2 of updateEmailFax, add:
And on the ContactToOpp trigger:
This should break the chain and allow the save to complete.
Hi Sfdcfox,
Thanks for replying can you please look into dis thread
http://boards.developerforce.com/t5/Apex-Code-Development/Need-urgent-Help-to-Increase-Test-Coverage/td-p/582745
i writtem a Followuptaskhelper class to avoid recuesion.i'm getting only 30% of code covereage when include this lines in my trigger please help me out in this ,how to increase my code coverage.
Here is my class, the above thread contains my trigger and test class i need my trigger to cover above 75%.
public class FollowUpTaskHelper {
// Static variables are local to the context of a Web request
// (or testMethod during a runTests call)
// Therefore, this variable will be initialized as false
// at the beginning of each Web request which accesses it.
private static boolean alreadyCreatedTasks = false;
public static boolean hasAlreadyCreatedFollowUpTasks() {
return alreadyCreatedTasks;
}
// By setting the variable to true, it maintains this
// new value throughout the duration of the request
// (or testMethod)
public static void setAlreadyCreatedFollowUpTasks() {
alreadyCreatedTasks = true;
}
public static String getFollowUpSubject(String subject) {
return 'Follow Up: ' + subject;
}
}