function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
aborchyaborchy 

Contact Required

i have downloaded from the app exchange the contact required app and like it except that it produces a warning only for the user and forces them to back out and re-enter that data that is required. What I would like it to do is rather than create an error message is to open a new window with the contact role related list where the user can enter the required data and save. this would allow users to work without having to backout of the record.

 

It seems the code does what I want up until I get to the area highlighted in red text.

 

Apart of our business requirement is to capture contact and partner roles for each and every opportunity as it closes. I cant make a related list a requirement today so this seems to be the best work-around i have found. If anyone has any other solution please share :)

 

Any assistance is welcome.

 

 

 

 //This is provided as a sample to require a contact on opportunities it is provided without warranty and support.

trigger opportunity_contact_required on Opportunity (before insert, before update) {

//map to keep track of the contact_required = 1

Map<String, Opportunity> oppy_contact = new Map<String, Opportunity>();

//Trigger.new is an array of opportunities
//and adds any that have Contact_Required = 1 to the oppy_contact Map

for (Integer i = 0; i < Trigger.new.size(); i++) {

    if  (Trigger.new[i].contact_required__c == 1)
            {
            oppy_contact.put(Trigger.new[i].id,
            Trigger.new[i]);

            //system.debug('This is the trigger.new.id - '+Trigger.new[i].id);

    }
}

//map to keep track of the opportunity contact roles

map<Id, OpportunityContactRole> oppycontactroles = new map<Id, OpportunityContactRole>();


//select OpportunityContactRoles for the opportunities with contact role required

for (OpportunityContactRole ocr : [select OpportunityId, IsPrimary
from OpportunityContactRole
where (OpportunityContactRole.IsPrimary = True and OpportunityContactRole.OpportunityId
in :oppy_contact.keySet())])
  {


//puts the contact roles in the map with the Opportunity ID as the key
    
        oppycontactroles.put(ocr.OpportunityId,ocr);
}

// Loop through the opportunities and check if they exists in the contact roles map or contact role isn't required
        
for (Opportunity oppy : system.trigger.new) {

    //system.debug('List oppy Id - '+oppy.id);
    
    if  (oppycontactroles.containsKey(oppy.id) || oppy.contact_required__c ==0)
        {
            
        }
    
    else
        {
            oppy.addError('No Primary Contact Exists. Please go to the Opportunity Contact Roles Related List and add a primary contact.  Insure that all contacts related to this Opportunity are properly added in the Contact Roles with respective roles assigned.');

                
        }
    

} //for

    
    
 }

mtbclimbermtbclimber

You have a couple of options depending on your dependency on using the standard edit page (and the page layout editor for manageability of it)

 

1) You want to keep the standard edit page.

 

Given the standard edit page constraints you would need to add a lookup to contact from oppty for the "Primary contact" which you'd need a trigger on oppty to keep in sync with the actual contact role. Since there are no triggers on contactrole you'd need something to go through and check whether they were out of sync due to a contact role change.  Then your user could select the contact on the oppty edit page in the event the validation is kicking in.  Of course you can't filter the results to just the current contacts so I'm not sure what the usability would be on that necessarily but I don't see another solution that satisfies the requirement of having the user not lose their edits or have to otherwise leave the page when the validation is triggered.

 

2) You don't mind overriding the standard edit page

 

If you don't update your Opportunity page frequently, have minor variations across your profiles for layouts and are OK modifying Visualforce pages then you could override the oppty edit page with Visualforce and incorporate contact roles into the flow more naturally. In this case I would still recommend keeping the trigger in place because the UI isn't the *only* way opportunities can be edited of course and if this is a strict rule you need triggers in addition to the UI logic.

 

A third option is sort of a combination of the two where you could include a Visualforce page *just* for closing the opportunity which assures all the data is there as required.  Your users would need to be trained that in order to close the opportunity they would need to click a "Close Opportunity" button rather than edit and save. 

 

Hope that helps.

Manu ErwinManu Erwin

How about a link that a user can click to open the required new window?

 

This code:

trigger OpportunityBeforeUpdate on Opportunity (before update) {
for (Opportunity opp : trigger.new) {
Id oppId = opp.Id;
System.debug('## oppId: ' + oppId);
String strURL = '<a href="https://na4.salesforce.com/p/opp/ContactRoleEditUi/e?oppid=' + oppId + '" target="_blank" title="Opens in new window">here</a>';
System.debug('## strURL: ' + strURL);
opp.addError('No Primary Contact Exists. Please open the Opportunity Contact Roles Related List by clicking ' + strURL + ' and add a primary contact. Insure that all contacts related to this Opportunity are properly added in the Contact Roles with respective roles assigned.');
}
}

 produces an error on screen with an embedded href link that opens the Contact Roles for this Opportunity.

 

href in addError

Cannot guarantee how long the URL syntax will last but perhaps it will help.

Note: users will need to be trained to close the popup window after entering
.

 

regards,

Manu

Message Edited by manu on 01-25-2010 03:19 AM
Manu ErwinManu Erwin

Another option is override the Opportunity View with a VF page that immediately executes Apex.

 

 

<apex:page standardController="Opportunity"
extensions="OpptyRedirect_Vf_Ext"
action="{!redirect}" >
<apex:detail />
</apex:page>

 

The Apex checks to see if at least one child Contact Role exists and redirects to the Contact Role page if there are none.

