1<?php 2/* Copyright (C) 2013-2016 Jean-François FERRY <hello@librethic.io> 3 * Copyright (C) 2016 Christophe Battarel <christophe@altairis.fr> 4 * Copyright (C) 2018 Laurent Destailleur <eldy@users.sourceforge.net> 5 * Copyright (C) 2021 Frédéric France <frederic.france@netlogic.fr> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <https://www.gnu.org/licenses/>. 19 */ 20 21/** 22 * \file htdocs/ticket/card.php 23 * \ingroup ticket 24 */ 25 26require '../main.inc.php'; 27require_once DOL_DOCUMENT_ROOT.'/ticket/class/actions_ticket.class.php'; 28require_once DOL_DOCUMENT_ROOT.'/core/class/html.formticket.class.php'; 29require_once DOL_DOCUMENT_ROOT.'/core/lib/ticket.lib.php'; 30require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; 31require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; 32require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; 33require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; 34if (!empty($conf->projet->enabled)) { 35 include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; 36 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php'; 37 include_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php'; 38} 39if (!empty($conf->contrat->enabled)) { 40 include_once DOL_DOCUMENT_ROOT.'/core/lib/contract.lib.php'; 41 include_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php'; 42 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formcontract.class.php'; 43} 44 45// Load translation files required by the page 46$langs->loadLangs(array("companies", "other", "ticket")); 47 48// Get parameters 49$id = GETPOST('id', 'int'); 50$socid = GETPOST('socid', 'int'); 51$track_id = GETPOST('track_id', 'alpha', 3); 52$ref = GETPOST('ref', 'alpha'); 53$projectid = GETPOST('projectid', 'int'); 54$cancel = GETPOST('cancel', 'alpha'); 55$action = GETPOST('action', 'aZ09'); 56$backtopage = GETPOST('$backtopage', 'alpha'); 57 58$notifyTiers = GETPOST("notify_tiers_at_create", 'alpha'); 59 60$sortfield = GETPOST('sortfield', 'aZ09comma'); 61$sortorder = GETPOST('sortorder', 'aZ09comma'); 62 63if (GETPOST('actioncode', 'array')) { 64 $actioncode = GETPOST('actioncode', 'array', 3); 65 if (!count($actioncode)) { 66 $actioncode = '0'; 67 } 68} else { 69 $actioncode = GETPOST("actioncode", "alpha", 3) ?GETPOST("actioncode", "alpha", 3) : (GETPOST("actioncode") == '0' ? '0' : (empty($conf->global->AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT) ? '' : $conf->global->AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT)); 70} 71$search_agenda_label = GETPOST('search_agenda_label'); 72 73// Initialize technical object to manage hooks of ticket. Note that conf->hooks_modules contains array array 74$hookmanager->initHooks(array('ticketcard', 'globalcard')); 75 76$object = new Ticket($db); 77$extrafields = new ExtraFields($db); 78 79// Fetch optionals attributes and labels 80$extrafields->fetch_name_optionals_label($object->table_element); 81 82$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); 83 84// Initialize array of search criterias 85$search_all = GETPOST("search_all", 'alpha'); 86$search = array(); 87foreach ($object->fields as $key => $val) { 88 if (GETPOST('search_'.$key, 'alpha')) { 89 $search[$key] = GETPOST('search_'.$key, 'alpha'); 90 } 91} 92 93if (empty($action) && empty($id) && empty($ref)) { 94 $action = 'view'; 95} 96 97//Select mail models is same action as add_message 98if (GETPOST('modelselected', 'alpha')) { 99 $action = 'presend'; 100} 101 102// Load object 103//include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals 104if ($id || $track_id || $ref) { 105 $res = $object->fetch($id, $ref, $track_id); 106 if ($res >= 0) { 107 $id = $object->id; 108 $track_id = $object->track_id; 109 } 110} 111 112// Store current page url 113$url_page_current = DOL_URL_ROOT.'/ticket/card.php'; 114 115// Security check - Protection if external user 116$socid = 0; 117if ($user->socid > 0) $socid = $user->socid; 118$result = restrictedArea($user, 'ticket', $object->id); 119 120$triggermodname = 'TICKET_MODIFY'; 121$permissiontoadd = $user->rights->ticket->write; 122 123$actionobject = new ActionsTicket($db); 124 125$now = dol_now(); 126 127 128/* 129 * Actions 130 */ 131 132$parameters = array(); 133$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks 134if ($reshook < 0) { 135 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); 136} 137 138$error = 0; 139if (empty($reshook)) { 140 // Purge search criteria 141 if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All test are required to be compatible with all browsers{ 142 $actioncode = ''; 143 $search_agenda_label = ''; 144 } 145 146 if ($cancel) { 147 if (!empty($backtopage)) { 148 header("Location: ".$backtopage); 149 exit; 150 } 151 152 $action = 'view'; 153 } 154 155 // Action to add an action (not a message) 156 if (GETPOST('add', 'alpha') && !empty($user->rights->ticket->write)) { 157 $error = 0; 158 159 if (!GETPOST("subject", 'alphanohtml')) { 160 $error++; 161 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Subject")), null, 'errors'); 162 $action = 'create'; 163 } elseif (!GETPOST("message", 'restricthtml')) { 164 $error++; 165 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Message")), null, 'errors'); 166 $action = 'create'; 167 } 168 $ret = $extrafields->setOptionalsFromPost(null, $object); 169 if ($ret < 0) { 170 $error++; 171 } 172 173 if (!$error) { 174 $db->begin(); 175 176 $object->ref = GETPOST("ref", 'alphanohtml'); 177 $object->fk_soc = GETPOST("socid", 'int') > 0 ? GETPOST("socid", 'int') : 0; 178 $object->subject = GETPOST("subject", 'alphanohtml'); 179 $object->message = GETPOST("message", 'restricthtml'); 180 181 $object->type_code = GETPOST("type_code", 'alpha'); 182 $object->type_label = $langs->trans($langs->getLabelFromKey($db, $object->type_code, 'c_ticket_type', 'code', 'label')); 183 $object->category_code = GETPOST("category_code", 'alpha'); 184 $object->category_label = $langs->trans($langs->getLabelFromKey($db, $object->category_code, 'c_ticket_category', 'code', 'label')); 185 $object->severity_code = GETPOST("severity_code", 'alpha'); 186 $object->severity_label = $langs->trans($langs->getLabelFromKey($db, $object->severity_code, 'c_ticket_severity', 'code', 'label')); 187 $object->email_from = $user->email; 188 $notifyTiers = GETPOST("notify_tiers_at_create", 'alpha'); 189 $object->notify_tiers_at_create = empty($notifyTiers) ? 0 : 1; 190 191 $object->fk_project = $projectid; 192 193 $id = $object->create($user); 194 if ($id <= 0) { 195 $error++; 196 setEventMessages($object->error, $object->errors, 'errors'); 197 $action = 'create'; 198 } 199 200 if (!$error) { 201 // Add contact 202 $contactid = GETPOST('contactid', 'int'); 203 $type_contact = GETPOST("type", 'alpha'); 204 205 if ($contactid > 0 && $type_contact) { 206 $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type')); 207 $result = $object->add_contact($contactid, $typeid, 'external'); 208 } 209 210 // Link ticket to project 211 if ($projectid > 0) { 212 $object->setProject($projectid); 213 } 214 215 // Auto assign user 216 if (!empty($conf->global->TICKET_AUTO_ASSIGN_USER_CREATE)) { 217 $result = $object->assignUser($user, $user->id, 1); 218 $object->add_contact($user->id, "SUPPORTTEC", 'internal'); 219 } 220 221 // Auto assign contrat 222 $contractid = 0; 223 if (!empty($conf->global->TICKET_AUTO_ASSIGN_CONTRACT_CREATE)) { 224 $contrat = new Contrat($db); 225 $contrat->socid = $object->fk_soc; 226 $list = $contrat->getListOfContracts(); 227 228 if (is_array($list) && !empty($list)) { 229 if (count($list) == 1) { 230 $contractid = $list[0]->id; 231 $object->setContract($contractid); 232 } else { 233 } 234 } 235 } 236 237 // Auto create fiche intervention 238 if (!empty($conf->global->TICKET_AUTO_CREATE_FICHINTER_CREATE)) { 239 $fichinter = new Fichinter($db); 240 $fichinter->socid = $object->fk_soc; 241 $fichinter->fk_project = $projectid; 242 $fichinter->fk_contrat = $contractid; 243 $fichinter->author = $user->id; 244 $fichinter->model_pdf = 'soleil'; 245 $fichinter->origin = $object->element; 246 $fichinter->origin_id = $object->id; 247 248 // Extrafields 249 $extrafields->fetch_name_optionals_label($fichinter->table_element); 250 $array_options = $extrafields->getOptionalsFromPost($fichinter->table_element); 251 $fichinter->array_options = $array_options; 252 253 $id = $fichinter->create($user); 254 if ($id <= 0) { 255 setEventMessages($fichinter->error, null, 'errors'); 256 } 257 } 258 } 259 260 if (!$error) { 261 // File transfer 262 $object->copyFilesForTicket(); 263 } 264 265 if (!$error) { 266 $db->commit(); 267 268 if (!empty($backtopage)) { 269 $url = $backtopage; 270 } else { 271 $url = 'card.php?track_id='.$object->track_id; 272 } 273 274 header("Location: ".$url); 275 exit; 276 } else { 277 $db->rollback(); 278 setEventMessages($object->error, $object->errors, 'errors'); 279 } 280 } else { 281 setEventMessages($object->error, $object->errors, 'errors'); 282 } 283 } 284 285 if ($action == 'update' && $user->rights->ticket->write && $object->fk_statut < Ticket::STATUS_CLOSED) { 286 $error = 0; 287 288 $ret = $object->fetch(GETPOST('id', 'int'), GETPOST('ref', 'alpha'), GETPOST('track_id', 'alpha')); 289 if ($ret < 0) { 290 $error++; 291 array_push($object->errors, $langs->trans('ErrorTicketIsNotValid')); 292 } 293 294 // check fields 295 if (!$error) { 296 if (!GETPOST('subject', 'alpha')) { 297 $error++; 298 array_push($object->errors, $langs->trans('ErrorFieldRequired', $langs->transnoentities('Subject'))); 299 } 300 $ret = $extrafields->setOptionalsFromPost(null, $object); 301 if ($ret < 0) { 302 $error++; 303 } 304 } 305 306 if (!$error) { 307 $db->begin(); 308 309 $object->subject = GETPOST('subject', 'alpha'); 310 $object->type_code = GETPOST('type_code', 'alpha'); 311 $object->category_code = GETPOST('category_code', 'alpha'); 312 $object->severity_code = GETPOST('severity_code', 'alpha'); 313 314 $ret = $object->update($user); 315 if ($ret <= 0) { 316 $error++; 317 } 318 319 if ($error) { 320 $db->rollback(); 321 } else { 322 $db->commit(); 323 } 324 } 325 326 if ($error) { 327 setEventMessages($object->error, $object->errors, 'errors'); 328 $action = 'edit'; 329 } else { 330 if (!empty($backtopage)) { 331 $url = $backtopage; 332 } else { 333 $url = 'card.php?track_id='.$object->track_id; 334 } 335 336 header('Location: '.$url); 337 exit(); 338 } 339 } 340 341 // Mark as Read 342 if ($action == "mark_ticket_read" && $user->rights->ticket->write) { 343 $object->fetch('', '', GETPOST("track_id", 'alpha')); 344 345 if ($object->markAsRead($user) > 0) { 346 setEventMessages($langs->trans('TicketMarkedAsRead'), null, 'mesgs'); 347 348 header("Location: card.php?track_id=".$object->track_id."&action=view"); 349 exit; 350 } else { 351 setEventMessages($object->error, $object->errors, 'errors'); 352 } 353 $action = 'view'; 354 } 355 356 // Assign to someone 357 if ($action == "assign_user" && GETPOST('btn_assign_user', 'alpha') && $user->rights->ticket->write) { 358 $object->fetch('', '', GETPOST("track_id", 'alpha')); 359 $useroriginassign = $object->fk_user_assign; 360 $usertoassign = GETPOST('fk_user_assign', 'int'); 361 362 /*if (! ($usertoassign > 0)) { 363 $error++; 364 array_push($object->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("AssignedTo"))); 365 $action = 'view'; 366 }*/ 367 368 if (!$error) { 369 $ret = $object->assignUser($user, $usertoassign); 370 if ($ret < 0) { 371 $error++; 372 } 373 } 374 375 if (!$error) { // Update list of contacts 376 // Si déjà un user assigné on le supprime des contacts 377 if ($useroriginassign > 0) { 378 $internal_contacts = $object->listeContact(-1, 'internal'); 379 380 foreach ($internal_contacts as $key => $contact) { 381 if ($contact['code'] == "SUPPORTTEC" && $contact['id'] == $useroriginassign) { 382 } 383 { 384 //print "user à effacer : ".$useroriginassign; 385 $object->delete_contact($contact['rowid']); 386 } 387 } 388 } 389 390 if ($usertoassign > 0) { 391 $object->add_contact($usertoassign, "SUPPORTTEC", 'internal', $notrigger = 0); 392 } 393 } 394 395 if (!$error) { 396 // Log action in ticket logs table 397 $object->fetch_user($usertoassign); 398 $log_action = $langs->trans('TicketLogAssignedTo', $object->user->getFullName($langs)); 399 400 setEventMessages($langs->trans('TicketAssigned'), null, 'mesgs'); 401 402 header("Location: card.php?track_id=".$object->track_id."&action=view"); 403 exit; 404 } else { 405 array_push($object->errors, $object->error); 406 } 407 $action = 'view'; 408 } 409 410 // Action to add an action (not a message) 411 if ($action == 'add_message' && GETPOSTISSET('btn_add_message') && $user->rights->ticket->read) { 412 $ret = $object->newMessage($user, $action, (GETPOST('private_message', 'alpha') == "on" ? 1 : 0)); 413 414 if ($ret > 0) { 415 if (!empty($backtopage)) { 416 $url = $backtopage; 417 } else { 418 $url = 'card.php?action=view&track_id='.$object->track_id; 419 } 420 421 header("Location: ".$url); 422 exit; 423 } else { 424 setEventMessages($object->error, null, 'errors'); 425 $action = 'presend'; 426 } 427 } 428 429 if (($action == "confirm_close" || $action == "confirm_abandon") && GETPOST('confirm', 'alpha') == 'yes' && $user->rights->ticket->write) { 430 $object->fetch(GETPOST('id', 'int'), '', GETPOST('track_id', 'alpha')); 431 432 if ($object->close($user, ($action == "confirm_abandon" ? 1 : 0))) { 433 setEventMessages($langs->trans('TicketMarkedAsClosed'), null, 'mesgs'); 434 435 $url = 'card.php?action=view&track_id='.GETPOST('track_id', 'alpha'); 436 header("Location: ".$url); 437 } else { 438 $action = ''; 439 setEventMessages($object->error, $object->errors, 'errors'); 440 } 441 } 442 443 if ($action == "confirm_public_close" && GETPOST('confirm', 'alpha') == 'yes') { 444 $object->fetch(GETPOST('id', 'int'), '', GETPOST('track_id', 'alpha')); 445 if ($_SESSION['email_customer'] == $object->origin_email || $_SESSION['email_customer'] == $object->thirdparty->email) { 446 $object->close($user); 447 448 // Log action in ticket logs table 449 $log_action = $langs->trans('TicketLogClosedBy', $_SESSION['email_customer']); 450 451 setEventMessages('<div class="confirm">'.$langs->trans('TicketMarkedAsClosed').'</div>', null, 'mesgs'); 452 453 $url = 'card.php?action=view_ticket&track_id='.GETPOST('track_id', 'alpha'); 454 header("Location: ".$url); 455 } else { 456 setEventMessages($object->error, $object->errors, 'errors'); 457 $action = ''; 458 } 459 } 460 461 if ($action == 'confirm_delete_ticket' && GETPOST('confirm', 'alpha') == "yes" && $user->rights->ticket->delete) { 462 if ($object->fetch(GETPOST('id', 'int'), '', GETPOST('track_id', 'alpha')) >= 0) { 463 if ($object->delete($user) > 0) { 464 setEventMessages('<div class="confirm">'.$langs->trans('TicketDeletedSuccess').'</div>', null, 'mesgs'); 465 Header("Location: ".DOL_URL_ROOT."/ticket/list.php"); 466 exit; 467 } else { 468 $langs->load("errors"); 469 $mesg = '<div class="error">'.$langs->trans($object->error).'</div>'; 470 $action = ''; 471 } 472 } 473 } 474 475 // Set parent company 476 if ($action == 'set_thirdparty' && $user->rights->ticket->write) { 477 if ($object->fetch(GETPOST('id', 'int'), '', GETPOST('track_id', 'alpha')) >= 0) { 478 $result = $object->setCustomer(GETPOST('editcustomer', 'int')); 479 $url = 'card.php?action=view&track_id='.GETPOST('track_id', 'alpha'); 480 header("Location: ".$url); 481 exit(); 482 } 483 } 484 485 if ($action == 'set_progression' && $user->rights->ticket->write) { 486 if ($object->fetch(GETPOST('id', 'int'), '', GETPOST('track_id', 'alpha')) >= 0) { 487 $result = $object->setProgression(GETPOST('progress', 'alpha')); 488 489 $url = 'card.php?action=view&track_id='.$object->track_id; 490 header("Location: ".$url); 491 exit(); 492 } 493 } 494 495 if ($action == 'setsubject' && $user->rights->ticket->write) { 496 if ($object->fetch(GETPOST('id', 'int'))) { 497 if ($action == 'setsubject') { 498 $object->subject = GETPOST('subject', 'alphanohtml'); 499 } 500 501 if ($action == 'setsubject' && empty($object->subject)) { 502 $error++; 503 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Subject")), null, 'errors'); 504 } 505 506 if (!$error) { 507 if ($object->update($user) >= 0) { 508 header("Location: ".$_SERVER['PHP_SELF']."?track_id=".$object->track_id); 509 exit; 510 } else { 511 $error++; 512 setEventMessages($object->error, $object->errors, 'errors'); 513 } 514 } 515 } 516 } 517 518 if ($action == 'confirm_reopen' && $user->rights->ticket->manage && !GETPOST('cancel')) { 519 if ($object->fetch(GETPOST('id', 'int'), '', GETPOST('track_id', 'alpha')) >= 0) { 520 // prevent browser refresh from reopening ticket several times 521 if ($object->fk_statut == Ticket::STATUS_CLOSED || $object->fk_statut == Ticket::STATUS_CANCELED) { 522 $res = $object->setStatut(Ticket::STATUS_ASSIGNED); 523 if ($res) { 524 // Log action in ticket logs table 525 $log_action = $langs->trans('TicketLogReopen'); 526 527 $url = 'card.php?action=view&track_id='.$object->track_id; 528 header("Location: ".$url); 529 exit(); 530 } else { 531 $error++; 532 setEventMessages($object->error, $object->errors, 'errors'); 533 } 534 } 535 } 536 } elseif ($action == 'classin' && $user->rights->ticket->write) { 537 // Categorisation dans projet 538 if ($object->fetch(GETPOST('id', 'int'), '', GETPOST('track_id', 'alpha')) >= 0) { 539 $object->setProject($projectid); 540 $url = 'card.php?action=view&track_id='.$object->track_id; 541 header("Location: ".$url); 542 exit(); 543 } 544 } elseif ($action == 'setcontract' && $user->rights->ticket->write) { 545 // Categorisation dans contrat 546 if ($object->fetch(GETPOST('id', 'int'), '', GETPOST('track_id', 'alpha')) >= 0) { 547 $object->setContract(GETPOST('contractid', 'int')); 548 $url = 'card.php?action=view&track_id='.$object->track_id; 549 header("Location: ".$url); 550 exit(); 551 } 552 } elseif ($action == "set_message" && $user->rights->ticket->manage) { 553 // altairis: manage cancel button 554 if (!GETPOST('cancel')) { 555 $object->fetch('', '', GETPOST('track_id', 'alpha')); 556 $oldvalue_message = $object->message; 557 $fieldtomodify = GETPOST('message_initial', 'restricthtml'); 558 559 $object->message = $fieldtomodify; 560 $ret = $object->update($user); 561 if ($ret > 0) { 562 $log_action = $langs->trans('TicketInitialMessageModified')." \n"; 563 // include the Diff class 564 dol_include_once('/ticket/class/utils_diff.class.php'); 565 // output the result of comparing two files as plain text 566 $log_action .= Diff::toString(Diff::compare(strip_tags($oldvalue_message), strip_tags($object->message))); 567 568 setEventMessages($langs->trans('TicketMessageSuccesfullyUpdated'), null, 'mesgs'); 569 } else { 570 $error++; 571 setEventMessages($object->error, $object->errors, 'errors'); 572 } 573 } 574 575 $action = 'view'; 576 } elseif ($action == 'confirm_set_status' && $user->rights->ticket->write && !GETPOST('cancel')) { 577 // Reopen ticket 578 if ($object->fetch(GETPOST('id', 'int'), GETPOST('track_id', 'alpha')) >= 0) { 579 $new_status = GETPOST('new_status', 'int'); 580 $old_status = $object->fk_statut; 581 $res = $object->setStatut($new_status); 582 if ($res) { 583 // Log action in ticket logs table 584 $log_action = $langs->trans('TicketLogStatusChanged', $langs->transnoentities($object->statuts_short[$old_status]), $langs->transnoentities($object->statuts_short[$new_status])); 585 586 $url = 'card.php?action=view&track_id='.$object->track_id; 587 header("Location: ".$url); 588 exit(); 589 } else { 590 $error++; 591 setEventMessages($object->error, $object->errors, 'errors'); 592 } 593 } 594 } 595 596 // Action to update one extrafield 597 if ($action == "update_extras" && !empty($permissiontoadd)) { 598 $object->fetch(GETPOST('id', 'int'), '', GETPOST('track_id', 'alpha')); 599 600 $ret = $extrafields->setOptionalsFromPost(null, $object, GETPOST('attribute', 'restricthtml')); 601 if ($ret < 0) { 602 $error++; 603 } 604 605 if (!$error) { 606 $result = $object->insertExtraFields(empty($triggermodname) ? '' : $triggermodname, $user); 607 if ($result < 0) { 608 $error++; 609 } 610 } 611 612 if ($error) { 613 setEventMessages($object->error, $object->errors, 'errors'); 614 $action = 'edit_extras'; 615 } else { 616 setEventMessages($langs->trans('RecordSaved'), null, 'mesgs'); 617 $action = 'view'; 618 } 619 } 620 621 if ($action == "change_property" && GETPOST('btn_update_ticket_prop', 'alpha') && $user->rights->ticket->write) { 622 $object->fetch(GETPOST('id', 'int'), '', GETPOST('track_id', 'alpha')); 623 624 $object->type_code = GETPOST('update_value_type', 'aZ09'); 625 $object->severity_code = GETPOST('update_value_severity', 'aZ09'); 626 $object->category_code = GETPOST('update_value_category', 'aZ09'); 627 628 $ret = $object->update($user); 629 if ($ret > 0) { 630 $log_action = $langs->trans('TicketLogPropertyChanged', $oldvalue_label, $newvalue_label); 631 632 setEventMessages($langs->trans('TicketUpdated'), null, 'mesgs'); 633 } else { 634 $error++; 635 setEventMessages($object->error, $object->errors, 'errors'); 636 } 637 $action = 'view'; 638 } 639 640 641 $permissiondellink = $user->rights->ticket->write; 642 include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; // Must be include, not include_once 643 644 // Actions to build doc 645 $upload_dir = $conf->ticket->dir_output; 646 $permissiontoadd = $user->rights->ticket->write; 647 include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; 648 649 // Actions to send emails 650 $triggersendname = 'TICKET_SENTBYMAIL'; 651 $paramname = 'id'; 652 $autocopy = 'MAIN_MAIL_AUTOCOPY_TICKET_TO'; // used to know the automatic BCC to add 653 $trackid = 'tic'.$object->id; 654 include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php'; 655 656 // Set $action to correct value for the case we used presend action to add a message 657 if (GETPOSTISSET('actionbis') && $action == 'presend') { 658 $action = 'presend_addmessage'; 659 } 660} 661 662 663/* 664 * View 665 */ 666 667$userstat = new User($db); 668$form = new Form($db); 669$formticket = new FormTicket($db); 670if (!empty($conf->projet->enabled)) { 671 $formproject = new FormProjets($db); 672} 673 674$help_url = 'EN:Module_Ticket|FR:DocumentationModuleTicket'; 675 676$page_title = $actionobject->getTitle($action); 677 678llxHeader('', $page_title, $help_url); 679 680if ($action == 'create' || $action == 'presend') { 681 $formticket = new FormTicket($db); 682 683 print load_fiche_titre($langs->trans('NewTicket'), '', 'ticket'); 684 685 $formticket->withfromsocid = $socid ? $socid : $user->socid; 686 $formticket->withfromcontactid = $contactid ? $contactid : ''; 687 $formticket->withtitletopic = 1; 688 $formticket->withnotifytiersatcreate = ($notifyTiers ? 1 : 0); 689 $formticket->withusercreate = 0; 690 $formticket->withref = 1; 691 $formticket->fk_user_create = $user->id; 692 $formticket->withfile = 2; 693 $formticket->withextrafields = 1; 694 $formticket->param = array('origin' => GETPOST('origin'), 'originid' => GETPOST('originid')); 695 696 $formticket->showForm(1, 'create', 0); 697 /*} elseif ($action == 'edit' && $user->rights->ticket->write && $object->fk_statut < Ticket::STATUS_CLOSED) { 698 $formticket = new FormTicket($db); 699 700 $head = ticket_prepare_head($object); 701 702 print '<form method="POST" name="form_ticket" id="form_edit_ticket" action="'.$_SERVER['PHP_SELF'].'?track_id='.$object->track_id.'">'; 703 print '<input type="hidden" name="token" value="'.newToken().'">'; 704 print '<input type="hidden" name="action" value="update">'; 705 print '<input type="hidden" name="tack_id" value="'.$object->track_id.'">'; 706 707 print dol_get_fiche_head($head, 'card', $langs->trans('Ticket'), 0, 'ticket'); 708 709 print '<div class="fichecenter2">'; 710 print '<table class="border" width="100%">'; 711 712 // Type 713 print '<tr><td class="titlefield"><span class="fieldrequired"><label for="selecttype_code">'.$langs->trans("TicketTypeRequest").'</span></label></td><td>'; 714 $formticket->selectTypesTickets((GETPOSTISSET('type_code') ? GETPOST('type_code') : $object->type_code), 'type_code', '', '2'); 715 print '</td></tr>'; 716 717 // Severity 718 print '<tr><td><span class="fieldrequired"><label for="selectseverity_code">'.$langs->trans("TicketSeverity").'</span></label></td><td>'; 719 $formticket->selectSeveritiesTickets((GETPOSTISSET('severity_code') ? GETPOST('severity_code') : $object->severity_code), 'severity_code', '', '2'); 720 print '</td></tr>'; 721 722 // Group 723 print '<tr><td><span class="fieldrequired"><label for="selectcategory_code">'.$langs->trans("TicketCategory").'</span></label></td><td>'; 724 $formticket->selectGroupTickets((GETPOSTISSET('category_code') ? GETPOST('category_code') : $object->category_code), 'category_code', '', '2'); 725 print '</td></tr>'; 726 727 // Subject 728 print '<tr><td><label for="subject"><span class="fieldrequired">'.$langs->trans("Subject").'</span></label></td><td>'; 729 print '<input class="text minwidth200" id="subject" name="subject" value="'.dol_escape_htmltag(GETPOSTISSET('subject') ? GETPOST('subject', 'alpha') : $object->subject).'" />'; 730 print '</td></tr>'; 731 732 // Other attributes 733 $parameters = array('colspan' => ' colspan="3"', 'colspanvalue' => '3'); 734 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook 735 print $hookmanager->resPrint; 736 if (empty($reshook)) { 737 print $object->showOptionals($extrafields, 'edit'); 738 } 739 740 print '</table>'; 741 print '</div>'; 742 743 print dol_get_fiche_end(); 744 745 print '<div class="center">'; 746 print '<input type="submit" class="button button-save" name="save" value="'.$langs->trans("Save").'">'; 747 print ' '; 748 print '<input type="submit" class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">'; 749 print '</div>'; 750 751 print '</form>'; */ 752} elseif (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'dellink' || $action == 'presend' || $action == 'presend_addmessage' || $action == 'close' || $action == 'abandon' || $action == 'delete' || $action == 'editcustomer' || $action == 'progression' || $action == 'reopen' 753 || $action == 'editsubject' || $action == 'edit_extras' || $action == 'update_extras' || $action == 'edit_extrafields' || $action == 'set_extrafields' || $action == 'classify' || $action == 'sel_contract' || $action == 'edit_message_init' || $action == 'set_status' || $action == 'dellink') { 754 if ($res > 0) { 755 // or for unauthorized internals users 756 if (!$user->socid && (!empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY) && $object->fk_user_assign != $user->id) && !$user->rights->ticket->manage) { 757 accessforbidden('', 0, 1); 758 } 759 760 // Confirmation close 761 if ($action == 'close') { 762 print $form->formconfirm($url_page_current."?track_id=".$object->track_id, $langs->trans("CloseATicket"), $langs->trans("ConfirmCloseAticket"), "confirm_close", '', '', 1); 763 if ($ret == 'html') { 764 print '<br>'; 765 } 766 } 767 // Confirmation abandon 768 if ($action == 'abandon') { 769 print $form->formconfirm($url_page_current."?track_id=".$object->track_id, $langs->trans("AbandonTicket"), $langs->trans("ConfirmAbandonTicket"), "confirm_abandon", '', '', 1); 770 if ($ret == 'html') { 771 print '<br>'; 772 } 773 } 774 // Confirmation delete 775 if ($action == 'delete') { 776 print $form->formconfirm($url_page_current."?track_id=".$object->track_id, $langs->trans("Delete"), $langs->trans("ConfirmDeleteTicket"), "confirm_delete_ticket", '', '', 1); 777 } 778 // Confirm reopen 779 if ($action == 'reopen') { 780 print $form->formconfirm($url_page_current.'?track_id='.$object->track_id, $langs->trans('ReOpen'), $langs->trans('ConfirmReOpenTicket'), 'confirm_reopen', '', '', 1); 781 } 782 // Confirmation status change 783 if ($action == 'set_status') { 784 $new_status = GETPOST('new_status'); 785 //var_dump($url_page_current . "?track_id=" . $object->track_id); 786 print $form->formconfirm($url_page_current."?track_id=".$object->track_id."&new_status=".GETPOST('new_status'), $langs->trans("TicketChangeStatus"), $langs->trans("TicketConfirmChangeStatus", $langs->transnoentities($object->statuts_short[$new_status])), "confirm_set_status", '', '', 1); 787 } 788 789 // project info 790 if ($projectid > 0) { 791 $projectstat = new Project($db); 792 if ($projectstat->fetch($projectid) > 0) { 793 $projectstat->fetch_thirdparty(); 794 795 // To verify role of users 796 //$userAccess = $object->restrictedProjectArea($user,'read'); 797 $userWrite = $projectstat->restrictedProjectArea($user, 'write'); 798 //$userDelete = $object->restrictedProjectArea($user,'delete'); 799 //print "userAccess=".$userAccess." userWrite=".$userWrite." userDelete=".$userDelete; 800 801 $head = project_prepare_head($projectstat); 802 print dol_get_fiche_head($head, 'ticket', $langs->trans("Project"), 0, ($projectstat->public ? 'projectpub' : 'project')); 803 804 /* 805 * Projet synthese pour rappel 806 */ 807 print '<table class="border centpercent">'; 808 809 $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>'; 810 811 // Ref 812 print '<tr><td width="30%">'.$langs->trans('Ref').'</td><td colspan="3">'; 813 // Define a complementary filter for search of next/prev ref. 814 if (!$user->rights->projet->all->lire) { 815 $objectsListId = $projectstat->getProjectsAuthorizedForUser($user, $mine, 0); 816 $projectstat->next_prev_filter = " rowid IN (".$db->sanitize(count($objectsListId) ? join(',', array_keys($objectsListId)) : '0').")"; 817 } 818 print $form->showrefnav($projectstat, 'ref', $linkback, 1, 'ref', 'ref', ''); 819 print '</td></tr>'; 820 821 // Label 822 print '<tr><td>'.$langs->trans("Label").'</td><td>'.$projectstat->title.'</td></tr>'; 823 824 // Customer 825 print "<tr><td>".$langs->trans("ThirdParty")."</td>"; 826 print '<td colspan="3">'; 827 if ($projectstat->thirdparty->id > 0) { 828 print $projectstat->thirdparty->getNomUrl(1); 829 } else { 830 print ' '; 831 } 832 833 print '</td></tr>'; 834 835 // Visibility 836 print '<tr><td>'.$langs->trans("Visibility").'</td><td>'; 837 if ($projectstat->public) { 838 print $langs->trans('SharedProject'); 839 } else { 840 print $langs->trans('PrivateProject'); 841 } 842 843 print '</td></tr>'; 844 845 // Statut 846 print '<tr><td>'.$langs->trans("Status").'</td><td>'.$projectstat->getLibStatut(4).'</td></tr>'; 847 848 print "</table>"; 849 850 print '</div>'; 851 } else { 852 print "ErrorRecordNotFound"; 853 } 854 } elseif ($socid > 0) { 855 $object->fetch_thirdparty(); 856 $head = societe_prepare_head($object->thirdparty); 857 858 print dol_get_fiche_head($head, 'ticket', $langs->trans("ThirdParty"), 0, 'company'); 859 860 dol_banner_tab($object->thirdparty, 'socid', '', ($user->socid ? 0 : 1), 'rowid', 'nom'); 861 862 print dol_get_fiche_end(); 863 } 864 865 if (!$user->socid && !empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY)) { 866 $object->next_prev_filter = "te.fk_user_assign = '".$user->id."'"; 867 } elseif ($user->socid > 0) { 868 $object->next_prev_filter = "te.fk_soc = '".$user->socid."'"; 869 } 870 871 $head = ticket_prepare_head($object); 872 873 print dol_get_fiche_head($head, 'tabTicket', $langs->trans("Ticket"), -1, 'ticket'); 874 875 $morehtmlref = '<div class="refidno">'; 876 $morehtmlref .= $object->subject; 877 // Author 878 if ($object->fk_user_create > 0) { 879 $morehtmlref .= '<br>'.$langs->trans("CreatedBy").' : '; 880 881 $langs->load("users"); 882 $fuser = new User($db); 883 $fuser->fetch($object->fk_user_create); 884 $morehtmlref .= $fuser->getNomUrl(-1); 885 } 886 if (!empty($object->origin_email)) { 887 $morehtmlref .= '<br>'.$langs->trans("CreatedBy").' : '; 888 $morehtmlref .= img_picto('', 'email', 'class="paddingrightonly"'); 889 $morehtmlref .= dol_escape_htmltag($object->origin_email).' <small class="hideonsmartphone opacitymedium">('.$langs->trans("TicketEmailOriginIssuer").')</small>'; 890 } 891 892 // Thirdparty 893 if (!empty($conf->societe->enabled)) { 894 $morehtmlref .= '<br>'.$langs->trans('ThirdParty').' '; 895 if ($action != 'editcustomer' && $object->fk_statut < 8 && !$user->socid && $user->rights->ticket->write) { 896 $morehtmlref .= '<a class="editfielda" href="'.$url_page_current.'?action=editcustomer&track_id='.$object->track_id.'">'.img_edit($langs->transnoentitiesnoconv('Edit'), 0).'</a> : '; 897 } 898 if ($action == 'editcustomer') { 899 $morehtmlref .= $form->form_thirdparty($url_page_current.'?track_id='.$object->track_id, $object->socid, 'editcustomer', '', 1, 0, 0, array(), 1); 900 } else { 901 $morehtmlref .= $form->form_thirdparty($url_page_current.'?track_id='.$object->track_id, $object->socid, 'none', '', 1, 0, 0, array(), 1); 902 } 903 } 904 905 // Project 906 if (!empty($conf->projet->enabled)) { 907 $langs->load("projects"); 908 $morehtmlref .= '<br>'.$langs->trans('Project').' '; 909 if ($user->rights->ticket->write) { 910 if ($action != 'classify') { 911 $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a>'; 912 } 913 $morehtmlref .= ' : '; 914 if ($action == 'classify') { 915 //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); 916 $morehtmlref .= '<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">'; 917 $morehtmlref .= '<input type="hidden" name="action" value="classin">'; 918 $morehtmlref .= '<input type="hidden" name="token" value="'.newToken().'">'; 919 $morehtmlref .= $formproject->select_projects($object->socid, $object->fk_project, 'projectid', 0, 0, 1, 0, 1, 0, 0, '', 1, 0, 'maxwidth500'); 920 $morehtmlref .= '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">'; 921 $morehtmlref .= '</form>'; 922 } else { 923 $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); 924 } 925 } else { 926 if (!empty($object->fk_project)) { 927 $proj = new Project($db); 928 $proj->fetch($object->fk_project); 929 $morehtmlref .= $proj->getNomUrl(1); 930 } else { 931 $morehtmlref .= ''; 932 } 933 } 934 } 935 936 $morehtmlref .= '</div>'; 937 938 $linkback = '<a href="'.DOL_URL_ROOT.'/ticket/list.php?restore_lastsearch_values=1"><strong>'.$langs->trans("BackToList").'</strong></a> '; 939 940 dol_banner_tab($object, 'ref', $linkback, ($user->socid ? 0 : 1), 'ref', 'ref', $morehtmlref); 941 942 print '<div class="fichecenter">'; 943 print '<div class="fichehalfleft">'; 944 print '<div class="underbanner clearboth"></div>'; 945 946 print '<table class="border tableforfield centpercent">'; 947 948 // Track ID 949 print '<tr><td class="titlefield">'.$langs->trans("TicketTrackId").'</td><td>'; 950 if (!empty($object->track_id)) { 951 if (empty($object->ref)) { 952 $object->ref = $object->id; 953 print $form->showrefnav($object, 'id', $linkback, 1, 'rowid', 'track_id'); 954 } else { 955 print $object->track_id; 956 } 957 } else { 958 print $langs->trans('None'); 959 } 960 print '</td></tr>'; 961 962 // Subject 963 print '<tr><td>'; 964 print $form->editfieldkey("Subject", 'subject', $object->subject, $object, $user->rights->ticket->write && !$user->socid, 'string'); 965 print '</td><td>'; 966 print $form->editfieldval("Subject", 'subject', $object->subject, $object, $user->rights->ticket->write && !$user->socid, 'string'); 967 print '</td></tr>'; 968 969 // Creation date 970 print '<tr><td>'.$langs->trans("DateCreation").'</td><td>'; 971 print dol_print_date($object->datec, 'dayhour', 'tzuser'); 972 print '<span class="opacitymedium"> - '.$langs->trans("TimeElapsedSince").': <i>'.convertSecondToTime(roundUpToNextMultiple($now - $object->datec, 60)).'</i></span>'; 973 print '</td></tr>'; 974 975 // Read date 976 print '<tr><td>'.$langs->trans("TicketReadOn").'</td><td>'; 977 if (!empty($object->date_read)) { 978 print dol_print_date($object->date_read, 'dayhour', 'tzuser'); 979 print '<span class="opacitymedium"> - '.$langs->trans("TicketTimeElapsedBeforeSince").': <i>'.convertSecondToTime(roundUpToNextMultiple($object->date_read - $object->datec, 60)).'</i>'; 980 print ' / <i>'.convertSecondToTime(roundUpToNextMultiple($now - $object->date_read, 60)).'</i></span>'; 981 } 982 print '</td></tr>'; 983 984 // Close date 985 print '<tr><td>'.$langs->trans("TicketCloseOn").'</td><td>'; 986 if (!empty($object->date_close)) { 987 print dol_print_date($object->date_close, 'dayhour', 'tzuser'); 988 } 989 print '</td></tr>'; 990 991 // User assigned 992 print '<tr><td>'; 993 print '<table class="nobordernopadding" width="100%"><tr><td class="nowrap">'; 994 print $langs->trans("AssignedTo"); 995 if ($object->fk_statut < $object::STATUS_CLOSED && GETPOST('set', 'alpha') != "assign_ticket" && $user->rights->ticket->manage) { 996 print '<td class="right"><a class="editfielda" href="'.$url_page_current.'?track_id='.$object->track_id.'&action=view&set=assign_ticket">'.img_edit($langs->trans('Modify'), '').'</a></td>'; 997 } 998 print '</tr></table>'; 999 print '</td><td>'; 1000 if ($object->fk_user_assign > 0) { 1001 $userstat->fetch($object->fk_user_assign); 1002 print $userstat->getNomUrl(-1); 1003 } 1004 1005 // Show user list to assignate one if status is "read" 1006 if (GETPOST('set', 'alpha') == "assign_ticket" && $object->fk_statut < 8 && !$user->socid && $user->rights->ticket->write) { 1007 print '<form method="post" name="ticket" enctype="multipart/form-data" action="'.$url_page_current.'">'; 1008 print '<input type="hidden" name="token" value="'.newToken().'">'; 1009 print '<input type="hidden" name="action" value="assign_user">'; 1010 print '<input type="hidden" name="track_id" value="'.$object->track_id.'">'; 1011 print '<label for="fk_user_assign">'.$langs->trans("AssignUser").'</label> '; 1012 print $form->select_dolusers($user->id, 'fk_user_assign', 1); 1013 print ' <input class="button" type="submit" name="btn_assign_user" value="'.$langs->trans("Validate").'" />'; 1014 print '</form>'; 1015 } 1016 print '</td></tr>'; 1017 1018 // Progression 1019 print '<tr><td>'; 1020 print '<table class="nobordernopadding" width="100%"><tr><td class="nowrap">'; 1021 print $langs->trans('Progression').'</td><td class="left">'; 1022 print '</td>'; 1023 if ($action != 'progression' && $object->fk_statut < $object::STATUS_CLOSED && !$user->socid) { 1024 print '<td class="right"><a class="editfielda" href="'.$url_page_current.'?action=progression&track_id='.$object->track_id.'">'.img_edit($langs->trans('Modify')).'</a></td>'; 1025 } 1026 print '</tr></table>'; 1027 print '</td><td colspan="5">'; 1028 if ($user->rights->ticket->write && $action == 'progression') { 1029 print '<form action="'.$url_page_current.'" method="post">'; 1030 print '<input type="hidden" name="token" value="'.newToken().'">'; 1031 print '<input type="hidden" name="track_id" value="'.$track_id.'">'; 1032 print '<input type="hidden" name="action" value="set_progression">'; 1033 print '<input type="text" class="flat" size="20" name="progress" value="'.$object->progress.'">'; 1034 print ' <input type="submit" class="button" value="'.$langs->trans('Modify').'">'; 1035 print '</form>'; 1036 } else { 1037 print($object->progress > 0 ? $object->progress : '0').'%'; 1038 } 1039 print '</td>'; 1040 print '</tr>'; 1041 1042 // Timing (Duration sum of linked fichinter) 1043 if ($conf->ficheinter->enabled) { 1044 $object->fetchObjectLinked(); 1045 $num = count($object->linkedObjects); 1046 $timing = 0; 1047 if ($num) { 1048 foreach ($object->linkedObjects as $objecttype => $objects) { 1049 if ($objecttype = "fichinter") { 1050 foreach ($objects as $fichinter) { 1051 $timing += $fichinter->duration; 1052 } 1053 } 1054 } 1055 } 1056 print '<tr><td valign="top">'; 1057 1058 print $form->textwithpicto($langs->trans("TicketDurationAuto"), $langs->trans("TicketDurationAutoInfos"), 1); 1059 print '</td><td>'; 1060 print convertSecondToTime($timing, 'all', $conf->global->MAIN_DURATION_OF_WORKDAY); 1061 print '</td></tr>'; 1062 } 1063 1064 // Other attributes 1065 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php'; 1066 1067 print '</table>'; 1068 1069 1070 // Fin colonne gauche et début colonne droite 1071 print '</div><div class="fichehalfright"><div class="ficheaddleft">'; 1072 1073 1074 // View Original message 1075 $actionobject->viewTicketOriginalMessage($user, $action, $object); 1076 1077 // Classification of ticket 1078 print '<form method="post" name="formticketproperties" action="'.$url_page_current.'">'; 1079 print '<input type="hidden" name="token" value="'.newToken().'">'; 1080 print '<input type="hidden" name="action" value="change_property">'; 1081 print '<input type="hidden" name="track_id" value="'.$track_id.'">'; 1082 1083 print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table 1084 print '<table class="noborder tableforfield centpercent margintable">'; 1085 print '<tr class="liste_titre">'; 1086 print '<td>'; 1087 print $langs->trans('Properties'); 1088 print '</td>'; 1089 print '<td>'; 1090 if (GETPOST('set', 'alpha') == 'properties' && $user->rights->ticket->write) { 1091 print '<input class="button" type="submit" name="btn_update_ticket_prop" value="'.$langs->trans("Modify").'" />'; 1092 } else { 1093 // Button to edit Properties 1094 if ($object->fk_statut < $object::STATUS_NEED_MORE_INFO && $user->rights->ticket->write) { 1095 print '<a class="editfielda" href="card.php?track_id='.$object->track_id.'&action=view&set=properties">'.img_edit($langs->trans('Modify')).'</a>'; 1096 } 1097 } 1098 print '</td>'; 1099 print '</tr>'; 1100 1101 if (GETPOST('set', 'alpha') == 'properties' && $user->rights->ticket->write) { 1102 print '<tr>'; 1103 // Type 1104 print '<td class="titlefield">'; 1105 print $langs->trans('TicketChangeType'); 1106 print '</td><td>'; 1107 $formticket->selectTypesTickets($object->type_code, 'update_value_type', '', 2); 1108 print '</td>'; 1109 print '</tr>'; 1110 // Group 1111 print '<tr>'; 1112 print '<td>'; 1113 print $langs->trans('TicketChangeCategory'); 1114 print '</td><td>'; 1115 $formticket->selectGroupTickets($object->category_code, 'update_value_category', '', 2); 1116 print '</td>'; 1117 print '</tr>'; 1118 // Severity 1119 print '<tr>'; 1120 print '<td>'; 1121 print $langs->trans('TicketChangeSeverity'); 1122 print '</td><td>'; 1123 $formticket->selectSeveritiesTickets($object->severity_code, 'update_value_severity', '', 2); 1124 print '</td>'; 1125 print '</tr>'; 1126 } else { 1127 // Type 1128 print '<tr><td class="titlefield">'.$langs->trans("Type").'</td><td>'; 1129 if (!empty($object->type_code)) { 1130 print $langs->getLabelFromKey($db, 'TicketTypeShort'.$object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code); 1131 } 1132 print '</td></tr>'; 1133 // Group 1134 print '<tr><td>'.$langs->trans("TicketCategory").'</td><td>'; 1135 if (!empty($object->category_code)) { 1136 print $langs->getLabelFromKey($db, 'TicketCategoryShort'.$object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code); 1137 } 1138 print '</td></tr>'; 1139 // Severity 1140 print '<tr><td>'.$langs->trans("TicketSeverity").'</td><td>'; 1141 if (!empty($object->severity_code)) { 1142 print $langs->getLabelFromKey($db, 'TicketSeverityShort'.$object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code); 1143 } 1144 print '</td></tr>'; 1145 } 1146 print '</table>'; // End table actions 1147 print '</div>'; 1148 1149 print '</form>'; 1150 1151 // Display navbar with links to change ticket status 1152 print '<!-- navbar with status -->'; 1153 if (!$user->socid && $user->rights->ticket->write && $object->fk_statut < $object::STATUS_CLOSED && GETPOST('set') !== 'properties') { 1154 $actionobject->viewStatusActions($object); 1155 } 1156 1157 1158 if (!empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) { 1159 print load_fiche_titre($langs->trans('Contacts'), '', 'title_companies.png'); 1160 1161 print '<div class="div-table-responsive-no-min">'; 1162 print '<div class="tagtable centpercent noborder allwidth">'; 1163 1164 print '<div class="tagtr liste_titre">'; 1165 print '<div class="tagtd">'.$langs->trans("Source").'</div> 1166 <div class="tagtd">' . $langs->trans("Company").'</div> 1167 <div class="tagtd">' . $langs->trans("Contacts").'</div> 1168 <div class="tagtd">' . $langs->trans("ContactType").'</div> 1169 <div class="tagtd">' . $langs->trans("Phone").'</div> 1170 <div class="tagtd center">' . $langs->trans("Status").'</div>'; 1171 print '</div><!-- tagtr -->'; 1172 1173 // Contact list 1174 $companystatic = new Societe($db); 1175 $contactstatic = new Contact($db); 1176 $userstatic = new User($db); 1177 foreach (array('internal', 'external') as $source) { 1178 $tmpobject = $object; 1179 $tab = $tmpobject->listeContact(-1, $source); 1180 $num = count($tab); 1181 $i = 0; 1182 while ($i < $num) { 1183 $var = !$var; 1184 print '<div class="tagtr '.($var ? 'pair' : 'impair').'">'; 1185 1186 print '<div class="tagtd left">'; 1187 if ($tab[$i]['source'] == 'internal') { 1188 echo $langs->trans("User"); 1189 } 1190 1191 if ($tab[$i]['source'] == 'external') { 1192 echo $langs->trans("ThirdPartyContact"); 1193 } 1194 1195 print '</div>'; 1196 print '<div class="tagtd left">'; 1197 1198 if ($tab[$i]['socid'] > 0) { 1199 $companystatic->fetch($tab[$i]['socid']); 1200 echo $companystatic->getNomUrl(-1); 1201 } 1202 if ($tab[$i]['socid'] < 0) { 1203 echo $conf->global->MAIN_INFO_SOCIETE_NOM; 1204 } 1205 if (!$tab[$i]['socid']) { 1206 echo ' '; 1207 } 1208 print '</div>'; 1209 1210 print '<div class="tagtd">'; 1211 if ($tab[$i]['source'] == 'internal') { 1212 if ($userstatic->fetch($tab[$i]['id'])) { 1213 print $userstatic->getNomUrl(-1); 1214 } 1215 } 1216 if ($tab[$i]['source'] == 'external') { 1217 if ($contactstatic->fetch($tab[$i]['id'])) { 1218 print $contactstatic->getNomUrl(-1); 1219 } 1220 } 1221 print ' </div> 1222 <div class="tagtd">' . $tab[$i]['libelle'].'</div>'; 1223 1224 print '<div class="tagtd">'; 1225 1226 print dol_print_phone($tab[$i]['phone'], '', '', '', 'AC_TEL').'<br>'; 1227 1228 if (!empty($tab[$i]['phone_perso'])) { 1229 //print img_picto($langs->trans('PhonePerso'),'object_phoning.png','',0,0,0).' '; 1230 print '<br>'.dol_print_phone($tab[$i]['phone_perso'], '', '', '', 'AC_TEL').'<br>'; 1231 } 1232 if (!empty($tab[$i]['phone_mobile'])) { 1233 //print img_picto($langs->trans('PhoneMobile'),'object_phoning.png','',0,0,0).' '; 1234 print dol_print_phone($tab[$i]['phone_mobile'], '', '', '', 'AC_TEL').'<br>'; 1235 } 1236 print '</div>'; 1237 1238 print '<div class="tagtd center">'; 1239 if ($object->statut >= 0) { 1240 echo '<a href="contact.php?track_id='.$object->track_id.'&action=swapstatut&ligne='.$tab[$i]['rowid'].'">'; 1241 } 1242 1243 if ($tab[$i]['source'] == 'internal') { 1244 $userstatic->id = $tab[$i]['id']; 1245 $userstatic->lastname = $tab[$i]['lastname']; 1246 $userstatic->firstname = $tab[$i]['firstname']; 1247 echo $userstatic->LibStatut($tab[$i]['statuscontact'], 3); 1248 } 1249 if ($tab[$i]['source'] == 'external') { 1250 $contactstatic->id = $tab[$i]['id']; 1251 $contactstatic->lastname = $tab[$i]['lastname']; 1252 $contactstatic->firstname = $tab[$i]['firstname']; 1253 echo $contactstatic->LibStatut($tab[$i]['statuscontact'], 3); 1254 } 1255 if ($object->statut >= 0) { 1256 echo '</a>'; 1257 } 1258 1259 print '</div>'; 1260 1261 print '</div><!-- tagtr -->'; 1262 1263 $i++; 1264 } 1265 } 1266 1267 print '</div><!-- contact list -->'; 1268 print '</div>'; 1269 } 1270 1271 print '</div></div></div>'; 1272 print '<div style="clear:both"></div>'; 1273 1274 print dol_get_fiche_end(); 1275 1276 1277 // Buttons for actions 1278 if ($action != 'presend' && $action != 'presend_addmessage' && $action != 'editline') { 1279 print '<div class="tabsAction">'."\n"; 1280 $parameters = array(); 1281 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook 1282 if ($reshook < 0) { 1283 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); 1284 } 1285 1286 if (empty($reshook)) { 1287 // Show link to add a message (if read and not closed) 1288 if ($object->fk_statut < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage") { 1289 print '<div class="inline-block divButAction"><a class="butAction reposition" href="card.php?track_id='.$object->track_id.'&action=presend_addmessage&mode=init">'.$langs->trans('TicketAddMessage').'</a></div>'; 1290 } 1291 1292 // Link to create an intervention 1293 // socid is needed otherwise fichinter ask it and forgot origin after form submit :\ 1294 if (!$object->fk_soc && $user->rights->ficheinter->creer) { 1295 print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans('UnableToCreateInterIfNoSocid').'">'.$langs->trans('TicketAddIntervention').'</a></div>'; 1296 } 1297 if ($object->fk_soc > 0 && $object->fk_statut < Ticket::STATUS_CLOSED && $user->rights->ficheinter->creer) { 1298 print '<div class="inline-block divButAction"><a class="butAction" href="'.dol_buildpath('/fichinter/card.php', 1).'?action=create&socid='.$object->fk_soc.'&origin=ticket_ticket&originid='.$object->id.'">'.$langs->trans('TicketAddIntervention').'</a></div>'; 1299 } 1300 1301 /* This is useless. We can already modify each field individually 1302 if ($user->rights->ticket->write && $object->fk_statut < Ticket::STATUS_CLOSED) { 1303 print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?track_id='.$object->track_id.'&action=edit">'.$langs->trans('Modify').'</a></div>'; 1304 } 1305 */ 1306 1307 // Close ticket if statut is read 1308 if ($object->fk_statut > 0 && $object->fk_statut < Ticket::STATUS_CLOSED && $user->rights->ticket->write) { 1309 print '<div class="inline-block divButAction"><a class="butAction" href="card.php?track_id='.$object->track_id.'&action=close">'.$langs->trans('CloseTicket').'</a></div>'; 1310 } 1311 1312 // Abadon ticket if statut is read 1313 if ($object->fk_statut > 0 && $object->fk_statut < Ticket::STATUS_CLOSED && $user->rights->ticket->write) { 1314 print '<div class="inline-block divButAction"><a class="butAction" href="card.php?track_id='.$object->track_id.'&action=abandon">'.$langs->trans('AbandonTicket').'</a></div>'; 1315 } 1316 1317 // Re-open ticket 1318 if (!$user->socid && ($object->fk_statut == Ticket::STATUS_CLOSED || $object->fk_statut == Ticket::STATUS_CANCELED) && !$user->socid) { 1319 print '<div class="inline-block divButAction"><a class="butAction" href="card.php?track_id='.$object->track_id.'&action=reopen">'.$langs->trans('ReOpen').'</a></div>'; 1320 } 1321 1322 // Delete ticket 1323 if ($user->rights->ticket->delete && !$user->socid) { 1324 print '<div class="inline-block divButAction"><a class="butActionDelete" href="card.php?track_id='.$object->track_id.'&action=delete&token='.newToken().'">'.$langs->trans('Delete').'</a></div>'; 1325 } 1326 } 1327 print '</div>'."\n"; 1328 } else { 1329 //print '<br>'; 1330 } 1331 1332 // Select mail models is same action as presend 1333 if (GETPOST('modelselected')) { 1334 $action = 'presend'; 1335 } 1336 // Set $action to correct value for the case we used presend action to add a message 1337 if (GETPOSTISSET('actionbis') && $action == 'presend') { 1338 $action = 'presend_addmessage'; 1339 } 1340 1341 // add a message 1342 if ($action == 'presend' || $action == 'presend_addmessage') { 1343 if ($object->fk_soc > 0) { 1344 $object->fetch_thirdparty(); 1345 } 1346 1347 $outputlangs = $langs; 1348 $newlang = ''; 1349 if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { 1350 $newlang = GETPOST('lang_id', 'aZ09'); 1351 } elseif ($conf->global->MAIN_MULTILANGS && empty($newlang) && is_object($object->thirdparty)) { 1352 $newlang = $object->thirdparty->default_lang; 1353 } 1354 if (!empty($newlang)) { 1355 $outputlangs = new Translate("", $conf); 1356 $outputlangs->setDefaultLang($newlang); 1357 } 1358 1359 $arrayoffamiliestoexclude = array('objectamount'); 1360 1361 $action = 'add_message'; // action to use to post the message 1362 $modelmail = 'ticket_send'; 1363 1364 // Substitution array 1365 $morehtmlright = ''; 1366 $help = ""; 1367 $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, $arrayoffamiliestoexclude, $object); 1368 if ($object->fk_soc > 0) { 1369 $substitutionarray['__THIRDPARTY_NAME__'] = $object->thirdparty->name; 1370 } 1371 $substitutionarray['__USER_SIGNATURE__'] = $user->signature; 1372 $substitutionarray['__TICKET_TRACKID__'] = $object->track_id; 1373 $substitutionarray['__TICKET_REF__'] = $object->ref; 1374 $substitutionarray['__TICKET_SUBJECT__'] = $object->subject; 1375 $substitutionarray['__TICKET_TYPE__'] = $object->type_code; 1376 $substitutionarray['__TICKET_SEVERITY__'] = $object->severity_code; 1377 $substitutionarray['__TICKET_CATEGORY__'] = $object->category_code; // For backward compatibility 1378 $substitutionarray['__TICKET_ANALYTIC_CODE__'] = $object->category_code; 1379 $substitutionarray['__TICKET_MESSAGE__'] = $object->message; 1380 $substitutionarray['__TICKET_PROGRESSION__'] = $object->progress; 1381 if ($object->fk_user_assign > 0) { 1382 $userstat->fetch($object->fk_user_assign); 1383 $substitutionarray['__TICKET_USER_ASSIGN__'] = dolGetFirstLastname($userstat->firstname, $userstat->lastname); 1384 } 1385 1386 if ($object->fk_user_create > 0) { 1387 $userstat->fetch($object->fk_user_create); 1388 $substitutionarray['__TICKET_USER_CREATE__'] = dolGetFirstLastname($userstat->firstname, $userstat->lastname); 1389 } 1390 foreach ($substitutionarray as $key => $val) { 1391 $help .= $key.' -> '.$langs->trans($val).'<br>'; 1392 } 1393 $morehtmlright .= $form->textwithpicto('<span class="opacitymedium">'.$langs->trans("TicketMessageSubstitutionReplacedByGenericValues").'</span>', $help, 1, 'helpclickable', '', 0, 3, 'helpsubstitution'); 1394 1395 print '<div>'; 1396 1397 print load_fiche_titre($langs->trans('TicketAddMessage'), $morehtmlright, 'messages@ticket'); 1398 1399 print '<hr>'; 1400 1401 $formticket = new FormTicket($db); 1402 1403 $formticket->action = $action; 1404 $formticket->track_id = $object->track_id; 1405 $formticket->ref = $object->ref; 1406 $formticket->id = $object->id; 1407 1408 $formticket->withfile = 2; 1409 $formticket->withcancel = 1; 1410 $formticket->param = array('fk_user_create' => $user->id); 1411 $formticket->param['langsmodels'] = (empty($newlang) ? $langs->defaultlang : $newlang); 1412 1413 // Tableau des parametres complementaires du post 1414 $formticket->param['models'] = $modelmail; 1415 $formticket->param['models_id'] = GETPOST('modelmailselected', 'int'); 1416 //$formticket->param['socid']=$object->fk_soc; 1417 $formticket->param['returnurl'] = $_SERVER["PHP_SELF"].'?track_id='.$object->track_id; 1418 1419 $formticket->withsubstit = 1; 1420 $formticket->substit = $substitutionarray; 1421 $formticket->showMessageForm('100%'); 1422 print '</div>'; 1423 } 1424 1425 // Show messages on card (Note: this is a duplicate of the view Events/Agenda but on the main tab) 1426 if (!empty($conf->global->TICKET_SHOW_MESSAGES_ON_CARD)) { 1427 $param = '&id='.$object->id; 1428 if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { 1429 $param .= '&contextpage='.$contextpage; 1430 } 1431 if ($limit > 0 && $limit != $conf->liste_limit) { 1432 $param .= '&limit='.$limit; 1433 } 1434 if ($actioncode) { 1435 $param .= '&actioncode='.urlencode($actioncode); 1436 } 1437 if ($search_agenda_label) { 1438 $param .= '&search_agenda_label='.urlencode($search_agenda_label); 1439 } 1440 1441 $morehtmlright = ''; 1442 1443 $messagingUrl = DOL_URL_ROOT.'/ticket/agenda.php?track_id='.$object->track_id; 1444 $morehtmlright .= dolGetButtonTitle($langs->trans('MessageListViewType'), '', 'fal fa-list-alt imgforviewmode', $messagingUrl, '', 1); 1445 1446 // Show link to add a message (if read and not closed) 1447 $btnstatus = $object->fk_statut < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage" && $action != "add_message"; 1448 $url = 'card.php?track_id='.$object->track_id.'&action=presend_addmessage&mode=init'; 1449 $morehtmlright .= dolGetButtonTitle($langs->trans('TicketAddMessage'), '', 'fal fa-comment-dots', $url, 'add-new-ticket-title-button', $btnstatus); 1450 1451 // Show link to add event (if read and not closed) 1452 $btnstatus = $object->fk_statut < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage" && $action != "add_message"; ; 1453 $url = dol_buildpath('/comm/action/card.php', 1).'?action=create&datep='.date('YmdHi').'&origin=ticket&originid='.$object->id.'&projectid='.$object->fk_project.'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?track_id='.$object->track_id); 1454 $morehtmlright .= dolGetButtonTitle($langs->trans('AddAction'), '', 'fal fa-plus-circle', $url, 'add-new-ticket-even-button', $btnstatus); 1455 1456 print_barre_liste($langs->trans("ActionsOnTicket"), 0, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', 0, -1, '', 0, $morehtmlright, '', 0, 1, 1); 1457 1458 // List of all actions 1459 $filters = array(); 1460 $filters['search_agenda_label'] = $search_agenda_label; 1461 show_ticket_messaging($conf, $langs, $db, $object, null, 0, $actioncode, '', $filters, $sortfield, $sortorder); 1462 } 1463 1464 if ($action != 'presend' && $action != 'presend_addmessage' && $action != 'add_message') { 1465 print '<div class="fichecenter"><div class="fichehalfleft">'; 1466 print '<a name="builddoc"></a>'; // ancre 1467 1468 // Show links to link elements 1469 $linktoelem = $form->showLinkToObjectBlock($object, null, array('ticket')); 1470 $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem); 1471 1472 // Show direct link to public interface 1473 print '<br><!-- Link to public interface -->'."\n"; 1474 print showDirectPublicLink($object).'<br>'; 1475 print '</div>'; 1476 1477 if (empty($conf->global->TICKET_SHOW_MESSAGES_ON_CARD)) { 1478 print '<div class="fichehalfright"><div class="ficheaddleft">'; 1479 1480 $MAXEVENT = 10; 1481 1482 $morehtmlcenter = '<div class="nowraponall">'; 1483 $morehtmlcenter .= dolGetButtonTitle($langs->trans('FullConversation'), '', 'fa fa-comments imgforviewmode', DOL_URL_ROOT.'/ticket/messaging.php?id='.$object->id); 1484 $morehtmlcenter .= ' '; 1485 $morehtmlcenter .= dolGetButtonTitle($langs->trans('FullList'), '', 'fa fa-list-alt imgforviewmode', DOL_URL_ROOT.'/ticket/agenda.php?id='.$object->id); 1486 $morehtmlcenter .= '</div>'; 1487 1488 // List of actions on element 1489 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php'; 1490 $formactions = new FormActions($db); 1491 $somethingshown = $formactions->showactions($object, 'ticket', $socid, 1, 'listactions', $MAXEVENT, '', $morehtmlcenter); 1492 1493 print '</div></div>'; 1494 } 1495 1496 print '</div>'; 1497 } 1498 } 1499} 1500 1501// End of page 1502llxFooter(); 1503$db->close(); 1504