dolibarr  16.0.1
index.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2001-2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2004-2013 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
5  * Copyright (C) 2012 Marcos García <marcosgdf@gmail.com>
6  * Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
7  * Copyright (C) 2020 Maxime DEMAREST <maxime@indelog.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <https://www.gnu.org/licenses/>.
21  */
22 
29 require '../../main.inc.php';
30 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
31 require_once DOL_DOCUMENT_ROOT.'/commande/class/commandestats.class.php';
32 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
33 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formorder.class.php';
34 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
35 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
36 require_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php';
37 
39 $HEIGHT = DolGraph::getDefaultGraphSizeForStats('height');
40 
41 $mode = GETPOSTISSET("mode") ? GETPOST("mode", 'aZ09') : 'customer';
42 if ($mode == 'customer' && !$user->rights->commande->lire) {
44 }
45 if ($mode == 'supplier' && empty($user->rights->fournisseur->commande->lire)) {
47 }
48 if ($mode == 'supplier') {
49  $object_status = GETPOST('object_status', 'array:int');
50  $object_status = implode(',', $object_status);
51 } else {
52  $object_status = GETPOST('object_status', 'intcomma');
53 }
54 
55 
56 $typent_id = GETPOST('typent_id', 'int');
57 $categ_id = GETPOST('categ_id', 'categ_id');
58 
59 $userid = GETPOST('userid', 'int');
60 $socid = GETPOST('socid', 'int');
61 // Security check
62 if ($user->socid > 0) {
63  $action = '';
64  $socid = $user->socid;
65 }
66 
67 $nowyear = strftime("%Y", dol_now());
68 $year = GETPOST('year') > 0 ?GETPOST('year') : $nowyear;
69 $startyear = $year - (empty($conf->global->MAIN_STATS_GRAPHS_SHOW_N_YEARS) ? 2 : max(1, min(10, $conf->global->MAIN_STATS_GRAPHS_SHOW_N_YEARS)));
70 $endyear = $year;
71 
72 // Load translation files required by the page
73 $langs->loadLangs(array('orders', 'companies', 'other', 'suppliers'));
74 
75 
76 /*
77  * View
78  */
79 
80 $form = new Form($db);
81 $formorder = new FormOrder($db);
82 $formcompany = new FormCompany($db);
83 $formother = new FormOther($db);
84 
85 $picto = 'order';
86 $title = $langs->trans("OrdersStatistics");
87 $dir = $conf->commande->dir_temp;
88 
89 if ($mode == 'supplier') {
90  $picto = 'supplier_order';
91  $title = $langs->trans("OrdersStatisticsSuppliers");
92  $dir = $conf->fournisseur->commande->dir_temp;
93 }
94 
95 llxHeader('', $title);
96 
97 print load_fiche_titre($title, '', $picto);
98 
99 dol_mkdir($dir);
100 
101 $stats = new CommandeStats($db, $socid, $mode, ($userid > 0 ? $userid : 0), ($typent_id > 0 ? $typent_id : 0), ($categ_id > 0 ? $categ_id : 0));
102 if ($mode == 'customer') {
103  if ($object_status != '' && $object_status >= -1) {
104  $stats->where .= ' AND c.fk_statut IN ('.$db->sanitize($object_status).')';
105  }
106 }
107 if ($mode == 'supplier') {
108  if ($object_status != '' && $object_status >= 0) {
109  $stats->where .= ' AND c.fk_statut IN ('.$db->sanitize($object_status).')';
110  }
111 }
112 
113 
114 // Build graphic number of object
115 $data = $stats->getNbByMonthWithPrevYear($endyear, $startyear);
116 
117 //var_dump($data);
118 // $data = array(array('Lib',val1,val2,val3),...)
119 
120 
121 if (empty($user->rights->societe->client->voir) || $user->socid) {
122  $filenamenb = $dir.'/ordersnbinyear-'.$user->id.'-'.$year.'.png';
123  if ($mode == 'customer') {
124  $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersnbinyear-'.$user->id.'-'.$year.'.png';
125  }
126  if ($mode == 'supplier') {
127  $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersnbinyear-'.$user->id.'-'.$year.'.png';
128  }
129 } else {
130  $filenamenb = $dir.'/ordersnbinyear-'.$year.'.png';
131  if ($mode == 'customer') {
132  $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersnbinyear-'.$year.'.png';
133  }
134  if ($mode == 'supplier') {
135  $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersnbinyear-'.$year.'.png';
136  }
137 }
138 
139 $px1 = new DolGraph();
140 $mesg = $px1->isGraphKo();
141 if (!$mesg) {
142  $px1->SetData($data);
143  $i = $startyear; $legend = array();
144  while ($i <= $endyear) {
145  $legend[] = $i;
146  $i++;
147  }
148  $px1->SetLegend($legend);
149  $px1->SetMaxValue($px1->GetCeilMaxValue());
150  $px1->SetMinValue(min(0, $px1->GetFloorMinValue()));
151  $px1->SetWidth($WIDTH);
152  $px1->SetHeight($HEIGHT);
153  $px1->SetYLabel($langs->trans("NbOfOrder"));
154  $px1->SetShading(3);
155  $px1->SetHorizTickIncrement(1);
156  $px1->mode = 'depth';
157  $px1->SetTitle($langs->trans("NumberOfOrdersByMonth"));
158 
159  $px1->draw($filenamenb, $fileurlnb);
160 }
161 
162 // Build graphic amount of object
163 $data = $stats->getAmountByMonthWithPrevYear($endyear, $startyear);
164 //var_dump($data);
165 // $data = array(array('Lib',val1,val2,val3),...)
166 
167 if (empty($user->rights->societe->client->voir) || $user->socid) {
168  $filenameamount = $dir.'/ordersamountinyear-'.$user->id.'-'.$year.'.png';
169  if ($mode == 'customer') {
170  $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersamountinyear-'.$user->id.'-'.$year.'.png';
171  }
172  if ($mode == 'supplier') {
173  $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersamountinyear-'.$user->id.'-'.$year.'.png';
174  }
175 } else {
176  $filenameamount = $dir.'/ordersamountinyear-'.$year.'.png';
177  if ($mode == 'customer') {
178  $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersamountinyear-'.$year.'.png';
179  }
180  if ($mode == 'supplier') {
181  $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersamountinyear-'.$year.'.png';
182  }
183 }
184 
185 $px2 = new DolGraph();
186 $mesg = $px2->isGraphKo();
187 if (!$mesg) {
188  $px2->SetData($data);
189  $i = $startyear; $legend = array();
190  while ($i <= $endyear) {
191  $legend[] = $i;
192  $i++;
193  }
194  $px2->SetLegend($legend);
195  $px2->SetMaxValue($px2->GetCeilMaxValue());
196  $px2->SetMinValue(min(0, $px2->GetFloorMinValue()));
197  $px2->SetWidth($WIDTH);
198  $px2->SetHeight($HEIGHT);
199  $px2->SetYLabel($langs->trans("AmountOfOrders"));
200  $px2->SetShading(3);
201  $px2->SetHorizTickIncrement(1);
202  $px2->mode = 'depth';
203  $px2->SetTitle($langs->trans("AmountOfOrdersByMonthHT"));
204 
205  $px2->draw($filenameamount, $fileurlamount);
206 }
207 
208 
209 $data = $stats->getAverageByMonthWithPrevYear($endyear, $startyear);
210 
211 if (empty($user->rights->societe->client->voir) || $user->socid) {
212  $filename_avg = $dir.'/ordersaverage-'.$user->id.'-'.$year.'.png';
213  if ($mode == 'customer') {
214  $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersaverage-'.$user->id.'-'.$year.'.png';
215  }
216  if ($mode == 'supplier') {
217  $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersaverage-'.$user->id.'-'.$year.'.png';
218  }
219 } else {
220  $filename_avg = $dir.'/ordersaverage-'.$year.'.png';
221  if ($mode == 'customer') {
222  $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersaverage-'.$year.'.png';
223  }
224  if ($mode == 'supplier') {
225  $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersaverage-'.$year.'.png';
226  }
227 }
228 
229 $px3 = new DolGraph();
230 $mesg = $px3->isGraphKo();
231 if (!$mesg) {
232  $px3->SetData($data);
233  $i = $startyear; $legend = array();
234  while ($i <= $endyear) {
235  $legend[] = $i;
236  $i++;
237  }
238  $px3->SetLegend($legend);
239  $px3->SetYLabel($langs->trans("AmountAverage"));
240  $px3->SetMaxValue($px3->GetCeilMaxValue());
241  $px3->SetMinValue($px3->GetFloorMinValue());
242  $px3->SetWidth($WIDTH);
243  $px3->SetHeight($HEIGHT);
244  $px3->SetShading(3);
245  $px3->SetHorizTickIncrement(1);
246  $px3->mode = 'depth';
247  $px3->SetTitle($langs->trans("AmountAverage"));
248 
249  $px3->draw($filename_avg, $fileurl_avg);
250 }
251 
252 
253 
254 // Show array
255 $data = $stats->getAllByYear();
256 $arrayyears = array();
257 foreach ($data as $val) {
258  if (!empty($val['year'])) {
259  $arrayyears[$val['year']] = $val['year'];
260  }
261 }
262 if (!count($arrayyears)) {
263  $arrayyears[$nowyear] = $nowyear;
264 }
265 
266 $h = 0;
267 $head = array();
268 $head[$h][0] = DOL_URL_ROOT.'/commande/stats/index.php?mode='.$mode;
269 $head[$h][1] = $langs->trans("ByMonthYear");
270 $head[$h][2] = 'byyear';
271 $h++;
272 
273 if ($mode == 'customer') {
274  $type = 'order_stats';
275 }
276 if ($mode == 'supplier') {
277  $type = 'supplier_order_stats';
278 }
279 
280 complete_head_from_modules($conf, $langs, null, $head, $h, $type);
281 
282 print dol_get_fiche_head($head, 'byyear', $langs->trans("Statistics"), -1);
283 
284 
285 print '<div class="fichecenter"><div class="fichethirdleft">';
286 
287 
288 // Show filter box
289 print '<form name="stats" method="POST" action="'.$_SERVER["PHP_SELF"].'">';
290 print '<input type="hidden" name="token" value="'.newToken().'">';
291 print '<input type="hidden" name="mode" value="'.$mode.'">';
292 
293 print '<table class="noborder centpercent">';
294 print '<tr class="liste_titre"><td class="liste_titre" colspan="2">'.$langs->trans("Filter").'</td></tr>';
295 // Company
296 print '<tr><td class="left">'.$langs->trans("ThirdParty").'</td><td class="left">';
297 if ($mode == 'customer') {
298  $filter = 's.client IN (1,2,3)';
299 }
300 if ($mode == 'supplier') {
301  $filter = 's.fournisseur = 1';
302 }
303 print img_picto('', 'company', 'class="pictofixedwidth"');
304 print $form->select_company($socid, 'socid', $filter, 1, 0, 0, array(), 0, 'widthcentpercentminusx maxwidth300');
305 print '</td></tr>';
306 // ThirdParty Type
307 print '<tr><td>'.$langs->trans("ThirdPartyType").'</td><td>';
308 $sortparam_typent = (empty($conf->global->SOCIETE_SORT_ON_TYPEENT) ? 'ASC' : $conf->global->SOCIETE_SORT_ON_TYPEENT); // NONE means we keep sort of original array, so we sort on position. ASC, means next function will sort on label.
309 print $form->selectarray("typent_id", $formcompany->typent_array(0), $typent_id, 1, 0, 0, '', 0, 0, 0, $sortparam_typent, '', 1);
310 if ($user->admin) {
311  print ' '.info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
312 }
313 print '</td></tr>';
314 // Category
315 if ($mode == 'customer') {
316  $cat_type = Categorie::TYPE_CUSTOMER;
317  $cat_label = $langs->trans("Category").' '.lcfirst($langs->trans("Customer"));
318 }
319 if ($mode == 'supplier') {
320  $cat_type = Categorie::TYPE_SUPPLIER;
321  $cat_label = $langs->trans("Category").' '.lcfirst($langs->trans("Supplier"));
322 }
323 print '<tr><td>'.$cat_label.'</td><td>';
324 print img_picto('', 'category', 'class="pictofixedwidth"');
325 print $formother->select_categories($cat_type, $categ_id, 'categ_id', 0, 1, 'widthcentpercentminusx maxwidth300');
326 print '</td></tr>';
327 // User
328 print '<tr><td>'.$langs->trans("CreatedBy").'</td><td>';
329 print img_picto('', 'user', 'class="pictofixedwidth"');
330 print $form->select_dolusers($userid, 'userid', 1, '', 0, '', '', 0, 0, 0, '', 0, '', 'widthcentpercentminusx maxwidth300');
331 // Status
332 print '<tr><td>'.$langs->trans("Status").'</td><td>';
333 if ($mode == 'customer') {
334  $liststatus = array(
335  Commande::STATUS_DRAFT=>$langs->trans("StatusOrderDraft"),
336  Commande::STATUS_VALIDATED=>$langs->trans("StatusOrderValidated"),
337  Commande::STATUS_SHIPMENTONPROCESS=>$langs->trans("StatusOrderSent"),
338  Commande::STATUS_CLOSED=>$langs->trans("StatusOrderDelivered"),
339  Commande::STATUS_CANCELED=>$langs->trans("StatusOrderCanceled")
340  );
341  print $form->selectarray('object_status', $liststatus, GETPOST('object_status', 'intcomma'), -4);
342 }
343 if ($mode == 'supplier') {
344  $formorder->selectSupplierOrderStatus((strstr($object_status, ',') ? -1 : $object_status), 0, 'object_status');
345 }
346 print '</td></tr>';
347 // Year
348 print '<tr><td class="left">'.$langs->trans("Year").'</td><td class="left">';
349 if (!in_array($year, $arrayyears)) {
350  $arrayyears[$year] = $year;
351 }
352 if (!in_array($nowyear, $arrayyears)) {
353  $arrayyears[$nowyear] = $nowyear;
354 }
355 arsort($arrayyears);
356 print $form->selectarray('year', $arrayyears, $year, 0, 0, 0, '', 0, 0, 0, '', 'width75');
357 print '</td></tr>';
358 print '<tr><td align="center" colspan="2"><input type="submit" class="button small" name="submit" value="'.$langs->trans("Refresh").'"></td></tr>';
359 print '</table>';
360 print '</form>';
361 print '<br><br>';
362 
363 
364 print '<div class="div-table-responsive-no-min">';
365 print '<table class="noborder centpercent">';
366 print '<tr class="liste_titre" height="24">';
367 print '<td class="center">'.$langs->trans("Year").'</td>';
368 print '<td class="right">'.$langs->trans("NbOfOrders").'</td>';
369 print '<td class="right">%</td>';
370 print '<td class="right">'.$langs->trans("AmountTotal").'</td>';
371 print '<td class="right">%</td>';
372 print '<td class="right">'.$langs->trans("AmountAverage").'</td>';
373 print '<td class="right">%</td>';
374 print '</tr>';
375 
376 $oldyear = 0;
377 foreach ($data as $val) {
378  $year = $val['year'];
379  while (!empty($year) && $oldyear > $year + 1) { // If we have empty year
380  $oldyear--;
381 
382  print '<tr class="oddeven" height="24">';
383  print '<td align="center"><a href="'.$_SERVER["PHP_SELF"].'?year='.$oldyear.'&amp;mode='.$mode.($socid > 0 ? '&socid='.$socid : '').($userid > 0 ? '&userid='.$userid : '').'">'.$oldyear.'</a></td>';
384  print '<td class="right">0</td>';
385  print '<td class="right"></td>';
386  print '<td class="right">0</td>';
387  print '<td class="right"></td>';
388  print '<td class="right">0</td>';
389  print '<td class="right"></td>';
390  print '</tr>';
391  }
392 
393 
394  print '<tr class="oddeven" height="24">';
395  print '<td align="center"><a href="'.$_SERVER["PHP_SELF"].'?year='.$year.'&amp;mode='.$mode.($socid > 0 ? '&socid='.$socid : '').($userid > 0 ? '&userid='.$userid : '').'">'.$year.'</a></td>';
396  print '<td class="right">'.$val['nb'].'</td>';
397  print '<td class="right opacitylow" style="'.((!isset($val['nb_diff']) || $val['nb_diff'] >= 0) ? 'color: green;' : 'color: red;').'">'.(isset($val['nb_diff']) ? round($val['nb_diff']): "0").'%</td>';
398  print '<td class="right">'.price(price2num($val['total'], 'MT'), 1).'</td>';
399  print '<td class="right opacitylow" style="'.((!isset($val['total_diff']) || $val['total_diff'] >= 0) ? 'color: green;' : 'color: red;').'">'.(isset($val['total_diff']) ? round($val['total_diff']) : "0").'%</td>';
400  print '<td class="right">'.price(price2num($val['avg'], 'MT'), 1).'</td>';
401  print '<td class="right opacitylow" style="'.((!isset($val['avg_diff']) || $val['avg_diff'] >= 0) ? 'color: green;' : 'color: red;').'">'.(isset($val['avg_diff']) ? round($val['avg_diff']) : "0").'%</td>';
402  print '</tr>';
403  $oldyear = $year;
404 }
405 
406 print '</table>';
407 print '</div>';
408 
409 
410 print '</div><div class="fichetwothirdright">';
411 
412 
413 // Show graphs
414 print '<table class="border centpercent"><tr class="pair nohover"><td align="center">';
415 if ($mesg) {
416  print $mesg;
417 } else {
418  print $px1->show();
419  print "<br>\n";
420  print $px2->show();
421  print "<br>\n";
422  print $px3->show();
423 }
424 print '</td></tr></table>';
425 
426 
427 print '</div></div>';
428 print '<div style="clear:both"></div>';
429 
430 print dol_get_fiche_end();
431 
432 // End of page
433 llxFooter();
434 $db->close();
GETPOST($paramname, $check= 'alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
const STATUS_CLOSED
Closed (Sent, billed or not)
if($cancel &&!$id) if($action== 'add'&&!$cancel) if($action== 'delete') if($id) $form
Actions.
Definition: card.php:142
dol_mkdir($dir, $dataroot= '', $newmask= '')
Creation of a directory (this can create recursive subdir)
dol_now($mode= 'auto')
Return date for now.
if(!defined('NOREQUIRESOC')) if(!defined('NOREQUIRETRAN')) if(!defined('NOCSRFCHECK')) if(!defined('NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) llxHeader()
Empty header.
Definition: wrapper.php:59
const STATUS_SHIPMENTONPROCESS
Shipment on process.
Class to build HTML component for third parties management Only common components are here...
Class to manage generation of HTML components Only common components must be here.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form...
load_fiche_titre($titre, $morehtmlright= '', $picto= 'generic', $pictoisfullpath=0, $id= '', $morecssontable= '', $morehtmlcenter= '')
Load a title with picto.
price2num($amount, $rounding= '', $option=0)
Function that return a number with universal decimal format (decimal separator is &#39;...
Class to manage HTML output components for orders Before adding component here, check they are not in...
img_picto($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt= '', $morecss= '', $marginleftonlyshort=2)
Show picto whatever it&#39;s its name (generic function)
const STATUS_DRAFT
Draft status.
Classe permettant la generation de composants html autre Only common components are here...
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 ...
const STATUS_VALIDATED
Validated status.
Class to manage order statistics (customer and supplier)
dol_get_fiche_head($links=array(), $active= '', $title= '', $notab=0, $picto= '', $pictoisfullpath=0, $morehtmlright= '', $morecss= '', $limittoshow=0, $moretabssuffix= '')
Show tabs of a record.
Class to build graphs.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
static getDefaultGraphSizeForStats($direction, $defaultsize= '')
getDefaultGraphSizeForStats
complete_head_from_modules($conf, $langs, $object, &$head, &$h, $type, $mode= 'add')
Complete or removed entries into a head array (used to build tabs).
llxFooter()
Empty footer.
Definition: wrapper.php:73
const STATUS_CANCELED
Canceled status.