Adding records to History Subpanel?

So I’ve got what I thought might be a simple project. I have NOTES that are added to PROJECT TASKS. They show up in the history of the Project Tasks subpanel. Great! What I also want to do is add this to the history subpanel for the related Opportunity to the Project. I’ve got that figured out how to get it and how to add the relationship via an after_relationship_add hook to the Opportunity. However, it REPLACES the relationship to the Project Task. Not what I want. I want to have both! So I created another relationship field in the note (opportunities_notes_1) which I can now populate with my hook. So now the note is related to two records. Great! But it shows in an extra subpanel in the Opportunities module. I want it to show in the History Subpanel.

Is there a way to add notes based on this new relationship to the History subpanel in Opportunities, or am I going about this all wrong?

I am not sure, but I would start by trying changes here

the basic idea is to incorporate the new relationship into the aggregating “history” subpanel.

In other modules I see a file called ForHistory.php which I guess is what that 'subpanel_name' => 'ForHistory' is referencing. But I don’t find it for Opportunities, so you’ll have to look for some default ForHistory metadata somewhere…

Actually, you could do it the same way e-mails are added to the accounts history subpanel and write a function that fetches the records you want to display. In that case, you wouldn’t even need a custom relationship.

I wish I documented how I did this! I have the occassion to do it again, and can’t remember how I did it or which project I did it for! Stay tuned, I’ve learned my lesson, when I figure it out again I’ll post the solution.

So I’ve followed this: Add custom subpanel in Accounts module

I can write a Task subpanel and I can write a cutom function to get tasks that are both related to the Account or the Opportunity.

So now move on to get more complicated, to also add calls and meetings, I’m trying to follow the existing structure similare to how emails are added to Activities. I just can’t get it to work. Has anyone ever tried extending the activities and the history to include other related records?

Here’s what I have so far (again, if I follow the example I can make it work, just not as a collection list):

