Many-to-many relationships in SugarCRM via REST and perl

Subject

In my previous article “Create appointments (meetings) in SugarCRM via REST and perl” I described how I created appointments using Web services. This worked, but with one major glitch – solution provided didn’t put appointment status in accepted for the appointment owner and I was determined to solve this. So, read on.

Challenge

An appointment created simple way is linked to two persons – appointment owner (User) and appointment participant (Contact). Just creating links to these two won’t set appointment status to accepted and I would say this is not logical for the appointment owner.  If we for example consider My Meetings dashlet, we realize that for these appointments there is still an option to accept or decline as on the screenshot below:
ScreenShot050_1

The reason for this is the following. The relation between appointment (Meeting) and appointment owner (User) is a many-to-many relationship, which is stored in the table meetings_users. But this table also holds the information about appointment accept status in the field accept_status.  By the way, same is valid for appointment-contact relationship, it will be meetings_contacts table, but I will focus on appointment owner only.

Fact is that my first solution doesn’t update this  accept_status field and searching for a solution has turned out to be challenging.

Platform/Tools

Nothing new here:

  • SugarCRM CE (Community Edition) version 6.5.16
  • ActiveState perl (v5.14.2) on Windows 7
  • And also one nice perl module Net::SugarCRM found on CPAN (version 2.17738).

Solution

The problem I’m trying to solve could be described as follows. Many-to-many  relationship between Meetings and Users has some additional attributes and we need to update these attributes. It turned out that the support for this is not completely implemented in SugarCRM Community Edition out of the box. Not sure about other editions though.

Modifying Meetings vardefs

Here is what I learned from the source code. Out of the box version of the vardefs.php file for Meetings module contains the following declaration for users field:
...
'users' =>
  array (
  	'name' => 'users',
    'type' => 'link',
    'relationship' => 'meetings_users',
    'source'=>'non-db',
		'vname'=>'LBL_USERS',
  ),
...
In SugarCRM terms the above declares an attribute of the Meeting bean, which is an array of links to User beans. This array is backed by meetings_users relationship. But this fragment doesn’t declare any additional attributes on this link (relationship) and this is why modifying these attributes is not working.
So the mission is to adjust the above declaration in an update-safe way. Fortunately this works.
First we need to create a new file in SUGAR_ROOT/custom/Extension/modules/Meetings/Ext/Vardefs/. Please note that this location is very important. File name seems to be less important as explained in some tutorials on the Web. Let’s name it vardefs.ext.php:
...
$dictionary['Meeting']['fields']['users']['rel_fields'] = array(
	'accept_status' => array(
		'type' => 'enum',
		'options' => 'dom_meeting_accept_status',
	),
);
...
Next step is to run Quick Repair and Rebuild from SugarCRM administration page. If there are no syntax errors in the above file it will report Database tables are synced with vardefs.
With the above code we extended existing declaration for Meetings bean, adding one attribute to it, named accept_status. This will make existing code in SUGAR_ROOT/service/core/SoapHelperWebService.php to update relationship attribute.
Final definition would probably look like this, this is what SugarCRM is doing during run-time:
...
'users' =>
    array (
        'name' => 'users',
        'type' => 'link',
        'relationship' => 'meetings_users',
        'source'=>'non-db',
        'vname'=>'LBL_USERS',
        'rel_fields' => array(
	        'accept_status' => array(
	                'type' => 'enum',
	                'options' => 'dom_meeting_accept_status',
	         ),
         ),
    ),
...
Just to emphasize, the above code snippet doesn’t exist in any file in the system, this is just my guess regarding how SugarCRM is merging its standard definition for Meetings bean with my custom extension.
Please also note that in the above code I use enum type for the accept_status attribute and the values are defined in the drop-down list dom_meeting_accept_status, which you can edit in SugarCRM administration interface. I observed also that it is possible to assign values, different from these in this drop-down list, but was too lazy to further investigate this.

Re-writing client side code

The rest was easy. I again used my perl module Net::SugarCRM::Links (see “Create appointments (meetings) in SugarCRM via REST and perl“) and my code looked like this:

...
my $user_link_entry = {
	accept_status => {
			'name' => 'accept_status',
			'value' => 'accept'
	}
};

$out = $s->create_module_links('Meetings',$meeting_id,'users',[$user_id],$user_link_entry);
...
Note that the accept_status attribute has to be constructed in a bit complex way, as a name-value pair. I don’t know if there is any explanation for this, in my case it worked and I was satisfied.

Discussion

And below is the result:
ScreenShot050_2

Now my appointments are created via Web service and they are already accepted by myself. I implemented this only for accept_status attribute, but one could also do it for required attribute and also for appointment participants (Contacts).

I have also checked other SugarCRM beans and just very few of them are making use of this vardef declaration for rel_fields. So, to modify any other many-to-many relationships with attributes vardef customisation will be needed as well.

Caveats

I must admit that I haven’t consulted any SugarCRM developer nor have I posted this to SugarCRM forums for discussion and probably the solution proposed here is not the best one. But this is the solution, which works for me and solves my particular case. So any suggestions to do it differently are welcome.
As to my plans for the future – I’ll continue blogging about my experience with SugarCRM customization, so stay tuned!

Comments

comments

Leave a Reply