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

Contact page not refreshing updated field
I have two buttons on the contact screen. Log a Call and Log a Meeting. When these are selected the corresponding screen to log a call or meeting comes up.
Upon saving the call or meeting a trigger is called on insert /update/delete. This trigger updates a Status field on the contact record. The updates works however, the contact screen will not show this field as updated until I hit F5. I have reproduced this in Both FireFox and Chrome.
Thanks in advance for your help.
Lawrence
Is the trigger executing in real time or as a result of a future method. If you use a future method, then the process becomes asynchronous and you will have to refresh the screen to see the update. A simple trigger though should give you the updated value when the contact screen opens up.
Also are you opening the log a call screen in a separate window or is it opening in the same window and returning to the contact screen?
Arun
Yes, the trigger is as a result of a future method. I needed to do this to avoid a soql 101 error... too many soql queries.
The log a screen is openng in the same window and returning to the contact screen
To make this instantaneous you have to make synchronous calls by avoiding future calls.
The SOQL 101 error that you are getting is due to inefficient trigger design. That can be corrected by following the best practices.
The use of future calls was the suggestion SalesForce Support gave me after looking at my code.
The Soql 101 error was not caused by have queries in loops. It was caused by the following.
When a user changes ownership of a candidate record all tasks and events are copied to that new owner.
This causes an edit to occur for each task associated with that contact. in turn this edit causes an existing task trigger to fire off that contains
a query(not in a loop). So if the contact has more than 100 tasks for example a recurring task.... this has caused the SOQL 101 error.
Any suggestions on improvement?
Best practice is to redesign the trigger.If thats time consuming, at least you can exchange, some dml operation with future method.
I agree seeing the code would help.
Would you like to see the trigger making the future call or the original trigger before I modified it to use the future call?
Lawrence
Below is the code before I added the future call..
trigger CandidateStatusFlow on Task (after insert, after update, before delete) {
if (Trigger.isDelete) {
for (Task t : Trigger.old) {
if (t.Status == 'Completed'&& (!(UserInfo.getProfileId ().equals('00eU0000000o4PBIAY')))) {
t.addError('You cannot delete a task with a status of complete.');
}
}
}
else
{
SingletonResource singleton = SingletonResource.getInstance();
List<Id> contactIds = new List<Id> ();
Id callRecId = singleton.callRecId;
Id meetingRecId = singleton.meetingRecId;
Id faceRecId = singleton.faceToFaceRecId;
Id prospectRecId = singleton.prospectRecId;
Id candidateRecId = singleton.candidateRecId;
String RecordType; //lreed 02/06/2012...variable to capture recordType ID of Button.... Log a Call or Log a Meeting
String TaskStatus;
for (Task t : Trigger.new) {
// The following code ensures that the contact status changes to 'Prospect: Contacted' once a task of type call has been completed
RecordType = t.RecordTypeId; //store value of recordType Based on Button Clicked ...Log a Call or Log a Meeting button
TaskStatus = t.Status;
if (t.Status == 'Completed' && !(t.IsRecurrence) && (t.Type == 'Inbound Call/Conversation' || t.Type == 'Outbound Call/Conversation') &&
t.RecordTypeId == callRecId ) {
contactIds.add(t.WhoId);
} else if (t.Status == 'Completed' && !(t.IsRecurrence) && t.RecordTypeId == meetingRecId) {
contactIds.add(t.WhoId);
}
}
if(Trigger.isUpdate)
{
for (Task t : Trigger.new) {
system.debug('NEW OwnerID' + t.OwnerId);
if(t.OwnerId != null && (trigger.new[0].OwnerId == trigger.old[0].OwnerId) && trigger.new[0].OwnerId != '005U0000001i4s1IAA' ){
Map<Id, Contact> contacts = new Map<Id, Contact> ([Select Id, Phone, MobilePhone, Status__c, RecordTypeId, AccountId, LeadSource, Last_Comment__c
From Contact
Where Id IN :contactIds]);
Map<Id, Contact> desiredContacts = new Map<Id, Contact> ();
for (Contact c : contacts.values()) {
if (RecordType == '012U0000000L2TJIA0'&& c.Status__c == 'Prospect: Not Contacted' ) { //Call
c.Status__c = 'Prospect: Contacted';
desiredContacts.put(c.Id, c);
}else if (RecordType == '012U0000000XcyZIAS' && c.Status__c == 'Candidate: Qualified') { //Meeting
c.Status__c = 'Candidate: Meeting';
desiredContacts.put(c.Id, c);
//Meeting //Prospect
}
if (Trigger.isInsert) {
if (RecordType == '012U0000000XcyZIAS' && c.RecordTypeId == '012U0000000Y3ybIAC' && c.Status__c != 'Candidate: Qualified') { /// 02-12-2013 lreed...If user has not qualified lead show error message
trigger.new[0].adderror('You Must Qualify The Candidate Before Logging A Meeting!');
}else if (RecordType == '012U0000000XcyZIAS' && c.RecordTypeId == '012U0000000Y3ybIAC' && c.Status__c != 'Prospect: Contacted')
{ /// 02-12-2013 lreed...If user has not qualified lead show error message
trigger.new[0].adderror('Please Log a Call Before Qualifying The Candidate!');
}
}
}
for (Task t2 : Trigger.new) {
if (contacts.containsKey(t2.WhoId)) {
Contact c = contacts.get(t2.WhoId);
if (desiredContacts.containsKey(c.Id)) {
c = desiredContacts.get(c.Id);
}
c.Last_Comment__c = t2.Description;
desiredContacts.put(c.Id, c);
}
}
update desiredContacts.values();
}
}
}
}
}
//I just moved the position of the update ...Its outside the loop now.YOu will not get any governor limit issue now..
So you can move the code from future method to trigger.
But be careful not to put dml,select statement inside the loop.
trigger CandidateStatusFlow on Task (after insert, after update, before delete) {
if (Trigger.isDelete) {
for (Task t : Trigger.old) {
if (t.Status == 'Completed'&& (!(UserInfo.getProfileId ().equals('00eU0000000o4PBIAY')))) {
t.addError('You cannot delete a task with a status of complete.');
}
}
}
else
{
SingletonResource singleton = SingletonResource.getInstance();
List<Id> contactIds = new List<Id> ();
Id callRecId = singleton.callRecId;
Id meetingRecId = singleton.meetingRecId;
Id faceRecId = singleton.faceToFaceRecId;
Id prospectRecId = singleton.prospectRecId;
Id candidateRecId = singleton.candidateRecId;
Map<Id, Contact> desiredContacts = new Map<Id, Contact> ();
String RecordType; //lreed 02/06/2012...variable to capture recordType ID of Button.... Log a Call or Log a Meeting
String TaskStatus;
for (Task t : Trigger.new) {
// The following code ensures that the contact status changes to 'Prospect: Contacted' once a task of type call has been completed
RecordType = t.RecordTypeId; //store value of recordType Based on Button Clicked ...Log a Call or Log a Meeting button
TaskStatus = t.Status;
if (t.Status == 'Completed' && !(t.IsRecurrence) && (t.Type == 'Inbound Call/Conversation' || t.Type == 'Outbound Call/Conversation') &&
t.RecordTypeId == callRecId ) {
contactIds.add(t.WhoId);
} else if (t.Status == 'Completed' && !(t.IsRecurrence) && t.RecordTypeId == meetingRecId) {
contactIds.add(t.WhoId);
}
}
if(Trigger.isUpdate)
{
for (Task t : Trigger.new) {
system.debug('NEW OwnerID' + t.OwnerId);
if(t.OwnerId != null && (trigger.new[0].OwnerId == trigger.old[0].OwnerId) && trigger.new[0].OwnerId != '005U0000001i4s1IAA' ){
Map<Id, Contact> contacts = new Map<Id, Contact> ([Select Id, Phone, MobilePhone, Status__c, RecordTypeId, AccountId, LeadSource, Last_Comment__c
From Contact
Where Id IN :contactIds]);
for (Contact c : contacts.values()) {
if (RecordType == '012U0000000L2TJIA0'&& c.Status__c == 'Prospect: Not Contacted' ) { //Call
c.Status__c = 'Prospect: Contacted';
desiredContacts.put(c.Id, c);
}else if (RecordType == '012U0000000XcyZIAS' && c.Status__c == 'Candidate: Qualified') { //Meeting
c.Status__c = 'Candidate: Meeting';
desiredContacts.put(c.Id, c);
//Meeting //Prospect
}
if (Trigger.isInsert) {
if (RecordType == '012U0000000XcyZIAS' && c.RecordTypeId == '012U0000000Y3ybIAC' && c.Status__c != 'Candidate: Qualified') { /// 02-12-2013 lreed...If user has not qualified lead show error message
trigger.new[0].adderror('You Must Qualify The Candidate Before Logging A Meeting!');
}else if (RecordType == '012U0000000XcyZIAS' && c.RecordTypeId == '012U0000000Y3ybIAC' && c.Status__c != 'Prospect: Contacted')
{ /// 02-12-2013 lreed...If user has not qualified lead show error message
trigger.new[0].adderror('Please Log a Call Before Qualifying The Candidate!');
}
}
}
for (Task t2 : Trigger.new) {
if (contacts.containsKey(t2.WhoId)) {
Contact c = contacts.get(t2.WhoId);
if (desiredContacts.containsKey(c.Id)) {
c = desiredContacts.get(c.Id);
}
c.Last_Comment__c = t2.Description;
desiredContacts.put(c.Id, c);
}
}
}
}
}
//Moved update outside the loop It should work now ....
if(desiredContacts.size()>0)
update desiredContacts.values();
}
}
When moving the update to that location I receive the following error on saving the change in code.
Save error: Variable does not exist: desiredContacts CandidateStatusFlow.trigger EARDEVTR2/src/triggers line 91 Force.com save problem
//Use this code .......................
trigger CandidateStatusFlow on Task (after insert, after update, before delete) {
Map<Id, Contact> desiredContacts = new Map<Id, Contact> ();
if (Trigger.isDelete) {
for (Task t : Trigger.old) {
if (t.Status == 'Completed'&& (!(UserInfo.getProfileId ().equals('00eU0000000o4PBIAY')))) {
t.addError('You cannot delete a task with a status of complete.');
}
}
}
else
{
SingletonResource singleton = SingletonResource.getInstance();
List<Id> contactIds = new List<Id> ();
Id callRecId = singleton.callRecId;
Id meetingRecId = singleton.meetingRecId;
Id faceRecId = singleton.faceToFaceRecId;
Id prospectRecId = singleton.prospectRecId;
Id candidateRecId = singleton.candidateRecId;
String RecordType; //lreed 02/06/2012...variable to capture recordType ID of Button.... Log a Call or Log a Meeting
String TaskStatus;
for (Task t : Trigger.new) {
// The following code ensures that the contact status changes to 'Prospect: Contacted' once a task of type call has been completed
RecordType = t.RecordTypeId; //store value of recordType Based on Button Clicked ...Log a Call or Log a Meeting button
TaskStatus = t.Status;
if (t.Status == 'Completed' && !(t.IsRecurrence) && (t.Type == 'Inbound Call/Conversation' || t.Type == 'Outbound Call/Conversation') &&
t.RecordTypeId == callRecId ) {
contactIds.add(t.WhoId);
} else if (t.Status == 'Completed' && !(t.IsRecurrence) && t.RecordTypeId == meetingRecId) {
contactIds.add(t.WhoId);
}
}
if(Trigger.isUpdate)
{
for (Task t : Trigger.new) {
system.debug('NEW OwnerID' + t.OwnerId);
if(t.OwnerId != null && (trigger.new[0].OwnerId == trigger.old[0].OwnerId) && trigger.new[0].OwnerId != '005U0000001i4s1IAA' ){
Map<Id, Contact> contacts = new Map<Id, Contact> ([Select Id, Phone, MobilePhone, Status__c, RecordTypeId, AccountId, LeadSource, Last_Comment__c
From Contact
Where Id IN :contactIds]);
for (Contact c : contacts.values()) {
if (RecordType == '012U0000000L2TJIA0'&& c.Status__c == 'Prospect: Not Contacted' ) { //Call
c.Status__c = 'Prospect: Contacted';
desiredContacts.put(c.Id, c);
}else if (RecordType == '012U0000000XcyZIAS' && c.Status__c == 'Candidate: Qualified') { //Meeting
c.Status__c = 'Candidate: Meeting';
desiredContacts.put(c.Id, c);
//Meeting //Prospect
}
if (Trigger.isInsert) {
if (RecordType == '012U0000000XcyZIAS' && c.RecordTypeId == '012U0000000Y3ybIAC' && c.Status__c != 'Candidate: Qualified') { /// 02-12-2013 lreed...If user has not qualified lead show error message
trigger.new[0].adderror('You Must Qualify The Candidate Before Logging A Meeting!');
}else if (RecordType == '012U0000000XcyZIAS' && c.RecordTypeId == '012U0000000Y3ybIAC' && c.Status__c != 'Prospect: Contacted')
{ /// 02-12-2013 lreed...If user has not qualified lead show error message
trigger.new[0].adderror('Please Log a Call Before Qualifying The Candidate!');
}
}
}
for (Task t2 : Trigger.new) {
if (contacts.containsKey(t2.WhoId)) {
Contact c = contacts.get(t2.WhoId);
if (desiredContacts.containsKey(c.Id)) {
c = desiredContacts.get(c.Id);
}
c.Last_Comment__c = t2.Description;
desiredContacts.put(c.Id, c);
}
}
}
}
}
//Moved update outside the loop It should work now ....
if(desiredContacts.size()>0)
update desiredContacts.values();
}
}