diff --git a/inc/history.class.php b/inc/history.class.php
index 5201ff72..a75fb754 100644
--- a/inc/history.class.php
+++ b/inc/history.class.php
@@ -231,9 +231,9 @@ public static function getHistory($tickets_id, $full_history = false)
if ($nb_histories - 1 > self::HISTORY_LIMIT && !$full_history) {
echo Ajax::createModalWindow(
'full_history',
- $plugin_dir . "/front/popup_histories.php?tickets_id=" . $tickets_id,
+ $plugin_dir . "front/popup_histories.php?tickets_id=" . $tickets_id,
[
- 'title' => __s("full assignation history", "escalade"),
+ 'title' => __("full assignation history", "escalade"),
],
);
echo "...";
diff --git a/inc/ticket.class.php b/inc/ticket.class.php
index 898271ef..bdedb43e 100644
--- a/inc/ticket.class.php
+++ b/inc/ticket.class.php
@@ -41,6 +41,11 @@ class PluginEscaladeTicket
public static function pre_item_update(CommonDBTM $item)
{
+ // If this is an escalation action, do not interfere
+ if (isset($item->input['_escalation_action']) && $item->input['_escalation_action']) {
+ return $item;
+ }
+
// Only process escalation logic if we're dealing with actor assignments
// Don't interfere with other updates like solutions, status changes, etc.
if (!isset($item->input['_actors']) && !isset($item->input['_itil_assign']) && !isset($item->input['actortype'])) {
@@ -597,7 +602,7 @@ public static function assignUserGroup(Ticket $ticket)
* @param int $tickets_id the ticket to change
* @param int $groups_id the group to assign
* @param bool $no_redirect if true, no redirection after the action
- * @return void
+ * @return bool true on success, false on error
*/
public static function climb_group($tickets_id, $groups_id, $no_redirect = false)
{
@@ -612,7 +617,7 @@ public static function climb_group($tickets_id, $groups_id, $no_redirect = false
'type' => CommonITILActor::ASSIGN,
];
if (!$group_ticket->find($condition)) {
- $ticket_group = new Group_Ticket();
+ // Add task for escalation history
PluginEscaladeTaskmanager::setTicketTask([
'tickets_id' => $tickets_id,
'is_private' => true,
@@ -622,23 +627,88 @@ public static function climb_group($tickets_id, $groups_id, $no_redirect = false
$group->getName() . '
',
),
]);
+
$ticket = new Ticket();
- $ticket->update([
- 'id' => $tickets_id,
- '_actors' => [
- 'assign' => [
- [
- 'items_id' => $groups_id,
- 'itemtype' => 'Group',
- ],
+ if (!$ticket->getFromDB($tickets_id)) {
+ if (!$no_redirect) {
+ Session::addMessageAfterRedirect(
+ __s('Error: ticket not found', 'escalade'),
+ false,
+ ERROR,
+ );
+ }
+
+ return false;
+ }
+
+ // Prepare input with all existing ticket data to satisfy mandatory field validation
+ $input = $ticket->fields;
+ $input['id'] = $tickets_id;
+
+ // Add existing requesters to pass mandatory field validation
+ $ticket_users = new Ticket_User();
+ $existing_requesters = $ticket_users->find([
+ 'tickets_id' => $tickets_id,
+ 'type' => CommonITILActor::REQUESTER,
+ ]);
+ if (!empty($existing_requesters)) {
+ $input['_users_id_requester'] = array_column($existing_requesters, 'users_id');
+ }
+
+ // Add existing requester groups
+ $existing_requester_groups = $group_ticket->find([
+ 'tickets_id' => $tickets_id,
+ 'type' => CommonITILActor::REQUESTER,
+ ]);
+ if (!empty($existing_requester_groups)) {
+ $input['_groups_id_requester'] = array_column($existing_requester_groups, 'groups_id');
+ }
+
+ // Add the new group assignment
+ $input['_actors'] = [
+ 'assign' => [
+ [
+ 'items_id' => $groups_id,
+ 'itemtype' => 'Group',
],
],
- ]);
+ ];
+
+ // Ensure content is not empty for template validation
+ if (empty($input['content'])) {
+ $input['content'] = 'Content preserved during escalation';
+ }
+
+ // Mark as escalation action and disable notifications during update
+ $input['_escalation_action'] = true;
+ $input['_disablenotif'] = true;
+
+ // Use ticket->update() to trigger rules while avoiding validation issues
+ $result = $ticket->update($input);
+
+ if ($result) {
+ Session::addMessageAfterRedirect(
+ sprintf(__s('Escalation to the group %s.', 'escalade'), $group->getName()),
+ );
+ } else {
+ Session::addMessageAfterRedirect(
+ __s('Error during escalation', 'escalade'),
+ false,
+ ERROR,
+ );
+ return false;
+ }
+ } else {
+ Session::addMessageAfterRedirect(
+ sprintf(__s('Ticket already assigned to group %s', 'escalade'), $group->getName()),
+ );
}
if (!$no_redirect) {
Html::back();
}
+
+ return true;
}
diff --git a/locales/en_GB.po b/locales/en_GB.po
index feb9650f..a01cdfaa 100644
--- a/locales/en_GB.po
+++ b/locales/en_GB.po
@@ -231,6 +231,19 @@ msgstr "Configuration Escalade plugin"
msgid "Default (not managed by plugin)"
msgstr "Default (not managed by plugin)"
+#: inc/ticket.class.php:629
+msgid "Ticket not found"
+msgstr "Ticket not found"
+
+#: inc/ticket.class.php:681
+msgid "Error during escalation"
+msgstr "Error during escalation"
+
+#: inc/ticket.class.php:688
+#, php-format
+msgid "Ticket already assigned to group %s"
+msgstr "Ticket already assigned to group %s"
+
#: hook.php:568
msgid "Group concerned by the escalation"
msgstr "Group concerned by the escalation"
diff --git a/locales/fr_FR.mo b/locales/fr_FR.mo
index 9f4c52c2..754ad697 100644
Binary files a/locales/fr_FR.mo and b/locales/fr_FR.mo differ
diff --git a/locales/fr_FR.po b/locales/fr_FR.po
index 6c409012..5bef2cf2 100644
--- a/locales/fr_FR.po
+++ b/locales/fr_FR.po
@@ -1,7 +1,7 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
-#
+#
# Translators:
# Alexandre DELAUNAY , 2013
# alexandre delaunay , 2016
@@ -238,6 +238,19 @@ msgstr "Configuration du plugin Escalade"
msgid "Default (not managed by plugin)"
msgstr "Par défaut (non géré par le plugin)"
+#: inc/ticket.class.php:629
+msgid "Ticket not found"
+msgstr "Ticket non trouvé"
+
+#: inc/ticket.class.php:681
+msgid "Error during escalation"
+msgstr "Erreur lors de l'escalade"
+
+#: inc/ticket.class.php:688
+#, php-format
+msgid "Ticket already assigned to group %s"
+msgstr "Ticket déjà assigné au groupe %s"
+
#: hook.php:568
msgid "Group concerned by the escalation"
msgstr "Groupe concerné par l'escalade"
diff --git a/public/js/cloneandlink_ticket.js.php b/public/js/cloneandlink_ticket.js.php
index 768c3627..3b6fe548 100644
--- a/public/js/cloneandlink_ticket.js.php
+++ b/public/js/cloneandlink_ticket.js.php
@@ -54,7 +54,7 @@
setTimeout( function () {
if ($("#cloneandlink_ticket").length > 0) { return; }
var duplicate_html = "";
$("#linked_tickets-heading .accordion-button")