Nearly everything you need to know about the Q4 2020 Release

Hello Sugar Developers!

We have another release for you with new features and fixes! We are calling this one Sugar Q4 2020 (or Sugar 10.2.0). This release is for cloud customers only.

Here are some of the new features and fixes for this release. This is not an exhaustive list of everything we did for Sugar 10.2 - just the items that we thought would be important for a developer to take note of. 

  • Studio and Module Builder field updates - New options have been added when creating/editing fields in Studio and Module Builder to make them conditionally required.
    • If a field is marked required with no formula input, they will be required always.
    • If a field is marked required WITH a formula input, they will be conditionally required depending on the formula's evaluation.
    • If a field is NOT marked required, the presence of a formula is irrelevant - it will not be required. 
  • Autoincrement field - "Admins can now create an AutoIncrement-type field in Studio or Module Builder!
    • The starting seed value may be specified but not the step increment - it will always increment by 1
  • Audit Log - Audit Log is now available for Calls, Meetings, Notes, and Tasks.
  • New SugarLogic function year() returns the year portion of a Date or DateTime field in YYYY format.
  • New SugarLogic function strReplace() will replace a substring of a string. 
    • example: strReplace("a great", "the best", "SugarCRM is a great platform", false)
      will change "SugarCRM is a great platform" to "SugarCRM is the best platform"
  • BPM Multiselect Field Evaluation - Multiselect fields can now be evaluated in BPM using "is one of" where records with the selected option set as one of its selected options satisfy the condition. The existing SugarLogic function isInList() has been updated to allow evaluations on multiselect fields. The field is passed in place of a list, and the function returns true if the 1st argument is one of the mutliselect field's selected dropdown options.
  • New Scheduled Job - A new Scheduled Job has been added. The update product definitions job will check for updates daily to ensure that the correct product features are enabled and accessible.
  • Default Scheduler Jobs End Date & Time - The End Date & Time fields for new installs of 10.2 will have NO default values set by default. But, others will need to update their stock schedulers to remove or change their default End Date prior to the end of this year, or else the schedulers will cease working.
  • Relate fields available in BPM - This change exposes Relate Fields for criteria in Events (e.g. Start), Actions filters (e.g. Change Field, Add Related Record), Gateway (e.g. Criteria), Process Definition (e.g. Terminate Process). This change is applied to Process Definitions. Relate Fields are not exposed for Business Rules and Email Templates. Relate Field values are not changeable in SugarBPM from this change.
  • Audit log enhancement for logic hooks - Sugar developers are now able to provide a source_name attribute in the logic hook array, to be used in the audit log Source column to help identify which logic hook made a change to the record.
  • MySQL 8.0 compatibility - The users_feeds table has been REMOVED. The module that uses this table was removed before Sugar 6.X. If creating a dedicated mysql user (For on-premise), this is the command that should be used with MySQL 8.0:
    CREATE USER 'sugaruser'@'sugarhost' IDENTIFIED WITH mysql_native_password BY 'sugarpassword'

    Alternatively, you can configure MySQL to use native password systemwide:

    [mysqld]
    default-authentication-plugin=mysql_native_password
  • Emails BWC code cleanup - Old (dead) Emails BWC code has been removed. This code was unused, but if there are any customizations that utilize this code, it will need to be refactored.
  • Multiple Quotes from RLIs - Users can now generate multiple quotes from the same set of RLIs. Previously, a single RLI could only be quoted once. All of the generated quotes will appear in the Opportunity's Quotes subpanel.
  • Active Subscriptions dashlet - The Active Subscriptions dashlet was previously only available on the Renewals Console and the Accounts module. Now it is available to add on every module's record view dashboard, but it will display an error message if the user doesn't or can't (because one doesn't exist) select an Account relate field while adding it to the dashboard.
  • New Relationship - A new 1-to-Many relationship between RLI and QLI is being set during quote generation. It is not exposed anywhere in the UI by default. It is being added now for future use.
  • ElasticSearch update - "A new config entry (enable_long_text_search) has been added. By default, this will be set to false. When the option is set to true, ElasticSearch will enable long text search for the 'longtext' and 'htmleditable_tinymce' field types
  • Flexible Dashboards - All Dashboards now have a grid layout.
    • Dashlets can be resized by the user manually
    • Drag/drop enabled for positioning the dashlets
    • Limit of 10 rows of dashlets has been removed
    • A new library has been added to accomplish this - gridstack.js
    • Dashboard name is now changed via inline editing
  • Introducing SugarLive! - voice and chat integration for Sugar Serve using AWS services
  • New Messages module has been added
    • for chat, SMS (future), or social (future) conversations with customer
    • does not require SugarLive
    • available for Sugar Serve
  • New Knowledge Base Search dashlet has been added
    • Search returns published and non-expired Knowledge Base articles
    • Will display hyperlinked title and first 500 words of article
    • renamed the portal config's "portal" search setting to "generic_search" BUT "portal" is still honored for backwards compatibility
  • Coterminus Add-on RLIs
    • adding an RLI as an add-on will maintain the end date set by the parent opportunity
  • API endpoint updates
    • New Portal API endpoint for Cases
      • PUT /request_close/Cases/<record>/request_close
        This method sets the case as "requested for closure".
    • 2 new endpoints for BPM process validation (used internally)
      • GET /pmse_Project/validateCrmData/<data>
        ex: /rest/v11/pmse_Project/validateCrmData/users?key=seed_sally_id
      • GET /pmse_Project/validateCrmData/<data>/<filter>
        ex: /rest/v11/pmse_Project/validateCrmData/field/Accounts?key=data_entered
    • Added new upsert endpoints!! NOTE: "Upsert" endpoints combine an INSERT with an UPDATE based on an external ID. The service will determine which method to use (if no matching record exists, it will INSERT, if a record does exist, an UPDATE will be made). To implement these new endpoints, we have added the new sync_key field to the core Sugar modules (calls, meetings, tasks, leads, etc) 
      • GET /<module>/sync_key/<sync_key_field_value>
        Retrieve record with given sync_key

      • GET /integrate/<module>/<sync_key_field_name>/<sync_key_field_value>
        Retrieve record with given field name and value

      • DELETE /<module>/sync_key/<sync_key_field_value>
        Delete record with given sync_key

      • DELETE /integrate/<module>/<sync_key_field_name>/<sync_key_field_value>
        Delete record with given field name and value

      • PATCH/PUT /<module>/sync_key/<sync_key_field_value>
        Upsert based on sync_key. If the record can be found with sync_key, then update. If the record does not exist, then create it. Recommended use of PATCH.

      • PATCH/PUT /integrate/<module>/<sync_key_field_name>/<sync_key_field_value>
        Upsert based on a field. If the record can be found with the provided field, then update. If the record does not exist, then create it. Recommended use of PATCH.

    • Added new relate endpoints
      • POST /<module>/<lhs_sync_key_field_value>/link_by_sync_keys/<link_name>/<rhs_sync_key_field_value>
        Create a relationship based on both sync_keys. If both the Left Hand Side (LHS) and Right Hand Side (RHS) records can be found with the respective sync_key, then relate the RHS record to the LHS record.

      • POST /integrate/<module>/<lhs_sync_key_field_name>/<lhs_sync_key_field_value>/link/<link_name>/<rhs_sync_key_field_name>/<rhs_sync_key_field_value>
        Create a relationship based on fields. If both the LHS and RHS records can be found with the respective fields, then relate the RHS record to the LHS record.

      • DELETE /<module>/<lhs_sync_key_field_value>/link_by_sync_keys/<link_name>/<rhs_sync_key_field_value>
        Remove a relationship based on both sync_keys. If both the LHS and RHS records can be found with the respective sync_key, and those records are related, then remove the relationship of the RHS record to the LHS record.

      • DELETE /integrate/<module>/<lhs_sync_key_field_name>/<lhs_sync_key_field_value>/link/<link_name>/<rhs_sync_key_field_name>/<rhs_sync_key_field_value>
        Remove a relationship based on fields. If both the LHS and RHS records can be found with the respective fields, and those records are related, then remove the relationship of the RHS record to the LHS record.

    • Added new endpoints for AWS Connect configuration
      • GET /Administration/aws
        Retrieves configuration settings for Amazon Web Services integrations. Accessible by Sugar Serve admins only

      • POST /Administration/aws
        Sets configuration settings for Amazon Web Services integrations. Accessible by Sugar Serve admins only

    • Added new generic search endpoint.
      • GET/POST /genericsearch
        Searches the content of the given modules using the provider specified by the "generic_search" configuration variable. If the variable is absent, the default provider is "Elastic". This endpoint will take a search expression query, a comma delimited list of modules to search, max number of records to return and a results offset value.

  • Since the upsert and relate API endpoints have been added to the core code, there is no longer a need for the Sugar Essentials package that was previously required for the Sugar Integrate templates to function properly. In fact, if you have the essentials package installed and upgrade to 10.2, the upgrader Health Check will throw an error. You must UNINSTALL the Sugar Essentials Module Loadable Package before upgrading to 10.2 (or beyond).
  • New SugarCloud regions added
    • Singapore
    • London
  • Admins can now search, filter, select, and mass update users in SugarCloud settings
  • SugarIdentity Users can now update their passwords from Users Menu. No longer have to trigger the "Forgot Password" link
  • A new field called Service Duration has been added to the opportunities record view that is calculated as the longest service duration of all open related service revenue line items.
  • The existing Service Duration field on each of the line item records is now being used in the following calculations:
    • RLIs Calculated Amount
    • PLIs Calculated Revenue
    • QLIs Subtotal
    • QLIs Line Item Total
  • The previous formulas are the same but are now multiplied by the Service Duration.
    • So, if you are using the default formulas, they have been changed
    • Check your formulas to ensure they are still performing as expected.
    • Here is a before/after of the formulas:
