diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 27e63efa8e7..ceb4eb39ade 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -2492,6 +2492,21 @@ class Contrat extends CommonObject return $this->fetch_lines(); } + /** + * Create an array of associated tickets + * + * @return array|int Array o tickets or <0 if KO + */ + public function getTicketsArray() + { + global $user; + + $ticket = new Ticket($this->db); + $nbTicket = $ticket->fetchAll($user, 'ASC', 't.datec', '', 0, '', array('t.fk_contract' => $this->id)); + + return ($nbTicket < 0 ? $nbTicket : $ticket->lines); + } + /** * Create a document onto disk according to template module. diff --git a/htdocs/contrat/ticket.php b/htdocs/contrat/ticket.php new file mode 100644 index 00000000000..dff2cf5dceb --- /dev/null +++ b/htdocs/contrat/ticket.php @@ -0,0 +1,185 @@ + + * Copyright (C) 2004-2016 Laurent Destailleur + * Copyright (C) 2012-2023 Charlene BENKE + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 this program. If not, see . + */ + +/** + * \file htdocs/contrat/ticket.php + * \ingroup contrat + * \brief Page of associated ticket + */ + + +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/contract.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php'; +if (isModEnabled('project')) { + require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; +} + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +require_once DOL_DOCUMENT_ROOT."/ticket/class/ticket.class.php"; + +$langs->loadLangs(array('companies', 'contracts', 'tickets')); + +$socid=GETPOST('socid', 'int'); +$id=GETPOST('id', 'int'); +$ref=GETPOST('ref', 'alpha'); +$action=GETPOST('action', 'alpha'); + +if ($id == '' && $ref == '') { + dol_print_error('', 'Bad parameter'); + exit; +} + +// Security check +$socid=0; +if ($user->socid > 0) + $socid=$user->socid; + +$result=restrictedArea($user, 'contrat', $id); + + +/* + * View + */ + +llxHeader("", $langs->trans("Tickets"), "Contrat"); + +$form = new Form($db); +$userstatic=new User($db); + +$object= new Contrat($db); +$result=$object->fetch($id, $ref); +$ret=$object->fetch_thirdparty(); +$head = contract_prepare_head($object); + + +dol_fiche_head($head, 'ticket', $langs->trans("Contract"), -1, 'contract'); + +$linkback = ''; +$linkback.= $langs->trans("BackToList").''; + +$morehtmlref=''; +$morehtmlref.=$object->ref; + +$morehtmlref.='
'; +// Ref customer +$morehtmlref.=$form->editfieldkey( + "RefCustomer", 'ref_customer', $object->ref_customer, + $object, 0, 'string', '', 0, 1 +); +$morehtmlref.=$form->editfieldval( + "RefCustomer", 'ref_customer', $object->ref_customer, + $object, 0, 'string', '', null, null, '', 1 +); +// Ref supplier +$morehtmlref.='
'; +$morehtmlref.=$form->editfieldkey( + "RefSupplier", 'ref_supplier', $object->ref_supplier, + $object, 0, 'string', '', 0, 1 +); +$morehtmlref.=$form->editfieldval( + "RefSupplier", 'ref_supplier', $object->ref_supplier, + $object, 0, 'string', '', null, null, '', 1 +); +// Thirdparty +$morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1); +// Project +if (! empty($conf->projet->enabled)) { + require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; + + $langs->load("projects"); + $morehtmlref.='
'.$langs->trans('Project') . ' : '; + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref.=''; + $morehtmlref.=$proj->ref; + $morehtmlref.=''; + } else { + $morehtmlref.=''; + } +} +$morehtmlref.='
'; + +dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'none', $morehtmlref); + +print '
'; + + +/* + * Referers types + */ + +$title=$langs->trans("ListTicketsLinkToContract"); + +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +// on récupère la totalité des tickets liés au contrat +$allticketarray = $object->getTicketsArray(); +if (is_array($allticketarray) && count($allticketarray) > 0) { + foreach ($allticketarray as $key => $value) { + $total_ht = 0; + $total_ttc = 0; + + $element = $value; + + print ""; + + // Ref + print '\n"; + + // Information + print ''; + print ''; + print ''; + print ''; + + // Date + print ''; + print ''; + + // Duration + print ''; + + // Status + print ''; + print ''; + } +} +print "
'.$langs->trans("Ref").''.$langs->trans("Subject").''.$langs->trans("Type").''.$langs->trans("TicketCategory").''.$langs->trans("Severity").''.$langs->trans("Date").''.$langs->trans("DateEnd").''.$langs->trans("Progress").''.$langs->trans("Status").'
'; + print $element->getNomUrl(1); + print "'.$value->subject.''.$value->type_label.''.$value->category_label.''.$value->severity_label.''.dol_print_date($element->datec, 'day').''.dol_print_date($element->date_close, 'day').''; + print (isset($element->progress) ? $element->progress.'%' : ''); + print ''.$element->getLibStatut(5).'
"; + + +llxFooter(); +$db->close(); diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index e395166fd1d..5a1823c03c0 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -4,6 +4,7 @@ * Copyright (C) 2019-2022 Frédéric France * Copyright (C) 2021 Juanjo Menent * Copyright (C) 2021 Alexandre Spangaro + * Copyright (C) 2023 Charlene Benke * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -651,6 +652,16 @@ class FormTicket } } + if ($subelement != 'contract') { + if (isModEnabled('contract') && !$this->ispublic) { + $formcontract = new FormContract($this->db); + print ''; + print img_picto('', 'contract'); + print $formcontract->select_contract(-1, GETPOST('contactid', 'int'), 'contractid', 0, 1, 1); + print ''; + } + } + // Other attributes $parameters = array(); $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $ticketstat, $action); // Note that $action and $object may have been modified by hook diff --git a/htdocs/core/lib/contract.lib.php b/htdocs/core/lib/contract.lib.php index 75ffdbf9a7c..2099ca86783 100644 --- a/htdocs/core/lib/contract.lib.php +++ b/htdocs/core/lib/contract.lib.php @@ -1,6 +1,7 @@ * Copyright (C) 2009-2012 Regis Houssin + * Copyright (C) 2023 Charlene BENKE * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -51,6 +52,13 @@ function contract_prepare_head(Contrat $object) $h++; } + if (isModEnabled('ticket')) { + $head[$h][0] = DOL_URL_ROOT.'/contrat/ticket.php?id='.$object->id; + $head[$h][1] = $langs->trans("Tickets"); + $head[$h][2] = 'ticket'; + $h++; + } + // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index ad9c15926cc..f569a812fa0 100755 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -4,7 +4,7 @@ * Copyright (C) 2018 Laurent Destailleur * Copyright (C) 2021 Frédéric France * Copyright (C) 2021 Alexandre Spangaro - * Copyright (C) 2022 Charlene Benke + * Copyright (C) 2022-2023 Charlene Benke * Copyright (C) 2023 Benjamin Falière * * This program is free software; you can redistribute it and/or modify @@ -245,6 +245,7 @@ if (empty($reshook)) { } $object->fk_project = $projectid; + $object->fk_contract = GETPOST('fk_contract', 'int'); $id = $object->create($user); if ($id <= 0) { @@ -813,7 +814,7 @@ if ($action == 'create' || $action == 'presend') { print ''; */ } 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 == 'categories' || $action == 'reopen' - || $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') { + || $action== 'edit_contrat' || $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') { if ($res > 0) { // or for unauthorized internals users if (!$user->socid && (!empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY) && $object->fk_user_assign != $user->id) && !$user->rights->ticket->manage) { @@ -1008,6 +1009,32 @@ if ($action == 'create' || $action == 'presend') { } } + // Contract + if (isModEnabled('contrat')) { + $langs->load('contracts'); + $morehtmlref .= '
'; + $morehtmlref .= $langs->trans('Contract'); + + if ($action != 'edit_contrat') { + $morehtmlref .= 'id.'">'; + $morehtmlref .= img_edit($langs->trans('SetContract'), 1); + $morehtmlref .= ''; + } + if ($action == 'edit_contrat') { + $formcontract = new Formcontract($db); + $morehtmlref .= $formcontract->formSelectContract($_SERVER["PHP_SELF"].'?id='.$object->id, $object->socid, $object->fk_contract, 'contratid', 0, 1, 1, 1); + } else { + if ($object->fk_contract) { + $contratstatic = new Contrat($db); + $contratstatic->fetch($object->fk_contract); + //print ''.$projet->title.''; + $morehtmlref .= $contratstatic->getNomUrl(0, '', 1); + } else { + $morehtmlref .= " "; + } + } + } + $morehtmlref .= ''; $linkback = ''.$langs->trans("BackToList").' '; diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php index 168b48809e9..ca8cb090009 100644 --- a/htdocs/ticket/class/ticket.class.php +++ b/htdocs/ticket/class/ticket.class.php @@ -3,6 +3,7 @@ * Copyright (C) 2016 Christophe Battarel * Copyright (C) 2019-2023 Frédéric France * Copyright (C) 2020 Laurent Destailleur + * Copyright (C) 2023 Charlene Benke * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,6 +36,12 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/ticket.lib.php'; */ class Ticket extends CommonObject { + + /** + * @var db connector + */ + public $db; + /** * @var string ID to identify managed object */ @@ -324,6 +331,7 @@ class Ticket extends CommonObject 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'visible'=>1, 'enabled'=>'isModEnabled("societe")', 'position'=>50, 'notnull'=>-1, 'index'=>1, 'searchall'=>1, 'help'=>"OrganizationEventLinkToThirdParty", 'css'=>'tdoverflowmax150 maxwidth150onsmartphone'), 'notify_tiers_at_create' => array('type'=>'integer', 'label'=>'NotifyThirdparty', 'visible'=>-1, 'enabled'=>0, 'position'=>51, 'notnull'=>1, 'index'=>1), 'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php', 'label'=>'Project', 'visible'=>-1, 'enabled'=>'$conf->project->enabled', 'position'=>52, 'notnull'=>-1, 'index'=>1, 'help'=>"LinkToProject"), + 'fk_contract' => array('type'=>'integer:Contrat:contrat/class/contrat.class.php', 'label'=>'Contract', 'visible'=>-1, 'enabled'=>'$conf->contract->enabled', 'position'=>53, 'notnull'=>-1, 'index'=>1, 'help'=>"LinkToContract"), //'timing' => array('type'=>'varchar(20)', 'label'=>'Timing', 'visible'=>-1, 'enabled'=>1, 'position'=>42, 'notnull'=>-1, 'help'=>""), // what is this ? 'datec' => array('type'=>'datetime', 'label'=>'DateCreation', 'visible'=>1, 'enabled'=>1, 'position'=>500, 'notnull'=>1, 'csslist'=>'nowraponall'), 'date_read' => array('type'=>'datetime', 'label'=>'TicketReadOn', 'visible'=>-1, 'enabled'=>1, 'position'=>501, 'notnull'=>1), @@ -498,6 +506,7 @@ class Ticket extends CommonObject $sql .= "track_id,"; $sql .= "fk_soc,"; $sql .= "fk_project,"; + $sql .= "fk_contract,"; $sql .= "origin_email,"; $sql .= "fk_user_create,"; $sql .= "fk_user_assign,"; @@ -523,6 +532,7 @@ class Ticket extends CommonObject $sql .= " ".(!isset($this->track_id) ? 'NULL' : "'".$this->db->escape($this->track_id)."'").","; $sql .= " ".($this->fk_soc > 0 ? $this->db->escape($this->fk_soc) : "null").","; $sql .= " ".($this->fk_project > 0 ? $this->db->escape($this->fk_project) : "null").","; + $sql .= " ".($this->fk_contract > 0 ? $this->db->escape($this->fk_contract) : "null").","; $sql .= " ".(!isset($this->origin_email) ? 'NULL' : "'".$this->db->escape($this->origin_email)."'").","; $sql .= " ".(!isset($this->fk_user_create) ? ($user->id > 0 ? $user->id : 'NULL') : ($this->fk_user_create > 0 ? $this->fk_user_create : 'NULL')).","; $sql .= " ".($this->fk_user_assign > 0 ? $this->fk_user_assign : 'NULL').","; @@ -635,6 +645,7 @@ class Ticket extends CommonObject $sql .= " t.track_id,"; $sql .= " t.fk_soc,"; $sql .= " t.fk_project,"; + $sql .= " t.fk_contract,"; $sql .= " t.origin_email,"; $sql .= " t.fk_user_create,"; $sql .= " t.fk_user_assign,"; @@ -687,6 +698,7 @@ class Ticket extends CommonObject $this->fk_soc = $obj->fk_soc; $this->socid = $obj->fk_soc; // for fetch_thirdparty() method $this->fk_project = $obj->fk_project; + $this->fk_contract = $obj->fk_contract; $this->origin_email = $obj->origin_email; $this->fk_user_create = $obj->fk_user_create; $this->fk_user_assign = $obj->fk_user_assign; @@ -763,6 +775,7 @@ class Ticket extends CommonObject $sql .= " t.track_id,"; $sql .= " t.fk_soc,"; $sql .= " t.fk_project,"; + $sql .= " t.fk_contract,"; $sql .= " t.origin_email,"; $sql .= " t.fk_user_create, uc.lastname as user_create_lastname, uc.firstname as user_create_firstname,"; $sql .= " t.fk_user_assign, ua.lastname as user_assign_lastname, ua.firstname as user_assign_firstname,"; @@ -782,8 +795,10 @@ class Ticket extends CommonObject $sql .= " t.tms"; $sql .= ", type.label as type_label, category.label as category_label, severity.label as severity_label"; // Add fields for extrafields - foreach ($extrafields->attributes[$this->table_element]['label'] as $key => $val) { - $sql .= ($extrafields->attributes[$this->table_element]['type'][$key] != 'separate' ? ",ef.".$key." as options_".$key : ''); + if ($extrafields->attributes[$this->table_element]['count']> 0) { + foreach ($extrafields->attributes[$this->table_element]['label'] as $key => $val) { + $sql .= ($extrafields->attributes[$this->table_element]['type'][$key] != 'separate' ? ",ef.".$key." as options_".$key : ''); + } } $sql .= " FROM ".MAIN_DB_PREFIX."ticket as t"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_type as type ON type.code=t.type_code"; @@ -792,8 +807,10 @@ class Ticket extends CommonObject $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid=t.fk_soc"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as uc ON uc.rowid=t.fk_user_create"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as ua ON ua.rowid=t.fk_user_assign"; - if (is_array($extrafields->attributes[$this->table_element]['label']) && count($extrafields->attributes[$this->table_element]['label'])) { - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."ticket_extrafields as ef on (t.rowid = ef.fk_object)"; + if ($extrafields->attributes[$this->table_element]['count']> 0) { + if (is_array($extrafields->attributes[$this->table_element]['label']) && count($extrafields->attributes[$this->table_element]['label'])) { + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."ticket_extrafields as ef on (t.rowid = ef.fk_object)"; + } } if (empty($user->rights->societe->client->voir) && !$user->socid) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; @@ -814,6 +831,8 @@ class Ticket extends CommonObject } else { $sql .= " AND ".$key.' = '.((int) $value); } + } elseif ($key == 't.fk_contract') { + $sql .= " AND ".$key.' = '.((int) $value); } else { $sql .= " AND ".$key." LIKE '%".$this->db->escape($value)."%'"; } @@ -851,6 +870,7 @@ class Ticket extends CommonObject $line->track_id = $obj->track_id; $line->fk_soc = $obj->fk_soc; $line->fk_project = $obj->fk_project; + $line->fk_contract = $obj->fk_contract; $line->origin_email = $obj->origin_email; $line->fk_user_create = $obj->fk_user_create; @@ -881,13 +901,14 @@ class Ticket extends CommonObject $line->date_close = $this->db->jdate($obj->date_close); // Extra fields - if (is_array($extrafields->attributes[$this->table_element]['label']) && count($extrafields->attributes[$this->table_element]['label'])) { - foreach ($extrafields->attributes[$this->table_element]['label'] as $key => $val) { - $tmpkey = 'options_'.$key; - $line->{$tmpkey} = $obj->$tmpkey; + if ($extrafields->attributes[$this->table_element]['count']> 0) { + if (is_array($extrafields->attributes[$this->table_element]['label']) && count($extrafields->attributes[$this->table_element]['label'])) { + foreach ($extrafields->attributes[$this->table_element]['label'] as $key => $val) { + $tmpkey = 'options_'.$key; + $line->{$tmpkey} = $obj->$tmpkey; + } } } - $this->lines[$i] = $line; $i++; } @@ -934,6 +955,10 @@ class Ticket extends CommonObject $this->fk_project = (int) $this->fk_project; } + if (isset($this->fk_contract)) { + $this->fk_contract = (int) $this->fk_contract; + } + if (isset($this->origin_email)) { $this->origin_email = trim($this->origin_email); } @@ -995,6 +1020,7 @@ class Ticket extends CommonObject $sql .= " track_id=".(isset($this->track_id) ? "'".$this->db->escape($this->track_id)."'" : "null").","; $sql .= " fk_soc=".(isset($this->fk_soc) ? "'".$this->db->escape($this->fk_soc)."'" : "null").","; $sql .= " fk_project=".(isset($this->fk_project) ? "'".$this->db->escape($this->fk_project)."'" : "null").","; + $sql .= " fk_contract=".(isset($this->fk_contract) ? "'".$this->db->escape($this->fk_contract)."'" : "null").","; $sql .= " origin_email=".(isset($this->origin_email) ? "'".$this->db->escape($this->origin_email)."'" : "null").","; $sql .= " fk_user_create=".(isset($this->fk_user_create) ? $this->fk_user_create : "null").","; $sql .= " fk_user_assign=".(isset($this->fk_user_assign) ? $this->fk_user_assign : "null").","; @@ -2048,17 +2074,19 @@ class Ticket extends CommonObject */ public function setContract($contractid) { - if (!$this->table_element) { - dol_syslog(get_class($this)."::setContract was called on objet with property table_element not defined", LOG_ERR); - return -1; - } - - $result = $this->add_object_linked('contrat', $contractid); - if ($result) { - $this->fk_contract = $contractid; - return 1; + if ($this->id) { + $sql = "UPDATE ".MAIN_DB_PREFIX."ticket"; + $sql .= " SET fk_contract = ".($contractid > 0 ? $contractid : "null"); + $sql .= " WHERE rowid = ".((int) $this->id); + dol_syslog(get_class($this).'::setContract sql='.$sql); + $resql = $this->db->query($sql); + print $sql; + if ($resql) { + return 1; + } else { + return -1; + } } else { - dol_print_error($this->db); return -1; } } diff --git a/htdocs/ticket/list.php b/htdocs/ticket/list.php index f1bd192fcd8..27e7ca09d3f 100644 --- a/htdocs/ticket/list.php +++ b/htdocs/ticket/list.php @@ -681,6 +681,9 @@ if ($search_societe) { if ($projectid > 0) { $param .= '&projectid='.urlencode($projectid); } +if ($contractid > 0) { + $param .= '&contractid='.urlencode($contractid); +} if ($search_date_start) { $tmparray = dol_getdate($search_date_start); $param .= '&search_date_startday='.urlencode($tmparray['mday']);