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
139if (!$user->hasRight('societe', 'client', 'voir')) {
140 $filenamenb = $dir.'/ordersnbinyear-'.$user->id.'-'.$year.'.png';
141 if ($mode == 'customer') {
142 $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersnbinyear-'.$user->id.'-'.$year.'.png';
143 }
144 if ($mode == 'supplier') {
145 $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersnbinyear-'.$user->id.'-'.$year.'.png';
146 }
147} else {
148 $filenamenb = $dir.'/ordersnbinyear-'.$year.'.png';
149 if ($mode == 'customer') {
150 $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersnbinyear-'.$year.'.png';
151 }
152 if ($mode == 'supplier') {
153 $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersnbinyear-'.$year.'.png';
154 }
155}
156
157$px1 = new DolGraph();
158$mesg = $px1->isGraphKo();
159if (!$mesg) {
160 $px1->SetData($data);
161 $i = $startyear;
162 $legend = array();
163 while ($i <= $endyear) {
164 $legend[] = $i;
165 $i++;
166 }
167 $px1->SetLegend($legend);
168 $px1->SetMaxValue($px1->GetCeilMaxValue());
169 $px1->SetMinValue(min(0, $px1->GetFloorMinValue()));
170 $px1->SetWidth($WIDTH);
171 $px1->SetHeight($HEIGHT);
172 $px1->SetYLabel($langs->trans("NbOfOrder"));
173 $px1->SetShading(3);
174 $px1->SetHorizTickIncrement(1);
175 $px1->mode = 'depth';
176 $px1->SetTitle($langs->trans("NumberOfOrdersByMonth"));
177
178 $px1->draw($filenamenb, $fileurlnb);
179}
180
181// Build graphic amount of object
182$data = $stats->getAmountByMonthWithPrevYear($endyear, $startyear);
183//var_dump($data);
184// $data = array(array('Lib',val1,val2,val3),...)
185
186if (!$user->hasRight('societe', 'client', 'voir')) {
187 $filenameamount = $dir.'/ordersamountinyear-'.$user->id.'-'.$year.'.png';
188 if ($mode == 'customer') {
189 $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersamountinyear-'.$user->id.'-'.$year.'.png';
190 }
191 if ($mode == 'supplier') {
192 $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersamountinyear-'.$user->id.'-'.$year.'.png';
193 }
194} else {
195 $filenameamount = $dir.'/ordersamountinyear-'.$year.'.png';
196 if ($mode == 'customer') {
197 $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersamountinyear-'.$year.'.png';
198 }
199 if ($mode == 'supplier') {
200 $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersamountinyear-'.$year.'.png';
201 }
202}
203
204$px2 = new DolGraph();
205$mesg = $px2->isGraphKo();
206if (!$mesg) {
207 $px2->SetData($data);
208 $i = $startyear;
209 $legend = array();
210 while ($i <= $endyear) {
211 $legend[] = $i;
212 $i++;
213 }
214 $px2->SetLegend($legend);
215 $px2->SetMaxValue($px2->GetCeilMaxValue());
216 $px2->SetMinValue(min(0, $px2->GetFloorMinValue()));
217 $px2->SetWidth($WIDTH);
218 $px2->SetHeight($HEIGHT);
219 $px2->SetYLabel($langs->trans("AmountOfOrders"));
220 $px2->SetShading(3);
221 $px2->SetHorizTickIncrement(1);
222 $px2->mode = 'depth';
223 $px2->SetTitle($langs->trans("AmountOfOrdersByMonthHT"));
224
225 $px2->draw($filenameamount, $fileurlamount);
226}
227
228
229$data = $stats->getAverageByMonthWithPrevYear($endyear, $startyear);
230
231if (!$user->hasRight('societe', 'client', 'voir')) {
232 $filename_avg = $dir.'/ordersaverage-'.$user->id.'-'.$year.'.png';
233 if ($mode == 'customer') {
234 $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersaverage-'.$user->id.'-'.$year.'.png';
235 }
236 if ($mode == 'supplier') {
237 $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersaverage-'.$user->id.'-'.$year.'.png';
238 }
239} else {
240 $filename_avg = $dir.'/ordersaverage-'.$year.'.png';
241 if ($mode == 'customer') {
242 $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersaverage-'.$year.'.png';
243 }
244 if ($mode == 'supplier') {
245 $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersaverage-'.$year.'.png';
246 }
247}
248
249$px3 = new DolGraph();
250$mesg = $px3->isGraphKo();
251if (!$mesg) {
252 $px3->SetData($data);
253 $i = $startyear;
254 $legend = array();
255 while ($i <= $endyear) {
256 $legend[] = $i;
257 $i++;
258 }
259 $px3->SetLegend($legend);
260 $px3->SetYLabel($langs->trans("AmountAverage"));
261 $px3->SetMaxValue($px3->GetCeilMaxValue());
262 $px3->SetMinValue($px3->GetFloorMinValue());
263 $px3->SetWidth($WIDTH);
264 $px3->SetHeight($HEIGHT);
265 $px3->SetShading(3);
266 $px3->SetHorizTickIncrement(1);
267 $px3->mode = 'depth';
268 $px3->SetTitle($langs->trans("AmountAverage"));
269
270 $px3->draw($filename_avg, $fileurl_avg);
271}
272
273
274
275// Show array
276$data = $stats->getAllByYear();
277$arrayyears = array();
278foreach ($data as $val) {
279 if (!empty($val['year'])) {
280 $arrayyears[$val['year']] = $val['year'];
281 }
282}
283if (!count($arrayyears)) {
284 $arrayyears[$nowyear] = $nowyear;
285}
286
287$h = 0;
288$head = array();
289$head[$h][0] = DOL_URL_ROOT.'/commande/stats/index.php?mode='.$mode;
290$head[$h][1] = $langs->trans("ByMonthYear");
291$head[$h][2] = 'byyear';
292$h++;
293
294if ($mode == 'customer') {
295 $type = 'order_stats';
296}
297if ($mode == 'supplier') {
298 $type = 'supplier_order_stats';
299}
300
301complete_head_from_modules($conf, $langs, null, $head, $h, $type);
302
303print dol_get_fiche_head($head, 'byyear', '', -1);
304
305
306print '<div class="fichecenter"><div class="fichethirdleft">';
307
308
309// Show filter box
310print '<form name="stats" method="POST" action="'.$_SERVER["PHP_SELF"].'">';
311print '<input type="hidden" name="token" value="'.newToken().'">';
312print '<input type="hidden" name="mode" value="'.$mode.'">';
313
314print '<table class="noborder centpercent">';
315print '<tr class="liste_titre"><td class="liste_titre" colspan="2">'.$langs->trans("Filter").'</td></tr>';
316// Company
317print '<tr><td class="left">'.$langs->trans("ThirdParty").'</td><td class="left">';
318$filter = '';
319if ($mode == 'customer') {
320 $filter = '(s.client:IN:1,2,3)';
321}
322if ($mode == 'supplier') {
323 $filter = '(s.fournisseur:=:1)';
324}
325print img_picto('', 'company', 'class="pictofixedwidth"');
326print $form->select_company($socid, 'socid', $filter, 1, 0, 0, array(), 0, 'widthcentpercentminusx maxwidth300');
327print '</td></tr>';
328// ThirdParty Type
329print '<tr><td>'.$langs->trans("ThirdPartyType").'</td><td>';
330$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.
331print $form->selectarray("typent_id", $formcompany->typent_array(0), $typent_id, 1, 0, 0, '', 0, 0, 0, $sortparam_typent, '', 1);
332if ($user->admin) {
333 print ' '.info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
334}
335print '</td></tr>';
336// Category
337if ($mode == 'customer') {
338 $cat_type = Categorie::TYPE_CUSTOMER;
339 $cat_label = $langs->trans("Category").' '.lcfirst($langs->trans("Customer"));
340}
341if ($mode == 'supplier') {
342 $cat_type = Categorie::TYPE_SUPPLIER;
343 $cat_label = $langs->trans("Category").' '.lcfirst($langs->trans("Supplier"));
344}
345print '<tr><td>'.$cat_label.'</td><td>';
346print img_picto('', 'category', 'class="pictofixedwidth"');
347print $formother->select_categories($cat_type, $categ_id, 'categ_id', 0, 1, 'widthcentpercentminusx maxwidth300');
348print '</td></tr>';
349// User
350print '<tr><td>'.$langs->trans("CreatedBy").'</td><td>';
351print img_picto('', 'user', 'class="pictofixedwidth"');
352print $form->select_dolusers($userid, 'userid', 1, '', 0, '', '', 0, 0, 0, '', 0, '', 'widthcentpercentminusx maxwidth300');
353// Status
354print '<tr><td>'.$langs->trans("Status").'</td><td>';
355if ($mode == 'customer') {
356 $liststatus = array(
357 Commande::STATUS_DRAFT => $langs->trans("StatusOrderDraft"),
358 Commande::STATUS_VALIDATED => $langs->trans("StatusOrderValidated"),
359 Commande::STATUS_SHIPMENTONPROCESS => $langs->trans("StatusOrderSent"),
360 Commande::STATUS_CLOSED => $langs->trans("StatusOrderDelivered"),
361 Commande::STATUS_CANCELED => $langs->trans("StatusOrderCanceled")
362 );
363 print $form->selectarray('object_status', $liststatus, GETPOST('object_status', 'intcomma'), -4);
364}
365if ($mode == 'supplier') {
366 $formorder->selectSupplierOrderStatus((strstr($object_status, ',') ? -1 : $object_status), 0, 'object_status');
367}
368print '</td></tr>';
369// Year
370print '<tr><td class="left">'.$langs->trans("Year").'</td><td class="left">';
371if (!in_array($year, $arrayyears)) {
372 $arrayyears[$year] = $year;
373}
374if (!in_array($nowyear, $arrayyears)) {
375 $arrayyears[$nowyear] = $nowyear;
376}
377arsort($arrayyears);
378print $form->selectarray('year', $arrayyears, $year, 0, 0, 0, '', 0, 0, 0, '', 'width75');
379print '</td></tr>';
380print '<tr><td align="center" colspan="2"><input type="submit" class="button small" name="submit" value="'.$langs->trans("Refresh").'"></td></tr>';
381print '</table>';
382print '</form>';
383print '<br><br>';
384
385
386print '<div class="div-table-responsive-no-min">';
387print '<table class="noborder centpercent">';
388print '<tr class="liste_titre" height="24">';
389print '<td class="center">'.$langs->trans("Year").'</td>';
390print '<td class="right">'.$langs->trans("NbOfOrders").'</td>';
391print '<td class="right">%</td>';
392print '<td class="right">'.$langs->trans("AmountTotal").'</td>';
393print '<td class="right">%</td>';
394print '<td class="right">'.$langs->trans("AmountAverage").'</td>';
395print '<td class="right">%</td>';
396print '</tr>';
397
398$oldyear = 0;
399foreach ($data as $val) {
400 $year = $val['year'];
401 while (!empty($year) && $oldyear > $year + 1) { // If we have empty year
402 $oldyear--;
403
404 print '<tr class="oddeven" height="24">';
405 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>';
406 print '<td class="right">0</td>';
407 print '<td class="right"></td>';
408 print '<td class="right">0</td>';
409 print '<td class="right"></td>';
410 print '<td class="right">0</td>';
411 print '<td class="right"></td>';
412 print '</tr>';
413 }
414
415
416 print '<tr class="oddeven" height="24">';
417 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>';
418 print '<td class="right">'.$val['nb'].'</td>';
419 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>';
420 print '<td class="right">'.price(price2num($val['total'], 'MT'), 1).'</td>';
421 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>';
422 print '<td class="right">'.price(price2num($val['avg'], 'MT'), 1).'</td>';
423 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>';
424 print '</tr>';
425 $oldyear = $year;
426}
427
428print '</table>';
429print '</div>';
430
431
432print '</div><div class="fichetwothirdright">';
433
434
435// Show graphs
436print '<table class="border centpercent"><tr class="pair nohover"><td align="center">';
437if ($mesg) {
438 print $mesg;
439} else {
440 print $px1->show();
441 print "<br>\n";
442 print $px2->show();
443 print "<br>\n";
444 print $px3->show();
445}
446print '</td></tr></table>';
447
448
449print '</div></div>';
450print '<div class="clearboth"></div>';
451
452print dol_get_fiche_end();
453
454// End of page
455llxFooter();
456$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.
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 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.