10.1 10.2
QLI Subtotal
ifElse(and(isNumeric($quantity), isNumeric($discount_price)),
 ifElse(equal($quantity, 0), "0", currencyMultiply($discount_price, $quantity))
 , "")
multiply(
 ifElse(
 isNumeric($service_duration_multiplier),
 $service_duration_multiplier,
 1
 ),
 ifElse(and(isNumeric($quantity), isNumeric($discount_price)),
 ifElse(equal($quantity, 0), "0", currencyMultiply($discount_price, $quantity))
 , "")
 )
QLI Line Item Total
ifElse(and(isNumeric(toString($quantity)), isNumeric(toString($discount_price))),
                    currencySubtract(
                        currencyMultiply(
                            $discount_price,
                            $quantity
                        ),
                        ifElse(equal($discount_select, "1"),
                            currencyMultiply(currencyMultiply($discount_price, $quantity), currencyDivide($discount_amount, 100)),
                            ifElse(greaterThan($quantity, 0), ifElse(isNumeric(toString($discount_amount)), $discount_amount, 0),
                            ifElse(isNumeric(toString($discount_amount)), negate($discount_amount), 0))
                        )
                    ),
                    ""
                )
multiply(
                ifElse(
                    isNumeric($service_duration_multiplier),
                    $service_duration_multiplier,
                    1
                ),
                ifElse(and(isNumeric(toString($quantity)), isNumeric(toString($discount_price))),
                    currencySubtract(
                        currencyMultiply(
                            $discount_price,
                            $quantity
                        ),
                        ifElse(equal($discount_select, "1"),
                            currencyMultiply(currencyMultiply($discount_price, $quantity), currencyDivide($discount_amount, 100)),
                            ifElse(greaterThan($quantity, 0), ifElse(isNumeric(toString($discount_amount)), $discount_amount, 0),
                            ifElse(isNumeric(toString($discount_amount)), negate($discount_amount), 0))
                        )
                    ),
                    ""
                )
            )
