dolibarr 21.0.0-beta
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 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
9 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 */
24
31// Load Dolibarr environment
32require '../../main.inc.php';
33require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
34require_once DOL_DOCUMENT_ROOT.'/commande/class/commandestats.class.php';
35require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
36require_once DOL_DOCUMENT_ROOT.'/core/class/html.formorder.class.php';
37require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
38require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
39require_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php';
40
51
52$mode = GETPOSTISSET("mode") ? GETPOST("mode", 'aZ09') : 'customer';
53
54$hookmanager->initHooks(array('orderstats', 'globalcard'));
55
56$usercanreadcustumerstatistic = $user->hasRight('commande', 'lire');
57$usercanreadsupplierstatistic = $user->hasRight('fournisseur', 'commande', 'lire');
58if (getDolGlobalInt('MAIN_NEED_EXPORT_PERMISSION_TO_READ_STATISTICS')) {
59 $usercanreadcustumerstatistic = $user->hasRight('commande', 'commande', 'export');
60 $usercanreadsupplierstatistic = $user->hasRight('fournisseur', 'commande', 'export');
61}
62if ($mode == 'customer' && !$usercanreadcustumerstatistic) {
64}
65if ($mode == 'supplier' && !$usercanreadsupplierstatistic) {
67}
68
69if ($mode == 'supplier') {
70 $object_status = GETPOST('object_status', 'array:int');
71 $object_status = implode(',', $object_status);
72} else {
73 $object_status = GETPOST('object_status', 'intcomma');
74}
75
76
77$typent_id = GETPOSTINT('typent_id');
78$categ_id = GETPOSTINT('categ_id');
79
80$userid = GETPOSTINT('userid');
81$socid = GETPOSTINT('socid');
82// Security check
83if ($user->socid > 0) {
84 $action = '';
85 $socid = $user->socid;
86}
87
88$parameters = array();
89$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
90if ($reshook < 0) {
91 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
92}
93
94$nowyear = (int) dol_print_date(dol_now('gmt'), "%Y", 'gmt');
95$year = GETPOSTINT('year') > 0 ? GETPOSTINT('year') : $nowyear;
96$startyear = $year - (!getDolGlobalInt('MAIN_STATS_GRAPHS_SHOW_N_YEARS') ? 2 : max(1, min(10, getDolGlobalInt('MAIN_STATS_GRAPHS_SHOW_N_YEARS'))));
97$endyear = $year;
98
99// Load translation files required by the page
100$langs->loadLangs(array('orders', 'companies', 'other', 'suppliers'));
101
102
103/*
104 * View
105 */
106
107$form = new Form($db);
108$formorder = new FormOrder($db);
109$formcompany = new FormCompany($db);
110$formother = new FormOther($db);
111
112$picto = 'order';
113$title = $langs->trans("OrdersStatistics");
114$dir = $conf->commande->dir_temp;
115
116if ($mode == 'supplier') {
117 $picto = 'supplier_order';
118 $title = $langs->trans("OrdersStatisticsSuppliers");
119 $dir = $conf->fournisseur->commande->dir_temp;
120}
121
122llxHeader('', $title, '', '', 0, 0, '', '', '', 'mod-order page-stats');
123
124print load_fiche_titre($title, '', $picto);
125
126dol_mkdir($dir);
127
128$stats = new CommandeStats($db, $socid, $mode, ($userid > 0 ? $userid : 0), ($typent_id > 0 ? $typent_id : 0), ($categ_id > 0 ? $categ_id : 0));
129if ($mode == 'customer') {
130 if ($object_status != '' && $object_status >= -1) {
131 $stats->where .= ' AND c.fk_statut IN ('.$db->sanitize($object_status).')';
132 }
133}
134if ($mode == 'supplier') {
135 if ($object_status != '' && $object_status >= 0) {
136 $stats->where .= ' AND c.fk_statut IN ('.$db->sanitize($object_status).')';
137 }
138}
139
140
141// Build graphic number of object
142$data = $stats->getNbByMonthWithPrevYear($endyear, $startyear);
143
144//var_dump($data);
145// $data = array(array('Lib',val1,val2,val3),...)
146
147
148$fileurlnb = '';
149if (!$user->hasRight('societe', 'client', 'voir')) {
150 $filenamenb = $dir.'/ordersnbinyear-'.$user->id.'-'.$year.'.png';
151 if ($mode == 'customer') {
152 $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersnbinyear-'.$user->id.'-'.$year.'.png';
153 }
154 if ($mode == 'supplier') {
155 $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersnbinyear-'.$user->id.'-'.$year.'.png';
156 }
157} else {
158 $filenamenb = $dir.'/ordersnbinyear-'.$year.'.png';
159 if ($mode == 'customer') {
160 $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersnbinyear-'.$year.'.png';
161 }
162 if ($mode == 'supplier') {
163 $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersnbinyear-'.$year.'.png';
164 }
165}
166
167$px1 = new DolGraph();
168$mesg = $px1->isGraphKo();
169if (!$mesg) {
170 $px1->SetData($data);
171 $i = $startyear;
172 $legend = array();
173 while ($i <= $endyear) {
174 $legend[] = $i;
175 $i++;
176 }
177 $px1->SetLegend($legend);
178 $px1->SetMaxValue($px1->GetCeilMaxValue());
179 $px1->SetMinValue(min(0, $px1->GetFloorMinValue()));
180 $px1->SetWidth($WIDTH);
181 $px1->SetHeight($HEIGHT);
182 $px1->SetYLabel($langs->trans("NbOfOrder"));
183 $px1->SetShading(3);
184 $px1->SetHorizTickIncrement(1);
185 $px1->mode = 'depth';
186 $px1->SetTitle($langs->trans("NumberOfOrdersByMonth"));
187
188 $px1->draw($filenamenb, $fileurlnb);
189}
190
191// Build graphic amount of object
192$data = $stats->getAmountByMonthWithPrevYear($endyear, $startyear);
193//var_dump($data);
194// $data = array(array('Lib',val1,val2,val3),...)
195
196$fileurlamount = '';
197if (!$user->hasRight('societe', 'client', 'voir')) {
198 $filenameamount = $dir.'/ordersamountinyear-'.$user->id.'-'.$year.'.png';
199 if ($mode == 'customer') {
200 $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersamountinyear-'.$user->id.'-'.$year.'.png';
201 }
202 if ($mode == 'supplier') {
203 $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersamountinyear-'.$user->id.'-'.$year.'.png';
204 }
205} else {
206 $filenameamount = $dir.'/ordersamountinyear-'.$year.'.png';
207 if ($mode == 'customer') {
208 $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersamountinyear-'.$year.'.png';
209 }
210 if ($mode == 'supplier') {
211 $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersamountinyear-'.$year.'.png';
212 }
213}
214
215$px2 = new DolGraph();
216$mesg = $px2->isGraphKo();
217if (!$mesg) {
218 $px2->SetData($data);
219 $i = $startyear;
220 $legend = array();
221 while ($i <= $endyear) {
222 $legend[] = $i;
223 $i++;
224 }
225 $px2->SetLegend($legend);
226 $px2->SetMaxValue($px2->GetCeilMaxValue());
227 $px2->SetMinValue(min(0, $px2->GetFloorMinValue()));
228 $px2->SetWidth($WIDTH);
229 $px2->SetHeight($HEIGHT);
230 $px2->SetYLabel($langs->trans("AmountOfOrders"));
231 $px2->SetShading(3);
232 $px2->SetHorizTickIncrement(1);
233 $px2->mode = 'depth';
234 $px2->SetTitle($langs->trans("AmountOfOrdersByMonthHT"));
235
236 $px2->draw($filenameamount, $fileurlamount);
237}
238
239
240$data = $stats->getAverageByMonthWithPrevYear($endyear, $startyear);
241
242
243$fileurl_avg = '';
244if (!$user->hasRight('societe', 'client', 'voir')) {
245 $filename_avg = $dir.'/ordersaverage-'.$user->id.'-'.$year.'.png';
246 if ($mode == 'customer') {
247 $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersaverage-'.$user->id.'-'.$year.'.png';
248 }
249 if ($mode == 'supplier') {
250 $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersaverage-'.$user->id.'-'.$year.'.png';
251 }
252} else {
253 $filename_avg = $dir.'/ordersaverage-'.$year.'.png';
254 if ($mode == 'customer') {
255 $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersaverage-'.$year.'.png';
256 }
257 if ($mode == 'supplier') {
258 $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersaverage-'.$year.'.png';
259 }
260}
261
262$px3 = new DolGraph();
263$mesg = $px3->isGraphKo();
264if (!$mesg) {
265 $px3->SetData($data);
266 $i = $startyear;
267 $legend = array();
268 while ($i <= $endyear) {
269 $legend[] = $i;
270 $i++;
271 }
272 $px3->SetLegend($legend);
273 $px3->SetYLabel($langs->trans("AmountAverage"));
274 $px3->SetMaxValue($px3->GetCeilMaxValue());
275 $px3->SetMinValue($px3->GetFloorMinValue());
276 $px3->SetWidth($WIDTH);
277 $px3->SetHeight($HEIGHT);
278 $px3->SetShading(3);
279 $px3->SetHorizTickIncrement(1);
280 $px3->mode = 'depth';
281 $px3->SetTitle($langs->trans("AmountAverage"));
282
283 $px3->draw($filename_avg, $fileurl_avg);
284}
285
286
287
288// Show array
289$data = $stats->getAllByYear();
290$arrayyears = array();
291foreach ($data as $val) {
292 if (!empty($val['year'])) {
293 $arrayyears[$val['year']] = $val['year'];
294 }
295}
296if (!count($arrayyears)) {
297 $arrayyears[$nowyear] = $nowyear;
298}
299
300$h = 0;
301$head = array();
302$head[$h][0] = DOL_URL_ROOT.'/commande/stats/index.php?mode='.$mode;
303$head[$h][1] = $langs->trans("ByMonthYear");
304$head[$h][2] = 'byyear';
305$h++;
306
307$type = 'order_stats';
308
309if ($mode == 'supplier') {
310 $type = 'supplier_order_stats';
311}
312
313complete_head_from_modules($conf, $langs, null, $head, $h, $type);
314
315print dol_get_fiche_head($head, 'byyear', '', -1);
316
317
318print '<div class="fichecenter"><div class="fichethirdleft">';
319
320
321// Show filter box
322print '<form name="stats" method="POST" action="'.$_SERVER["PHP_SELF"].'">';
323print '<input type="hidden" name="token" value="'.newToken().'">';
324print '<input type="hidden" name="mode" value="'.$mode.'">';
325
326print '<table class="noborder centpercent">';
327print '<tr class="liste_titre"><td class="liste_titre" colspan="2">'.$langs->trans("Filter").'</td></tr>';
328// Company
329print '<tr><td class="left">'.$langs->trans("ThirdParty").'</td><td class="left">';
330$filter = '';
331if ($mode == 'customer') {
332 $filter = '(s.client:IN:1,2,3)';
333}
334if ($mode == 'supplier') {
335 $filter = '(s.fournisseur:=:1)';
336}
337print img_picto('', 'company', 'class="pictofixedwidth"');
338print $form->select_company($socid, 'socid', $filter, 1, 0, 0, array(), 0, 'widthcentpercentminusx maxwidth300');
339print '</td></tr>';
340// ThirdParty Type
341print '<tr><td>'.$langs->trans("ThirdPartyType").'</td><td>';
342$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.
343print $form->selectarray("typent_id", $formcompany->typent_array(0), $typent_id, 1, 0, 0, '', 0, 0, 0, $sortparam_typent, '', 1);
344if ($user->admin) {
345 print ' '.info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
346}
347print '</td></tr>';
348// Category
349$cat_type = 0;
350$cat_label = '';
351if ($mode == 'customer') {
352 $cat_type = Categorie::TYPE_CUSTOMER;
353 $cat_label = $langs->trans("Category").' '.lcfirst($langs->trans("Customer"));
354}
355if ($mode == 'supplier') {
356 $cat_type = Categorie::TYPE_SUPPLIER;
357 $cat_label = $langs->trans("Category").' '.lcfirst($langs->trans("Supplier"));
358}
359print '<tr><td>'.$cat_label.'</td><td>';
360print img_picto('', 'category', 'class="pictofixedwidth"');
361print $formother->select_categories($cat_type, $categ_id, 'categ_id', 0, 1, 'widthcentpercentminusx maxwidth300');
362print '</td></tr>';
363// User
364print '<tr><td>'.$langs->trans("CreatedBy").'</td><td>';
365print img_picto('', 'user', 'class="pictofixedwidth"');
366print $form->select_dolusers($userid, 'userid', 1, '', 0, '', '', 0, 0, 0, '', 0, '', 'widthcentpercentminusx maxwidth300');
367// Status
368print '<tr><td>'.$langs->trans("Status").'</td><td>';
369if ($mode == 'customer') {
370 $liststatus = array(
371 Commande::STATUS_DRAFT => $langs->trans("StatusOrderDraft"),
372 Commande::STATUS_VALIDATED => $langs->trans("StatusOrderValidated"),
373 Commande::STATUS_SHIPMENTONPROCESS => $langs->trans("StatusOrderSent"),
374 Commande::STATUS_CLOSED => $langs->trans("StatusOrderDelivered"),
375 Commande::STATUS_CANCELED => $langs->trans("StatusOrderCanceled")
376 );
377 print $form->selectarray('object_status', $liststatus, GETPOST('object_status', 'intcomma'), -4);
378}
379if ($mode == 'supplier') {
380 $formorder->selectSupplierOrderStatus((strstr($object_status, ',') ? -1 : $object_status), 0, 'object_status');
381}
382print '</td></tr>';
383// Year
384print '<tr><td class="left">'.$langs->trans("Year").'</td><td class="left">';
385if (!in_array($year, $arrayyears)) {
386 $arrayyears[$year] = $year;
387}
388if (!in_array($nowyear, $arrayyears)) {
389 $arrayyears[$nowyear] = $nowyear;
390}
391arsort($arrayyears);
392print $form->selectarray('year', $arrayyears, $year, 0, 0, 0, '', 0, 0, 0, '', 'width75');
393print '</td></tr>';
394print '<tr><td align="center" colspan="2"><input type="submit" class="button small" name="submit" value="'.$langs->trans("Refresh").'"></td></tr>';
395print '</table>';
396print '</form>';
397print '<br><br>';
398
399
400print '<div class="div-table-responsive-no-min">';
401print '<table class="noborder centpercent">';
402print '<tr class="liste_titre" height="24">';
403print '<td class="center">'.$langs->trans("Year").'</td>';
404print '<td class="right">'.$langs->trans("NbOfOrders").'</td>';
405print '<td class="right">%</td>';
406print '<td class="right">'.$langs->trans("AmountTotal").'</td>';
407print '<td class="right">%</td>';
408print '<td class="right">'.$langs->trans("AmountAverage").'</td>';
409print '<td class="right">%</td>';
410print '</tr>';
411
412$oldyear = 0;
413foreach ($data as $val) {
414 $year = $val['year'];
415 while (!empty($year) && $oldyear > (int) $year + 1) { // If we have empty year
416 $oldyear--;
417
418 print '<tr class="oddeven" height="24">';
419 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>';
420 print '<td class="right">0</td>';
421 print '<td class="right"></td>';
422 print '<td class="right">0</td>';
423 print '<td class="right"></td>';
424 print '<td class="right">0</td>';
425 print '<td class="right"></td>';
426 print '</tr>';
427 }
428
429
430 print '<tr class="oddeven" height="24">';
431 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>';
432 print '<td class="right">'.$val['nb'].'</td>';
433 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>';
434 print '<td class="right">'.price(price2num($val['total'], 'MT'), 1).'</td>';
435 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>';
436 print '<td class="right">'.price(price2num($val['avg'], 'MT'), 1).'</td>';
437 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>';
438 print '</tr>';
439 $oldyear = $year;
440}
441
442print '</table>';
443print '</div>';
444
445
446print '</div><div class="fichetwothirdright">';
447
448
449// Show graphs
450print '<table class="border centpercent"><tr class="pair nohover"><td align="center">';
451if ($mesg) {
452 print $mesg;
453} else {
454 print $px1->show();
455 print "<br>\n";
456 print $px2->show();
457 print "<br>\n";
458 print $px3->show();
459}
460print '</td></tr></table>';
461
462
463print '</div></div>';
464print '<div class="clearboth"></div>';
465
466print dol_get_fiche_end();
467
468// End of page
469llxFooter();
470$db->close();
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:71
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.
llxFooter()
Footer empty.
Definition document.php:107
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
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.
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 a Dolibarr global constant string value.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.