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
Michael Snow 5Michael Snow 5 

Link Contact Activities to Opportunities using Visualforce

Hi There,

So I am attempting to create a VF page that brings in all Activities onto an Opportunity from the Opportunities Primary Contact that is identified on the Opportunity. I attempted to create a custom controller class to complete this but then learned that you have to use the standard controller i norder to be able to embed the VF section onto SFDC. 

Also unfortunately now you can no longer switch the Controller from a standard controller to a custom controller anymore :( 

Any ideas on how to work around this? I shared the VF page and custom controller below

VF Page:
<apex:page controller="related_activities_from_contacts">
    <apex:form >
        <apex:pageBlock title="Activites with Contacts" id="activites_list">
            <!-- Events List -->
            <apex:pageBlockTable value="{! events }" var="evt">
                <apex:column value="{! evt.ActivityDate }"/>
                <apex:column value="{! evt.ActivityType }"/>
                <apex:column value="{! evt.Description }"/>
                <apex:column value="{! evt.OwnerId }"/>
                <apex:column value="{! evt.PrimaryWhoId }"/>
                <apex:column value="{! evt.Subject }"/>
                <apex:column value="{! evt.WhoId }"/>
            </apex:pageBlockTable>
        </apex:pageBlock>
    </apex:form>
</apex:page>

Custom Controller:
public class related_activities_from_contacts {
    // This would be the Id of the Opportunity
    Id OppID = (Id) ApexPages.currentPage().getParameters().get('id');
    // Select only one of those contacts for use in the Contact ID Below
    OpportunityContactRole[] contactRoleArray =
        [select ContactID
         from OpportunityContactRole 
         where OpportunityId =: OppID AND isPrimary = TRUE];
    
    // Id ContactID = contactRoleArray[0];
    public List<ActivityHistory> getEvents() {
        List<ActivityHistory> results = Database.query(
            'SELECT ActivityDate, ActivityType, Description, OwnerId, PrimaryWhoId, Subject, WhoId' +
            'FROM ActivityHistory ' +
            'Where WhoId =' + contactRoleArray[0]
        );
        return results;
    }  
}

 
Best Answer chosen by Michael Snow 5
cvuyyurucvuyyuru
public class related_activities_from_contacts {
    
		public Id oppId{get; set;}
		public list<OpportunityContactRole> contactRoleArray {get; set;}
        public Id primaryContactId{get; set;}
		
		public related_activities_from_contacts(ApexPages.StandardController sc){
			OppID = (Id) ApexPages.currentPage().getParameters().get('id');
			contactRoleArray = [select ContactID
								 from OpportunityContactRole 
								 where OpportunityId =: OppID AND isPrimary = TRUE];
			if(!contactRoleArray.isEmpty())
				primaryContactId = contactRoleArray[0].Id;
			else
				ApexPages.addMessages(new ApexPages.Message(ApexPage.Severity.Fatal, 'No Primary Contact found.'));
		}
	
    	public List<ActivityHistory> getEvents() {
			List<ActivityHistory> results = Database.query(
				'SELECT ActivityDate, ActivityType, Description, OwnerId, PrimaryWhoId, Subject, WhoId' +
				'FROM ActivityHistory ' +
				'Where WhoId =' + primaryContactId
			);
			return results;
		}  
	}
	
	<apex:page StandardController="opportunity" extensions="related_activities_from_contacts" showHeader="false">
		<apex:form >
			<apex:pageMessages/>
			<apex:pageBlock title="Activites with Contacts" id="activites_list">
				<!-- Events List -->
				<apex:pageBlockTable value="{! events }" var="evt">
					<apex:column value="{! evt.ActivityDate }"/>
					<apex:column value="{! evt.ActivityType }"/>
					<apex:column value="{! evt.Description }"/>
					<apex:column value="{! evt.OwnerId }"/>
					<apex:column value="{! evt.PrimaryWhoId }"/>
					<apex:column value="{! evt.Subject }"/>
					<apex:column value="{! evt.WhoId }"/>
				</apex:pageBlockTable>
			</apex:pageBlock>
		</apex:form>
	</apex:page>

Try this.

All Answers

cvuyyurucvuyyuru
public class related_activities_from_contacts {
    
		public Id oppId{get; set;}
		public list<OpportunityContactRole> contactRoleArray {get; set;}
        public Id primaryContactId{get; set;}
		
		public related_activities_from_contacts(ApexPages.StandardController sc){
			OppID = (Id) ApexPages.currentPage().getParameters().get('id');
			contactRoleArray = [select ContactID
								 from OpportunityContactRole 
								 where OpportunityId =: OppID AND isPrimary = TRUE];
			if(!contactRoleArray.isEmpty())
				primaryContactId = contactRoleArray[0].Id;
			else
				ApexPages.addMessages(new ApexPages.Message(ApexPage.Severity.Fatal, 'No Primary Contact found.'));
		}
	
    	public List<ActivityHistory> getEvents() {
			List<ActivityHistory> results = Database.query(
				'SELECT ActivityDate, ActivityType, Description, OwnerId, PrimaryWhoId, Subject, WhoId' +
				'FROM ActivityHistory ' +
				'Where WhoId =' + primaryContactId
			);
			return results;
		}  
	}
	
	<apex:page StandardController="opportunity" extensions="related_activities_from_contacts" showHeader="false">
		<apex:form >
			<apex:pageMessages/>
			<apex:pageBlock title="Activites with Contacts" id="activites_list">
				<!-- Events List -->
				<apex:pageBlockTable value="{! events }" var="evt">
					<apex:column value="{! evt.ActivityDate }"/>
					<apex:column value="{! evt.ActivityType }"/>
					<apex:column value="{! evt.Description }"/>
					<apex:column value="{! evt.OwnerId }"/>
					<apex:column value="{! evt.PrimaryWhoId }"/>
					<apex:column value="{! evt.Subject }"/>
					<apex:column value="{! evt.WhoId }"/>
				</apex:pageBlockTable>
			</apex:pageBlock>
		</apex:form>
	</apex:page>

Try this.
This was selected as the best answer
Michael Snow 5Michael Snow 5
Wow - thanks for the super quick and helpful response on this Charan! 

The only issue now that I'm running into on the Opportunity page itself where I am running into the following error: 
"Content cannot be displayed: unexpected token: Where"

Do you know what is causing this error? (Also looking currently on my end) And thanks again for your quick and helpful support on this! 

For reference for others that use this, there is just a slight error around the if/else logic with missing {} as well with the Apex pages add a message. I was able to replace that with a code example from this SFDC documentation (https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/apex_pages_message.htm) to get rid of the error 
cvuyyurucvuyyuru
public class related_activities_from_contacts {
    
		public Id oppId{get; set;}
		public list<OpportunityContactRole> contactRoleArray {get; set;}
        public Id primaryContactId{get; set;}
		
		public related_activities_from_contacts(ApexPages.StandardController sc){
			OppID = (Id) ApexPages.currentPage().getParameters().get('id');
			contactRoleArray = [select ContactID
								 from OpportunityContactRole 
								 where OpportunityId =: OppID AND isPrimary = TRUE];
			if(!contactRoleArray.isEmpty())
				primaryContactId = contactRoleArray[0].Id;
			else
				ApexPages.addMessages(new ApexPages.Message(ApexPage.Severity.Fatal, 'No Primary Contact found.'));
		}
	
    	public List<ActivityHistory> getEvents() {
			List<ActivityHistory> results = [Select ActivityDate, ActivityType, Description, OwnerId, PrimaryWhoId, Subject, WhoId from ActivityHistory where whoId =: primaryContactId];
			return results;
		}  
	}

Check this controller now.
Michael Snow 5Michael Snow 5
Charan Thanks again for the quick response! It looks like the real error from this is coming from the fact that we can't query activity history directly but can access it from a parent object. As pointed out in these discussions as well:
  • https://developer.salesforce.com/forums/?id=906F000000099ZNIAY
  • https://stackoverflow.com/questions/10939796/soql-issue-when-querying-activityhistory-as-a-subquery
So I am attempting to write a subquery here but then get the following error on the APEX Page: "Illegal assignment from List to ist"

Here are the adjustments I made: 
public List<ActivityHistory> getEvents() {
        List<ActivityHistory> results = [Select Id, 
                                         (Select ActivityDate, ActivityType, Description, OwnerId, PrimaryWhoId, Subject, WhoId 
                                         FROM ActivityHistories) 
                                         FROM Contact
                                         WHERE Id =: primaryContactId];
        return results;
    }

 
cvuyyurucvuyyuru
The query should be assigned to list not to list
Michael Snow 5Michael Snow 5
Thanks Charan, can you explain how this should be assigned to a list and also not assigned to a list? 
Michael Snow 5Michael Snow 5
So was able to figure out that this has to do with this being a sub-query and that I have to access the sub list. Challenge now though is that when looking at an Opportuity record that has a Primary contact that has an activity history then I receive the following error: "Content cannot be displayed: List index out of bounds: 0"

Is there something wrong earlier in the public class maybe? 

Here are the adjustments that I was able to make: 
public List<ActivityHistory> getEvents() {
        List<Contact> results1 = [Select Id, 
                                         (Select ActivityDate, ActivityType, Description, OwnerId, PrimaryWhoId, Subject, WhoId 
                                         FROM ActivityHistories) 
                                         FROM Contact
                                         WHERE Id =: primaryContactId];

        List<ActivityHistory> results = results1[0].ActivityHistories;
        return results;
    }

 
Michael Snow 5Michael Snow 5
So to close the loop here for anyone else who needs this the other adjustment that had to happen is selecting ContactID vs ID when setting up the primary Contact: Posted below - couldn't have reached this point without Charan though! 
 
public related_activities_from_contacts(ApexPages.StandardController sc){
        OppID = (Id) ApexPages.currentPage().getParameters().get('id');
        contactRoleArray = [select ContactId
                            from OpportunityContactRole 
                            where OpportunityId =: OppID AND isPrimary = TRUE];
        if(!contactRoleArray.isEmpty()){
            primaryContactId = contactRoleArray[0].contactid;
        }
        else {
            ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.FATAL, 'No Primary Contact found.');
        }
    }