Relating Existing Records in Sugar BPM: Practical Example

Author: Yuri Gee

Date: 18 Jul 2025

5 minute read time

The current Sugar BPM Process Definition Designer includes a built-in action—Add a Related Record—which creates a new record and links it to the target module of the process. This article presents a prototype extension of that action, enabling the ability to relate existing records based on field value comparisons. The implementation is designed to be simple and straightforward, avoiding the need for custom logic hook development while still supporting common business scenarios that require linking existing records.

Scenario

Imagine you want to associate Call records that begin with “Bad time, will call back” to a specific Cases record. This can be accomplished using the extension demonstrated here by creating a service field called relate__condition_c in the Calls module.

You then can assign a value to this field within a Sugar BPM Process Definition, where Cases is the target module and Calls is a 1:M relationship. The related record can be matched using either a static value or a dynamic value pulled from the parent Case record, using standard Sugar BPM syntax. Additionally, Sugar Logic formulas can be used to populate the assignment field as needed.

In this example, a static value is applied—targeting the name field of a Call, using the format: field_name field_value, separated by a space.

Example of adding a related record condition in BPM designer

This BPM definition using the special field assignment will not create new records,  instead it adds up to 10 existing related Call records that match the specified criteria (e.g., Call names starting with the given value). It also updates the parent-child relationship—which, in the case of Cases and Calls, is the primary link—by setting the parent_type and parent_id fields on the related Call records, ensuring they are properly associated with the Case.

Example of relating Calls to a Case

The service field in the related module (Calls) is used only to align with the existing layout of the Sugar BPM Add Related Record action.

Service field for BPM definition 

Code Prototype

This file is based on the original stock ./modules/pmse_Inbox/engine/PMSEElements/PMSEAddRelatedRecord.php, incorporating some elements from ./modules/pmse_Inbox/engine/PMSERelatedModule.php.

Extensions are then applied within either the ./modules or ./custom/modules/pmse_Inbox/engine/PMSEElements/PMSEAddRelatedRecord.php directories.

Note that the original file is not included here, but it can be retrieved from your Sugar instance or a backup of its filesystem.

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//Added at line 159 of the original file////////////////////////////////////////////////////////////////////////////////////////
// This is a service field-relate__condition_c-that should be included in the Process Definition of the main module to define the condition for adding an existing related record.
if (isset($fields['relate__condition_c']))
{
$parentBean = $bean;
$relationship_name = $arr_module;
if (!empty($parentBean)) {
if (empty($parentBean->field_defs[$relationship_name])) {
throw ProcessManager\Factory::getException('InvalidData', "Unable to find field {$fieldName}", 1);
}
$chainModulePresent = false;
$additional_params = (isset($definitionBean) && !empty($definitionBean->act_params)) ? json_decode($definitionBean->act_params) : null;
if (isset($additional_params->chainedRelationship->module) && !empty($additional_params->chainedRelationship->module)) $chainModulePresent = true;
$relate_condition = !empty($fields['relate__condition_c']) && is_scalar($fields['relate__condition_c']) ? (string)$fields['relate__condition_c'] : '';
list($field_name, $field_value) = strpos($relate_condition, ' ') !== false ? explode(' ', $relate_condition, 2): ['', ''];
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
     

Implementation Highlights and Constraints

Supports only one related module; second-level (chained) relationships are not included.

Field names used for matching are sanitized using standard SugarQuery logic; further sanitization may be needed. Matching respects Teams and Role-based permissions of the user executing the BPM.

Data types tested include strings or possibly fields convertible to strings.

To prevent slow queries, consider adding an index to the matching column; default query limit is 10 records.

Both stock and custom fields can be used for matching, including BPM expressions and Sugar Logic formulas.

Saving related and parent beans may occur but is not always required; careful design and testing is needed to avoid loops.

SugarCRM supports various relationship types: one-to-one, one-to-many, many-to-many, parent-child, circular, and relationships via module or linking tables.

Relationship types may use true_relationship_type and relationship_type; some may default to many even if they are many-to-one. In many-to-one relationships, the logic may still add a parent record if a valid parent-child link exists and the query returns multiple results; this behavior can be disabled.

Some tested scenarios included: adding Contacts to Accounts, linking Calls to Cases, relating Parent Accounts, assigning Users to Cases, and relating Accounts to Cases.

Final Thoughts

This prototype illustrates how existing records can be linked using simple Sugar BPM extensions, leveraging various relationship types and dynamically populated fields from the main record—including Sugar Logic formulas. A similar approach can be applied to removing existing relationships as needed.

Before considering production use, please ensure thorough testing across different scenarios, data types, and relationship structures. Also consider potential interactions with other BPM processes, as this example is provided as-is and may require further refinement for stable deployment.

I’d love to hear how you’re exploring SugarCRM BPM in this and similar use cases!