dolibarr 20.0.0
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// Load Dolibarr environment
30require '../../main.inc.php';
31require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
32require_once DOL_DOCUMENT_ROOT.'/commande/class/commandestats.class.php';
33require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
34require_once DOL_DOCUMENT_ROOT.'/core/class/html.formorder.class.php';
35require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
36require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
37require_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php';
38
41
42$mode = GETPOSTISSET("mode") ? GETPOST("mode", 'aZ09') : 'customer';
43
44$hookmanager->initHooks(array('orderstats', 'globalcard'));
45
46$usercanreadcustumerstatistic = $user->hasRight('commande', 'lire');
47$usercanreadsupplierstatistic = $user->hasRight('fournisseur', 'commande', 'lire');
48if (getDolGlobalInt('MAIN_NEED_EXPORT_PERMISSION_TO_READ_STATISTICS')) {
49 $usercanreadcustumerstatistic = $user->hasRight('commande', 'commande', 'export');
50 $usercanreadsupplierstatistic = $user->hasRight('fournisseur', 'commande', 'export');
51}
52if ($mode == 'customer' && !$usercanreadcustumerstatistic) {
54}
55if ($mode == 'supplier' && !$usercanreadsupplierstatistic) {
57}
58
59if ($mode == 'supplier') {
60 $object_status = GETPOST('object_status', 'array:int');
61 $object_status = implode(',', $object_status);
62} else {
63 $object_status = GETPOST('object_status', 'intcomma');
64}
65
66
67$typent_id = GETPOSTINT('typent_id');
68$categ_id = GETPOSTINT('categ_id');
69
70$userid = GETPOSTINT('userid');
71$socid = GETPOSTINT('socid');
72// Security check
73if ($user->socid > 0) {
74 $action = '';
75 $socid = $user->socid;
76}
77
78$parameters = array();
79$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
80if ($reshook < 0) {
81 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
82}
83
84$nowyear = dol_print_date(dol_now('gmt'), "%Y", 'gmt');
85$year = GETPOST('year') > 0 ? GETPOST('year') : $nowyear;
86$startyear = $year - (!getDolGlobalString('MAIN_STATS_GRAPHS_SHOW_N_YEARS') ? 2 : max(1, min(10, getDolGlobalString('MAIN_STATS_GRAPHS_SHOW_N_YEARS'))));
87$endyear = $year;
88
89// Load translation files required by the page
90$langs->loadLangs(array('orders', 'companies', 'other', 'suppliers'));
91
92
93/*
94 * View
95 */
96
97$form = new Form($db);
98$formorder = new FormOrder($db);
99$formcompany = new FormCompany($db);
100$formother = new FormOther($db);
101
102$picto = 'order';
103$title = $langs->trans("OrdersStatistics");
104$dir = $conf->commande->dir_temp;
105
106if ($mode == 'supplier') {
107 $picto = 'supplier_order';
108 $title = $langs->trans("OrdersStatisticsSuppliers");
109 $dir = $conf->fournisseur->commande->dir_temp;
110}
111
112llxHeader('', $title, '', '', 0, 0, '', '', '', 'mod-order page-stats');
113
114print load_fiche_titre($title, '', $picto);
115
116dol_mkdir($dir);
117
118$stats = new CommandeStats($db, $socid, $mode, ($userid > 0 ? $userid : 0), ($typent_id > 0 ? $typent_id : 0), ($categ_id > 0 ? $categ_id : 0));
119if ($mode == 'customer') {
120 if ($object_status != '' && $object_status >= -1) {
121 $stats->where .= ' AND c.fk_statut IN ('.$db->sanitize($object_status).')';
122 }
123}
124if ($mode == 'supplier') {
125 if ($object_status != '' && $object_status >= 0) {
126 $stats->where .= ' AND c.fk_statut IN ('.$db->sanitize($object_status).')';
127 }
128}
129
130
131// Build graphic number of object
132$data = $stats->getNbByMonthWithPrevYear($endyear, $startyear);
133
134//var_dump($data);
135// $data = array(array('Lib',val1,val2,val3),...)
136
137
138if (!$user->hasRight('societe', 'client', 'voir')) {
139 $filenamenb = $dir.'/ordersnbinyear-'.$user->id.'-'.$year.'.png';
140 if ($mode == 'customer') {
141 $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersnbinyear-'.$user->id.'-'.$year.'.png';
142 }
143 if ($mode == 'supplier') {
144 $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersnbinyear-'.$user->id.'-'.$year.'.png';
145 }
146} else {
147 $filenamenb = $dir.'/ordersnbinyear-'.$year.'.png';
148 if ($mode == 'customer') {
149 $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersnbinyear-'.$year.'.png';
150 }
151 if ($mode == 'supplier') {
152 $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersnbinyear-'.$year.'.png';
153 }
154}
155
156$px1 = new DolGraph();
157$mesg = $px1->isGraphKo();
158if (!$mesg) {
159 $px1->SetData($data);
160 $i = $startyear;
161 $legend = array();
162 while ($i <= $endyear) {
163 $legend[] = $i;
164 $i++;
165 }
166 $px1->SetLegend($legend);
167 $px1->SetMaxValue($px1->GetCeilMaxValue());
168 $px1->SetMinValue(min(0, $px1->GetFloorMinValue()));
169 $px1->SetWidth($WIDTH);
170 $px1->SetHeight($HEIGHT);
171 $px1->SetYLabel($langs->trans("NbOfOrder"));
172 $px1->SetShading(3);
173 $px1->SetHorizTickIncrement(1);
174 $px1->mode = 'depth';
175 $px1->SetTitle($langs->trans("NumberOfOrdersByMonth"));
176
177 $px1->draw($filenamenb, $fileurlnb);
178}
179
180// Build graphic amount of object
181$data = $stats->getAmountByMonthWithPrevYear($endyear, $startyear);
182//var_dump($data);
183// $data = array(array('Lib',val1,val2,val3),...)
184
185if (!$user->hasRight('societe', 'client', 'voir')) {
186 $filenameamount = $dir.'/ordersamountinyear-'.$user->id.'-'.$year.'.png';
187 if ($mode == 'customer') {
188 $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersamountinyear-'.$user->id.'-'.$year.'.png';
189 }
190 if ($mode == 'supplier') {
191 $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersamountinyear-'.$user->id.'-'.$year.'.png';
192 }
193} else {
194 $filenameamount = $dir.'/ordersamountinyear-'.$year.'.png';
195 if ($mode == 'customer') {
196 $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersamountinyear-'.$year.'.png';
197 }
198 if ($mode == 'supplier') {
199 $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersamountinyear-'.$year.'.png';
200 }
201}
202
203$px2 = new DolGraph();
204$mesg = $px2->isGraphKo();
205if (!$mesg) {
206 $px2->SetData($data);
207 $i = $startyear;
208 $legend = array();
209 while ($i <= $endyear) {
210 $legend[] = $i;
211 $i++;
212 }
213 $px2->SetLegend($legend);
214 $px2->SetMaxValue($px2->GetCeilMaxValue());
215 $px2->SetMinValue(min(0, $px2->GetFloorMinValue()));
216 $px2->SetWidth($WIDTH);
217 $px2->SetHeight($HEIGHT);
218 $px2->SetYLabel($langs->trans("AmountOfOrders"));
219 $px2->SetShading(3);
220 $px2->SetHorizTickIncrement(1);
221 $px2->mode = 'depth';
222 $px2->SetTitle($langs->trans("AmountOfOrdersByMonthHT"));
223
224 $px2->draw($filenameamount, $fileurlamount);
225}
226
227
228$data = $stats->getAverageByMonthWithPrevYear($endyear, $startyear);
229
230if (!$user->hasRight('societe', 'client', 'voir')) {
231 $filename_avg = $dir.'/ordersaverage-'.$user->id.'-'.$year.'.png';
232 if ($mode == 'customer') {
233 $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersaverage-'.$user->id.'-'.$year.'.png';
234 }
235 if ($mode == 'supplier') {
236 $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersaverage-'.$user->id.'-'.$year.'.png';
237 }
238} else {
239 $filename_avg = $dir.'/ordersaverage-'.$year.'.png';
240 if ($mode == 'customer') {
241 $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersaverage-'.$year.'.png';
242 }
243 if ($mode == 'supplier') {
244 $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersaverage-'.$year.'.png';
245 }
246}
247
248$px3 = new DolGraph();
249$mesg = $px3->isGraphKo();
250if (!$mesg) {
251 $px3->SetData($data);
252 $i = $startyear;
253 $legend = array();
254 while ($i <= $endyear) {
255 $legend[] = $i;
256 $i++;
257 }
258 $px3->SetLegend($legend);
259 $px3->SetYLabel($langs->trans("AmountAverage"));
260 $px3->SetMaxValue($px3->GetCeilMaxValue());
261 $px3->SetMinValue($px3->GetFloorMinValue());
262 $px3->SetWidth($WIDTH);
263 $px3->SetHeight($HEIGHT);
264 $px3->SetShading(3);
265 $px3->SetHorizTickIncrement(1);
266 $px3->mode = 'depth';
267 $px3->SetTitle($langs->trans("AmountAverage"));
268
269 $px3->draw($filename_avg, $fileurl_avg);
270}
271
272
273
274// Show array
275$data = $stats->getAllByYear();
276$arrayyears = array();
277foreach ($data as $val) {
278 if (!empty($val['year'])) {
279 $arrayyears[$val['year']] = $val['year'];
280 }
281}
282if (!count($arrayyears)) {
283 $arrayyears[$nowyear] = $nowyear;
284}
285
286$h = 0;
287$head = array();
288$head[$h][0] = DOL_URL_ROOT.'/commande/stats/index.php?mode='.$mode;
289$head[$h][1] = $langs->trans("ByMonthYear");
290$head[$h][2] = 'byyear';
291$h++;
292
293if ($mode == 'customer') {
294 $type = 'order_stats';
295}
296if ($mode == 'supplier') {
297 $type = 'supplier_order_stats';
298}
299
300complete_head_from_modules($conf, $langs, null, $head, $h, $type);
301
302print dol_get_fiche_head($head, 'byyear', '', -1);
303
304
305print '<div class="fichecenter"><div class="fichethirdleft">';
306
307
308// Show filter box
309print '<form name="stats" method="POST" action="'.$_SERVER["PHP_SELF"].'">';
310print '<input type="hidden" name="token" value="'.newToken().'">';
311print '<input type="hidden" name="mode" value="'.$mode.'">';
312
313print '<table class="noborder centpercent">';
314print '<tr class="liste_titre"><td class="liste_titre" colspan="2">'.$langs->trans("Filter").'</td></tr>';
315// Company
316print '<tr><td class="left">'.$langs->trans("ThirdParty").'</td><td class="left">';
317$filter = '';
318if ($mode == 'customer') {
319 $filter = '(s.client:IN:1,2,3)';
320}
321if ($mode == 'supplier') {
322 $filter = '(s.fournisseur:=:1)';
323}
324print img_picto('', 'company', 'class="pictofixedwidth"');
325print $form->select_company($socid, 'socid', $filter, 1, 0, 0, array(), 0, 'widthcentpercentminusx maxwidth300');
326print '</td></tr>';
327// ThirdParty Type
328print '<tr><td>'.$langs->trans("ThirdPartyType").'</td><td>';
329$sortparam_typent = (!getDolGlobalString('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.
330print $form->selectarray("typent_id", $formcompany->typent_array(0), $typent_id, 1, 0, 0, '', 0, 0, 0, $sortparam_typent, '', 1);
331if ($user->admin) {
332 print ' '.info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
333}
334print '</td></tr>';
335// Category
336if ($mode == 'customer') {
337 $cat_type = Categorie::TYPE_CUSTOMER;
338 $cat_label = $langs->trans("Category").' '.lcfirst($langs->trans("Customer"));
339}
340if ($mode == 'supplier') {
341 $cat_type = Categorie::TYPE_SUPPLIER;
342 $cat_label = $langs->trans("Category").' '.lcfirst($langs->trans("Supplier"));
343}
344print '<tr><td>'.$cat_label.'</td><td>';
345print img_picto('', 'category', 'class="pictofixedwidth"');
346print $formother->select_categories($cat_type, $categ_id, 'categ_id', 0, 1, 'widthcentpercentminusx maxwidth300');
347print '</td></tr>';
348// User
349print '<tr><td>'.$langs->trans("CreatedBy").'</td><td>';
350print img_picto('', 'user', 'class="pictofixedwidth"');
351print $form->select_dolusers($userid, 'userid', 1, '', 0, '', '', 0, 0, 0, '', 0, '', 'widthcentpercentminusx maxwidth300');
352// Status
353print '<tr><td>'.$langs->trans("Status").'</td><td>';
354if ($mode == 'customer') {
355 $liststatus = array(
356 Commande::STATUS_DRAFT => $langs->trans("StatusOrderDraft"),
357 Commande::STATUS_VALIDATED => $langs->trans("StatusOrderValidated"),
358 Commande::STATUS_SHIPMENTONPROCESS => $langs->trans("StatusOrderSent"),
359 Commande::STATUS_CLOSED => $langs->trans("StatusOrderDelivered"),
360 Commande::STATUS_CANCELED => $langs->trans("StatusOrderCanceled")
361 );
362 print $form->selectarray('object_status', $liststatus, GETPOST('object_status', 'intcomma'), -4);
363}
364if ($mode == 'supplier') {
365 $formorder->selectSupplierOrderStatus((strstr($object_status, ',') ? -1 : $object_status), 0, 'object_status');
366}
367print '</td></tr>';
368// Year
369print '<tr><td class="left">'.$langs->trans("Year").'</td><td class="left">';
370if (!in_array($year, $arrayyears)) {
371 $arrayyears[$year] = $year;
372}
373if (!in_array($nowyear, $arrayyears)) {
374 $arrayyears[$nowyear] = $nowyear;
375}
376arsort($arrayyears);
377print $form->selectarray('year', $arrayyears, $year, 0, 0, 0, '', 0, 0, 0, '', 'width75');
378print '</td></tr>';
379print '<tr><td align="center" colspan="2"><input type="submit" class="button small" name="submit" value="'.$langs->trans("Refresh").'"></td></tr>';
380print '</table>';
381print '</form>';
382print '<br><br>';
383
384
385print '<div class="div-table-responsive-no-min">';
386print '<table class="noborder centpercent">';
387print '<tr class="liste_titre" height="24">';
388print '<td class="center">'.$langs->trans("Year").'</td>';
389print '<td class="right">'.$langs->trans("NbOfOrders").'</td>';
390print '<td class="right">%</td>';
391print '<td class="right">'.$langs->trans("AmountTotal").'</td>';
392print '<td class="right">%</td>';
393print '<td class="right">'.$langs->trans("AmountAverage").'</td>';
394print '<td class="right">%</td>';
395print '</tr>';
396
397$oldyear = 0;
398foreach ($data as $val) {
399 $year = $val['year'];
400 while (!empty($year) && $oldyear > $year + 1) { // If we have empty year
401 $oldyear--;
402
403 print '<tr class="oddeven" height="24">';
404 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>';
405 print '<td class="right">0</td>';
406 print '<td class="right"></td>';
407 print '<td class="right">0</td>';
408 print '<td class="right"></td>';
409 print '<td class="right">0</td>';
410 print '<td class="right"></td>';
411 print '</tr>';
412 }
413
414
415 print '<tr class="oddeven" height="24">';
416 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>';
417 print '<td class="right">'.$val['nb'].'</td>';
418 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>';
419 print '<td class="right">'.price(price2num($val['total'], 'MT'), 1).'</td>';
420 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>';
421 print '<td class="right">'.price(price2num($val['avg'], 'MT'), 1).'</td>';
422 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>';
423 print '</tr>';
424 $oldyear = $year;
425}
426
427print '</table>';
428print '</div>';
429
430
431print '</div><div class="fichetwothirdright">';
432
433
434// Show graphs
435print '<table class="border centpercent"><tr class="pair nohover"><td align="center">';
436if ($mesg) {
437 print $mesg;
438} else {
439 print $px1->show();
440 print "<br>\n";
441 print $px2->show();
442 print "<br>\n";
443 print $px3->show();
444}
445print '</td></tr></table>';
446
447
448print '</div></div>';
449print '<div class="clearboth"></div>';
450
451print dol_get_fiche_end();
452
453// End of page
454llxFooter();
455$db->close();
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader()
Empty header.
Definition wrapper.php:55
llxFooter()
Empty footer.
Definition wrapper.php:69
const STATUS_SHIPMENTONPROCESS
Shipment on process.
const STATUS_CLOSED
Closed (Sent, billed or not)
const STATUS_CANCELED
Canceled status.
const STATUS_DRAFT
Draft status.
const STATUS_VALIDATED
Validated status.
Class to manage order statistics (customer and supplier)
Class to build graphs.
static getDefaultGraphSizeForStats($direction, $defaultsize='')
getDefaultGraphSizeForStats
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.
Class to manage HTML output components for orders Before adding component here, check they are not in...
Class permettant la generation de composants html autre Only common components are here.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
complete_head_from_modules($conf, $langs, $object, &$head, &$h, $type, $mode='add', $filterorigmodule='')
Complete or removed entries into a head array (used to build tabs).
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.