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