Skip to content

FOUR-26628 | Fix Error When Opening a Task with an Imported Assignment Rule - #9110

Open
mcraeteisha wants to merge 3 commits into
developfrom
bugfix/FOUR-26628
Open

mcraeteisha wants to merge 3 commits into
developfrom
bugfix/FOUR-26628

Conversation

@mcraeteisha

@mcraeteisha mcraeteisha commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Issue

Ticket: FOUR-26628

After importing a Process that contains a task with a Rule Expression assignment, clicking the task in the Modeler displays an error message. In the reported case, opening the task triggered a request for a user ID from the source environment that did not exist in the target environment, resulting in a visible 404 error.

The imported pm:assignmentRules data preserved the source environment's numeric user and group IDs. Neither the current nor legacy import flow reconciled those IDs, so the task inspector attempted to load the stale assignees when the task was opened. If the numeric ID belonged to a different user or group in the target environment, the inspector could also display the wrong assignee.

This change affects imported Rule Expression assignments for users and groups. Regular user and group assignments continue to use the existing assignment import behavior.

Solution

processmaker

  • Added AssignmentRulesReconciliation to reconcile pm:assignmentRules during import without trusting the exported numeric assignee ID.
  • Rebinds user rules by parsing the username from the existing assignmentName value, including values with the - Inactive suffix.
  • Rebinds group rules by assignmentName only when exactly one matching group exists.
  • Clears the assignee and marks the rule as unresolved when a unique target user or group cannot be found.
  • Applied assignment-rule reconciliation to the current import flow through ProcessExporter and to legacy process imports through ImportProcess.
  • Updated SelectUserGroup so missing assignees do not produce a global 404 alert, do not leave the picker in a loading state, and are handled locally.
  • Updated AssignExpression so unresolved assignees are not passed to the user/group picker and instead display “This assignee was not found in this environment. Select a user or group.” under Default Assignment and in the edit card.
  • Added feature tests covering username-based rebinding, stale-ID collisions, unresolved users and groups, ambiguous group names, the current import flow, and the legacy import flow.

How To Test

Automated Tests

  • php vendor/bin/phpunit --filter AssignmentRulesReconciliationTest tests/Feature/ImportExport/AssignmentRulesReconciliationTest.php
  • php vendor/bin/phpunit --filter ImportProcessAssignmentRulesTest tests/Feature/Jobs/ImportProcessAssignmentRulesTest.php

Manual Tests

  1. Import a Process containing a Rule Expression task whose assignment rule references a user or group that exists in the target environment under a different numeric ID, then open the task in the Modeler.
  2. Confirm that the task opens without an error and that the assignment rule is rebound to the matching target user or group.
  3. Import a Process containing a Rule Expression task whose assignment rule references a user or group that does not exist in the target environment, then open the task in the Modeler.
  4. Confirm that no 404 error is displayed, the Default Assignment picker remains usable, and “This assignee was not found in this environment. Select a user or group.” is displayed.
  5. Select a valid user or group for the unresolved assignment and confirm that the assignment can be saved.

ci:deploy

Code Review Checklist

  • I have pulled this code locally and tested it on my instance, along with any associated packages.
  • This code adheres to ProcessMaker Coding Guidelines.
  • This code includes a unit test or an E2E test that tests its functionality, or is covered by an existing test.
  • This solution fixes the bug reported in the original ticket.
  • This solution does not alter the expected output of a component in a way that would break existing Processes.
  • This solution does not implement any breaking changes that would invalidate documentation or cause existing Processes to fail.
  • This solution has been tested with enterprise packages that rely on its functionality and does not introduce bugs in those packages.
  • This code does not duplicate functionality that already exists in the framework or in ProcessMaker.l
  • This ticket conforms to the PRD associated with this part of ProcessMaker.

This change rebinds imported rule_expression assignee records to valid users/groups in the target environment, clearing stale unresolved assignees and marking them for re-selection. It also adds guarded user/group fetches in the picker to avoid noisy 404s when stale assignees remain, and surfaces explicit warnings in the assignment expression inspector when an imported assignee cannot be resolved.
@cursor

cursor Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes process import BPMN mutation and task assignment identity resolution; incorrect matching could mis-route work, though ambiguity is handled by marking rules unresolved.

Overview
Fixes modeler errors when opening imported tasks that use Rule Expression assignment by reconciling pm:assignmentRules on import instead of keeping source-environment numeric assignee IDs.

A new AssignmentRulesReconciliation pass runs during both the modern ProcessExporter import path and legacy ImportProcess save: user rules rebind by username parsed from assignmentName (including inactive-user suffixes); group rules rebind only when exactly one group matches the name; otherwise the assignee is cleared and the rule is flagged unresolved.

On the UI side, SelectUserGroup no longer shows global 404 toasts or sticks loading when an assignee ID is missing, and AssignExpression surfaces a clear message for unresolved rules and avoids pre-fetching invalid assignees into the picker.

Reviewed by Cursor Bugbot for commit 6386cf3. Bugbot is set up for automated code reviews on this repo. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 6c4f656. Configure here.

Group assignees can be stored as either numeric IDs or strings like group-<id>. This change centralizes normalization so default and special assignments consistently use the plain ID value before string operations, comparisons, and persisted assignment data.
@decisions-sonarqube

Copy link
Copy Markdown

@mcraeteisha mcraeteisha self-assigned this Oct 22, 2026
*/
public static function markRuleUnresolved(object|array $rule): object|array
{
$rule = self::ruleSet($rule, 'assignee', null);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Prevent unresolved rules from bypassing the default assignment

When an imported rule is marked unresolved, its expression remains executable with assignee=null. A matching unresolved user rule caused the task to be assigned to the Process Manager instead of the valid Default Assignment. Please skip unresolved rules during evaluation or prevent execution until they are resolved.

$this->importScripts();
$this->importSubprocesses();
$this->importAssignments();
$this->importAssignmentRules();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Reconcile assignment rules in the model-only template editor

This call runs only for saveAllAssets, so opening a saveModelOnly template preserves source assignee IDs. Confirmed with an ID collision: the expression row displayed the exported user, while its edit picker loaded a different target user. Creating a process from that template subsequently reconciled the reference, so the confirmed issue is limited to template editing. Please reconcile assignment rules independently of the asset-import mode and cover this template editing path.

return null;
}

$username = trim(preg_replace('/\s+-\s+Inactive$/i', '', trim($matches[1])));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Handle translated inactive-user suffixes

The picker generates the inactive suffix using $t('Inactive'), but this parser strips only the English text. Confirmed with the Spanish formatter output: Name (username - inactivo) is parsed as username - inactivo, causing an existing target user to be marked unresolved and its assignee cleared. Please support the localized label format generated by the picker.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants