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