PLI Calculated Revenue
ifElse(and(isNumeric(toString($quantity)), isNumeric(toString($discount_price))),
                            currencySubtract(
                                currencyMultiply(
                                    $discount_price,
                                    $quantity
                                ),
                                ifElse(equal($discount_select, "1"),
                                    currencyMultiply(currencyMultiply($discount_price, $quantity), currencyDivide($discount_amount, 100)),
                                    ifElse(greaterThan($quantity, 0), ifElse(isNumeric(toString($discount_amount)), $discount_amount, 0),
                                    ifElse(isNumeric(toString($discount_amount)), negate($discount_amount), 0))
                                )
                            ),
                            ""
                        )
multiply(
                ifElse(
                    isNumeric($service_duration_multiplier),
                    $service_duration_multiplier,
                    1
                ),
                ifElse(and(isNumeric($quantity), isNumeric($discount_price)),
                    currencySubtract(
                        currencyMultiply(
                            $discount_price,
                            $quantity
                        ),
                        ifElse(equal($discount_select, "1"),
                            currencyMultiply(currencyMultiply($discount_price, $quantity), currencyDivide($discount_amount, 100)),
                            ifElse(greaterThan($quantity, 0), ifElse(isNumeric(toString($discount_amount)), $discount_amount, 0),
                            ifElse(isNumeric(toString($discount_amount)), negate($discount_amount), 0))
                        )
                    ),
                    ""
                )
            )
