dolibarr  13.0.2
stats.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (c) 2008-2013 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2012 Regis Houssin <regis.houssin@inodbox.com>
5  * Copyright (C) 2012 Marcos GarcĂ­a <marcosgdf@gmail.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <https://www.gnu.org/licenses/>.
19  */
20 
30 abstract class Stats
31 {
32  protected $db;
33  protected $lastfetchdate = array(); // Dates of cache file read by methods
34  public $cachefilesuffix = ''; // Suffix to add to name of cache file (to avoid file name conflicts)
35 
46  public function getNbByMonthWithPrevYear($endyear, $startyear, $cachedelay = 0, $format = 0, $startmonth = 1)
47  {
48  global $conf, $user, $langs;
49 
50  if ($startyear > $endyear) return -1;
51 
52  $datay = array();
53 
54  // Search into cache
55  if (!empty($cachedelay))
56  {
57  include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
58  include_once DOL_DOCUMENT_ROOT.'/core/lib/json.lib.php';
59  }
60 
61  $newpathofdestfile = $conf->user->dir_temp.'/'.get_class($this).'_'.__FUNCTION__.'_'.(empty($this->cachefilesuffix) ? '' : $this->cachefilesuffix.'_').$langs->defaultlang.'_entity.'.$conf->entity.'_user'.$user->id.'.cache';
62  $newmask = '0644';
63 
64  $nowgmt = dol_now();
65 
66  $foundintocache = 0;
67  if ($cachedelay > 0)
68  {
69  $filedate = dol_filemtime($newpathofdestfile);
70  if ($filedate >= ($nowgmt - $cachedelay))
71  {
72  $foundintocache = 1;
73 
74  $this->lastfetchdate[get_class($this).'_'.__FUNCTION__] = $filedate;
75  } else {
76  dol_syslog(get_class($this).'::'.__FUNCTION__." cache file ".$newpathofdestfile." is not found or older than now - cachedelay (".$nowgmt." - ".$cachedelay.") so we can't use it.");
77  }
78  }
79  // Load file into $data
80  if ($foundintocache) // Cache file found and is not too old
81  {
82  dol_syslog(get_class($this).'::'.__FUNCTION__." read data from cache file ".$newpathofdestfile." ".$filedate.".");
83  $data = json_decode(file_get_contents($newpathofdestfile), true);
84  } else {
85  $year = $startyear;
86  $sm = $startmonth - 1;
87  if ($sm != 0) $year = $year - 1;
88  while ($year <= $endyear)
89  {
90  $datay[$year] = $this->getNbByMonth($year, $format);
91  $year++;
92  }
93 
94  $data = array();
95 
96  for ($i = 0; $i < 12; $i++)
97  {
98  $data[$i][] = $datay[$endyear][($i + $sm) % 12][0];
99  $year = $startyear;
100  while ($year <= $endyear)
101  {
102  $data[$i][] = $datay[$year - (1 - ((int) ($i + $sm) / 12)) + ($sm == 0 ? 1 : 0)][($i + $sm) % 12][1];
103  $year++;
104  }
105  }
106  }
107 
108  // Save cache file
109  if (empty($foundintocache) && ($cachedelay > 0 || $cachedelay == -1))
110  {
111  dol_syslog(get_class($this).'::'.__FUNCTION__." save cache file ".$newpathofdestfile." onto disk.");
112  if (!dol_is_dir($conf->user->dir_temp)) dol_mkdir($conf->user->dir_temp);
113  $fp = fopen($newpathofdestfile, 'w');
114  fwrite($fp, json_encode($data));
115  fclose($fp);
116  if (!empty($conf->global->MAIN_UMASK)) $newmask = $conf->global->MAIN_UMASK;
117  @chmod($newpathofdestfile, octdec($newmask));
118 
119  $this->lastfetchdate[get_class($this).'_'.__FUNCTION__] = $nowgmt;
120  }
121 
122  // return array(array('Month',val1,val2,val3),...)
123  return $data;
124  }
125 
139  public function getAmountByMonthWithPrevYear($endyear, $startyear, $cachedelay = 0, $format = 0, $startmonth = 1)
140  {
141  global $conf, $user, $langs;
142 
143  if ($startyear > $endyear) return -1;
144 
145  $datay = array();
146 
147  // Search into cache
148  if (!empty($cachedelay))
149  {
150  include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
151  include_once DOL_DOCUMENT_ROOT.'/core/lib/json.lib.php';
152  }
153 
154  $newpathofdestfile = $conf->user->dir_temp.'/'.get_class($this).'_'.__FUNCTION__.'_'.(empty($this->cachefilesuffix) ? '' : $this->cachefilesuffix.'_').$langs->defaultlang.'_entity.'.$conf->entity.'_user'.$user->id.'.cache';
155  $newmask = '0644';
156 
157  $nowgmt = dol_now();
158 
159  $foundintocache = 0;
160  if ($cachedelay > 0)
161  {
162  $filedate = dol_filemtime($newpathofdestfile);
163  if ($filedate >= ($nowgmt - $cachedelay))
164  {
165  $foundintocache = 1;
166 
167  $this->lastfetchdate[get_class($this).'_'.__FUNCTION__] = $filedate;
168  } else {
169  dol_syslog(get_class($this).'::'.__FUNCTION__." cache file ".$newpathofdestfile." is not found or older than now - cachedelay (".$nowgmt." - ".$cachedelay.") so we can't use it.");
170  }
171  }
172 
173  // Load file into $data
174  if ($foundintocache) // Cache file found and is not too old
175  {
176  dol_syslog(get_class($this).'::'.__FUNCTION__." read data from cache file ".$newpathofdestfile." ".$filedate.".");
177  $data = json_decode(file_get_contents($newpathofdestfile), true);
178  } else {
179  $year = $startyear;
180  $sm = $startmonth - 1;
181  if ($sm != 0) $year = $year - 1;
182  while ($year <= $endyear)
183  {
184  $datay[$year] = $this->getAmountByMonth($year, $format);
185  $year++;
186  }
187 
188  $data = array();
189  // $data = array('xval'=>array(0=>xlabel,1=>yval1,2=>yval2...),...)
190  for ($i = 0; $i < 12; $i++)
191  {
192  $data[$i][] = isset($datay[$endyear][($i + $sm) % 12]['label']) ? $datay[$endyear][($i + $sm) % 12]['label'] : $datay[$endyear][($i + $sm) % 12][0]; // set label
193  $year = $startyear;
194  while ($year <= $endyear)
195  {
196  $data[$i][] = $datay[$year - (1 - ((int) ($i + $sm) / 12)) + ($sm == 0 ? 1 : 0)][($i + $sm) % 12][1]; // set yval for x=i
197  $year++;
198  }
199  }
200  }
201 
202  // Save cache file
203  if (empty($foundintocache) && ($cachedelay > 0 || $cachedelay == -1))
204  {
205  dol_syslog(get_class($this).'::'.__FUNCTION__." save cache file ".$newpathofdestfile." onto disk.");
206  if (!dol_is_dir($conf->user->dir_temp)) dol_mkdir($conf->user->dir_temp);
207  $fp = fopen($newpathofdestfile, 'w');
208  if ($fp)
209  {
210  fwrite($fp, json_encode($data));
211  fclose($fp);
212  if (!empty($conf->global->MAIN_UMASK)) $newmask = $conf->global->MAIN_UMASK;
213  @chmod($newpathofdestfile, octdec($newmask));
214  } else dol_syslog("Failed to write cache file", LOG_ERR);
215  $this->lastfetchdate[get_class($this).'_'.__FUNCTION__] = $nowgmt;
216  }
217 
218  return $data;
219  }
220 
228  public function getAverageByMonthWithPrevYear($endyear, $startyear)
229  {
230  if ($startyear > $endyear) return -1;
231 
232  $datay = array();
233 
234  $year = $startyear;
235  while ($year <= $endyear)
236  {
237  $datay[$year] = $this->getAverageByMonth($year);
238  $year++;
239  }
240 
241  $data = array();
242 
243  for ($i = 0; $i < 12; $i++)
244  {
245  $data[$i][] = $datay[$endyear][$i][0];
246  $year = $startyear;
247  while ($year <= $endyear)
248  {
249  $data[$i][] = $datay[$year][$i][1];
250  $year++;
251  }
252  }
253 
254  return $data;
255  }
256 
265  public function getAllByProductEntry($year, $cachedelay = 0, $limit = 10)
266  {
267  global $conf, $user, $langs;
268 
269  $data = array();
270 
271  // Search into cache
272  if (!empty($cachedelay))
273  {
274  include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
275  include_once DOL_DOCUMENT_ROOT.'/core/lib/json.lib.php';
276  }
277 
278  $newpathofdestfile = $conf->user->dir_temp.'/'.get_class($this).'_'.__FUNCTION__.'_'.(empty($this->cachefilesuffix) ? '' : $this->cachefilesuffix.'_').$langs->defaultlang.'_entity.'.$conf->entity.'_user'.$user->id.'.cache';
279  $newmask = '0644';
280 
281  $nowgmt = dol_now();
282 
283  $foundintocache = 0;
284  if ($cachedelay > 0)
285  {
286  $filedate = dol_filemtime($newpathofdestfile);
287  if ($filedate >= ($nowgmt - $cachedelay))
288  {
289  $foundintocache = 1;
290 
291  $this->lastfetchdate[get_class($this).'_'.__FUNCTION__] = $filedate;
292  } else {
293  dol_syslog(get_class($this).'::'.__FUNCTION__." cache file ".$newpathofdestfile." is not found or older than now - cachedelay (".$nowgmt." - ".$cachedelay.") so we can't use it.");
294  }
295  }
296 
297  // Load file into $data
298  if ($foundintocache) // Cache file found and is not too old
299  {
300  dol_syslog(get_class($this).'::'.__FUNCTION__." read data from cache file ".$newpathofdestfile." ".$filedate.".");
301  $data = json_decode(file_get_contents($newpathofdestfile), true);
302  } else {
303  $data = $this->getAllByProduct($year, $limit);
304  // $data[$i][]=$datay[$year][$i][1]; // set yval for x=i
305  }
306 
307  // Save cache file
308  if (empty($foundintocache) && ($cachedelay > 0 || $cachedelay == -1))
309  {
310  dol_syslog(get_class($this).'::'.__FUNCTION__." save cache file ".$newpathofdestfile." onto disk.");
311  if (!dol_is_dir($conf->user->dir_temp)) dol_mkdir($conf->user->dir_temp);
312  $fp = fopen($newpathofdestfile, 'w');
313  if ($fp)
314  {
315  fwrite($fp, json_encode($data));
316  fclose($fp);
317  if (!empty($conf->global->MAIN_UMASK)) $newmask = $conf->global->MAIN_UMASK;
318  @chmod($newpathofdestfile, octdec($newmask));
319  }
320  $this->lastfetchdate[get_class($this).'_'.__FUNCTION__] = $nowgmt;
321  }
322 
323  return $data;
324  }
325 
326 
327  // Here we have low level of shared code called by XxxStats.class.php
328 
329 
330  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
337  protected function _getNbByYear($sql)
338  {
339  // phpcs:enable
340  $result = array();
341 
342  dol_syslog(get_class($this).'::'.__FUNCTION__."", LOG_DEBUG);
343  $resql = $this->db->query($sql);
344  if ($resql)
345  {
346  $num = $this->db->num_rows($resql);
347  $i = 0;
348  while ($i < $num)
349  {
350  $row = $this->db->fetch_row($resql);
351  $result[$i] = $row;
352  $i++;
353  }
354  $this->db->free($resql);
355  } else {
356  dol_print_error($this->db);
357  }
358  return $result;
359  }
360 
361  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
368  protected function _getAllByYear($sql)
369  {
370  // phpcs:enable
371  $result = array();
372 
373  dol_syslog(get_class($this).'::'.__FUNCTION__."", LOG_DEBUG);
374  $resql = $this->db->query($sql);
375  if ($resql)
376  {
377  $num = $this->db->num_rows($resql);
378  $i = 0;
379  while ($i < $num)
380  {
381  $row = $this->db->fetch_object($resql);
382  $result[$i]['year'] = $row->year;
383  $result[$i]['nb'] = $row->nb;
384  if ($i > 0 && $row->nb > 0) $result[$i - 1]['nb_diff'] = ($result[$i - 1]['nb'] - $row->nb) / $row->nb * 100;
385  $result[$i]['total'] = $row->total;
386  if ($i > 0 && $row->total > 0) $result[$i - 1]['total_diff'] = ($result[$i - 1]['total'] - $row->total) / $row->total * 100;
387  $result[$i]['avg'] = $row->avg;
388  if ($i > 0 && $row->avg > 0) $result[$i - 1]['avg_diff'] = ($result[$i - 1]['avg'] - $row->avg) / $row->avg * 100;
389  // For some $sql only
390  if (isset($row->weighted))
391  {
392  $result[$i]['weighted'] = $row->weighted;
393  if ($i > 0 && $row->weighted > 0) $result[$i - 1]['avg_weighted'] = ($result[$i - 1]['weighted'] - $row->weighted) / $row->weighted * 100;
394  }
395  $i++;
396  }
397  $this->db->free($resql);
398  } else {
399  dol_print_error($this->db);
400  }
401  return $result;
402  }
403 
404  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
414  protected function _getNbByMonth($year, $sql, $format = 0)
415  {
416  // phpcs:enable
417  global $langs;
418 
419  $result = array();
420  $res = array();
421 
422  dol_syslog(get_class($this).'::'.__FUNCTION__."", LOG_DEBUG);
423  $resql = $this->db->query($sql);
424  if ($resql)
425  {
426  $num = $this->db->num_rows($resql);
427  $i = 0; $j = 0;
428  while ($i < $num)
429  {
430  $row = $this->db->fetch_row($resql);
431  $j = $row[0] * 1;
432  $result[$j] = $row[1];
433  $i++;
434  }
435  $this->db->free($resql);
436  } else {
437  dol_print_error($this->db);
438  }
439 
440  for ($i = 1; $i < 13; $i++)
441  {
442  $res[$i] = (isset($result[$i]) ? $result[$i] : 0);
443  }
444 
445  $data = array();
446 
447  for ($i = 1; $i < 13; $i++)
448  {
449  $month = 'unknown';
450  if ($format == 0) $month = $langs->transnoentitiesnoconv('MonthShort'.sprintf("%02d", $i));
451  elseif ($format == 1) $month = $i;
452  elseif ($format == 2) $month = $langs->transnoentitiesnoconv('MonthVeryShort'.sprintf("%02d", $i));
453  //$month=dol_print_date(dol_mktime(12,0,0,$i,1,$year),($format?"%m":"%b"));
454  //$month=dol_substr($month,0,3);
455  $data[$i - 1] = array($month, $res[$i]);
456  }
457 
458  return $data;
459  }
460 
461 
462  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
471  protected function _getAmountByMonth($year, $sql, $format = 0)
472  {
473  // phpcs:enable
474  global $langs;
475 
476  $result = array();
477  $res = array();
478 
479  dol_syslog(get_class($this).'::'.__FUNCTION__."", LOG_DEBUG);
480 
481  $resql = $this->db->query($sql);
482  if ($resql)
483  {
484  $num = $this->db->num_rows($resql);
485  $i = 0;
486  while ($i < $num)
487  {
488  $row = $this->db->fetch_row($resql);
489  $j = $row[0] * 1;
490  $result[$j] = $row[1];
491  $i++;
492  }
493  $this->db->free($resql);
494  } else dol_print_error($this->db);
495 
496  for ($i = 1; $i < 13; $i++)
497  {
498  $res[$i] = (int) round((isset($result[$i]) ? $result[$i] : 0));
499  }
500 
501  $data = array();
502 
503  for ($i = 1; $i < 13; $i++)
504  {
505  $month = 'unknown';
506  if ($format == 0) $month = $langs->transnoentitiesnoconv('MonthShort'.sprintf("%02d", $i));
507  elseif ($format == 1) $month = $i;
508  elseif ($format == 2) $month = $langs->transnoentitiesnoconv('MonthVeryShort'.sprintf("%02d", $i));
509  //$month=dol_print_date(dol_mktime(12,0,0,$i,1,$year),($format?"%m":"%b"));
510  //$month=dol_substr($month,0,3);
511  $data[$i - 1] = array($month, $res[$i]);
512  }
513 
514  return $data;
515  }
516 
517  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
527  protected function _getAverageByMonth($year, $sql, $format = 0)
528  {
529  // phpcs:enable
530  global $langs;
531 
532  $result = array();
533  $res = array();
534 
535  dol_syslog(get_class($this).'::'.__FUNCTION__."", LOG_DEBUG);
536  $resql = $this->db->query($sql);
537  if ($resql)
538  {
539  $num = $this->db->num_rows($resql);
540  $i = 0; $j = 0;
541  while ($i < $num)
542  {
543  $row = $this->db->fetch_row($resql);
544  $j = $row[0] * 1;
545  $result[$j] = $row[1];
546  $i++;
547  }
548  $this->db->free($resql);
549  } else dol_print_error($this->db);
550 
551  for ($i = 1; $i < 13; $i++)
552  {
553  $res[$i] = (isset($result[$i]) ? $result[$i] : 0);
554  }
555 
556  $data = array();
557 
558  for ($i = 1; $i < 13; $i++)
559  {
560  $month = 'unknown';
561  if ($format == 0) $month = $langs->transnoentitiesnoconv('MonthShort'.sprintf("%02d", $i));
562  elseif ($format == 1) $month = $i;
563  elseif ($format == 2) $month = $langs->transnoentitiesnoconv('MonthVeryShort'.sprintf("%02d", $i));
564  //$month=dol_print_date(dol_mktime(12,0,0,$i,1,$year),($format?"%m":"%b"));
565  //$month=dol_substr($month,0,3);
566  $data[$i - 1] = array($month, $res[$i]);
567  }
568 
569  return $data;
570  }
571 
572 
573  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
581  protected function _getAllByProduct($sql, $limit = 10)
582  {
583  // phpcs:enable
584  global $langs;
585 
586  $result = array();
587 
588  dol_syslog(get_class($this).'::'.__FUNCTION__."", LOG_DEBUG);
589  $resql = $this->db->query($sql);
590  if ($resql)
591  {
592  $num = $this->db->num_rows($resql);
593  $i = 0; $other = 0;
594  while ($i < $num)
595  {
596  $row = $this->db->fetch_row($resql);
597  if ($i < $limit || $num == $limit) $result[$i] = array($row[0], $row[1]); // Ref of product, nb
598  else $other += $row[1];
599  $i++;
600  }
601  if ($num > $limit) $result[$i] = array($langs->transnoentitiesnoconv("Other"), $other);
602  $this->db->free($resql);
603  } else dol_print_error($this->db);
604 
605  return $result;
606  }
607 }
getAllByProductEntry($year, $cachedelay=0, $limit=10)
Return count, and sum of products.
Parent class of statistics class.
Definition: stats.class.php:30
getAmountByMonthWithPrevYear($endyear, $startyear, $cachedelay=0, $format=0, $startmonth=1)
Return amount of elements by month for several years.
getNbByMonthWithPrevYear($endyear, $startyear, $cachedelay=0, $format=0, $startmonth=1)
Return nb of elements by month for several years.
Definition: stats.class.php:46
dol_now($mode= 'auto')
Return date for now.
dol_is_dir($folder)
Test if filename is a directory.
Definition: files.lib.php:432
_getNbByMonth($year, $sql, $format=0)
Renvoie le nombre de documents par mois pour une annee donnee Return number of documents per month fo...
$conf db
API class for accounts.
Definition: inc.php:54
_getAllByProduct($sql, $limit=10)
Return number or total of product refs.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename= '', $restricttologhandler= '', $logcontext=null)
Write log message into outputs.
_getAllByYear($sql)
Return nb of elements, total amount and avg amount each year.
dol_filemtime($pathoffile)
Return time of a file.
Definition: files.lib.php:567
if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) if(!empty($conf->don->enabled)&&$user->rights->don->lire) if(!empty($conf->tax->enabled)&&$user->rights->tax->charges->lire) if(!empty($conf->facture->enabled)&&!empty($conf->commande->enabled)&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1232
dol_print_error($db= '', $error= '', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
_getAmountByMonth($year, $sql, $format=0)
Return the amount per month for a given year.
getAverageByMonthWithPrevYear($endyear, $startyear)
Return average of entity by month for several years.
_getNbByYear($sql)
Return nb of elements by year.
_getAverageByMonth($year, $sql, $format=0)
Renvoie le montant moyen par mois pour une annee donnee Return the amount average par month for a giv...
if(!defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN'
Draft customers invoices.
dol_mkdir($dir, $dataroot= '', $newmask=null)
Creation of a directory (this can create recursive subdir)