Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [UNRELEASED]

### Fixed

- Fix rules duplication

## [2.10.1] - 2025-12-09

### Fixed
Expand Down
4 changes: 4 additions & 0 deletions inc/ticket.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,14 @@ public static function pre_item_update(CommonDBTM $item)
}

$temp_input['_disablenotif'] = true; // Disable notifications for this validation
$item->input['_skip_rules'] = true;
$input = $item->prepareInputForUpdate($temp_input);
$item->input['_skip_rules'] = false;
unset($item->input['_no_escalade_template_validation']); // Clean up flag
} else {
$item->input['_skip_rules'] = true;
$input = $item->prepareInputForUpdate($item->input);
$item->input['_skip_rules'] = false;
}

if (!$input) {
Expand Down
78 changes: 78 additions & 0 deletions tests/Units/TicketTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,12 @@
use Group_User;
use ITILCategory;
use PluginEscaladeTicket;
use Rule;
use RuleCommonITILObject;
use Ticket;
use Ticket_User;
use User;
use TicketTask;

final class TicketTest extends EscaladeTestCase
{
Expand Down Expand Up @@ -1257,4 +1260,79 @@ public function testHistoryButtonEscalationWithMandatoryTemplateFields()
$group1->delete(['id' => $group1_id], true);
$group2->delete(['id' => $group2_id], true);
}

public function testRuleCreatesTaskWhenCategoryAssigned()
{
$this->initConfig();

// Create a task template that will be added by the rule
$task_template = $this->createItem('TaskTemplate', [
'name' => 'Rule task template',
'content' => '<p>Task created by rule</p>',
'entities_id' => 0,
'is_recursive' => 1,
]);
$task_template_id = $task_template->getID();

// Create the rule that appends a task template when category is set on update
$rule = $this->createItem('Rule', [
'name' => 'Create task on category assign',
'sub_type' => 'RuleTicket',
'match' => 'AND',
'is_active' => 1,
'condition' => RuleCommonITILObject::ONUPDATE,
'is_recursive' => 1,
'entities_id' => 0,
]);
$rule_id = $rule->getID();

$this->createItem('RuleAction', [
'rules_id' => $rule_id,
'action_type' => 'append',
'field' => 'task_template',
'value' => $task_template_id,
]);

// Create a category that will trigger the rule when assigned
$category = $this->createItem('ITILCategory', [
'name' => 'Category triggering task',
'entities_id' => 0,
'is_recursive' => 1,
]);
$category_id = $category->getID();

// Ensure the rule triggers only when the ticket category matches the created category
$this->createItem('RuleCriteria', [
'rules_id' => $rule_id,
'criteria' => 'itilcategories_id',
'condition' => Rule::PATTERN_IS,
'pattern' => $category_id,
]);

// Create a ticket without category
$ticket = $this->createItem('Ticket', [
'name' => 'Ticket for rule test',
'content' => 'Content for rule test',
'entities_id' => 0,
]);
$ticket_id = $ticket->getID();

$tickettask = new TicketTask();
$this->assertEquals(0, count($tickettask->find(['tickets_id' => $ticket_id])));

// Assign the category (update) - rule should fire and create a single task
$this->updateItem('Ticket', $ticket_id, [
'id' => $ticket_id,
'itilcategories_id' => $category_id,
]);

$tasks = $tickettask->find(['tickets_id' => $ticket_id]);
$this->assertEquals(1, count($tasks));

// Clean up
$ticket->delete(['id' => $ticket_id], true);
$task_template->delete(['id' => $task_template_id], true);
$category->delete(['id' => $category_id], true);
$rule->delete(['id' => $rule_id], true);
}
}