Pages

Monday, August 4, 2014

SugarCRM Customization: Dynamic RecordView

Recently the need to explore the topic of applying user specific fields to a Sugar 7 view made its way to my desk. With past versions of Sugar, this type of customization could be implemented by creating the user specific metadata definitions, a custom view with the logic that drove the selection of the metadata and some logic that flushed out the cache so as to force the new metadata to be displayed upon the view being rendered. Given my history with the topic, I was curious to see how different the process would be in Sugar 7.

For those of you that are new to Sugar 7, it is worth noting that the metadata for a given view is stored in a JSON object accessible through the namespace this.meta. Said object can be easily manipulated through the controller relating to that view, thus we can leverage this.meta to adjust the metadata for a given view.

In our example we will assume we have two different users that should be viewing different fields on the RecordView. User 1 is the default admin user, identified by the ID value of "1" within the database, and User 2 is the user Jim, identified by the ID value of "seed_jim_id" within the database. Our goal will be to modify the default RecordView on the Contacts module such that User 1 automatically receives the default set of fields upon accessing the RecordView, but User 2 receives a modified version of that view, i.e. a different set of fields, with some overlap.

How do we go about applying this customization?


To accomplish this task we need to do the following:

1. Create the modified version of the metadata applicable to User 2
2. Create a custom view based off the modified metadata
3. Create a custom controller for the default RecordView to introduce our logic

Completing the first step should be pretty straightforward, even if your experience with Sugar 7 development is limited. For this example I merely took the standard record.php metadata found in ./modules/Contacts/clients/base/views/record/, copied it to ./custom/modules/Contacts/clients/base/views/group1/ and applied the following modifications:

1. Changed the file name from record.php to group1.php
2. Changed $viewdefs['Contacts']['base']['view']['record'] to $viewdefs['Contacts']['base']['view']['group1']

Once the above changes had been applied, I proceeded to manually apply my desired metadata changes to group1.php. That included the removal and addition of fields, as well as modifications to their positioning.

Changing the file name to group1.php, along with the folder name and the change to the array key from record to group1 effectively addresses our second requirement. Thus, we have already defined our new view named group1 by following the steps illustrated above.

Lastly, we need to create a custom controller for the RecordView and apply our change. To do this, place the following file into ./custom/modules/Contacts/clients/base/views/record/



...and finally, apply the change by purging the contents of the ./cache folder and reloading Sugar in your browser.

Side note: Given that this.meta represents a JSON object of the metadata for the view, it is possible to simplify this further to only affect the specific elements of the JSON object that need manipulation. For this scenario, the use of the full metadata file is used only for the purposes of simplifying the example.

13 comments:

  1. Is it possible to define two moduleIconList entries and have a specific 2-letter (or more) code for each of the views as a reminder of which view you are in?
    Thanks. FrancescaS

    ReplyDelete
    Replies
    1. I am not sure, but it might be worthwhile considering the use of another view similar to the extra-info view.

      If you take a look at the generic record.php in ./clients/base/views/record/, you will find it references a layout called extra-info, but said layout is only really used in the Leads module (./modules/Leads/clients/base/layouts/extra-info). You could use a similar technique and load two different layouts with a very basic view that includes some distinguishing attribute.

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
  3. I find that while this is working well in record view, in create-actions the form renders before the initialize is complete and therefore before the script has a chance to set the metadata for the view.
    ( I have to fetch the current user bean and check a custom field to see what view they should get). Any suggestions on how to make the create form use the appropriate record view for different users?

    Thanks,
    FrancescaS

    ReplyDelete
    Replies
    1. One thing that comes to mind as a possibility is to use custom create-actions.php metadata. I haven't tested it, but perhaps the timing issue sorts itself out if you force the create-actions view to use a create-actions.php file, and then adjust accordingly, versus the default behavior where it inherits the metadata from the record view.

      Delete
  4. Avoided fetching the user bean by customizing the CurrentUserApi.
    This makes it so the condition can be immediately evaluated and avoids the delay issue in completing the initialize. Thanks.

    ReplyDelete
  5. Silly question time ...
    Why not use the standard method of user Roles via Admin interface instead of code?

    ReplyDelete
    Replies
    1. Because Role based Views only became available with 7.6.1 Enterprise.
      I started using this approach with 7.5.0 Professional.

      Delete
    2. I wasn't referring to the new 'Role based Views'
      just the regular 'Role Management' top right-hand side of Admin screen, click on a Role, then adjust access to any module and field from ACL the grid

      Delete
    3. The example in the above post extends the functionality in significant ways. Through a role you can control which fields a user can see, and via roles based views you can also control the placement of fields.

      However, those changes are always based on the current user. In contrast, this approach allows you to also use the actual data of the record being viewed to determine either the placement and/or visibility of a field. You can also control buttons based on similar criteria, which you also cannot do via standard roles or role based views.

      Delete
  6. This comment has been removed by the author.

    ReplyDelete
  7. This comment has been removed by the author.

    ReplyDelete
  8. Hi Angel,
    Thanks for your blog post. I have a specific problem, maybe you can give me some clues.
    I want to generate a dynamic view from a field coming from another module, or to make it simple, let say the field is in the same module.
    Basically, I have a Mandat object, with a field type containing the number of broker I can set (static list).
    Depending on this value, I need to duplicate three dropdowns (Account - Contact - Contact) and save them in three different records.
    Do you have an idea ?
    Thanks a lot and best regards,
    Enes

    ReplyDelete

Your comments, feedback and suggestions are welcome, but please refrain from using offensive language and/or berating others. Thank you in advance.