Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into

develop
This commit is contained in:
Laurent Destailleur
2023-08-11 12:34:27 +02:00
7 changed files with 298 additions and 21 deletions

View File

@@ -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.

185
htdocs/contrat/ticket.php Normal file
View File

@@ -0,0 +1,185 @@
<?php
/* Copyright (C) 2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2004-2016 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2012-2023 Charlene BENKE <charlene@patas-monkey.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**
* \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 = '<a href="'.DOL_URL_ROOT.'/contrat/list.php'.(! empty($socid)?'?socid='.$socid:'').'">';
$linkback.= $langs->trans("BackToList").'</a>';
$morehtmlref='';
$morehtmlref.=$object->ref;
$morehtmlref.='<div class="refidno">';
// 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.='<br>';
$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.='<br>'.$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.='<br>'.$langs->trans('Project') . ' : ';
if (! empty($object->fk_project)) {
$proj = new Project($db);
$proj->fetch($object->fk_project);
$morehtmlref.='<a href="'.DOL_URL_ROOT.'/projet/card.php?id=';
$morehtmlref.=$object->fk_project . '" title="' . $langs->trans('ShowProject') . '">';
$morehtmlref.=$proj->ref;
$morehtmlref.='</a>';
} else {
$morehtmlref.='';
}
}
$morehtmlref.='</div>';
dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'none', $morehtmlref);
print '<div class="underbanner clearboth"></div>';
/*
* Referers types
*/
$title=$langs->trans("ListTicketsLinkToContract");
print '<table class="noborder" width="100%">';
print '<tr class="liste_titre">';
print '<td >'.$langs->trans("Ref").'</td>';
print '<td width="300">'.$langs->trans("Subject").'</td>';
print '<td align="left">'.$langs->trans("Type").'</td>';
print '<td align="left" nowrap >'.$langs->trans("TicketCategory").'</td>';
print '<td align="left">'.$langs->trans("Severity").'</td>';
print '<td align="center">'.$langs->trans("Date").'</td>';
print '<td align="center" nowrap >'.$langs->trans("DateEnd").'</td>';
print '<td align="right">'.$langs->trans("Progress").'</td>';
print '<td align="right" width="100">'.$langs->trans("Status").'</td>';
print '</tr>';
// 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 "<tr>";
// Ref
print '<td align="left">';
print $element->getNomUrl(1);
print "</td>\n";
// Information
print '<td align="left">'.$value->subject.'</td>';
print '<td align="left">'.$value->type_label.'</td>';
print '<td align="left">'.$value->category_label.'</td>';
print '<td align="left">'.$value->severity_label.'</td>';
// Date
print '<td align="center">'.dol_print_date($element->datec, 'day').'</td>';
print '<td align="center">'.dol_print_date($element->date_close, 'day').'</td>';
// Duration
print '<td align="right">';
print (isset($element->progress) ? $element->progress.'%' : '');
print '</td>';
// Status
print '<td align="right">'.$element->getLibStatut(5).'</td>';
print '</tr>';
}
}
print "</table>";
llxFooter();
$db->close();

View File

@@ -4,6 +4,7 @@
* Copyright (C) 2019-2022 Frédéric France <frederic.france@netlogic.fr>
* Copyright (C) 2021 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2021 Alexandre Spangaro <aspangaro@open-dsi.fr>
* Copyright (C) 2023 Charlene Benke <charlene.r@patas-monkey.com>
*
* 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 '<tr><td><label for="contract"><span class="">'.$langs->trans("Contract").'</span></label></td><td>';
print img_picto('', 'contract');
print $formcontract->select_contract(-1, GETPOST('contactid', 'int'), 'contractid', 0, 1, 1);
print '</td></tr>';
}
}
// Other attributes
$parameters = array();
$reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $ticketstat, $action); // Note that $action and $object may have been modified by hook

View File

@@ -1,6 +1,7 @@
<?php
/* Copyright (C) 2006-2012 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2009-2012 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2023 Charlene BENKE <charlene@patas-monkey.com>
*
* 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

View File

@@ -4,7 +4,7 @@
* Copyright (C) 2018 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2021 Frédéric France <frederic.france@netlogic.fr>
* Copyright (C) 2021 Alexandre Spangaro <aspangaro@open-dsi.fr>
* Copyright (C) 2022 Charlene Benke <charlene@patas-monkey.com>
* Copyright (C) 2022-2023 Charlene Benke <charlene@patas-monkey.com>
* Copyright (C) 2023 Benjamin Falière <benjamin.faliere@altairis.fr>
*
* 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 '</form>'; */
} 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 .= '<br>';
$morehtmlref .= $langs->trans('Contract');
if ($action != 'edit_contrat') {
$morehtmlref .= '<a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=edit_contrat&token='.newToken().'&id='.$object->id.'">';
$morehtmlref .= img_edit($langs->trans('SetContract'), 1);
$morehtmlref .= '</a>';
}
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 '<a href="'.DOL_URL_ROOT.'/projet/card.php?id='.$selected.'">'.$projet->title.'</a>';
$morehtmlref .= $contratstatic->getNomUrl(0, '', 1);
} else {
$morehtmlref .= "&nbsp;";
}
}
}
$morehtmlref .= '</div>';
$linkback = '<a href="'.DOL_URL_ROOT.'/ticket/list.php?restore_lastsearch_values=1"><strong>'.$langs->trans("BackToList").'</strong></a> ';

View File

@@ -3,6 +3,7 @@
* Copyright (C) 2016 Christophe Battarel <christophe@altairis.fr>
* Copyright (C) 2019-2023 Frédéric France <frederic.france@netlogic.fr>
* Copyright (C) 2020 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2023 Charlene Benke <charlene@patas-monkey.com>
*
* 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,9 +795,11 @@ 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
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";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_category as category ON category.code=t.category_code";
@@ -792,9 +807,11 @@ 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 ($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 ($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;
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 {
dol_print_error($this->db);
return -1;
}
} else {
return -1;
}
}

View File

@@ -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']);