dolibarr 20.0.0
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('category')) {
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';
47
48$hookmanager->initHooks(array('invoicestats', 'globalcard'));
49
50if ($mode == 'customer' && !$user->hasRight('facture', 'lire')) {
52}
53if ($mode == 'supplier' && !$user->hasRight('fournisseur', 'facture', 'lire')) {
55}
56
57$object_status = GETPOST('object_status', 'intcomma');
58$typent_id = GETPOSTINT('typent_id');
59$categ_id = GETPOSTINT('categ_id');
60
61$userid = GETPOSTINT('userid');
62$socid = GETPOSTINT('socid');
63$custcats = GETPOST('custcats', 'array');
64// Security check
65if ($user->socid > 0) {
66 $action = '';
67 $socid = $user->socid;
68}
69
70$parameters = array();
71$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
72if ($reshook < 0) {
73 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
74}
75
76$nowyear = dol_print_date(dol_now('gmt'), "%Y", 'gmt');
77$year = GETPOST('year') > 0 ? GETPOSTINT('year') : $nowyear;
78$startyear = $year - (!getDolGlobalString('MAIN_STATS_GRAPHS_SHOW_N_YEARS') ? 2 : max(1, min(10, getDolGlobalString('MAIN_STATS_GRAPHS_SHOW_N_YEARS'))));
79$endyear = $year;
80
81
82/*
83 * View
84 */
85if (isModEnabled('category')) {
86 $langs->load('categories');
87}
88$form = new Form($db);
89$formcompany = new FormCompany($db);
90$formother = new FormOther($db);
91
92llxHeader();
93
94$picto = 'bill';
95$title = $langs->trans("BillsStatistics");
96$dir = $conf->facture->dir_temp;
97
98if ($mode == 'supplier') {
99 $picto = 'supplier_invoice';
100 $title = $langs->trans("BillsStatisticsSuppliers");
101 $dir = $conf->fournisseur->facture->dir_temp;
102}
103
104
105print load_fiche_titre($title, '', $picto);
106
107dol_mkdir($dir);
108
109$stats = new FactureStats($db, $socid, $mode, ($userid > 0 ? $userid : 0), ($typent_id > 0 ? $typent_id : 0), ($categ_id > 0 ? $categ_id : 0));
110if ($mode == 'customer') {
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_societe as cat ON (f.fk_soc = cat.fk_soc)';
116 $stats->where .= ' AND cat.fk_categorie IN ('.$db->sanitize(implode(',', $custcats)).')';
117 }
118}
119if ($mode == 'supplier') {
120 if ($object_status != '' && $object_status >= 0) {
121 $stats->where .= ' AND f.fk_statut IN ('.$db->sanitize($object_status).')';
122 }
123 if (is_array($custcats) && !empty($custcats)) {
124 $stats->from .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_fournisseur as cat ON (f.fk_soc = cat.fk_soc)';
125 $stats->where .= ' AND cat.fk_categorie IN ('.$db->sanitize(implode(',', $custcats)).')';
126 }
127}
128
129// Build graphic number of object
130// $data = array(array('Lib',val1,val2,val3),...)
131$data = $stats->getNbByMonthWithPrevYear($endyear, $startyear);
132//var_dump($data);
133
134$filenamenb = $dir."/invoicesnbinyear-".$year.".png";
135if ($mode == 'customer') {
136 $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=billstats&file=invoicesnbinyear-'.$year.'.png';
137}
138if ($mode == 'supplier') {
139 $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=billstatssupplier&file=invoicesnbinyear-'.$year.'.png';
140}
141
142$px1 = new DolGraph();
143$mesg = $px1->isGraphKo();
144if (!$mesg) {
145 $px1->SetData($data);
146 $i = $startyear;
147 $legend = array();
148 while ($i <= $endyear) {
149 $legend[] = $i;
150 $i++;
151 }
152 $px1->SetLegend($legend);
153 $px1->SetMaxValue($px1->GetCeilMaxValue());
154 $px1->SetWidth($WIDTH);
155 $px1->SetHeight($HEIGHT);
156 $px1->SetYLabel($langs->trans("NumberOfBills"));
157 $px1->SetShading(3);
158 $px1->SetHorizTickIncrement(1);
159 $px1->mode = 'depth';
160 $px1->SetTitle($langs->trans("NumberOfBillsByMonth"));
161
162 $px1->draw($filenamenb, $fileurlnb);
163}
164
165// Build graphic amount of object
166$data = $stats->getAmountByMonthWithPrevYear($endyear, $startyear);
167//var_dump($data);
168// $data = array(array('Lib',val1,val2,val3),...)
169
170$filenameamount = $dir."/invoicesamountinyear-".$year.".png";
171if ($mode == 'customer') {
172 $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=billstats&amp;file=invoicesamountinyear-'.$year.'.png';
173}
174if ($mode == 'supplier') {
175 $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=billstatssupplier&amp;file=invoicesamountinyear-'.$year.'.png';
176}
177
178$px2 = new DolGraph();
179$mesg = $px2->isGraphKo();
180if (!$mesg) {
181 $px2->SetData($data);
182 $i = $startyear;
183 $legend = array();
184 while ($i <= $endyear) {
185 $legend[] = $i;
186 $i++;
187 }
188 $px2->SetLegend($legend);
189 $px2->SetMaxValue($px2->GetCeilMaxValue());
190 $px2->SetMinValue(min(0, $px2->GetFloorMinValue()));
191 $px2->SetWidth($WIDTH);
192 $px2->SetHeight($HEIGHT);
193 $px2->SetYLabel($langs->trans("AmountOfBills"));
194 $px2->SetShading(3);
195 $px2->SetHorizTickIncrement(1);
196 $px2->mode = 'depth';
197 $px2->SetTitle($langs->trans("AmountOfBillsByMonthHT"));
198
199 $px2->draw($filenameamount, $fileurlamount);
200}
201
202
203$data = $stats->getAverageByMonthWithPrevYear($endyear, $startyear);
204
205if (!$user->hasRight('societe', 'client', 'voir')) {
206 $filename_avg = $dir.'/ordersaverage-'.$user->id.'-'.$year.'.png';
207 if ($mode == 'customer') {
208 $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersaverage-'.$user->id.'-'.$year.'.png';
209 }
210 if ($mode == 'supplier') {
211 $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersaverage-'.$user->id.'-'.$year.'.png';
212 }
213} else {
214 $filename_avg = $dir.'/ordersaverage-'.$year.'.png';
215 if ($mode == 'customer') {
216 $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersaverage-'.$year.'.png';
217 }
218 if ($mode == 'supplier') {
219 $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersaverage-'.$year.'.png';
220 }
221}
222
223$px3 = new DolGraph();
224$mesg = $px3->isGraphKo();
225if (!$mesg) {
226 $px3->SetData($data);
227 $i = $startyear;
228 $legend = array();
229 while ($i <= $endyear) {
230 $legend[] = $i;
231 $i++;
232 }
233 $px3->SetLegend($legend);
234 $px3->SetYLabel($langs->trans("AmountAverage"));
235 $px3->SetMaxValue($px3->GetCeilMaxValue());
236 $px3->SetMinValue($px3->GetFloorMinValue());
237 $px3->SetWidth($WIDTH);
238 $px3->SetHeight($HEIGHT);
239 $px3->SetShading(3);
240 $px3->SetHorizTickIncrement(1);
241 $px3->mode = 'depth';
242 $px3->SetTitle($langs->trans("AmountAverage"));
243
244 $px3->draw($filename_avg, $fileurl_avg);
245}
246
247
248// Show array
249$data = $stats->getAllByYear();
250$arrayyears = array();
251foreach ($data as $val) {
252 $arrayyears[$val['year']] = $val['year'];
253}
254if (!count($arrayyears)) {
255 $arrayyears[$nowyear] = $nowyear;
256}
257
258
259$h = 0;
260$head = array();
261$head[$h][0] = DOL_URL_ROOT.'/compta/facture/stats/index.php?mode='.urlencode($mode);
262$head[$h][1] = $langs->trans("ByMonthYear");
263$head[$h][2] = 'byyear';
264$h++;
265
266if ($mode == 'customer') {
267 $type = 'invoice_stats';
268}
269if ($mode == 'supplier') {
270 $type = 'supplier_invoice_stats';
271}
272
273complete_head_from_modules($conf, $langs, null, $head, $h, $type);
274
275print dol_get_fiche_head($head, 'byyear', '', -1);
276
277print '<div class="fichecenter"><div class="fichethirdleft">';
278
279
280// Show filter box
281print '<form name="stats" method="POST" action="'.$_SERVER["PHP_SELF"].'">';
282print '<input type="hidden" name="token" value="'.newToken().'">';
283print '<input type="hidden" name="mode" value="'.$mode.'">';
284
285print '<table class="noborder centpercent">';
286print '<tr class="liste_titre"><td class="liste_titre" colspan="2">'.$langs->trans("Filter").'</td></tr>';
287// Company
288print '<tr><td>'.$langs->trans("ThirdParty").'</td><td>';
289$filter = '';
290if ($mode == 'customer') {
291 $filter = '(s.client:IN:1,2,3)';
292}
293if ($mode == 'supplier') {
294 $filter = '(s.fournisseur:=:1)';
295}
296print img_picto('', 'company', 'class="pictofixedwidth"');
297print $form->select_company($socid, 'socid', $filter, 1, 0, 0, array(), 0, 'widthcentpercentminusx maxwidth300');
298print '</td></tr>';
299
300// ThirdParty Type
301print '<tr><td>'.$langs->trans("ThirdPartyType").'</td><td>';
302$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.
303print $form->selectarray("typent_id", $formcompany->typent_array(0), $typent_id, 1, 0, 0, '', 0, 0, 0, $sortparam_typent, '', 1);
304if ($user->admin) {
305 print ' '.info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
306}
307print '</td></tr>';
308
309// Category
310if (isModEnabled('category')) {
311 if ($mode == 'customer') {
312 $cat_type = Categorie::TYPE_CUSTOMER;
313 $cat_label = $langs->trans("Category").' '.lcfirst($langs->trans("Customer"));
314 }
315 if ($mode == 'supplier') {
316 $cat_type = Categorie::TYPE_SUPPLIER;
317 $cat_label = $langs->trans("Category").' '.lcfirst($langs->trans("Supplier"));
318 }
319 print '<tr><td>'.$cat_label.'</td><td>';
320 $cate_arbo = $form->select_all_categories($cat_type, null, 'parent', null, null, 1);
321 print img_picto('', 'category', 'class="pictofixedwidth"');
322 print $form->multiselectarray('custcats', $cate_arbo, GETPOST('custcats', 'array'), 0, 0, 'widthcentpercentminusx maxwidth300');
323 //print $formother->select_categories($cat_type, $categ_id, 'categ_id', true);
324 print '</td></tr>';
325}
326
327// User
328print '<tr><td>'.$langs->trans("CreatedBy").'</td><td>';
329print img_picto('', 'user', 'class="pictofixedwidth"');
330print $form->select_dolusers($userid, 'userid', 1, '', 0, '', '', 0, 0, 0, '', 0, '', 'widthcentpercentminusx maxwidth300');
331print '</td></tr>';
332// Status
333print '<tr><td>'.$langs->trans("Status").'</td><td>';
334if ($mode == 'customer') {
335 $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"));
336 print $form->selectarray('object_status', $liststatus, $object_status, 1);
337}
338if ($mode == 'supplier') {
339 $liststatus = array('0'=>$langs->trans("BillStatusDraft"), '1'=>$langs->trans("BillStatusNotPaid"), '2'=>$langs->trans("BillStatusPaid"));
340 print $form->selectarray('object_status', $liststatus, $object_status, 1);
341}
342print '</td></tr>';
343// Year
344print '<tr><td>'.$langs->trans("Year").'</td><td>';
345if (!in_array($year, $arrayyears)) {
346 $arrayyears[$year] = $year;
347}
348if (!in_array($nowyear, $arrayyears)) {
349 $arrayyears[$nowyear] = $nowyear;
350}
351arsort($arrayyears);
352print $form->selectarray('year', $arrayyears, $year, 0, 0, 0, '', 0, 0, 0, '', 'width75');
353print '</td></tr>';
354print '<tr><td class="center" colspan="2"><input type="submit" name="submit" class="button small" value="'.$langs->trans("Refresh").'"></td></tr>';
355print '</table>';
356print '</form>';
357print '<br><br>';
358
359print '<div class="div-table-responsive-no-min">';
360print '<table class="noborder centpercent">';
361print '<tr class="liste_titre" height="24">';
362print '<td class="center">'.$langs->trans("Year").'</td>';
363print '<td class="right">'.$langs->trans("NumberOfBills").'</td>';
364print '<td class="right">%</td>';
365print '<td class="right">'.$langs->trans("AmountTotal").'</td>';
366print '<td class="right">%</td>';
367print '<td class="right">'.$langs->trans("AmountAverage").'</td>';
368print '<td class="right">%</td>';
369print '</tr>';
370
371$oldyear = 0;
372foreach ($data as $val) {
373 $year = $val['year'];
374 while ($year && $oldyear > $year + 1) { // If we have empty year
375 $oldyear--;
376
377 print '<tr class="oddeven" height="24">';
378 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>';
379 print '<td class="right">0</td>';
380 print '<td class="right"></td>';
381 print '<td class="right amount">0</td>';
382 print '<td class="right"></td>';
383 print '<td class="right amount">0</td>';
384 print '<td class="right"></td>';
385 print '</tr>';
386 }
387
388 if ($mode == 'supplier') {
389 $greennb = (empty($val['nb_diff']) || $val['nb_diff'] <= 0);
390 $greentotal = (empty($val['total_diff']) || $val['total_diff'] <= 0);
391 $greenavg = (empty($val['avg_diff']) || $val['avg_diff'] <= 0);
392 } else {
393 $greennb = (empty($val['nb_diff']) || $val['nb_diff'] >= 0);
394 $greentotal = (empty($val['total_diff']) || $val['total_diff'] >= 0);
395 $greenavg = (empty($val['avg_diff']) || $val['avg_diff'] >= 0);
396 }
397
398 print '<tr class="oddeven" height="24">';
399 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>';
400 print '<td class="right">'.$val['nb'].'</td>';
401 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>';
402 print '<td class="right"><span class="amount">'.price(price2num($val['total'], 'MT'), 1).'</span></td>';
403 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>';
404 print '<td class="right"><span class="amount">'.price(price2num($val['avg'], 'MT'), 1).'</span></td>';
405 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>';
406 print '</tr>';
407 $oldyear = $year;
408}
409
410print '</table>';
411print '</div>';
412
413print '</div><div class="fichetwothirdright">';
414
415
416// Show graphs
417print '<table class="border centpercent"><tr class="pair nohover"><td align="center">';
418if ($mesg) {
419 print $mesg;
420} else {
421 print $px1->show();
422 print "<br>\n";
423 print $px2->show();
424 print "<br>\n";
425 print $px3->show();
426}
427print '</td></tr></table>';
428
429
430print '</div></div>';
431print '<div class="clearboth"></div>';
432
433
434print dol_get_fiche_end();
435
436// End of page
437llxFooter();
438$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
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.
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.
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.