dolibarr 18.0.6
index.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2003-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (c) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2012 Marcos García <marcosgdf@gmail.com>
5 * Copyright (C) 2013 Juanjo Menent <jmenent@2byte.es>
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.'/core/class/dolgraph.class.php';
32require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
33require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
34require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
35require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facturestats.class.php';
36if (isModEnabled('categorie')) {
37 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
38}
39
42
43// Load translation files required by the page
44$langs->loadLangs(array('bills', 'companies', 'other'));
45
46$mode = GETPOST("mode") ? GETPOST("mode") : 'customer';
47if ($mode == 'customer' && !$user->hasRight('facture', 'lire')) {
49}
50if ($mode == 'supplier' && empty($user->rights->fournisseur->facture->lire)) {
52}
53
54$object_status = GETPOST('object_status', 'intcomma');
55$typent_id = GETPOST('typent_id', 'int');
56$categ_id = GETPOST('categ_id', 'categ_id');
57
58$userid = GETPOST('userid', 'int');
59$socid = GETPOST('socid', 'int');
60$custcats = GETPOST('custcats', 'array');
61// Security check
62if ($user->socid > 0) {
63 $action = '';
64 $socid = $user->socid;
65}
66
67$nowyear = dol_print_date(dol_now('gmt'), "%Y", 'gmt');
68$year = GETPOST('year') > 0 ? GETPOST('year', 'int') : $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
73/*
74 * View
75 */
76if (isModEnabled('categorie')) {
77 $langs->load('categories');
78}
79$form = new Form($db);
80$formcompany = new FormCompany($db);
81$formother = new FormOther($db);
82
83llxHeader();
84
85$picto = 'bill';
86$title = $langs->trans("BillsStatistics");
87$dir = $conf->facture->dir_temp;
88
89if ($mode == 'supplier') {
90 $picto = 'supplier_invoice';
91 $title = $langs->trans("BillsStatisticsSuppliers");
92 $dir = $conf->fournisseur->facture->dir_temp;
93}
94
95
96print load_fiche_titre($title, '', $picto);
97
98dol_mkdir($dir);
99
100$stats = new FactureStats($db, $socid, $mode, ($userid > 0 ? $userid : 0), ($typent_id > 0 ? $typent_id : 0), ($categ_id > 0 ? $categ_id : 0));
101if ($mode == 'customer') {
102 if ($object_status != '' && $object_status >= 0) {
103 $stats->where .= ' AND f.fk_statut IN ('.$db->sanitize($object_status).')';
104 }
105 if (is_array($custcats) && !empty($custcats)) {
106 $stats->from .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_societe as cat ON (f.fk_soc = cat.fk_soc)';
107 $stats->where .= ' AND cat.fk_categorie IN ('.$db->sanitize(implode(',', $custcats)).')';
108 }
109}
110if ($mode == 'supplier') {
111 if ($object_status != '' && $object_status >= 0) {
112 $stats->where .= ' AND f.fk_statut IN ('.$db->sanitize($object_status).')';
113 }
114 if (is_array($custcats) && !empty($custcats)) {
115 $stats->from .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_fournisseur as cat ON (f.fk_soc = cat.fk_soc)';
116 $stats->where .= ' AND cat.fk_categorie IN ('.$db->sanitize(implode(',', $custcats)).')';
117 }
118}
119
120// Build graphic number of object
121// $data = array(array('Lib',val1,val2,val3),...)
122$data = $stats->getNbByMonthWithPrevYear($endyear, $startyear);
123//var_dump($data);
124
125$filenamenb = $dir."/invoicesnbinyear-".$year.".png";
126if ($mode == 'customer') {
127 $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=billstats&file=invoicesnbinyear-'.$year.'.png';
128}
129if ($mode == 'supplier') {
130 $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=billstatssupplier&file=invoicesnbinyear-'.$year.'.png';
131}
132
133$px1 = new DolGraph();
134$mesg = $px1->isGraphKo();
135if (!$mesg) {
136 $px1->SetData($data);
137 $i = $startyear;
138 $legend = array();
139 while ($i <= $endyear) {
140 $legend[] = $i;
141 $i++;
142 }
143 $px1->SetLegend($legend);
144 $px1->SetMaxValue($px1->GetCeilMaxValue());
145 $px1->SetWidth($WIDTH);
146 $px1->SetHeight($HEIGHT);
147 $px1->SetYLabel($langs->trans("NumberOfBills"));
148 $px1->SetShading(3);
149 $px1->SetHorizTickIncrement(1);
150 $px1->mode = 'depth';
151 $px1->SetTitle($langs->trans("NumberOfBillsByMonth"));
152
153 $px1->draw($filenamenb, $fileurlnb);
154}
155
156// Build graphic amount of object
157$data = $stats->getAmountByMonthWithPrevYear($endyear, $startyear);
158//var_dump($data);
159// $data = array(array('Lib',val1,val2,val3),...)
160
161$filenameamount = $dir."/invoicesamountinyear-".$year.".png";
162if ($mode == 'customer') {
163 $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=billstats&amp;file=invoicesamountinyear-'.$year.'.png';
164}
165if ($mode == 'supplier') {
166 $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=billstatssupplier&amp;file=invoicesamountinyear-'.$year.'.png';
167}
168
169$px2 = new DolGraph();
170$mesg = $px2->isGraphKo();
171if (!$mesg) {
172 $px2->SetData($data);
173 $i = $startyear;
174 $legend = array();
175 while ($i <= $endyear) {
176 $legend[] = $i;
177 $i++;
178 }
179 $px2->SetLegend($legend);
180 $px2->SetMaxValue($px2->GetCeilMaxValue());
181 $px2->SetMinValue(min(0, $px2->GetFloorMinValue()));
182 $px2->SetWidth($WIDTH);
183 $px2->SetHeight($HEIGHT);
184 $px2->SetYLabel($langs->trans("AmountOfBills"));
185 $px2->SetShading(3);
186 $px2->SetHorizTickIncrement(1);
187 $px2->mode = 'depth';
188 $px2->SetTitle($langs->trans("AmountOfBillsByMonthHT"));
189
190 $px2->draw($filenameamount, $fileurlamount);
191}
192
193
194$data = $stats->getAverageByMonthWithPrevYear($endyear, $startyear);
195
196if (empty($user->rights->societe->client->voir) || $user->socid) {
197 $filename_avg = $dir.'/ordersaverage-'.$user->id.'-'.$year.'.png';
198 if ($mode == 'customer') {
199 $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersaverage-'.$user->id.'-'.$year.'.png';
200 }
201 if ($mode == 'supplier') {
202 $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersaverage-'.$user->id.'-'.$year.'.png';
203 }
204} else {
205 $filename_avg = $dir.'/ordersaverage-'.$year.'.png';
206 if ($mode == 'customer') {
207 $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersaverage-'.$year.'.png';
208 }
209 if ($mode == 'supplier') {
210 $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersaverage-'.$year.'.png';
211 }
212}
213
214$px3 = new DolGraph();
215$mesg = $px3->isGraphKo();
216if (!$mesg) {
217 $px3->SetData($data);
218 $i = $startyear;
219 $legend = array();
220 while ($i <= $endyear) {
221 $legend[] = $i;
222 $i++;
223 }
224 $px3->SetLegend($legend);
225 $px3->SetYLabel($langs->trans("AmountAverage"));
226 $px3->SetMaxValue($px3->GetCeilMaxValue());
227 $px3->SetMinValue($px3->GetFloorMinValue());
228 $px3->SetWidth($WIDTH);
229 $px3->SetHeight($HEIGHT);
230 $px3->SetShading(3);
231 $px3->SetHorizTickIncrement(1);
232 $px3->mode = 'depth';
233 $px3->SetTitle($langs->trans("AmountAverage"));
234
235 $px3->draw($filename_avg, $fileurl_avg);
236}
237
238
239// Show array
240$data = $stats->getAllByYear();
241$arrayyears = array();
242foreach ($data as $val) {
243 $arrayyears[$val['year']] = $val['year'];
244}
245if (!count($arrayyears)) {
246 $arrayyears[$nowyear] = $nowyear;
247}
248
249
250$h = 0;
251$head = array();
252$head[$h][0] = DOL_URL_ROOT.'/compta/facture/stats/index.php?mode='.urlencode($mode);
253$head[$h][1] = $langs->trans("ByMonthYear");
254$head[$h][2] = 'byyear';
255$h++;
256
257if ($mode == 'customer') {
258 $type = 'invoice_stats';
259}
260if ($mode == 'supplier') {
261 $type = 'supplier_invoice_stats';
262}
263
264complete_head_from_modules($conf, $langs, null, $head, $h, $type);
265
266print dol_get_fiche_head($head, 'byyear', $langs->trans("Statistics"), -1);
267
268print '<div class="fichecenter"><div class="fichethirdleft">';
269
270
271// Show filter box
272print '<form name="stats" method="POST" action="'.$_SERVER["PHP_SELF"].'">';
273print '<input type="hidden" name="token" value="'.newToken().'">';
274print '<input type="hidden" name="mode" value="'.$mode.'">';
275
276print '<table class="noborder centpercent">';
277print '<tr class="liste_titre"><td class="liste_titre" colspan="2">'.$langs->trans("Filter").'</td></tr>';
278// Company
279print '<tr><td>'.$langs->trans("ThirdParty").'</td><td>';
280$filter = '';
281if ($mode == 'customer') {
282 $filter = '(s.client:IN:1,2,3)';
283}
284if ($mode == 'supplier') {
285 $filter = '(s.fournisseur:=:1)';
286}
287print img_picto('', 'company', 'class="pictofixedwidth"');
288print $form->select_company($socid, 'socid', $filter, 1, 0, 0, array(), 0, 'widthcentpercentminusx maxwidth300');
289print '</td></tr>';
290
291// ThirdParty Type
292print '<tr><td>'.$langs->trans("ThirdPartyType").'</td><td>';
293$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.
294print $form->selectarray("typent_id", $formcompany->typent_array(0), $typent_id, 1, 0, 0, '', 0, 0, 0, $sortparam_typent, '', 1);
295if ($user->admin) {
296 print ' '.info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
297}
298print '</td></tr>';
299
300// Category
301if (isModEnabled('categorie')) {
302 if ($mode == 'customer') {
303 $cat_type = Categorie::TYPE_CUSTOMER;
304 $cat_label = $langs->trans("Category").' '.lcfirst($langs->trans("Customer"));
305 }
306 if ($mode == 'supplier') {
307 $cat_type = Categorie::TYPE_SUPPLIER;
308 $cat_label = $langs->trans("Category").' '.lcfirst($langs->trans("Supplier"));
309 }
310 print '<tr><td>'.$cat_label.'</td><td>';
311 $cate_arbo = $form->select_all_categories($cat_type, null, 'parent', null, null, 1);
312 print img_picto('', 'category', 'class="pictofixedwidth"');
313 print $form->multiselectarray('custcats', $cate_arbo, GETPOST('custcats', 'array'), 0, 0, 'widthcentpercentminusx maxwidth300');
314 //print $formother->select_categories($cat_type, $categ_id, 'categ_id', true);
315 print '</td></tr>';
316}
317
318// User
319print '<tr><td>'.$langs->trans("CreatedBy").'</td><td>';
320print img_picto('', 'user', 'class="pictofixedwidth"');
321print $form->select_dolusers($userid, 'userid', 1, '', 0, '', '', 0, 0, 0, '', 0, '', 'widthcentpercentminusx maxwidth300');
322print '</td></tr>';
323// Status
324print '<tr><td>'.$langs->trans("Status").'</td><td>';
325if ($mode == 'customer') {
326 $liststatus = array('0'=>$langs->trans("BillStatusDraft"), '1'=>$langs->trans("BillStatusNotPaid"), '2'=>$langs->trans("BillStatusPaid"), '1,2'=>$langs->trans("BillStatusNotPaid").' / '.$langs->trans("BillStatusPaid"), '3'=>$langs->trans("BillStatusCanceled"));
327 print $form->selectarray('object_status', $liststatus, $object_status, 1);
328}
329if ($mode == 'supplier') {
330 $liststatus = array('0'=>$langs->trans("BillStatusDraft"), '1'=>$langs->trans("BillStatusNotPaid"), '2'=>$langs->trans("BillStatusPaid"));
331 print $form->selectarray('object_status', $liststatus, $object_status, 1);
332}
333print '</td></tr>';
334// Year
335print '<tr><td>'.$langs->trans("Year").'</td><td>';
336if (!in_array($year, $arrayyears)) {
337 $arrayyears[$year] = $year;
338}
339if (!in_array($nowyear, $arrayyears)) {
340 $arrayyears[$nowyear] = $nowyear;
341}
342arsort($arrayyears);
343print $form->selectarray('year', $arrayyears, $year, 0, 0, 0, '', 0, 0, 0, '', 'width75');
344print '</td></tr>';
345print '<tr><td class="center" colspan="2"><input type="submit" name="submit" class="button small" value="'.$langs->trans("Refresh").'"></td></tr>';
346print '</table>';
347print '</form>';
348print '<br><br>';
349
350print '<div class="div-table-responsive-no-min">';
351print '<table class="noborder centpercent">';
352print '<tr class="liste_titre" height="24">';
353print '<td class="center">'.$langs->trans("Year").'</td>';
354print '<td class="right">'.$langs->trans("NumberOfBills").'</td>';
355print '<td class="right">%</td>';
356print '<td class="right">'.$langs->trans("AmountTotal").'</td>';
357print '<td class="right">%</td>';
358print '<td class="right">'.$langs->trans("AmountAverage").'</td>';
359print '<td class="right">%</td>';
360print '</tr>';
361
362$oldyear = 0;
363foreach ($data as $val) {
364 $year = $val['year'];
365 while ($year && $oldyear > $year + 1) { // If we have empty year
366 $oldyear--;
367
368 print '<tr class="oddeven" height="24">';
369 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>';
370 print '<td class="right">0</td>';
371 print '<td class="right"></td>';
372 print '<td class="right amount">0</td>';
373 print '<td class="right"></td>';
374 print '<td class="right amount">0</td>';
375 print '<td class="right"></td>';
376 print '</tr>';
377 }
378
379 if ($mode == 'supplier') {
380 $greennb = (empty($val['nb_diff']) || $val['nb_diff'] <= 0);
381 $greentotal = (empty($val['total_diff']) || $val['total_diff'] <= 0);
382 $greenavg = (empty($val['avg_diff']) || $val['avg_diff'] <= 0);
383 } else {
384 $greennb = (empty($val['nb_diff']) || $val['nb_diff'] >= 0);
385 $greentotal = (empty($val['total_diff']) || $val['total_diff'] >= 0);
386 $greenavg = (empty($val['avg_diff']) || $val['avg_diff'] >= 0);
387 }
388
389 print '<tr class="oddeven" height="24">';
390 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>';
391 print '<td class="right">'.$val['nb'].'</td>';
392 print '<td class="right opacitylow" style="'.($greennb ? 'color: green;' : 'color: red;').'">'.(!empty($val['nb_diff']) && $val['nb_diff'] < 0 ? '' : '+').round(!empty($val['nb_diff']) ? $val['nb_diff'] : 0).'%</td>';
393 print '<td class="right"><span class="amount">'.price(price2num($val['total'], 'MT'), 1).'</span></td>';
394 print '<td class="right opacitylow" style="'.($greentotal ? 'color: green;' : 'color: red;').'">'.( !empty($val['total_diff']) && $val['total_diff'] < 0 ? '' : '+').round(!empty($val['total_diff']) ? $val['total_diff'] : 0).'%</td>';
395 print '<td class="right"><span class="amount">'.price(price2num($val['avg'], 'MT'), 1).'</span></td>';
396 print '<td class="right opacitylow" style="'.($greenavg ? 'color: green;' : 'color: red;').'">'.(!empty($val['avg_diff']) && $val['avg_diff'] < 0 ? '' : '+').round(!empty($val['avg_diff']) ? $val['avg_diff'] : 0).'%</td>';
397 print '</tr>';
398 $oldyear = $year;
399}
400
401print '</table>';
402print '</div>';
403
404print '</div><div class="fichetwothirdright">';
405
406
407// Show graphs
408print '<table class="border centpercent"><tr class="pair nohover"><td align="center">';
409if ($mesg) {
410 print $mesg;
411} else {
412 print $px1->show();
413 print "<br>\n";
414 print $px2->show();
415 print "<br>\n";
416 print $px3->show();
417}
418print '</td></tr></table>';
419
420
421print '</div></div>';
422print '<div class="clearboth"></div>';
423
424
425print dol_get_fiche_end();
426
427// End of page
428llxFooter();
429$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:56
llxFooter()
Empty footer.
Definition wrapper.php:70
Class to build graphs.
static getDefaultGraphSizeForStats($direction, $defaultsize='')
getDefaultGraphSizeForStats
Class to manage stats for invoices (customer and supplier)
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.
Classe permettant la generation de composants html autre Only common components are here.
load_fiche_titre($titre, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
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_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
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).
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.