If however there is at least one, then the redirect is to the normal Opportunity page with 'nooverride=1' appended to the end of the URL.

 

e.g.,

 

public class OpptyRedirect_Vf_Ext {
Opportunity opp;
Id oppId;

public OpptyRedirect_Vf_Ext (ApexPages.StandardController controller) {
System.Debug('## >>> OpptyRedirect_Vf_Ext <<< run by ' + UserInfo.getName());
System.Debug('## >>> Starting the constructor <<<');
// Get the current record's id from the page
oppId = controller.getId();
System.Debug('## DEBUG: oppId: ' + oppId);
System.Debug('## >>> Ending the constructor <<<');
}

public PageReference redirect() {
System.Debug('## >>> Starting redirect <<<');
// The no-action redirect is to the standard page so that standard functionality is available (e.g., inline editing)
PageReference pageRef = new PageReference('/' + oppId + '?nooverride=1');

// Proceed if the current user is the Opportunity owner
if ((UserInfo.getUserId() == opp.OwnerId)) {
// Obtain the number of child Contact Role records for the current opportunity
Integer intChildContactRoles = [select count()
from OpportunityContactRole
where OpportunityId = :oppId];
if (intChildContactRoles == 0) {
System.Debug('## There are zero child contact roles so need to navigate owner to add one');
pageRef = 'https://na4.salesforce.com/p/opp/ContactRoleEditUi/e?oppid=' + oppId + '&retURL=%2F' + oppId;
} else {
System.Debug('## There is already at least one child contact role - redirect to standard page');
}
} else {
System.Debug('## The current user is not the owner - redirect to standard page');
}
System.Debug('## pageRef: ' + pageRef);
System.Debug('## >>> Ending redirect <<<');
return pageRef;
}
}

 

 

 

Message Edited by manu on 01-25-2010 04:12 AM
aborchyaborchy

Thanks guys for the suggestions. I will play in my sandbox with them but may call on some more help as i am such a newby to code....any code :) that it is not funny.

 

Thanks again

aborchyaborchy

Ok i have been away for a while and now have some time to get back to this pet project.

 

As you can see i have a custom formula field called contact_required which is referenced before the trigger is triggered.

 

I am happy with how this works with the exception of the error message and that it forces a complete back out by the user before they can update and save the record.

 

I have checked the other trigger (second trigger) out and really like it however i either need it to reference my custom contact required field before it triggers or ideally i would like to incorporate it into the first trigger but instead of having the oridinal error message (highlighted in yellow) I would like it to have the "Click Here" message so that all a user has to do is click the click here and the new window opens for the contact roles.

 

I have had a play but just don't seem to be able to crack it. Any help appreciated :)

 

Thanks

 

Original trigger

 

 

//This is provided as a sample to require a contact on opportunities it is provided without warranty and support.

 

trigger opportunity_contact_required on Opportunity (before insert, before update) {

 

//map to keep track of the contact_required = 1

 

Map<String, Opportunity> oppy_contact = new Map<String, Opportunity>();

 

//Trigger.new is an array of opportunities

//and adds any that have Contact_Required = 1 to the oppy_contact Map

 

for (Integer i = 0; i < Trigger.new.size(); i++) {

 

    if  (Trigger.new[i].contact_required__c == 1)

            {

            oppy_contact.put(Trigger.new[i].id,

            Trigger.new[i]);

 

            //system.debug('This is the trigger.new.id - '+Trigger.new[i].id);

 

    }

}

 

//map to keep track of the opportunity contact roles

 

map<Id, OpportunityContactRole> oppycontactroles = new map<Id, OpportunityContactRole>();

 

 

//select OpportunityContactRoles for the opportunities with contact role required

 

for (OpportunityContactRole ocr : [select OpportunityId, IsPrimary

from OpportunityContactRole

where (OpportunityContactRole.IsPrimary = True and OpportunityContactRole.OpportunityId

in :oppy_contact.keySet())])

  {

 

 

//puts the contact roles in the map with the Opportunity ID as the key

   

        oppycontactroles.put(ocr.OpportunityId,ocr);

}

 

// Loop through the opportunities and check if they exists in the contact roles map or contact role isn't required

       

for (Opportunity oppy : system.trigger.new) {

 

    //system.debug('List oppy Id - '+oppy.id);

   

    if  (oppycontactroles.containsKey(oppy.id) || oppy.contact_required__c ==0)

        {

           

        }

   

    else

        {

            oppy.addError('No Partner Role Exists. Please go to the Opportunity Partners Related List and add a partner contact.  Insure that all contacts related to this Opportunity are properly added in the Partner Roles with respective roles assigned.');

               

        }

   

 

} //for

 

   

   

 }

 

 

Second trigger

 

trigger OpportunityBeforeUpdate on Opportunity (before update) {
    for (Opportunity opp : trigger.new) {
        Id oppId = opp.Id;
        System.debug('## oppId: ' + oppId);
        String strURL = '<a href="https://na4.salesforce.com/p/opp/ContactRoleEditUi/e?oppid=' + oppId + '" target="_blank" title="Opens in new window">here</a>';
        System.debug('## strURL: ' + strURL);
        opp.addError('No Primary Contact Exists. Please open the Opportunity Contact Roles Related List by clicking ' + strURL + ' and add a primary contact. Insure that all contacts related to this Opportunity are properly added in the Contact Roles with respective roles assigned.');
    }
}
 

 

 

aborchyaborchy

Any assistance welcome for the above issue :)