dolibarr 25.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-2009 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2015-2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
6 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
7 * Copyright (C) 2024-2026 Frédéric France <frederic.france@free.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.'/don/class/don.class.php';
32require_once DOL_DOCUMENT_ROOT.'/don/class/donstats.class.php';
33require_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php';
34require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
35if (isModEnabled('category')) {
36 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
37}
38
49
50// Load translation files required by the page
51$langs->loadLangs(array("donations"));
52
53$userid = GETPOSTINT('userid');
54$socid = GETPOSTINT('socid');
55// Security check
56if ($user->socid > 0) {
57 $action = '';
58 $socid = $user->socid;
59}
60
61$status = GETPOSTINT('status');
62$nowyear = (int) dol_print_date(dol_now('gmt'), "%Y", 'gmt');
63$typent_id = GETPOSTINT('typent_id');
64$year = GETPOSTINT('year') > 0 ? GETPOSTINT('year') : $nowyear;
65$startyear = $year - (!getDolGlobalString('MAIN_STATS_GRAPHS_SHOW_N_YEARS') ? 2 : max(1, min(10, getDolGlobalInt('MAIN_STATS_GRAPHS_SHOW_N_YEARS'))));
66$endyear = $year;
67$mode = GETPOST("mode") ? GETPOST("mode") : 'customer';
68$custcats = GETPOST('custcats', 'array');
69
70// Security check
71$result = restrictedArea($user, 'don');
72
73/*
74 * View
75 */
76$form = new Form($db);
77$formcompany = new FormCompany($db);
78
79$picto = 'donation';
80$title = $langs->trans("Donations");
81$dir = $conf->don->dir_temp;
82
83llxHeader('', $title, '', '', 0, 0, '', '', '', 'mod-don page-stats');
84
85$page = 0;
86$param = '';
87$sortfield = '';
88$sortorder = '';
89$massactionbutton = '';
90$num = 0;
91$nbtotalofrecords = $langs->trans("Statistics");
92$limit = 0;
93
94$urlnew = DOL_URL_ROOT.'/don/card.php?action=create';
95if (!empty($socid)) {
96 $urlnew .= '&socid='.$socid;
97}
98
99$newcardbutton = '';
100$newcardbutton .= dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/don/list.php?mode=common', '', 1, array('morecss' => 'reposition'));
101$newcardbutton .= dolGetButtonTitle($langs->trans('ViewKanban'), '', 'fa fa-th-list imgforviewmode', DOL_URL_ROOT.'/don/list.php?mode=kanban', '', 1, array('morecss' => 'reposition'));
102$newcardbutton .= dolGetButtonTitle($langs->trans('Statistics'), '', 'fa fa-chart-bar imgforviewmode', DOL_URL_ROOT.'/don/stats/index.php', '', 2, array('morecss' => 'reposition'));
103$newcardbutton .= dolGetButtonTitleSeparator();
104$newcardbutton .= dolGetButtonTitle($langs->trans('NewDonation'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/don/card.php?action=create', '', $user->hasRight('don', 'write'));
105
106print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, $picto, 0, $newcardbutton, '', $limit, 0, 0, 1);
107
108dol_mkdir($dir);
109
110$stats = new DonationStats($db, $socid, '', ($userid > 0 ? $userid : 0), ($typent_id > 0 ? $typent_id : 0), ($status > 0 ? $status : 4));
111
112if (is_array($custcats) && !empty($custcats)) {
113 $stats->from .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_societe as cat ON (d.fk_soc = cat.fk_soc)';
114 $stats->where .= ' AND cat.fk_categorie IN ('.$db->sanitize(implode(',', $custcats)).')';
115}
116
117// Build graphic number of object
118$data = $stats->getNbByMonthWithPrevYear($endyear, $startyear);
119
120$filenamenb = $dir."/salariesnbinyear-".$year.".png";
121$fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=donationStats&amp;file=donationinyear-'.$year.'.png';
122
123$px1 = new DolGraph();
124$mesg = $px1->isGraphKo();
125if (!$mesg) {
126 $px1->SetData($data);
127 $i = $startyear;
128 $legend = array();
129 while ($i <= $endyear) {
130 $legend[] = $i;
131 $i++;
132 }
133 $px1->SetLegend($legend);
134 $px1->SetMaxValue($px1->GetCeilMaxValue());
135 $px1->SetMinValue(min(0, $px1->GetFloorMinValue()));
136 $px1->SetWidth($WIDTH);
137 $px1->SetHeight($HEIGHT);
138 $px1->SetYLabel($langs->trans("NbOfDonations"));
139 $px1->SetShading(3);
140 $px1->SetHorizTickIncrement(1);
141 $px1->mode = 'depth';
142 $px1->SetTitle($langs->trans("NumberByMonth"));
143
144 $px1->draw($filenamenb, $fileurlnb);
145}
146
147$data = $stats->getAmountByMonthWithPrevYear($endyear, $startyear);
148
149$filenameamount = $dir."/donationamount-".$year.".png";
150$fileurlamount = dolBuildUrl(DOL_URL_ROOT.'/viewimage.php', ['modulepart' => 'donationStats', 'file' => 'donationamoutinyear-'.$year.'.png']);
151
152$px2 = new DolGraph();
153$mesg = $px2->isGraphKo();
154if (!$mesg) {
155 $px2->SetData($data);
156 $i = $startyear;
157 $legend = array();
158 while ($i <= $endyear) {
159 $legend[] = $i;
160 $i++;
161 }
162 $px2->SetLegend($legend);
163 $px2->SetMaxValue($px2->GetCeilMaxValue());
164 $px2->SetMinValue(min(0, $px2->GetFloorMinValue()));
165 $px2->SetWidth($WIDTH);
166 $px2->SetHeight($HEIGHT);
167 $px2->SetYLabel($langs->trans("Amount"));
168 $px2->SetShading(3);
169 $px2->SetHorizTickIncrement(1);
170 $px2->mode = 'depth';
171 $px2->SetTitle($langs->trans("AmountTotal"));
172
173 $px2->draw($filenameamount, $fileurlamount);
174}
175
176$data = $stats->getAverageByMonthWithPrevYear($endyear, $startyear);
177
178$filename_avg = $dir."/donationaverage-".$year.".png";
179$fileurl_avg = dolBuildUrl(DOL_URL_ROOT.'/viewimage.php', ['modulepart' => 'donationStats', 'file' => 'donationaverageinyear-'.$year.'.png']);
180
181$px3 = new DolGraph();
182$mesg = $px3->isGraphKo();
183if (!$mesg) {
184 $px3->SetData($data);
185 $i = $startyear;
186 $legend = array();
187 while ($i <= $endyear) {
188 $legend[] = $i;
189 $i++;
190 }
191 $px3->SetLegend($legend);
192 $px3->SetYLabel($langs->trans("AmountAverage"));
193 $px3->SetMaxValue($px3->GetCeilMaxValue());
194 $px3->SetMinValue((int) $px3->GetFloorMinValue());
195 $px3->SetWidth($WIDTH);
196 $px3->SetHeight($HEIGHT);
197 $px3->SetShading(3);
198 $px3->SetHorizTickIncrement(1);
199 $px3->mode = 'depth';
200 $px3->SetTitle($langs->trans("AmountAverage"));
201
202 $px3->draw($filename_avg, $fileurl_avg);
203}
204
205// Show array
206$data = $stats->getAllByYear();
207$arrayyears = array();
208foreach ($data as $val) {
209 if (!empty($val['year'])) {
210 $arrayyears[$val['year']] = $val['year'];
211 }
212}
213if (!count($arrayyears)) {
214 $arrayyears[$nowyear] = $nowyear;
215}
216
217$h = 0;
218$head = array();
219$head[$h][0] = DOL_URL_ROOT.'/don/stats/index.php';
220$head[$h][1] = $langs->trans("ByMonthYear");
221$head[$h][2] = 'byyear';
222$h++;
223
224$type = 'donation_stats';
225
226complete_head_from_modules($conf, $langs, null, $head, $h, $type);
227
228print dol_get_fiche_head($head, 'byyear', '', -1);
229
230
231print '<div class="fichecenter"><div class="fichethirdleft">';
232
233// Show filter box
234print '<form name="stats" method="POST" action="'.dolBuildUrl($_SERVER["PHP_SELF"]).'">';
235print '<input type="hidden" name="token" value="'.newToken().'">';
236
237print '<table class="noborder centpercent">';
238print '<tr class="liste_titre"><td class="liste_titre" colspan="2">'.$langs->trans("Filter").'</td></tr>';
239
240// Company
241if (getDolGlobalString('DONATION_USE_THIRDPARTIES')) {
242 print '<tr><td>'.$langs->trans("ThirdParty").'</td><td>';
243 print img_picto('', 'company', 'class="pictofixedwidth"');
244 print $form->select_company($socid, 'socid', '', 1, 0, 0, array(), 0, 'widthcentpercentminusx maxwidth300', '');
245 print '</td></tr>';
246}
247
248// ThirdParty Type
249print '<tr><td>'.$langs->trans("ThirdPartyType").'</td><td>';
250$sortparam_typent = getDolGlobalString('SOCIETE_SORT_ON_TYPEENT', 'ASC');
251print $form->selectarray("typent_id", $formcompany->typent_array(0), $typent_id, 1, 0, 0, '', 0, 0, 0, $sortparam_typent, '', 1);
252if ($user->admin) {
253 print ' '.info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
254}
255print '</td></tr>';
256
257// Category
258if (isModEnabled('category')) {
259 $cat_type = Categorie::TYPE_CUSTOMER;
260 $cat_label = $langs->trans("Category").' '.lcfirst($langs->trans("Customer"));
261 print '<tr><td>'.$cat_label.'</td><td>';
262 $cate_arbo = $form->select_all_categories($cat_type, '', 'parent', 0, 0, 1);
263 print img_picto('', 'category', 'class="pictofixedwidth"');
264 if (is_array($cate_arbo)) {
265 print $form->multiselectarray('custcats', $cate_arbo, GETPOST('custcats', 'array'), 0, 0, 'widthcentpercentminusx maxwidth300');
266 }
267 print '</td></tr>';
268}
269
270// User
271print '<tr><td>'.$langs->trans("CreatedBy").'</td><td>';
272print img_picto('', 'user', 'class="pictofixedwidth"');
273print $form->select_dolusers($userid, 'userid', 1, null, 0, '', '', '0', 0, 0, '', 0, '', 'widthcentpercentminusx maxwidth300');
274print '</td></tr>';
275
276// Status
277print '<tr><td>'.$langs->trans("Status").'</td><td>';
278$liststatus = array(
279 '2' => $langs->trans("DonationStatusPaid"),
280 '0' => $langs->trans("DonationStatusPromiseNotValidated"),
281 '1' => $langs->trans("DonationStatusPromiseValidated"),
282 '3' => $langs->trans("Canceled")
283);
284print $form->selectarray('status', $liststatus, 4, 1);
285
286// Year
287print '<tr><td>'.$langs->trans("Year").'</td><td>';
288arsort($arrayyears);
289print img_picto('', 'calendar', 'class="pictofixedwidth"');
290print $form->selectarray('year', $arrayyears, $year, 0, 0, 0, '', 0, 0, 0, '', 'width75');
291
292print '</td></tr>';
293print '<tr><td class="center" colspan="2"><input type="submit" name="submit" class="button small" value="'.$langs->trans("Refresh").'"></td></tr>';
294print '</table>';
295print '</form>';
296print '<br><br>';
297
298print '<div class="div-table-responsive-no-min">';
299print '<table class="noborder centpercent">';
300print '<tr class="liste_titre" height="24">';
301print '<td class="center">'.$langs->trans("Year").'</td>';
302print '<td class="right">'.$langs->trans("NbOfDonations").'</td>';
303print '<td class="right">%</td>';
304print '<td class="right">'.$langs->trans("AmountTotal").'</td>';
305print '<td class="right">%</td>';
306print '<td class="right">'.$langs->trans("AmountAverage").'</td>';
307print '<td class="right">%</td>';
308print '</tr>';
309
310$oldyear = 0;
311foreach ($data as $val) {
312 $year = $val['year'];
313 while (!empty($year) && $oldyear > (int) $year + 1) {
314 $oldyear--;
315 print '<tr class="oddeven" height="24">';
316 print '<td class="center"><a href="'.dolBuildUrl($_SERVER["PHP_SELF"], ['year' => $oldyear]).'">'.$oldyear.'</a></td>';
317
318 print '<td class="right">0</td>';
319 print '<td class="right"></td>';
320 print '<td class="right amount">0</td>';
321 print '<td class="right"></td>';
322 print '<td class="right amount">0</td>';
323 print '<td class="right"></td>';
324 print '</tr>';
325 }
326
327 $greennb = (empty($val['nb_diff']) || $val['nb_diff'] >= 0);
328 $greentotal = (empty($val['total_diff']) || $val['total_diff'] >= 0);
329 $greenavg = (empty($val['avg_diff']) || $val['avg_diff'] >= 0);
330
331 print '<tr class="oddeven" height="24">';
332 $query = ['year' => $year, 'mode' => $mode];
333 if ($socid > 0) {
334 $query += ['socid' => $socid];
335 }
336 if ($userid > 0) {
337 $query += ['userid' => $userid];
338 }
339 print '<td align="center"><a href="'.dolBuildUrl($_SERVER["PHP_SELF"], $query).'">'.$year.'</a></td>';
340 print '<td class="right">'.$val['nb'].'</td>';
341 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>';
342 print '<td class="right"><span class="amount">'.price(price2num($val['total'], 'MT'), 1).'</span></td>';
343 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>';
344 print '<td class="right"><span class="amount">'.price(price2num($val['avg'], 'MT'), 1).'</span></td>';
345 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>';
346 print '</tr>';
347 $oldyear = $year;
348}
349
350print '</table>';
351print '</div>';
352
353print '</div><div class="fichetwothirdright">';
354
355// Show graphs
356print '<table class="border centpercent"><tr class="pair nohover"><td class="center">';
357if ($mesg) {
358 print $mesg;
359} else {
360 print $px1->show();
361 print "<br>\n";
362 print $px2->show();
363 print "<br>\n";
364 print $px3->show();
365}
366print '</td></tr></table>';
367
368print '</div></div>';
369print '<div class="clearboth"></div>';
370
371print dol_get_fiche_end();
372
373llxFooter();
374$db->close();
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
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:73
Class to build graphs.
static getDefaultGraphSizeForStats($direction, $defaultsize='')
getDefaultGraphSizeForStats
Class to manage donations statistics.
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.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_now($mode='gmt')
Return date for now.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dolBuildUrl($url, $params=[], $addtoken=false, $anchor='')
Return path of url.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
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.
isModEnabled($module)
Is Dolibarr module enabled.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
print_barre_liste($title, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $selectlimitsuffix=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
Definition html.lib.php:519
dolGetButtonTitle($label, $helpText='', $iconClass='fa fa-file', $url='', $id='', $status=1, $params=array())
Function dolGetButtonTitle : this kind of buttons are used in title in list.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
Definition html.lib.php:717
dolGetButtonTitleSeparator($moreClass="")
Add space between dolGetButtonTitle.
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.