dolibarr  19.0.0-dev
index.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) - 2013-2016 Jean-François FERRY <hello@librethic.io>
3  * Copyright (C) - 2019 Nicolas ZABOURI <info@inovea-conseil.com>
4  * Copyright (C) 2021 Frédéric France <frederic.france@netlogic.fr>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <https://www.gnu.org/licenses/>.
18  */
19 
25 // Load Dolibarr environment
26 require '../main.inc.php';
27 require_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php';
28 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
29 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
30 require_once DOL_DOCUMENT_ROOT.'/ticket/class/actions_ticket.class.php';
31 require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticketstats.class.php';
32 
33 
34 $hookmanager = new HookManager($db);
35 
36 // Initialize technical object to manage hooks. Note that conf->hooks_modules contains array
37 $hookmanager->initHooks(array('ticketsindex'));
38 
39 // Load translation files required by the page
40 $langs->loadLangs(array('companies', 'other', 'ticket'));
41 
43 $HEIGHT = DolGraph::getDefaultGraphSizeForStats('height');
44 
45 // Get parameters
46 $id = GETPOST('id', 'int');
47 $msg_id = GETPOST('msg_id', 'int');
48 
49 $action = GETPOST('action', 'aZ09');
50 
51 $socid = 0;
52 if ($user->socid) {
53  $socid = $user->socid;
54 }
55 $userid = $user->id;
56 
57 $nowarray = dol_getdate(dol_now(), true);
58 $nowyear = $nowarray['year'];
59 $year = GETPOST('year', 'int') > 0 ? GETPOST('year', 'int') : $nowyear;
60 $startyear = $year - (empty($conf->global->MAIN_STATS_GRAPHS_SHOW_N_YEARS) ? 2 : max(1, min(10, $conf->global->MAIN_STATS_GRAPHS_SHOW_N_YEARS)));
61 $endyear = $year;
62 
63 // Initialize objects
64 $object = new Ticket($db);
65 
66 // Security check
67 //$result = restrictedArea($user, 'ticket|knowledgemanagement', 0, '', '', '', '');
68 if (empty($user->rights->ticket->read) && !$user->hasRight('knowledgemanagement', 'knowledgerecord', 'read')) {
69  accessforbidden('Not enought permissions');
70 }
71 
72 
73 
74 /*
75  * Actions
76  */
77 
78 // None
79 
80 
81 
82 /*
83  * View
84  */
85 
86 $resultboxes = FormOther::getBoxesArea($user, "11"); // Load $resultboxes (selectboxlist + boxactivated + boxlista + boxlistb)
87 
88 $form = new Form($db);
89 
90 llxHeader('', $langs->trans('TicketsIndex'), '');
91 
92 $linkback = '';
93 print load_fiche_titre($langs->trans('TicketsIndex'), $resultboxes['selectboxlist'], 'ticket');
94 
95 
96 $dir = '';
97 $filenamenb = $dir."/".$prefix."ticketinyear-".$endyear.".png";
98 $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=ticket&amp;file=ticketinyear-'.$endyear.'.png';
99 
100 $stats = new TicketStats($db, $socid, $userid);
101 $param_year = 'DOLUSERCOOKIE_ticket_by_status_year';
102 $param_shownb = 'DOLUSERCOOKIE_ticket_by_status_shownb';
103 $param_showtot = 'DOLUSERCOOKIE_ticket_by_status_showtot';
104 $autosetarray = preg_split("/[,;:]+/", GETPOST('DOL_AUTOSET_COOKIE'));
105 if (in_array('DOLUSERCOOKIE_ticket_by_status', $autosetarray)) {
106  $endyear = GETPOST($param_year, 'int');
107  $shownb = GETPOST($param_shownb, 'alpha');
108  $showtot = GETPOST($param_showtot, 'alpha');
109 } elseif (!empty($_COOKIE['DOLUSERCOOKIE_ticket_by_status'])) {
110  $tmparray = json_decode($_COOKIE['DOLUSERCOOKIE_ticket_by_status'], true);
111  $endyear = $tmparray['year'];
112  $shownb = empty($tmparray['shownb']) ? 0 : $tmparray['shownb'];
113  $showtot = empty($tmparray['showtot']) ? 0 : $tmparray['showtot'];
114 }
115 if (empty($shownb) && empty($showtot)) {
116  $showtot = 1;
117  $shownb = 0;
118 }
119 
120 if (empty($endyear)) {
121  $endyear = $nowarray['year'];
122 }
123 
124 $startyear = $endyear - 1;
125 
126 // Change default WIDHT and HEIGHT (we need a smaller than default for both desktop and smartphone)
127 $WIDTH = (($shownb && $showtot) || !empty($conf->dol_optimize_smallscreen)) ? '100%' : '80%';
128 if (empty($conf->dol_optimize_smallscreen)) {
129  $HEIGHT = '200';
130 } else {
131  $HEIGHT = '160';
132 }
133 
134 print '<div class="clearboth"></div>';
135 print '<div class="fichecenter fichecenterbis">';
136 
137 print '<div class="twocolumns">';
138 
139 print '<div class="firstcolumn fichehalfleft boxhalfleft" id="boxhalfleft">';
140 
141 /*
142  * Statistics area
143  */
144 $tick = array(
145  'unread' => 0,
146  'read' => 0,
147  'needmoreinfo' => 0,
148  'answered' => 0,
149  'assigned' => 0,
150  'inprogress' => 0,
151  'waiting' => 0,
152  'closed' => 0,
153  'canceled' => 0,
154  'deleted' => 0,
155 );
156 
157 $sql = "SELECT t.fk_statut, COUNT(t.fk_statut) as nb";
158 $sql .= " FROM ".MAIN_DB_PREFIX."ticket as t";
159 if (empty($user->rights->societe->client->voir) && !$socid) {
160  $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
161 }
162 $sql .= ' WHERE t.entity IN ('.getEntity('ticket').')';
163 $sql .= dolSqlDateFilter('datec', 0, 0, $endyear);
164 
165 if (empty($user->rights->societe->client->voir) && !$socid) {
166  $sql .= " AND t.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
167 }
168 
169 // External users restriction
170 if ($user->socid > 0) {
171  $sql .= " AND t.fk_soc= ".((int) $user->socid);
172 } else {
173  // For internals users,
174  if (!empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY) && !$user->rights->ticket->manage) {
175  $sql .= " AND t.fk_user_assign = ".((int) $user->id);
176  }
177 }
178 $sql .= " GROUP BY t.fk_statut";
179 
180 $result = $db->query($sql);
181 if ($result) {
182  while ($objp = $db->fetch_object($result)) {
183  $found = 0;
184  if ($objp->fk_statut == Ticket::STATUS_NOT_READ) {
185  $tick['unread'] = $objp->nb;
186  }
187  if ($objp->fk_statut == Ticket::STATUS_READ) {
188  $tick['read'] = $objp->nb;
189  }
190  if ($objp->fk_statut == Ticket::STATUS_NEED_MORE_INFO) {
191  $tick['needmoreinfo'] = $objp->nb;
192  }
193  if ($objp->fk_statut == Ticket::STATUS_ASSIGNED) {
194  $tick['assigned'] = $objp->nb;
195  }
196  if ($objp->fk_statut == Ticket::STATUS_IN_PROGRESS) {
197  $tick['inprogress'] = $objp->nb;
198  }
199  if ($objp->fk_statut == Ticket::STATUS_WAITING) {
200  $tick['waiting'] = $objp->nb;
201  }
202  if ($objp->fk_statut == Ticket::STATUS_CLOSED) {
203  $tick['closed'] = $objp->nb;
204  }
205  if ($objp->fk_statut == Ticket::STATUS_CANCELED) {
206  $tick['canceled'] = $objp->nb;
207  }
208  }
209 
210  include DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/theme_vars.inc.php';
211 
212  $dataseries = array();
213  $colorseries = array();
214 
215  $dataseries[] = array('label' => $langs->transnoentitiesnoconv($object->statuts_short[Ticket::STATUS_NOT_READ]), 'data' => round($tick['unread']));
216  $colorseries[Ticket::STATUS_NOT_READ] = '-'.$badgeStatus0;
217  $dataseries[] = array('label' => $langs->transnoentitiesnoconv($object->statuts_short[Ticket::STATUS_READ]), 'data' => round($tick['read']));
218  $colorseries[Ticket::STATUS_READ] = $badgeStatus1;
219  $dataseries[] = array('label' => $langs->transnoentitiesnoconv($object->statuts_short[Ticket::STATUS_ASSIGNED]), 'data' => round($tick['assigned']));
220  $colorseries[Ticket::STATUS_ASSIGNED] = $badgeStatus3;
221  $dataseries[] = array('label' => $langs->transnoentitiesnoconv($object->statuts_short[Ticket::STATUS_IN_PROGRESS]), 'data' => round($tick['inprogress']));
222  $colorseries[Ticket::STATUS_IN_PROGRESS] = $badgeStatus4;
223  $dataseries[] = array('label' => $langs->transnoentitiesnoconv($object->statuts_short[Ticket::STATUS_WAITING]), 'data' => round($tick['waiting']));
224  $colorseries[Ticket::STATUS_WAITING] = '-'.$badgeStatus4;
225  $dataseries[] = array('label' => $langs->transnoentitiesnoconv($object->statuts_short[Ticket::STATUS_NEED_MORE_INFO]), 'data' => round($tick['needmoreinfo']));
226  $colorseries[Ticket::STATUS_NEED_MORE_INFO] = '-'.$badgeStatus3;
227  $dataseries[] = array('label' => $langs->transnoentitiesnoconv($object->statuts_short[Ticket::STATUS_CANCELED]), 'data' => round($tick['canceled']));
228  $colorseries[Ticket::STATUS_CANCELED] = $badgeStatus9;
229  $dataseries[] = array('label' => $langs->transnoentitiesnoconv($object->statuts_short[Ticket::STATUS_CLOSED]), 'data' => round($tick['closed']));
230  $colorseries[Ticket::STATUS_CLOSED] = $badgeStatus6;
231 } else {
232  dol_print_error($db);
233 }
234 
235 $stringtoshow = '<script type="text/javascript">
236  jQuery(document).ready(function() {
237  jQuery("#idsubimgDOLUSERCOOKIE_ticket_by_status").click(function() {
238  jQuery("#idfilterDOLUSERCOOKIE_ticket_by_status").toggle();
239  });
240  });
241  </script>';
242 $stringtoshow .= '<div class="center hideobject" id="idfilterDOLUSERCOOKIE_ticket_by_status">'; // hideobject is to start hidden
243 $stringtoshow .= '<form class="flat formboxfilter" method="POST" action="'.$_SERVER["PHP_SELF"].'">';
244 $stringtoshow .= '<input type="hidden" name="token" value="'.newToken().'">';
245 $stringtoshow .= '<input type="hidden" name="action" value="refresh">';
246 $stringtoshow .= '<input type="hidden" name="DOL_AUTOSET_COOKIE" value="DOLUSERCOOKIE_ticket_by_status:year,shownb,showtot">';
247 $stringtoshow .= $langs->trans("Year").' <input class="flat" size="4" type="text" name="'.$param_year.'" value="'.$endyear.'">';
248 $stringtoshow .= '<input type="image" alt="'.$langs->trans("Refresh").'" src="'.img_picto($langs->trans("Refresh"), 'refresh.png', '', '', 1).'">';
249 $stringtoshow .= '</form>';
250 $stringtoshow .= '</div>';
251 
252 if (!empty($user->rights->ticket->read)) {
253  print '<div class="div-table-responsive-no-min">';
254  print '<table class="noborder centpercent">';
255  print '<tr class="liste_titre"><th >'.$langs->trans("Statistics").' '.$endyear.' '.img_picto('', 'filter.png', 'id="idsubimgDOLUSERCOOKIE_ticket_by_status" class="linkobject"').'</th></tr>';
256 
257  print '<tr><td class="center">';
258  print $stringtoshow;
259 
260  // don't display graph if no series
261  if (!empty($dataseries) && count($dataseries) > 1) {
262  $totalnb = 0;
263  foreach ($dataseries as $key => $value) {
264  $totalnb += $value['data'];
265  }
266 
267  $data = array();
268  foreach ($dataseries as $key => $value) {
269  $data[] = array($value['label'], $value['data']);
270  }
271  $px1 = new DolGraph();
272  $mesg = $px1->isGraphKo();
273  if (!$mesg) {
274  $px1->SetData($data);
275  $px1->SetDataColor(array_values($colorseries));
276 
277  unset($data1);
278  $i = $startyear;
279  $legend = array();
280  while ($i <= $endyear) {
281  $legend[] = $i;
282  $i++;
283  }
284  $px1->setShowLegend(2);
285  $px1->SetType(array('pie'));
286  $px1->SetLegend($legend);
287  $px1->SetMaxValue($px1->GetCeilMaxValue());
288  //$px1->SetWidth($WIDTH);
289  $px1->SetHeight($HEIGHT);
290  $px1->SetYLabel($langs->trans("TicketStatByStatus"));
291  $px1->SetShading(3);
292  $px1->SetHorizTickIncrement(1);
293  $px1->SetCssPrefix("cssboxes");
294  $px1->mode = 'depth';
295  //$px1->SetTitle($langs->trans("TicketStatByStatus"));
296 
297  $px1->draw($filenamenb, $fileurlnb);
298  print $px1->show($totalnb ? 0 : 1);
299  }
300  }
301  print '</td></tr>';
302 
303  print '</table>';
304  print '</div>';
305 }
306 
307 if (!empty($user->rights->ticket->read)) {
308  // Build graphic number of object
309  $data = $stats->getNbByMonthWithPrevYear($endyear, $startyear);
310 
311  print '<br>'."\n";
312 }
313 
314 print $resultboxes['boxlista'];
315 
316 print '</div>'."\n";
317 
318 print '<div class="secondcolumn fichehalfright boxhalfright" id="boxhalfright">';
319 
320 if (!empty($user->rights->ticket->read)) {
321  /*
322  * Latest unread tickets
323  */
324 
325  $max = 10;
326 
327  $sql = "SELECT t.rowid, t.ref, t.track_id, t.datec, t.subject, t.type_code, t.category_code, t.severity_code, t.fk_statut, t.progress,";
328  $sql .= " type.code as type_code, type.label as type_label,";
329  $sql .= " category.code as category_code, category.label as category_label,";
330  $sql .= " severity.code as severity_code, severity.label as severity_label";
331  $sql .= " FROM ".MAIN_DB_PREFIX."ticket as t";
332  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_type as type ON type.code=t.type_code";
333  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_category as category ON category.code=t.category_code";
334  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_severity as severity ON severity.code=t.severity_code";
335  if (empty($user->rights->societe->client->voir) && !$socid) {
336  $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
337  }
338 
339  $sql .= ' WHERE t.entity IN ('.getEntity('ticket').')';
340  $sql .= " AND t.fk_statut=0";
341  if (empty($user->rights->societe->client->voir) && !$socid) {
342  $sql .= " AND t.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
343  }
344 
345  if ($user->socid > 0) {
346  $sql .= " AND t.fk_soc= ".((int) $user->socid);
347  } else {
348  // Restricted to assigned user only
349  if (!empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY) && !$user->rights->ticket->manage) {
350  $sql .= " AND t.fk_user_assign = ".((int) $user->id);
351  }
352  }
353  $sql .= $db->order("t.datec", "DESC");
354  $sql .= $db->plimit($max, 0);
355 
356  //print $sql;
357  $result = $db->query($sql);
358  if ($result) {
359  $num = $db->num_rows($result);
360 
361  $i = 0;
362 
363  $transRecordedType = $langs->trans("LatestNewTickets", $max);
364 
365  print '<div class="div-table-responsive-no-min">';
366  print '<table class="noborder centpercent">';
367  print '<tr class="liste_titre"><th colspan="5">'.$transRecordedType.'</th>';
368  print '<th class="right" colspan="2"><a href="'.DOL_URL_ROOT.'/ticket/list.php?search_fk_statut[]='.Ticket::STATUS_NOT_READ.'">'.$langs->trans("FullList").'</th>';
369  print '</tr>';
370  if ($num > 0) {
371  while ($i < $num) {
372  $objp = $db->fetch_object($result);
373 
374  $object->id = $objp->rowid;
375  $object->ref = $objp->ref;
376  $object->track_id = $objp->track_id;
377  $object->fk_statut = $objp->fk_statut;
378  $object->progress = $objp->progress;
379  $object->subject = $objp->subject;
380 
381  print '<tr class="oddeven">';
382 
383  // Ref
384  print '<td class="nowraponall">';
385  print $object->getNomUrl(1);
386  print "</td>\n";
387 
388  // Creation date
389  print '<td class="left">';
390  print dol_print_date($db->jdate($objp->datec), 'dayhour');
391  print "</td>";
392 
393  // Subject
394  print '<td class="nowrap">';
395  print '<a href="card.php?track_id='.$objp->track_id.'">'.dol_trunc($objp->subject, 30).'</a>';
396  print "</td>\n";
397 
398  // Type
399  print '<td class="nowrap tdoverflowmax100">';
400  $s = $langs->getLabelFromKey($db, 'TicketTypeShort'.$objp->type_code, 'c_ticket_type', 'code', 'label', $objp->type_code);
401  print '<span title="'.dol_escape_htmltag($s).'">'.$s.'</span>';
402  print '</td>';
403 
404  // Category
405  print '<td class="nowrap">';
406  if (!empty($obp->category_code)) {
407  $s = $langs->getLabelFromKey($db, 'TicketCategoryShort'.$objp->category_code, 'c_ticket_category', 'code', 'label', $objp->category_code);
408  print '<span title="'.dol_escape_htmltag($s).'">'.$s.'</span>';
409  }
410  //print $objp->category_label;
411  print "</td>";
412 
413  // Severity = Priority
414  print '<td class="nowrap">';
415  $s = $langs->getLabelFromKey($db, 'TicketSeverityShort'.$objp->severity_code, 'c_ticket_severity', 'code', 'label', $objp->severity_code);
416  print '<span title="'.dol_escape_htmltag($s).'">'.$s.'</span>';
417  //print $objp->severity_label;
418  print "</td>";
419 
420  print '<td class="nowraponall right">';
421  print $object->getLibStatut(5);
422  print "</td>";
423 
424  print "</tr>\n";
425  $i++;
426  }
427 
428  $db->free($result);
429  } else {
430  print '<tr><td colspan="6"><span class="opacitymedium">'.$langs->trans('NoUnreadTicketsFound').'</span></td></tr>';
431  }
432 
433  print "</table>";
434  print '</div>';
435 
436  print '<br>';
437  } else {
438  dol_print_error($db);
439  }
440 }
441 
442 print $resultboxes['boxlistb'];
443 
444 print '</div>';
445 print '</div>';
446 print '</div>';
447 
448 
449 print '<div class="clearboth"></div>';
450 
451 $parameters = array('user' => $user);
452 $reshook = $hookmanager->executeHooks('dashboardTickets', $parameters, $object); // Note that $action and $object may have been modified by hook
453 
454 
455 
456 // End of page
457 llxFooter('');
458 $db->close();
Class to build graphs.
static getDefaultGraphSizeForStats($direction, $defaultsize='')
getDefaultGraphSizeForStats
Class to manage generation of HTML components Only common components must be here.
static getBoxesArea($user, $areacode)
Get array with HTML tabs with boxes of a particular area including personalized choices of user.
Class to manage hooks.
const STATUS_NOT_READ
Status.
Classe permettant la gestion des stats des deplacements et notes de frais.
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
dolSqlDateFilter($datefield, $day_date, $month_date, $year_date, $excludefirstand=0, $gm=false)
Generate a SQL string to make a filter into a range (for second of date until last second of date).
Definition: date.lib.php:359
load_fiche_titre($titre, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
Class to generate the form for creating a new ticket.
llxFooter()
Footer empty.
Definition: index.php:71
if(!defined('NOTOKENRENEWAL')) if(!defined('NOLOGIN')) if(!defined('NOCSRFCHECK')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) if(!defined('NOIPCHECK')) if(!defined('NOBROWSERNOTIF')) llxHeader()
Header empty.
Definition: index.php:63
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.