RLI Calculated Amount
ifElse(and(isNumeric($quantity), isNumeric($discount_price)),
                  ifElse(equal($quantity, 0),
                      $total_amount,
                      currencySubtract(
                          currencyMultiply(
                              $discount_price,
                              $quantity
                          ),
                          ifElse(equal($discount_select, "1"),
                              currencyMultiply(
                                  currencyMultiply($discount_price, $quantity), 
                                  currencyDivide($discount_amount, 100)
                              ),
                              ifElse(greaterThan($quantity, 0), 
                                  ifElse(isNumeric(toString($discount_amount)), 
                                  $discount_amount, 0
                              ),
                              ifElse(isNumeric(toString($discount_amount)), negate($discount_amount), 0))
                          )
                      )
                    ), ""
              )
multiply(
                    ifElse(
                        isNumeric($service_duration_multiplier),
                        $service_duration_multiplier,
                        1
                    ),
                    ifElse(and(isNumeric($quantity), isNumeric($discount_price)),
                        ifElse(equal($quantity, 0),
                            $total_amount,
                            currencySubtract(
                                currencyMultiply(
                                    $discount_price,
                                    $quantity
                                ),
                                ifElse(equal($discount_select, "1"),
                                    currencyMultiply(
                                        currencyMultiply($discount_price, $quantity),
                                        currencyDivide($discount_amount, 100)
                                    ),
                                    ifElse(greaterThan($quantity, 0),
                                        ifElse(isNumeric(toString($discount_amount)),
                                        $discount_amount, 0
                                    ),
                                    ifElse(isNumeric(toString($discount_amount)), negate($discount_amount), 0))
                                )
                            )
                        ), ""
                    )
                )
  • Checkboxes have been added to Opportunity record views for Expected Close Date, Sales Stage, Service Start Date, and the new field called Service Duration. These checkboxes will enable the cascade of your changes to all child RLIs.
  • The Change Log is now available to all modules (but still must be turned on by an Admin in Studio)
  • Audit log Source column now populated by optional source_name attribute in the logic hook array so that you can see a more descriptive value for that column.
  • OAuth2 for Google Mail and Exchange Online
    • New options in Connector Properties, System Email Settings, and Email Settings for Google OAuth2 and Exchange Online OAuth2
    • Legacy options for Google and MS have been renamed to "Microsoft Exchange" and "Google Less-Secure Apps"
    • Switch yours to use OAuth2 now before Google and MS discontinue support for the less-secure username/password methods
  • $sugar_config['aws'] has been deprecated and will be removed in an upcoming release
Parents Comment Children