$layout_defs['Accounts']['subpanel_setup']['custom_activities'] = array(
    'order' => 55,
    'type' => 'collection',
    'subpanel_name' => 'activities', // Using a generic 'activities' layout
    'module' => 'Activities',
    'header_definition_from_subpanel' => 'meetings',
    'collection_list' => array(
        'tasks' => array(
            'module' => 'Tasks',
            'subpanel_name' => 'ForActivities',
            'get_subpanel_data' => 'function:get_custom_related_tasks',
            'function_parameters' => array(
                'import_function_file' => 'custom/modules/Accounts/customActivitiesFunctions.php',// Path to your PHP file
				'account_id' => $this->_focus->id, // Passing current account ID dynamically
				'return_as_array' => 'true'

and the function

function get_custom_related_tasks($params) {
     $accountId = $params['account_id']; 
    $GLOBALS['log']->fatal("Fetching tasks related to Account ID and its Opportunities: {$accountId}");

    $return_array = array();
    $return_array['select'] = "SELECT tasks.*";
    $return_array['from'] = "FROM tasks";
    $return_array['where'] = "WHERE tasks.deleted = 0 AND (tasks.parent_id = '{$accountId}' AND tasks.parent_type = 'Accounts' OR tasks.parent_id IN (
        FROM opportunities 
        JOIN accounts_opportunities ON = accounts_opportunities.opportunity_id 
        WHERE accounts_opportunities.account_id = '{$accountId}' AND opportunities.deleted = 0 AND accounts_opportunities.deleted = 0
        ) AND tasks.parent_type = 'Opportunities')";
    $GLOBALS['log']->fatal('Constructed SQL for Task Fetch: ' . print_r($return_array, true));
    return $return_array;
1 Like

Bump on this one. I don’t think I was clear I was asking for some guidance on the above. Basically, I can create a custom subpanel for “tasks” lets say, and then get all tasks related to account, opportunity, or quotes. That works no problem.

HOWEVER, what I really want to do is kind of copy the activities subpanel and get the same, but for tasks, calls and meetings. So I tried to follow the “collection_list” structure of the stock activities subpanel but it just doesn’t work , the whole account page just generates a popup error “There was an error processing your request, please try again at a later time.”

Even with the exact same function that works by itself. I think there is something I’m fundamentally not understanding about the “collection_list” array. Has anyone ever done a custom subpanel with more than one module included in the list and can give me some pointers?

update I can get it to work if I disable AJAX for the module. How can I troubleshoot why this is causing an AJAX issue? There’s nothing specific in the error logs, and my queries I’m outputting to log all look good and are running.

update #2 It seems to work now even when I toggle AJAX back on for Accounts. That’s so weird. Something must have been cached and is now cleared by turning AJAX off and then on again. Happy I think I got it!!!

1 Like

Are you running in developer mode? Developer mode disables the caching, so your new custom subpanel should have worked right away, without having to disable and re-enable the AJAX for the module.

Thanks @chris001 I was in developer mode, but still had this issue. Argh! I spent so many hours trying different things and all I had to do was turn Ajax on and off and my origianl code worked fine! At least I know for next time.

Whoo hoo! Got it working for all Calls/Meetings/Tasks related to the Account/Contacts/Opps/Quotes for this account. Now on to the history subpanel.


Ok one last problem … I think.

I had to modify the layout too, to add the parent type and also to remove the “Remove” button. Since the record won’t necessarily be related to the Account directly, the “Remove” button won’t work. Which is fine. However, I can’t get the column sort to work right. When I sort any column, “no results found” displays. However, when I refresh the page, the list is now properly sorted.

Where can I look for the source of the sorting to troubleshoot this issue?

update Ok got it, it’s a bug, thankfully there is a fix. I have it totally working now.

1 Like

Ok got the history working (Almost!!!) I can’t get the filter to work. Which would be nice on History. The problem is I have two subanels using the history module and when I click the button on my All History subpanel it opens up the filter on the stock history subpanel. Any ideas on how I can redirect this, the button action? Not sure.

$layout_defs['Accounts']['subpanel_setup']['custom_history'] = array(
    'order' => 60,
    'sort_order' => 'desc',
    'sort_by' => 'date_entered', // Typically, history is sorted by the date entered or the date of the activity
    'type' => 'collection',
    'subpanel_name' => 'AllHistory', // Use a generic layout or create a specific one for history
    'module' => 'History',
	'searchdefs' => array(
			'name' => array (
            	'name' => 'status',
				'default' => true,
				'width' => '10%',
	'top_buttons' => array(
                array('widget_class' => 'SubPanelTopSummaryButton'),
                array('widget_class' => 'SubPanelTopFilterButton'),

I am so close on this one I have the search bar now appearing for my custom history subpanel. This is super useful as the Account manager can see all the history of the Account accross ACCOUNT, CONTACTS, OPPORTUNITIES, QUOTES and see all related calls, tasks, meetings etc. in one place.

And it more or less works and filters the subpanel EXCEPT… When I filter by CALLS. I get…

Not sure where to look for this one? Anyone can point me in the right direction? I’m so close!

It’s true, that class doesn’t exist. Did you mean SugarWidgetSubPanelDetailViewLink ?

That’s the weird thing! I have referenced this nowhere in my custom code and it doesn’t exist, I searched on github. Something must be constructing it in error, and I think as you do, that it really should be SugarWidgetSubpanelDetailViewLink

I’m considering a Cache flush next.

These class and filenames are dynamically generated, see


and, importantly, the autoloader, which is quite easy to overlook, but is crucial


Remember, the autoloader runs behind the scenes whenever a new occurs.

Thanks @pgr I was looking at the LayoutManager last night. I’m really hoping its a cache issue otherwise there’s hours of debugging in my future!

Ok so I kind of cheated. I made a copy of SugarWidgetSubpanelDetailViewLink.php and re-named it and the function SugarWidgetSubpanelDetailView.php IT WORKS! This isn’t the root of the problem, somewhere the class is being constructed for calls incorrectly, but I got it working! Next step I have to solve the date search isn’t working.


Could you please add this on your YouTube channel too? :crossed_fingers: :partying_face: