1083 lines
36 KiB
PHP
1083 lines
36 KiB
PHP
<?php
|
|
/**
|
|
* ---------------------------------------------------------------------
|
|
* GLPI - Gestionnaire Libre de Parc Informatique
|
|
* Copyright (C) 2015-2020 Teclib' and contributors.
|
|
*
|
|
* http://glpi-project.org
|
|
*
|
|
* based on GLPI - Gestionnaire Libre de Parc Informatique
|
|
* Copyright (C) 2003-2014 by the INDEPNET Development Team.
|
|
*
|
|
* ---------------------------------------------------------------------
|
|
*
|
|
* LICENSE
|
|
*
|
|
* This file is part of GLPI.
|
|
*
|
|
* GLPI is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* GLPI is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with GLPI. If not, see <http://www.gnu.org/licenses/>.
|
|
* ---------------------------------------------------------------------
|
|
*/
|
|
|
|
if (!defined('GLPI_ROOT')) {
|
|
die("Sorry. You can't access this file directly");
|
|
}
|
|
|
|
/**
|
|
* LevelAgreement base Class for OLA & SLA
|
|
* @since 9.2
|
|
**/
|
|
|
|
abstract class LevelAgreement extends CommonDBChild {
|
|
// From CommonDBTM
|
|
var $dohistory = true;
|
|
static $rightname = 'slm';
|
|
|
|
// From CommonDBChild
|
|
static public $itemtype = 'SLM';
|
|
static public $items_id = 'slms_id';
|
|
|
|
|
|
/**
|
|
* Display a specific OLA or SLA warning.
|
|
* Called into the above showForm() function
|
|
*
|
|
* @return void
|
|
*/
|
|
abstract function showFormWarning();
|
|
|
|
/**
|
|
* Return the text needed for a confirmation of adding level agreement to a ticket
|
|
*
|
|
* @return array of strings
|
|
*/
|
|
abstract function getAddConfirmation();
|
|
|
|
/**
|
|
* Get table fields
|
|
*
|
|
* @param integer $subtype of OLA/SLA, can be SLM::TTO or SLM::TTR
|
|
*
|
|
* @return array of 'date' and 'sla' field names
|
|
*/
|
|
static function getFieldNames($subtype) {
|
|
|
|
$dateField = null;
|
|
$laField = null;
|
|
|
|
switch ($subtype) {
|
|
case SLM::TTO:
|
|
$dateField = static::$prefixticket.'time_to_own';
|
|
$laField = static::$prefix.'s_id_tto';
|
|
break;
|
|
|
|
case SLM::TTR:
|
|
$dateField = static::$prefixticket.'time_to_resolve';
|
|
$laField = static::$prefix.'s_id_ttr';
|
|
break;
|
|
}
|
|
return [$dateField, $laField];
|
|
}
|
|
|
|
function defineTabs($options = []) {
|
|
|
|
$ong = [];
|
|
$this->addDefaultFormTab($ong);
|
|
$this->addStandardTab(static::$levelclass, $ong, $options);
|
|
$this->addStandardTab('Rule', $ong, $options);
|
|
$this->addStandardTab('Ticket', $ong, $options);
|
|
|
|
return $ong;
|
|
}
|
|
|
|
/**
|
|
* Define calendar of the ticket using the SLA/OLA when using this calendar as sla/ola-s calendar
|
|
*
|
|
* @param integer $calendars_id calendars_id of the ticket
|
|
**/
|
|
function setTicketCalendar($calendars_id) {
|
|
|
|
if ($this->fields['calendars_id'] == -1) {
|
|
$this->fields['calendars_id'] = $calendars_id;
|
|
}
|
|
}
|
|
|
|
function post_getFromDB() {
|
|
// get calendar from slm
|
|
$slm = new SLM;
|
|
if ($slm->getFromDB($this->fields['slms_id'])) {
|
|
$this->fields['calendars_id'] = $slm->fields['calendars_id'];
|
|
}
|
|
}
|
|
|
|
function post_getEmpty() {
|
|
$this->fields['number_time'] = 4;
|
|
$this->fields['definition_time'] = 'hour';
|
|
}
|
|
|
|
/**
|
|
* Print the form
|
|
*
|
|
* @param $ID integer ID of the item
|
|
* @param $options array of possible options:
|
|
* - target filename : where to go when done.
|
|
* - withtemplate boolean : template or basic item
|
|
*
|
|
*@return boolean item found
|
|
**/
|
|
function showForm($ID, $options = []) {
|
|
$rowspan = 3;
|
|
if ($ID > 0) {
|
|
$rowspan = 5;
|
|
}
|
|
|
|
// Get SLM object
|
|
$slm = new SLM();
|
|
if (isset($options['parent'])) {
|
|
$slm = $options['parent'];
|
|
} else {
|
|
$slm->getFromDB($this->fields['slms_id']);
|
|
}
|
|
|
|
if ($ID > 0) {
|
|
$this->check($ID, READ);
|
|
} else {
|
|
// Create item
|
|
$options[static::$items_id] = $slm->getField('id');
|
|
|
|
//force itemtype of parent
|
|
static::$itemtype = get_class($slm);
|
|
|
|
$this->check(-1, CREATE, $options);
|
|
}
|
|
|
|
$this->showFormHeader($options);
|
|
echo "<tr class='tab_bg_1'>";
|
|
echo "<td>".__('Name')."</td>";
|
|
echo "<td>";
|
|
Html::autocompletionTextField($this, "name", ['value' => $this->fields["name"]]);
|
|
echo "<td rowspan='".$rowspan."'>".__('Comments')."</td>";
|
|
echo "<td rowspan='".$rowspan."'>
|
|
<textarea cols='45' rows='8' name='comment' >".$this->fields["comment"]."</textarea>";
|
|
echo "</td></tr>";
|
|
|
|
echo "<tr class='tab_bg_1'>";
|
|
echo "<td>".__('SLM')."</td>";
|
|
echo "<td>";
|
|
echo $slm->getLink();
|
|
echo "<input type='hidden' name='slms_id' value='".$this->fields['slms_id']."'>";
|
|
echo "</td></tr>";
|
|
|
|
if ($ID > 0) {
|
|
echo "<tr class='tab_bg_1'>";
|
|
echo "<td>".__('Last update')."</td>";
|
|
echo "<td>".($this->fields["date_mod"] ? Html::convDateTime($this->fields["date_mod"])
|
|
: __('Never'));
|
|
echo "</td></tr>";
|
|
}
|
|
|
|
echo "<tr class='tab_bg_1'><td>"._n('Type', 'Types', 1)."</td>";
|
|
echo "<td>";
|
|
self::getTypeDropdown(['value' => $this->fields["type"]]);
|
|
echo "</td>";
|
|
echo "</tr>";
|
|
|
|
echo "<tr class='tab_bg_1'><td>".__('Maximum time')."</td>";
|
|
echo "<td>";
|
|
Dropdown::showNumber("number_time", ['value' => $this->fields["number_time"],
|
|
'min' => 0]);
|
|
$possible_values = ['minute' => _n('Minute', 'Minutes', Session::getPluralNumber()),
|
|
'hour' => _n('Hour', 'Hours', Session::getPluralNumber()),
|
|
'day' => _n('Day', 'Days', Session::getPluralNumber())];
|
|
$rand = Dropdown::showFromArray('definition_time', $possible_values,
|
|
['value' => $this->fields["definition_time"],
|
|
'on_change' => 'appearhideendofworking()']);
|
|
echo "\n<script type='text/javascript' >\n";
|
|
echo "function appearhideendofworking() {\n";
|
|
echo "if ($('#dropdown_definition_time$rand option:selected').val() == 'day') {
|
|
$('#title_endworkingday').show();
|
|
$('#dropdown_endworkingday').show();
|
|
} else {
|
|
$('#title_endworkingday').hide();
|
|
$('#dropdown_endworkingday').hide();
|
|
}";
|
|
echo "}\n";
|
|
echo "appearhideendofworking();\n";
|
|
echo "</script>\n";
|
|
|
|
echo "</td></tr>";
|
|
|
|
echo "<tr class='tab_bg_1'>";
|
|
echo "<td><div id='title_endworkingday'>".__('End of working day')."</div></td>";
|
|
echo "<td><div id='dropdown_endworkingday'>";
|
|
Dropdown::showYesNo("end_of_working_day", $this->fields["end_of_working_day"]);
|
|
echo "</div></td>";
|
|
|
|
echo "<td colspan='2'>";
|
|
$this->showFormWarning();
|
|
echo "</td>";
|
|
echo "</tr>";
|
|
|
|
$this->showFormButtons($options);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Show for ticket
|
|
*
|
|
* @param Ticket $ticket Ticket item
|
|
* @param integer $type
|
|
* @param ITILTemplate $tt ticket template object
|
|
* @param bool $canupdate update right
|
|
*/
|
|
function showForTicket(Ticket $ticket, $type, $tt, $canupdate) {
|
|
list($dateField, $laField) = static::getFieldNames($type);
|
|
$rand = mt_rand();
|
|
$pre = static::$prefix;
|
|
echo "<table width='100%'>";
|
|
echo "<tr class='tab_bg_1'>";
|
|
|
|
if (!isset($ticket->fields[$dateField]) || $ticket->fields[$dateField] == 'NULL') {
|
|
$ticket->fields[$dateField]='';
|
|
}
|
|
|
|
if ($ticket->fields['id']) {
|
|
if ($this->getDataForTicket($ticket->fields['id'], $type)) {
|
|
echo "<td style='width: 105px'>";
|
|
echo $tt->getBeginHiddenFieldValue($dateField);
|
|
echo Html::convDateTime($ticket->fields[$dateField]);
|
|
echo $tt->getEndHiddenFieldValue($dateField, $ticket);
|
|
echo "</td>";
|
|
echo "<td>";
|
|
echo $tt->getBeginHiddenFieldText($laField);
|
|
echo "<i class='fas fa-stopwatch slt'></i>";
|
|
echo Dropdown::getDropdownName(static::getTable(),
|
|
$ticket->fields[$laField])." ";
|
|
echo Html::hidden($laField, ['value' => $ticket->fields[$laField]]);
|
|
$obj = new static();
|
|
$obj->getFromDB($ticket->fields[$laField]);
|
|
$comment = isset($obj->fields['comment']) ? $obj->fields['comment'] : '';
|
|
$level = new static::$levelclass();
|
|
$nextaction = new static::$levelticketclass();
|
|
if ($nextaction->getFromDBForTicket($ticket->fields["id"], $type)) {
|
|
$comment .= '<br/><span class="b spaced">'.
|
|
sprintf(__('Next escalation: %s'),
|
|
Html::convDateTime($nextaction->fields['date'])).
|
|
'</span><br>';
|
|
if ($level->getFromDB($nextaction->fields[$pre.'levels_id'])) {
|
|
$comment .= '<span class="b spaced">'.
|
|
sprintf(__('%1$s: %2$s'), _n('Escalation level', 'Escalation levels', 1),
|
|
$level->getName()).
|
|
'</span>';
|
|
}
|
|
}
|
|
|
|
$options = [];
|
|
if (Session::haveRight('slm', READ)) {
|
|
$options['link'] = $this->getLinkURL();
|
|
}
|
|
Html::showToolTip($comment, $options);
|
|
if ($canupdate) {
|
|
$delete_field = strtolower(get_called_class())."_delete";
|
|
$fields = [$delete_field => $delete_field,
|
|
'id' => $ticket->getID(),
|
|
'type' => $type,
|
|
'_glpi_csrf_token' => Session::getNewCSRFToken(),
|
|
'_glpi_simple_form' => 1];
|
|
$ticket_url = $ticket->getFormURL();
|
|
echo Html::scriptBlock("
|
|
function delete_date$type$rand(e) {
|
|
e.preventDefault();
|
|
|
|
if (nativeConfirm('".addslashes(__('Also delete date?'))."')) {
|
|
submitGetLink('$ticket_url',
|
|
".json_encode(array_merge($fields, ['delete_date' => 1])).");
|
|
} else {
|
|
submitGetLink('$ticket_url',
|
|
".json_encode(array_merge($fields, ['delete_date' => 0])).");
|
|
}
|
|
}");
|
|
echo "<a class='fa fa-times-circle pointer'
|
|
onclick='delete_date$type$rand(event)'
|
|
title='"._sx('button', 'Delete permanently')."'>";
|
|
echo "<span class='sr-only'>"._x('button', 'Delete permanently')."</span>";
|
|
echo "</a>";
|
|
}
|
|
echo $tt->getEndHiddenFieldText($laField);
|
|
echo "</td>";
|
|
|
|
} else {
|
|
echo "<td width='200px'>";
|
|
echo $tt->getBeginHiddenFieldValue($dateField);
|
|
echo "<span class='assign_la'>";
|
|
if ($canupdate) {
|
|
Html::showDateTimeField($dateField, ['value' => $ticket->fields[$dateField],
|
|
'maybeempty' => true]);
|
|
} else {
|
|
echo Html::convDateTime($ticket->fields[$dateField]);
|
|
}
|
|
echo "</span>";
|
|
echo $tt->getEndHiddenFieldValue($dateField, $ticket);
|
|
$data = $this->find(
|
|
['type' => $type] + getEntitiesRestrictCriteria('', '', $ticket->fields['entities_id'], true)
|
|
);
|
|
if ($canupdate
|
|
&& !empty($data)) {
|
|
echo $tt->getBeginHiddenFieldText($laField);
|
|
echo "<span id='la_action$type$rand' class='assign_la'>";
|
|
echo "<a ".Html::addConfirmationOnAction($this->getAddConfirmation(),
|
|
"cleanhide('la_action$type$rand');cleandisplay('la_choice$type$rand');").
|
|
" class='pointer' title='".static::getTypeName()."'>
|
|
<i class='fas fa-stopwatch slt'></i></a>";
|
|
echo "</span>";
|
|
echo "<span id='la_choice$type$rand' style='display:none' class='assign_la'>";
|
|
echo "<i class='fas fa-stopwatch slt'></i>";
|
|
echo "<span class='b'>".static::getTypeName()."</span> ";
|
|
static::dropdown([
|
|
'name' => $laField,
|
|
'entity' => $ticket->fields["entities_id"],
|
|
'condition' => ['type' => $type]
|
|
]);
|
|
echo "</span>";
|
|
echo $tt->getEndHiddenFieldText($laField);
|
|
}
|
|
echo "</td>";
|
|
}
|
|
|
|
} else { // New Ticket
|
|
echo "<td>";
|
|
echo $tt->getBeginHiddenFieldValue($dateField);
|
|
Html::showDateTimeField($dateField, ['value' => $ticket->fields[$dateField],
|
|
'maybeempty' => false,
|
|
'canedit' => $canupdate,
|
|
'required' => $tt->isMandatoryField($dateField)]);
|
|
echo $tt->getEndHiddenFieldValue($dateField, $ticket);
|
|
echo "</td>";
|
|
$data = $this->find(
|
|
['type' => $type] + getEntitiesRestrictCriteria('', '', $ticket->fields['entities_id'], true)
|
|
);
|
|
if ($canupdate
|
|
&& !empty($data)) {
|
|
echo $tt->getBeginHiddenFieldText($laField);
|
|
if (!$tt->isHiddenField($laField) || $tt->isPredefinedField($laField)) {
|
|
echo "<th>".sprintf(__('%1$s%2$s'),
|
|
static::getTypeName(),
|
|
$tt->getMandatoryMark($laField))."</th>";
|
|
}
|
|
echo $tt->getEndHiddenFieldText($laField);
|
|
echo "<td class='nopadding'>".$tt->getBeginHiddenFieldValue($laField);
|
|
static::dropdown([
|
|
'name' => $laField,
|
|
'entity' => $ticket->fields["entities_id"],
|
|
'value' => isset($ticket->fields[$laField]) ? $ticket->fields[$laField] : 0,
|
|
'condition' => ['type' => $type]
|
|
]);
|
|
echo $tt->getEndHiddenFieldValue($laField, $ticket);
|
|
echo "</td>";
|
|
}
|
|
}
|
|
|
|
echo "</tr>";
|
|
echo "</table>";
|
|
}
|
|
|
|
|
|
/**
|
|
* Print the HTML for a SLM
|
|
*
|
|
* @param SLM $slm Slm item
|
|
*/
|
|
static function showForSLM(SLM $slm) {
|
|
global $CFG_GLPI;
|
|
|
|
if (!$slm->can($slm->fields['id'], READ)) {
|
|
return false;
|
|
}
|
|
|
|
$instID = $slm->fields['id'];
|
|
$la = new static();
|
|
$calendar = new Calendar();
|
|
$rand = mt_rand();
|
|
$canedit = ($slm->canEdit($instID)
|
|
&& Session::getCurrentInterface() == "central");
|
|
|
|
if ($canedit) {
|
|
echo "<div id='showLa$instID$rand'></div>\n";
|
|
|
|
echo "<script type='text/javascript' >";
|
|
echo "function viewAddLa$instID$rand() {";
|
|
$params = ['type' => $la->getType(),
|
|
'parenttype' => $slm->getType(),
|
|
$slm->getForeignKeyField() => $instID,
|
|
'id' => -1];
|
|
Ajax::updateItemJsCode("showLa$instID$rand",
|
|
$CFG_GLPI["root_doc"]."/ajax/viewsubitem.php", $params);
|
|
echo "}";
|
|
echo "</script>";
|
|
echo "<div class='center firstbloc'>".
|
|
"<a class='vsubmit' href='javascript:viewAddLa$instID$rand();'>";
|
|
echo __('Add a new item')."</a></div>\n";
|
|
}
|
|
|
|
// list
|
|
$laList = $la->find(['slms_id' => $instID]);
|
|
Session::initNavigateListItems(__CLASS__,
|
|
sprintf(__('%1$s = %2$s'),
|
|
$slm::getTypeName(1),
|
|
$slm->getName()));
|
|
echo "<div class='spaced'>";
|
|
if (count($laList)) {
|
|
if ($canedit) {
|
|
Html::openMassiveActionsForm('mass'.__CLASS__.$rand);
|
|
$massiveactionparams = ['container' => 'mass'.__CLASS__.$rand];
|
|
Html::showMassiveActions($massiveactionparams);
|
|
}
|
|
|
|
echo "<table class='tab_cadre_fixehov'>";
|
|
$header_begin = "<tr>";
|
|
$header_top = '';
|
|
$header_bottom = '';
|
|
$header_end = '';
|
|
if ($canedit) {
|
|
$header_top .= "<th width='10'>".Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand);
|
|
$header_top .= "</th>";
|
|
$header_bottom .= "<th width='10'>".Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand);
|
|
$header_bottom .= "</th>";
|
|
}
|
|
$header_end .= "<th>".__('Name')."</th>";
|
|
$header_end .= "<th>"._n('Type', 'Types', 1)."</th>";
|
|
$header_end .= "<th>".__('Maximum time')."</th>";
|
|
$header_end .= "<th>"._n('Calendar', 'Calendars', 1)."</th>";
|
|
|
|
echo $header_begin.$header_top.$header_end;
|
|
foreach ($laList as $val) {
|
|
$edit = ($canedit ? "style='cursor:pointer' onClick=\"viewEditLa".
|
|
$instID.$val["id"]."$rand();\""
|
|
: '');
|
|
echo "<script type='text/javascript' >";
|
|
echo "function viewEditLa".$instID.$val["id"]."$rand() {";
|
|
$params = ['type' => $la->getType(),
|
|
'parenttype' => $slm->getType(),
|
|
$slm->getForeignKeyField() => $instID,
|
|
'id' => $val["id"]];
|
|
Ajax::updateItemJsCode("showLa$instID$rand",
|
|
$CFG_GLPI["root_doc"]."/ajax/viewsubitem.php", $params);
|
|
echo "};";
|
|
echo "</script>\n";
|
|
|
|
echo "<tr class='tab_bg_1'>";
|
|
echo "<td width='10' $edit>";
|
|
if ($canedit) {
|
|
Html::showMassiveActionCheckBox($la->getType(), $val['id']);
|
|
}
|
|
echo "</td>";
|
|
$la->getFromDB($val['id']);
|
|
echo "<td $edit>".$la->getLink()."</td>";
|
|
echo "<td $edit>".$la->getSpecificValueToDisplay('type', $la->fields['type'])."</td>";
|
|
echo "<td $edit>";
|
|
echo $la->getSpecificValueToDisplay('number_time',
|
|
['number_time' => $la->fields['number_time'],
|
|
'definition_time' => $la->fields['definition_time']]);
|
|
echo "</td>";
|
|
if (!$slm->fields['calendars_id']) {
|
|
$link = __('24/7');
|
|
} else if ($slm->fields['calendars_id'] == -1) {
|
|
$link = __('Calendar of the ticket');
|
|
} else if ($calendar->getFromDB($slm->fields['calendars_id'])) {
|
|
$link = $calendar->getLink();
|
|
}
|
|
echo "<td $edit>".$link."</td>";
|
|
echo "</tr>";
|
|
}
|
|
echo $header_begin.$header_bottom.$header_end;
|
|
echo "</table>";
|
|
|
|
if ($canedit) {
|
|
$massiveactionparams['ontop'] = false;
|
|
Html::showMassiveActions($massiveactionparams);
|
|
Html::closeForm();
|
|
}
|
|
} else {
|
|
echo __('No item to display');
|
|
}
|
|
echo "</div>";
|
|
}
|
|
|
|
/**
|
|
* Display a list of rule for the current sla/ola
|
|
* @return void
|
|
*/
|
|
function showRulesList() {
|
|
global $DB;
|
|
|
|
$fk = static::getFieldNames($this->fields['type'])[1];
|
|
$rule = new RuleTicket;
|
|
$rand = mt_rand();
|
|
$canedit = self::canUpdate();
|
|
|
|
$rules_id_list = iterator_to_array($DB->request([
|
|
'SELECT' => 'rules_id',
|
|
'DISTINCT' => true,
|
|
'FROM' => 'glpi_ruleactions',
|
|
'WHERE' => [
|
|
'field' => $fk,
|
|
'value' => $this->getID()]]));
|
|
$nb = count($rules_id_list);
|
|
|
|
echo "<div class='spaced'>";
|
|
if (!$nb) {
|
|
echo "<table class='tab_cadre_fixehov'>";
|
|
echo "<tr><th>" . __('No item found') . "</th>";
|
|
echo "</tr>\n";
|
|
echo "</table>\n";
|
|
|
|
} else {
|
|
if ($canedit) {
|
|
Html::openMassiveActionsForm('massRuleTicket'.$rand);
|
|
$massiveactionparams
|
|
= ['num_displayed' => min($_SESSION['glpilist_limit'], $nb),
|
|
'specific_actions' => ['update' => _x('button', 'Update'),
|
|
'purge' => _x('button', 'Delete permanently')]];
|
|
Html::showMassiveActions($massiveactionparams);
|
|
}
|
|
echo "<table class='tab_cadre_fixehov'>";
|
|
$header_begin = "<tr>";
|
|
$header_top = '';
|
|
$header_bottom = '';
|
|
$header_end = '';
|
|
if ($canedit) {
|
|
$header_begin .= "<th width='10'>";
|
|
$header_top .= Html::getCheckAllAsCheckbox('massRuleTicket'.$rand);
|
|
$header_bottom .= Html::getCheckAllAsCheckbox('massRuleTicket'.$rand);
|
|
$header_end .= "</th>";
|
|
}
|
|
$header_end .= "<th>" . RuleTicket::getTypeName($nb) . "</th>";
|
|
$header_end .= "<th>" . __('Active') . "</th>";
|
|
$header_end .= "<th>" . __('Description') . "</th>";
|
|
$header_end .= "</tr>\n";
|
|
echo $header_begin.$header_top.$header_end;
|
|
|
|
Session::initNavigateListItems(get_class($this),
|
|
sprintf(__('%1$s = %2$s'),
|
|
$rule->getTypeName(1), $rule->getName()));
|
|
|
|
foreach ($rules_id_list as $data) {
|
|
$rule->getFromDB($data['rules_id']);
|
|
Session::addToNavigateListItems(get_class($this), $rule->fields["id"]);
|
|
echo "<tr class='tab_bg_1'>";
|
|
|
|
if ($canedit) {
|
|
echo "<td width='10'>";
|
|
Html::showMassiveActionCheckBox("RuleTicket", $rule->fields["id"]);
|
|
echo "</td>";
|
|
$ruleclassname = get_class($rule);
|
|
echo "<td><a href='".$ruleclassname::getFormURLWithID($rule->fields["id"])
|
|
. "&onglet=1'>" .$rule->fields["name"] ."</a></td>";
|
|
|
|
} else {
|
|
echo "<td>" . $rule->fields["name"] . "</td>";
|
|
}
|
|
|
|
echo "<td>" . Dropdown::getYesNo($rule->fields["is_active"]) . "</td>";
|
|
echo "<td>" . $rule->fields["description"] . "</td>";
|
|
echo "</tr>\n";
|
|
}
|
|
echo $header_begin.$header_bottom.$header_end;
|
|
echo "</table>\n";
|
|
|
|
if ($canedit) {
|
|
$massiveactionparams['ontop'] = false;
|
|
Html::showMassiveActions($massiveactionparams);
|
|
Html::closeForm();
|
|
}
|
|
}
|
|
echo "</div>";
|
|
}
|
|
|
|
function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) {
|
|
|
|
if (!$withtemplate) {
|
|
$nb = 0;
|
|
switch ($item->getType()) {
|
|
case 'SLM' :
|
|
if ($_SESSION['glpishow_count_on_tabs']) {
|
|
$nb = countElementsInTable(self::getTable(),
|
|
['slms_id' => $item->getField('id')]);
|
|
}
|
|
return self::createTabEntry(static::getTypeName($nb), $nb);
|
|
}
|
|
}
|
|
return '';
|
|
}
|
|
|
|
|
|
static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) {
|
|
|
|
switch ($item->getType()) {
|
|
case 'SLM' :
|
|
self::showForSLM($item);
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get data by type and ticket
|
|
*
|
|
* @param $tickets_id
|
|
* @param $type
|
|
*/
|
|
function getDataForTicket($tickets_id, $type) {
|
|
global $DB;
|
|
|
|
list($dateField, $field) = static::getFieldNames($type);
|
|
|
|
$iterator = $DB->request([
|
|
'SELECT' => [static::getTable() . '.id'],
|
|
'FROM' => static::getTable(),
|
|
'INNER JOIN' => [
|
|
'glpi_tickets' => [
|
|
'FKEY' => [
|
|
static::getTable() => 'id',
|
|
'glpi_tickets' => $field
|
|
]
|
|
]
|
|
],
|
|
'WHERE' => ['glpi_tickets.id' => $tickets_id],
|
|
'LIMIT' => 1
|
|
]);
|
|
|
|
if (count($iterator)) {
|
|
return $this->getFromIter($iterator);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
function rawSearchOptions() {
|
|
$tab = [];
|
|
|
|
$tab[] = [
|
|
'id' => 'common',
|
|
'name' => __('Characteristics')
|
|
];
|
|
|
|
$tab[] = [
|
|
'id' => '1',
|
|
'table' => $this->getTable(),
|
|
'field' => 'name',
|
|
'name' => __('Name'),
|
|
'datatype' => 'itemlink',
|
|
'massiveaction' => false,
|
|
'autocomplete' => true,
|
|
];
|
|
|
|
$tab[] = [
|
|
'id' => '2',
|
|
'table' => $this->getTable(),
|
|
'field' => 'id',
|
|
'name' => __('ID'),
|
|
'massiveaction' => false,
|
|
'datatype' => 'number'
|
|
];
|
|
|
|
$tab[] = [
|
|
'id' => '5',
|
|
'table' => $this->getTable(),
|
|
'field' => 'number_time',
|
|
'name' => _x('hour', 'Time'),
|
|
'datatype' => 'specific',
|
|
'massiveaction' => false,
|
|
'nosearch' => true,
|
|
'additionalfields' => ['definition_time']
|
|
];
|
|
|
|
$tab[] = [
|
|
'id' => '6',
|
|
'table' => $this->getTable(),
|
|
'field' => 'end_of_working_day',
|
|
'name' => __('End of working day'),
|
|
'datatype' => 'bool',
|
|
'massiveaction' => false
|
|
];
|
|
|
|
$tab[] = [
|
|
'id' => '7',
|
|
'table' => $this->getTable(),
|
|
'field' => 'type',
|
|
'name' => _n('Type', 'Types', 1),
|
|
'datatype' => 'specific'
|
|
];
|
|
|
|
$tab[] = [
|
|
'id' => '8',
|
|
'table' => 'glpi_slms',
|
|
'field' => 'name',
|
|
'name' => __('SLM'),
|
|
'datatype' => 'dropdown'
|
|
];
|
|
|
|
$tab[] = [
|
|
'id' => '16',
|
|
'table' => $this->getTable(),
|
|
'field' => 'comment',
|
|
'name' => __('Comments'),
|
|
'datatype' => 'text'
|
|
];
|
|
|
|
return $tab;
|
|
}
|
|
|
|
|
|
/**
|
|
* @param $field
|
|
* @param $values
|
|
* @param $options array
|
|
**/
|
|
static function getSpecificValueToDisplay($field, $values, array $options = []) {
|
|
|
|
if (!is_array($values)) {
|
|
$values = [$field => $values];
|
|
}
|
|
switch ($field) {
|
|
case 'number_time' :
|
|
switch ($values['definition_time']) {
|
|
case 'minute' :
|
|
return sprintf(_n('%d minute', '%d minutes', $values[$field]), $values[$field]);
|
|
|
|
case 'hour' :
|
|
return sprintf(_n('%d hour', '%d hours', $values[$field]), $values[$field]);
|
|
|
|
case 'day' :
|
|
return sprintf(_n('%d day', '%d days', $values[$field]), $values[$field]);
|
|
}
|
|
break;
|
|
|
|
case 'type' :
|
|
return self::getOneTypeName($values[$field]);
|
|
}
|
|
return parent::getSpecificValueToDisplay($field, $values, $options);
|
|
}
|
|
|
|
|
|
/**
|
|
* @param $field
|
|
* @param $name (default '')
|
|
* @param $values (default '')
|
|
* @param $options array
|
|
*
|
|
* @return string
|
|
**/
|
|
static function getSpecificValueToSelect($field, $name = '', $values = '', array $options = []) {
|
|
|
|
if (!is_array($values)) {
|
|
$values = [$field => $values];
|
|
}
|
|
$options['display'] = false;
|
|
switch ($field) {
|
|
case 'type':
|
|
$options['value'] = $values[$field];
|
|
return self::getTypeDropdown($options);
|
|
}
|
|
return parent::getSpecificValueToSelect($field, $name, $values, $options);
|
|
}
|
|
|
|
|
|
/**
|
|
* Get computed resolution time
|
|
*
|
|
* @return integer resolution time (default 0)
|
|
**/
|
|
function getTime() {
|
|
|
|
if (isset($this->fields['id'])) {
|
|
if ($this->fields['definition_time'] == "minute") {
|
|
return $this->fields['number_time'] * MINUTE_TIMESTAMP;
|
|
}
|
|
if ($this->fields['definition_time'] == "hour") {
|
|
return $this->fields['number_time'] * HOUR_TIMESTAMP;
|
|
}
|
|
if ($this->fields['definition_time'] == "day") {
|
|
return $this->fields['number_time'] * DAY_TIMESTAMP;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get active time between to date time for the active calendar
|
|
*
|
|
* @param datetime $start begin
|
|
* @param datetime $end end
|
|
*
|
|
* @return integer timestamp of delay
|
|
**/
|
|
function getActiveTimeBetween($start, $end) {
|
|
|
|
if ($end < $start) {
|
|
return 0;
|
|
}
|
|
|
|
if (isset($this->fields['id'])) {
|
|
$cal = new Calendar();
|
|
$work_in_days = ($this->fields['definition_time'] == 'day');
|
|
|
|
// Based on a calendar
|
|
if ($this->fields['calendars_id'] > 0) {
|
|
if ($cal->getFromDB($this->fields['calendars_id'])) {
|
|
return $cal->getActiveTimeBetween($start, $end, $work_in_days);
|
|
}
|
|
|
|
} else { // No calendar
|
|
$timestart = strtotime($start);
|
|
$timeend = strtotime($end);
|
|
return ($timeend-$timestart);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get date for current agreement
|
|
*
|
|
* @param string $start_date datetime start date
|
|
* @param integer $additional_delay integer additional delay to add or substract (for waiting time)
|
|
*
|
|
* @return string|null due date time (NULL if sla/ola not exists)
|
|
**/
|
|
function computeDate($start_date, $additional_delay = 0) {
|
|
|
|
if (isset($this->fields['id'])) {
|
|
$delay = $this->getTime();
|
|
// Based on a calendar
|
|
if ($this->fields['calendars_id'] > 0) {
|
|
$cal = new Calendar();
|
|
$work_in_days = ($this->fields['definition_time'] == 'day');
|
|
|
|
if ($cal->getFromDB($this->fields['calendars_id']) && $cal->hasAWorkingDay()) {
|
|
return $cal->computeEndDate($start_date, $delay,
|
|
$additional_delay, $work_in_days,
|
|
$this->fields['end_of_working_day']);
|
|
}
|
|
}
|
|
|
|
// No calendar defined or invalid calendar
|
|
if ($this->fields['number_time'] >= 0) {
|
|
$starttime = strtotime($start_date);
|
|
$endtime = $starttime + $delay + $additional_delay;
|
|
return date('Y-m-d H:i:s', $endtime);
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get execution date of a level
|
|
*
|
|
* @param string $start_date start date
|
|
* @param integer $levels_id sla/ola level id
|
|
* @param integer $additional_delay additional delay to add or substract (for waiting time)
|
|
*
|
|
* @return string|null execution date time (NULL if ola/sla not exists)
|
|
**/
|
|
function computeExecutionDate($start_date, $levels_id, $additional_delay = 0) {
|
|
|
|
if (isset($this->fields['id'])) {
|
|
$level = new static::$levelclass();
|
|
$fk = getForeignKeyFieldForItemType(get_called_class());
|
|
|
|
if ($level->getFromDB($levels_id)) { // level exists
|
|
if ($level->fields[$fk] == $this->fields['id']) { // correct level
|
|
$work_in_days = ($this->fields['definition_time'] == 'day');
|
|
$delay = $this->getTime();
|
|
|
|
// Based on a calendar
|
|
if ($this->fields['calendars_id'] > 0) {
|
|
$cal = new Calendar();
|
|
if ($cal->getFromDB($this->fields['calendars_id']) && $cal->hasAWorkingDay()) {
|
|
return $cal->computeEndDate($start_date, $delay,
|
|
$level->fields['execution_time'] + $additional_delay,
|
|
$work_in_days);
|
|
}
|
|
}
|
|
// No calendar defined or invalid calendar
|
|
$delay += $additional_delay+$level->fields['execution_time'];
|
|
$starttime = strtotime($start_date);
|
|
$endtime = $starttime+$delay;
|
|
return date('Y-m-d H:i:s', $endtime);
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get types
|
|
*
|
|
* @return array array of types
|
|
**/
|
|
static function getTypes() {
|
|
return [SLM::TTO => __('Time to own'),
|
|
SLM::TTR => __('Time to resolve')];
|
|
}
|
|
|
|
|
|
/**
|
|
* Get types name
|
|
*
|
|
* @param integer $type
|
|
* @return string name
|
|
**/
|
|
static function getOneTypeName($type) {
|
|
|
|
$types = self::getTypes();
|
|
$name = null;
|
|
if (isset($types[$type])) {
|
|
$name = $types[$type];
|
|
}
|
|
return $name;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get SLA types dropdown
|
|
*
|
|
* @param array $options
|
|
*
|
|
* @return string
|
|
*/
|
|
static function getTypeDropdown($options) {
|
|
|
|
$params = ['name' => 'type'];
|
|
|
|
foreach ($options as $key => $val) {
|
|
$params[$key] = $val;
|
|
}
|
|
|
|
return Dropdown::showFromArray($params['name'], self::getTypes(), $options);
|
|
}
|
|
|
|
|
|
function prepareInputForAdd($input) {
|
|
|
|
if ($input['definition_time'] != 'day') {
|
|
$input['end_of_working_day'] = 0;
|
|
}
|
|
return $input;
|
|
}
|
|
|
|
|
|
function prepareInputForUpdate($input) {
|
|
|
|
if (isset($input['definition_time']) && $input['definition_time'] != 'day') {
|
|
$input['end_of_working_day'] = 0;
|
|
}
|
|
return $input;
|
|
}
|
|
|
|
|
|
/**
|
|
* Add a level to do for a ticket
|
|
*
|
|
* @param Ticket $ticket Ticket object
|
|
* @param integer $levels_id SlaLevel or OlaLevel ID
|
|
*
|
|
* @return void
|
|
**/
|
|
function addLevelToDo(Ticket $ticket, $levels_id = 0) {
|
|
|
|
$pre = static::$prefix;
|
|
|
|
if (!$levels_id && isset($ticket->fields[$pre.'levels_id_ttr'])) {
|
|
$levels_id = $ticket->fields[$pre."levels_id_ttr"];
|
|
}
|
|
|
|
if ($levels_id) {
|
|
$toadd = [];
|
|
$date = $this->computeExecutionDate($ticket->fields['date'], $levels_id,
|
|
$ticket->fields[$pre.'_waiting_duration']);
|
|
if ($date != null) {
|
|
$toadd['date'] = $date;
|
|
$toadd[$pre.'levels_id'] = $levels_id;
|
|
$toadd['tickets_id'] = $ticket->fields["id"];
|
|
$levelticket = new static::$levelticketclass();
|
|
$levelticket->add($toadd);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* remove a level to do for a ticket
|
|
*
|
|
* @param $ticket Ticket object
|
|
*
|
|
* @return void
|
|
**/
|
|
static function deleteLevelsToDo(Ticket $ticket) {
|
|
global $DB;
|
|
|
|
$ticketfield = static::$prefix."levels_id_ttr";
|
|
|
|
if ($ticket->fields[$ticketfield] > 0) {
|
|
$levelticket = new static::$levelticketclass();
|
|
$iterator = $DB->request([
|
|
'SELECT' => 'id',
|
|
'FROM' => $levelticket::getTable(),
|
|
'WHERE' => ['tickets_id' => $ticket->fields['id']]
|
|
]);
|
|
|
|
while ($data = $iterator->next()) {
|
|
$levelticket->delete(['id' => $data['id']]);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function cleanDBonPurge() {
|
|
global $DB;
|
|
|
|
// Clean levels
|
|
$classname = get_called_class();
|
|
$fk = getForeignKeyFieldForItemType($classname);
|
|
$level = new static::$levelclass();
|
|
$level->deleteByCriteria([$fk => $this->getID()]);
|
|
|
|
// Update tickets : clean SLA/OLA
|
|
list($dateField, $laField) = static::getFieldNames($this->fields['type']);
|
|
$iterator = $DB->request([
|
|
'SELECT' => 'id',
|
|
'FROM' => 'glpi_tickets',
|
|
'WHERE' => [$laField => $this->fields['id']]
|
|
]);
|
|
|
|
if (count($iterator)) {
|
|
$ticket = new Ticket();
|
|
while ($data = $iterator->next()) {
|
|
$ticket->deleteLevelAgreement($classname, $data['id'], $this->fields['type']);
|
|
}
|
|
}
|
|
|
|
Rule::cleanForItemAction($this);
|
|
}
|
|
}
|