multi-dimensional visibility gird

Is there a way to set up a visibility grid based on a combination two or three other dropdown values?

Example:

dropdown 1 is a dropdown with of values A, B,C

dropdown 2 is a dropdown with of values 1, 2, 3, <blank>


Dropdown 3 should display a subset of options  dependent on dropdown 1 AND dropdown 2

dropdown1=A & dropdown2=1 -> dropdown 3 values i, ii

dropdown1=A & dropdown2=2 -> dropdown 3 values i, ii, iii

dropdown1=B & dropdown2=1 -> dropdown 3 values i

dropdown1=B & dropdown2= <blank> -> dropdown 3 values i, iii, iv

and so on...

thanks,
FrancescaS

Parents
  • I had to do something similar in the past and ended up using a custom SetOptions dependency to accomplish it.

  • Brett Zufelt,

    I am having some trouble....

    I keep getting an error: FATAL[2019-1-23 15:17:57]: Uncaught TypeError: expression.match is not a function

    I defined the Expression following some of the expressions that are in the core sugar (like ForecastSalesStageExpression which restricts the dropdown based on parameters passed) 

    I see the expression at the bottom of the list when I run the "Rebuild Sugar Logic Functions"

    (restrictSalesGoalsDropdown) RestrictSalesGoalsDropdownExpression

    custom/include/Expressions/Expression/Enum/RestrictSalesGoalsDropdownExpression.php

    <?php
    require_once 'include/Expressions/Expression/Enum/EnumExpression.php';
    class RestrictSalesGoalsDropdownExpression extends EnumExpression
    {
        /**
         * Returns the entire enumeration bare.
         */

        public function evaluate()
        {
            $GLOBALS['log']->fatal('RestrictSalesGoalsDropdownExpression');
            $params = $this->getParameters();
            $keysToRemove = array();
              $array = array_keys($GLOBALS['app_list_strings']['opp_transaction_type_dd']);
              $goal_type = $params[0]->evaluate();
              $sales_group = $params[1]->evaluate();
              $sales_sub_group = $params[2]->evaluate();
              if($goal_type == 'Quarterly Sales Target'){
                $keysToRemove = array("B2B","B2C","B2E") ;
              }elseif($goal_type == 'Quarterly Forecasting Sales Quota'){
                $keysToRemove = array("B2E") ;
              }elseif($goal_type == 'Annual Sales Quota'){
                switch ($sales_group){
                  case "Academic":
                    switch ($sales_sub_group){
                      case "Key Accounts":
                        $keysToRemove = array("B2C");
                        break;
                      case "Oubound":
                        $keysToRemove = array("B2C");
                        break;
                      case "Inside Sales":
                        $keysToRemove = array("B2B", "B2C");
                        break;
                    }
                  break;
                  case "Commercial":
                    switch ($sales_sub_group){
                      case "AE":
                        $keysToRemove = array("B2C", "B2E");
                        break;
                      case "Enterprise":
                        $keysToRemove = array("B2B", "B2C");
                        break;
                      case "Inside Sales":
                        $keysToRemove = array("B2B", "B2E");
                        break;
                      case "Sales Group":
                        $keysToRemove = array("B2B", "B2C", "B2E");
                        break;
                    }
                  break;
                  case "IBD":
                    switch ($sales_sub_group){
                      case "AE":
                        $keysToRemove = array();
                        break;
                      case "Sales Group":
                        $keysToRemove = array("B2B", "B2C", "B2E");
                        break;
                    }
                  break;
                }
              }
            $list = rtrim(implode(',', array_diff($array, $keysToRemove)), ',');
            return $list;
        }



        /**
         * Returns the JS Equivalent of the evaluate function.
         */

        public static function getJSEvaluate()
        {
            return <<<JS
            var array = [],
                keysToRemove = [],
                params = this.getParameters(),
                array = _.keys(App.lang.getAppListStrings('opp_transaction_type_dd')),
                goal_type = params[0].evaluate(),
                sales_group = params[1].evaluate(),
                sales_sub_group = params[2].evaluate();
            if(goal_type == 'Quarterly Sales Target'){
              keysToRemove = ["B2B","B2C","B2E"] ;
            }else if(goal_type == 'Quarterly Forecasting Sales Quota'){
              keysToRemove = ["B2E"] ;
            }else if(goal_type == 'Annual Sales Quota'){
              switch (sales_group){
                case "Academic":
                  switch (sales_sub_group){
                    case "Key Accounts":
                      keysToRemove = ["B2C"];
                      break;
                    case "Oubound":
                      keysToRemove = ["B2C"];
                      break;
                    case "Inside Sales":
                      keysToRemove = ["B2B", "B2C"];
                      break;
                  }
                break;
                 case "Commercial":
                   switch (sales_sub_group){
                    case "AE":
                      keysToRemove = ["B2C", "B2E"];
                      break;
                    case "Enterprise":
                      keysToRemove = ["B2B", "B2C"];
                      break;
                    case "Inside Sales":
                      keysToRemove = ["B2B", "B2E"];
                      break;
                    case "Sales Group":
                      keysToRemove = ["B2B", "B2C", "B2E"];
                      break;
                  }
                break;
                case "IBD":
                  switch (sales_sub_group){
                    case "AE":
                      keysToRemove = array();
                      break;
                    case "Sales Group":
                      keysToRemove = ["B2B", "B2C", "B2E"];
                      break;
                  }
                break;
              }
            }
            return _.difference(array, keysToRemove);
    JS;
        }

        public static function getParamCount()
        {
            return 3;
        }

        static function getParameterTypes() {
          return array(AbstractExpression::$ENUM_TYPE, AbstractExpression::$ENUM_TYPE, AbstractExpression::$ENUM_TYPE);
        }

        /**
         * Returns the operation name that this Expression could be called by.
         */

        public static function getOperationName()
        {
            return array("restrictSalesGoalsDropdown");
        }
        /**
         * Returns the String representation of this Expression.
         */

        public function toString()
        {
        }

    I defined the Dependency

    custom/Extension/modules/sgoal_SalesGoals/Ext/Dependencies/deps.ext.php

    $dependencies['sgoal_SalesGoals']['setoptions_order_origin'] = array(
       'hooks' => array("edit","save"),
       'trigger' => true,
       'triggerFields' => array('goal_type', 'sales_entity_type', 'sales_group'),
       'onload' => true,
       'actions' => array(
          array(
            'name' => 'SetOptions',
            'params' => array(
               'target' => 'order_origin',
               'keys' => 'createList(restrictSalesGoalsDropdown($goal_type, $sales_entity_type, $sales_group))',               
               'labels' => 'createList(restrictSalesGoalsDropdown($goal_type, $sales_entity_type, $sales_group))',
            ),
          ),
        ),
    );

    Where am I going wrong? Clearly I'm not understanding this fully.

    Interestingly the dependency is not showing in 

    cache/modules/sgoal_SalesGoals/clients/base/dependency.php

    but is showing in 

    custom/modules/sgoal_SalesGoals/Ext/Dependencies/deps.ext.php

    thanks,
    FrancescaS

  • Nothing obvious stands out to me on why it isn't working. It could be your use of the _.difference underscore function. If I recall correctly, I tried using an underscore function in a custom sugar logic function in the past and I kept on getting weird behavior or errors. I finally removed the underscore method and just used some standard javascript functions and the problem went away.

    My only other suggestion would be to strip the functions back to very basic behavior and slowly add the code back in pieces at a time to try and narrow down the line of code causing the problem.

  • André Lopes, sorry to bother you, can you see anything obvious in my code that would cause it not to work?

    thanks,

    FrancescaS

Reply Children
  • I'm afraid you had overcomplicated the solution Francesca Shiekh .

    You better implement it through SetOption dependency, find bellow a working scenario:

    $dependencies['Cases']['case_status_xpto'] = array(

       'hooks' => array("view", "edit"),

       'trigger' => '

    and(

       not(equal($id, "")), isUserInList(createList("SIMM_GER", "SIMM_SUP")), equal($status, "Ag. Postagem"),

       or(

          equal($acc_tipo_cliente_c, "Cliente VIP"),

          and(equal($acc_tipo_cliente_c, "Cliente Final"), equal($extravio_transporte_c, false))

       )

    )

    ',

       'triggerFields' => array('status', 'acc_tipo_cliente_c', 'extravio_transporte_c'),

       'onload' => true,

       'actions' => array(

          array(

             'name' => 'SetOptions',

             'params' => array(

                'target' => 'status',

                'keys' => 'getDropdownKeySet("case_status_AgPostagemCliente_mgnt")',

                'labels' => 'getDropdownValueSet("case_status_AgPostagemCliente_mgnt")'

             ),

          ),

       ),

    );

    Regards

    André Lopes
    Lampada Global
    Skype: andre.lampada
  • Thank you André Lopes, I have a profound hatred for sugar logic formulas, but I'll give it a try.

  • Is it a problem with your getParameterTypes function in your sugarLogic expression? You are requiring the parameter to be an enum type (dropdown list) but it appears in your dependency you are passing in strings (the values of the goal_type, sales_entity_type, and sales_group fields). I think you need to change the parameter types from AbstractExpression::$ENUM_TYPE to AbstractExpression::$STRING_TYPE.

  • I took your code and was able to get it to work for myself by making the following changes:

    In custom/include/Expressions/Expression/Enum/RestrictSalesGoalsDropdownExpression.php

    Changed

    static function getParameterTypes() {
          return array(AbstractExpression::$ENUM_TYPE, AbstractExpression::$ENUM_TYPE, AbstractExpression::$ENUM_TYPE);
    }

    To

    static function getParameterTypes() {
          return array(AbstractExpression::$STRING_TYPE, AbstractExpression::$STRING_TYPE, AbstractExpression::$STRING_TYPE);
    }

    Changed the parameter types to strings instead of enums because from your dependency it looks like you are passing in the values of three different fields, which would be strings, and not arrays.

    In custom/Extension/modules/sgoal_SalesGoals/Ext/Dependencies/deps.ext.php

    Changed

    'keys' => 'createList(restrictSalesGoalsDropdown($goal_type, $sales_entity_type, $sales_group))',                
    'labels' => 'createList(restrictSalesGoalsDropdown($goal_type, $sales_entity_type, $sales_group))',

    To

    'keys' => 'restrictSalesGoalsDropdown($goal_type, $sales_entity_type, $sales_group)',                
    'labels' => 'restrictSalesGoalsDropdown($goal_type, $sales_entity_type, $sales_group)',

     

    Removed the call to createList because your custom sugar logic functions are already returning an enum.

    I'm not sure if naming this file deps.ext.php, which is the same name as the file Sugar creates, will cause any problems. When I was testing I used a different name, such as cstm_restrict_sales_goals.php to prevent any problems with name conflicts.

    Hopefully these changes solve the problem for you.

  • Thank you Brett Zufelt,

    goal_type, sales_entity_type, and sales_group fields are actually enums, I'm wanting to pass the selected value for each of those fields, granted the value itself will be a string. I had tried changing this before and got an error 

    ERROR: restrictSalesGoalsDropdown: The parameter at index 0 must be of type enum

     

    As for the filename, there is no conflict, I do this often as I like to keep all the dependencies in one file, granted I could call it something else.

    I will keep working it from here. I'll let you know how it goes. 

    thanks,
    Francesca

  • The "ERROR: restrictSalesGoalsDropdown: The parameter at index 0 must be of type enum" was the same error I was getting when playing with your code that caused me to change the parameter type declarations in the getParameterTypes function from enum to string. Once I made that change, the error went away.

    Are you sure you did a rebuild sugar logic functions after you made the change? You also need to clear your browsers cache after doing the rebuild. That has caused me havoc in the past where I made changes to a sugar logic function, ran the rebuild sugar logic functions job only to find it was still using an older, cached version of the file. Once I cleared the browser's cache it started using the updated version of the function.

  • You are right, clearing browser cache helps.

    It's working!

    Thank you for all your help Brett Zufelt!

    I really appreciate it!

    FrancescaS

  • Awesome! Glad you were able to get it working. I've fought the browser cache many times. I've learned to just do a Ctrl+F5 after any repair/rebuild to force the browser to reload its cached files.