Pages

Wednesday, April 3, 2013

SugarCRM Customization: User Specific Dropdown Lists

Here is a scenario that has come up a couple of times in the last few weeks: 

While working with Opportunities, we wish to limit the choices available within the Sales Stage dropdown list, but based on the user that is currently accessing the record.

If you are wondering as to the reasons for such a request, consider a scenario where you wish to ensure that opportunities are not accidentally (or not so accidentally) moved to another sales stage by folks that do not have the authority to do so. Eliminating choices from the dropdown list would be the easiest way to ensure certain values are not selected. 

For the purposes of our example we will assume that we wish to eliminate Value Proposition as a choice from the Sales Stage dropdown list, but only for the user chris.

To do this, we first need a copy of the language file containing the dropdown list values. Using your text editor of choice, open the file en_us.lang.php, found in the /custom/include/language folder. If the file is not there, access Admin > Dropdown Editor, then select sales_stage_dom and click Save.

Once the file is open, you should see something similar to the following:

<?php
$GLOBALS['app_list_strings']['sales_stage_dom']=array (
  'Prospecting' => 'Prospecting',
  'Qualification' => 'Qualification',
  'Needs Analysis' => 'Needs Analysis',
  'Value Proposition' => 'Value Proposition',
  'Id. Decision Makers' => 'Id. Decision Makers',
  'Perception Analysis' => 'Perception Analysis',
  'Proposal/Price Quote' => 'Proposal/Price Quote',
  'Negotiation/Review' => 'Negotiation/Review',
  'Closed Won' => 'Closed Won',
  'Closed Lost' => 'Closed Lost',
); 

The bit of code above is the definition of the values displayed in the Sales Stage dropdown list. Next, we need to add our code that determines the current user and if it happens to be chris, instruct Sugar to remove the Value Proposition choice.

This is the code we will use, immediately following the code that defines the list:

//Retrieve user object for currently logged in user

global $current_user;

//Check if currently logged in user is indeed "chris"
if ($current_user->user_name == 'chris')
{
       //Remove choice for Value Proposition
unset($GLOBALS['app_list_strings']['sales_stage_dom']['Value Proposition']);
}

Save the file and you are ready to go! 

Update: Cédric Mourizard (@cedricmourizard), SugarCRM Engineer at Synolia (@synolia), was kind enough to share an observation about this topic via Twitter. In short, take care when limiting choices, as it could cause inadvertent data loss. For example, if a user that does not have access to the Value Proposition option edits an Opportunity whose sales stage is set to Value Proposition, saving that record would force the user to choose another value for the Sales Stage. This may or may not present a problem for your needs, but it is something to bear in mind. 

26 comments:

  1. Hi Angel,
    it' possible to do the same thing using role (or group) instead a user?

    Thanks for sharing

    ReplyDelete
    Replies
    1. Hi Danilo,

      Yes, you should be able to do that by injecting some code that takes the currently logged in user's ID ($current_user->id) and then checking which roles that user has been assigned. You should be able to check that via the ACLRole class in ACLRole.php

      Delete
    2. Hi Angle.

      Thanks for your help.

      Can you explaint in a example how we can do it. by role.

      Thaks.

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

    ReplyDelete
  3. thanks angel

    You can hide other types of sugarcrm fields, such as date or text area. user defined

    ReplyDelete
    Replies
    1. I am sorry, I don't understand the question/comment. Please elaborate.

      Delete
    2. I have a case module and in this module I have technicians level 1 and 2. My intention is when you create a case the level 1 technician, be able to see some fields of the module and Level 2 technicians can view all fields of the module. I like to hide the fields regarding date and text area.

      Delete
    3. There was a very similar example that was discussed in the Sugar Forums (http://forums.sugarcrm.com) not too long ago. I don't have the URL handy so you will have to search for it, but the basic idea is to have 2 different metadata files for the corresponding view (e.g. editviewdefs.php) and use a custom view to load the appropriate one based on the currently logged in user.

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

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
  5. Hi Angel,
    Searching the forum I found this information
    http://forums.sugarcrm.com/f6/hiding-panels-users-role-39599/

    but I'm new to programming languages ​​and do not understand very well the explanations of the post. You could make a post explaining how to do this, please please please :)

    ReplyDelete
  6. Hola Angel, al agregar las líneas correspondientes me da el siguiente error:

    Notice: Trying to get property of non-object in C:\prg\www\phoenix\custom\include\language\es_ES.lang.php

    en la línea de correspondiente a if ($current_user->user_name == 'aaaaa'). Alguna idea que puede estar pasando?

    ReplyDelete
    Replies
    1. Seguro se le olvido agregarle esta linea antes de su IF:

      global $current_user;

      Delete
  7. Gracias por su respuesta Angel, pero tengo esa línea. Es más, si hago un print_r del objeto $current_user lo veo perfectamente, con sus valores y sus atributos. Por eso me resulta tan extraño el error.

    ReplyDelete
  8. Say I have two dropdown values (in the same dropdown list), but I have two user departments: A and B. If A is true, I want one of the values not to show up, and if B is true then I want to show the value that A could not see, and not show the other value.

    This is what I have:

    global $current_user;

    if ($current_user->department == 'A')
    {
    unset($GLOBALS['app_list_strings']['depends_list']['B']);
    }
    if ($current_user->department == 'B')
    {
    unset($GLOBALS['app_list_strings']['depends_list']['A']);
    }

    It is not functioning as intended.

    ReplyDelete
    Replies
    1. One interesting thing I noticed with this:
      A user will be signed in and creating a case, and the dropdown may have the correct value. However, during the course of the case creation, another user signs in to create a case. If the user was from a different group, it causes the first users value to change to the incorrect value.

      Delete
    2. Are you saying that while user A is creating a Case, the drop down values change for that record if user B logs into the system, assuming user B is supposed to receive a different set of values?

      Delete
    3. Exactly the problem. User A will see option A, but as soon as User B starts entering a case, User A's option changes to B. Strange occurrence, to be sure. It is ok though, with the help of another user, I created a function to handle the dropdown value selection, which works quite nicely.

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

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

    ReplyDelete
  11. I'm trying to populate a dropdown dynamically depending on the last saved value of the dropdown.
    For that i'm using a file in custom\Extension\application\Ext\Utils with a getVal function defined in the vardef file of the field.
    In the function getVal.php inside Utils i determine the last saved value of the dropdown and populate it according to it.
    The problem is i want to know the last saved value of that specific record so i need the id of the record. I know how to retrieve the id of the specific record using logic hooks but in this case is a different function. Is that possible without using logic hooks?
    Thank you so much for your blog... it really helps a lot.

    Joana Lopes da Fonseca

    ReplyDelete
  12. Im a newbee, is it possible to do the following
    if (sales_stage == 'Qualification')
    {
    unset($GLOBALS['app_list_strings']['sales_stage_dom']['Prospecting']);
    }

    I am trying to avoid user from reverting back to a previous sales stage once they move on to the next stage

    ReplyDelete
    Replies
    1. You should be able to do that, although I don't recall offhand how to obtain the value of "sales_stage" within this context.

      Usually it is something similar to $bean->sales_stage or $focus->sales_stage.

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

    ReplyDelete
  14. i am currently using your code. but i get this after: Notice: Trying to get property of non-object in C:\sugar\htdocs\17\custom\include\language\en_us.lang.php on line 208. Do you have any idea where the problem is? my version is CE 6.5.17.Thanks

    ReplyDelete
  15. Hola Angel,
    Disculpa las molestias En SugarCRM 6.5 como se haria para obtener una lista desplegable obteniendo esta de una base de datos? muchas Gracias

    ReplyDelete

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