dolibarr 24.0.0-beta
index.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2001-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (c) 2004-2019 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2005 Eric Seigne <eric.seigne@ryxeo.com>
6 * Copyright (C) 2013 Juanjo Menent <jmenent@2byte.es>
7 * Copyright (C) 2019 Thibault FOUCART <support@ptibogxiv.net>
8 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
9 * Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 */
24
31// Load Dolibarr environment
32require '../../main.inc.php';
40require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
41require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
42require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
43require_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php';
44require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
45require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
46
47$WIDTH = DolGraph::getDefaultGraphSizeForStats('width', '380');
48$HEIGHT = DolGraph::getDefaultGraphSizeForStats('height', '160');
49
50// Load translation files required by the page
51$langs->loadLangs(array('companies', 'products', 'stocks', 'bills', 'other'));
52
53$id = GETPOSTINT('id'); // For this page, id can also be 'all'
54$ref = GETPOST('ref', 'alpha');
55$mode = (GETPOST('mode', 'alpha') ? (string) GETPOST('mode', 'alpha') : 'byunit');
56$search_year = GETPOSTINT('search_year');
57$search_categ = GETPOSTINT('search_categ');
58$notab = GETPOSTINT('notab');
59$type = GETPOST('type', 'alpha'); // Can be '' or '0' or '1'
60
61$error = 0;
62$mesg = '';
63$graphfiles = array();
64
65$socid = GETPOSTINT('socid');
66if (!empty($user->socid)) {
67 $socid = $user->socid;
68}
69if ($socid < 0) {
70 $socid = 0;
71}
72
73// Security check
74$fieldvalue = ($id > 0 ? $id : $ref);
75$fieldtype = (!empty($ref) ? 'ref' : 'rowid');
76
77// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
78$hookmanager->initHooks(array('productstatscard', 'globalcard'));
79
80$tmp = dol_getdate(dol_now());
81$currentyear = $tmp['year'];
82if (empty($search_year)) {
83 $search_year = $currentyear;
84}
85$moreforfilter = "";
86
87$object = new Product($db);
88if ($id > 0 || !empty($ref)) {
89 $result = $object->fetch($id, $ref);
90}
91
92$result = restrictedArea($user, 'produit|service', $fieldvalue, 'product&product', '', '', $fieldtype);
93
94
95/*
96 * Actions
97 */
98
99// None
100
101
102/*
103 * View
104 */
105
106$form = new Form($db);
107$htmlother = new FormOther($db);
108
109if (!($id > 0) && empty($ref) || $notab) {
110 $notab = 1;
111
112 $help_url = '';
113 if ($type === "" || $type === "-1") {
114 $help_url = 'EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
115 $title = $langs->trans("ProductsAndServices");
116 } elseif ($type == '0') {
117 $help_url = 'EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
118 //$title=$langs->trans("StatisticsOfProducts");
119 $title = $langs->trans("Products");
120 } else {
121 $help_url = 'EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
122 //$title=$langs->trans("StatisticsOfProductsOrServices");
123 $title = $langs->trans("Services");
124 }
125
126 llxHeader("", $title, $help_url, '', 0, 0, '', '', '', 'mod-product page-stats_card_general');
127
128 $picto = 'product';
129 if ($type == 1) {
130 $picto = 'service';
131 }
132
133
134 $page = 0;
135 $param = ($type === '' ? '' : '&type='.((int) $type));
136 $massactionbutton = '';
137 $limit = 0;
138 $num = 0;
139 $nbtotalofrecords = $langs->trans("Statistics");
140 $sortfield = '';
141 $sortorder = '';
142
143 $newcardbutton = '';
144 $newcardbutton .= dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/product/list.php?&mode=common'.preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ((empty($mode) || $mode == 'common') ? 2 : 1), array('morecss' => 'reposition'));
145 $newcardbutton .= dolGetButtonTitle($langs->trans('ViewKanban'), '', 'fa fa-th-list imgforviewmode', DOL_URL_ROOT.'/product/list.php?mode=kanban'.preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ($mode == 'kanban' ? 2 : 1), array('morecss' => 'reposition'));
146 $newcardbutton .= dolGetButtonTitle($langs->trans('Statistics'), '', 'fa fa-chart-bar imgforviewmode', DOL_URL_ROOT.'/product/stats/index.php?id=all'.preg_replace('/(&|\?)*(mode|groupby)=[^&]+/', '', $param), '', 2, array('morecss' => 'reposition'));
147
148 $perm = false;
149 if ($type === "") {
150 $perm = ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'));
151 } elseif ($type == Product::TYPE_SERVICE) {
152 $perm = $user->hasRight('service', 'creer');
153 } elseif ($type == Product::TYPE_PRODUCT) {
154 $perm = $user->hasRight('produit', 'creer');
155 }
156 $params = array();
157 if ($type === "") {
158 $params['forcenohideoftext'] = 1;
159 }
160 $newcardbutton .= dolGetButtonTitleSeparator();
161 if ((isModEnabled('product') && $type === "") || $type == Product::TYPE_PRODUCT) {
162 $label = 'NewProduct';
163 $newcardbutton .= dolGetButtonTitle($langs->trans($label), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/product/card.php?action=create&type=0', '', (int) $perm, $params);
164 }
165 if ((isModEnabled('service') && $type === "") || $type == Product::TYPE_SERVICE) {
166 $label = 'NewService';
167 $newcardbutton .= dolGetButtonTitle($langs->trans($label), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/product/card.php?action=create&type=1', '', (int) $perm, $params);
168 }
169
170 print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, $picto, 0, $newcardbutton, '', $limit, 0, 0, 1);
171} else {
172 $result = $object->fetch($id, $ref);
173
174 $title = $langs->trans('ProductServiceCard');
175 $helpurl = '';
176 $shortlabel = dol_trunc($object->label, 16);
177 if (GETPOST("type") == '0' || ($object->type == Product::TYPE_PRODUCT)) {
178 $title = $langs->trans('Product')." ".$shortlabel." - ".$langs->trans('Statistics');
179 $helpurl = 'EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
180 }
181 if (GETPOST("type") == '1' || ($object->type == Product::TYPE_SERVICE)) {
182 $title = $langs->trans('Service')." ".$shortlabel." - ".$langs->trans('Statistics');
183 $helpurl = 'EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
184 }
185
186 //HERE
187 llxHeader('', $title, $helpurl, '', 0, 0, '', '', '', 'mod-product page-stats_card_by_product');
188}
189
190
191if ($result && ($id > 0 || !empty($ref)) && empty($notab)) {
192 $head = product_prepare_head($object);
193 $titre = $langs->trans("CardProduct".$object->type);
194 $picto = ($object->type == Product::TYPE_SERVICE ? 'service' : 'product');
195
196 print dol_get_fiche_head($head, 'stats', $titre, -1, $picto);
197
198 $linkback = '<a href="'.DOL_URL_ROOT.'/product/list.php?restore_lastsearch_values=1&type='.$object->type.'">'.$langs->trans("BackToList").'</a>';
199 $object->next_prev_filter = "(te.fk_product_type:=:".((int) $object->type).")";
200
201 dol_banner_tab($object, 'ref', $linkback, ($user->socid ? 0 : 1), 'ref', '', '', '', 0, '', '', 1);
202
203 print dol_get_fiche_end();
204}
205if ((!($id > 0) && empty($ref)) || $notab) {
206 $h = 0;
207 $head = array();
208
209 $head[$h][0] = DOL_URL_ROOT.'/product/stats/index.php'.($type != '' ? '?type='.((int) $type) : '');
210 $head[$h][1] = $langs->trans("Chart");
211 $head[$h][2] = 'chart';
212 $h++;
213
214 $title = $langs->trans("ListProductServiceByPopularity");
215 if ((string) $type == '0') {
216 $title = $langs->trans("ListProductByPopularity");
217 }
218 if ((string) $type == '1') {
219 $title = $langs->trans("ListServiceByPopularity");
220 }
221
222
223 $head[$h][0] = DOL_URL_ROOT.'/product/stats/popuprop.php'.($type != '' ? '?type='.((int) $type) : '');
224 $head[$h][1] = $langs->trans("ProductsServicesPerPopularity");
225 if ((string) $type == '0') {
226 $head[$h][1] = $langs->trans("ProductsPerPopularity");
227 }
228 if ((string) $type == '1') {
229 $head[$h][1] = $langs->trans("ServicesPerPopularity");
230 }
231 $head[$h][2] = 'popularity';
232 $h++;
233
234 print dol_get_fiche_head($head, 'chart', '', -1);
235}
236
237
238if ($result || !($id > 0)) {
239 print '<form name="stats" method="POST" action="'.dolBuildUrl($_SERVER["PHP_SELF"]).'">';
240 print '<input type="hidden" name="token" value="'.newToken().'">';
241 print '<input type="hidden" name="page_y" value="">';
242 if (empty($id) || $notab) {
243 print '<input type="hidden" name="notab" value="1">';
244 }
245
246 print '<table class="noborder centpercent">';
247 print '<tr class="liste_titre"><td class="liste_titre">'.$langs->trans("Filter").'</td><td></td></tr>';
248
249 if (!($id > 0) || $notab) {
250 // Type
251 print '<tr class="nooddeven"><td class="titlefield">'.$langs->trans("Type").'</td><td>';
252 $array = array('-1' => '&nbsp;', '0' => $langs->trans('Product'), '1' => $langs->trans('Service'));
253 print $form->selectarray('type', $array, $type, 0, 0, 0, '', 0, 0, 0, '', 'minwidth100');
254 print '</td></tr>';
255
256 // Product
257 print '<tr class="nooddeven"><td class="titlefield">'.$langs->trans("ProductOrService").'</td><td>';
258 print img_picto('', 'product', 'class="pictofixedwidth"');
259 print $form->select_produits($id, 'id', '', 0, 0, 1, 2, '', 0, array(), 0, $langs->trans("RefOrLabel"), 0, 'widthcentpercentminusx maxwidth400');
260 print '</td></tr>';
261
262 // Tag
263 if (isModEnabled('category')) {
264 print '<tr class="nooddeven"><td class="titlefield">'.$langs->trans("Categories").'</td><td>';
265 $moreforfilter .= img_picto($langs->trans("Categories"), 'category', 'class="pictofixedwidth"');
266 $moreforfilter .= $htmlother->select_categories(Categorie::TYPE_PRODUCT, $search_categ, 'search_categ', 1, 1, 'widthcentpercentminusx maxwidth400');
267 print $moreforfilter;
268 print '</td></tr>';
269 }
270 } else {
271 print '<input type="hidden" name="id" value="'.$id.'">';
272 }
273 print '<input type="hidden" name="mode" value="'.$mode.'">';
274
275 // Year
276 print '<tr class="nooddeven"><td class="titlefield">'.$langs->trans("Year").'</td><td>';
277 $arrayyears = array();
278 $year = $currentyear - 25;
279 while ($year < $currentyear) {
280 $arrayyears[$year] = (string) $year;
281 $year++;
282 }
283 if (!in_array($year, $arrayyears)) {
284 $arrayyears[$year] = (string) $year;
285 }
286 if (!in_array($currentyear, $arrayyears)) {
287 $arrayyears[$currentyear] = (string) $currentyear;
288 }
289 arsort($arrayyears);
290 print img_picto('', 'calendar', 'class="pictofixedwidth"');
291 print $form->selectarray('search_year', $arrayyears, $search_year, 1, 0, 0, '', 0, 0, 0, '', 'width75');
292 print '</td></tr>';
293
294 // Thirdparty
295 print '<tr class="nooddeven"><td class="titlefield">'.$langs->trans("ThirdParty").'</td><td>';
296 print img_picto('', 'company', 'class="pictofixedwidth"');
297 print $form->select_company($socid, 'socid', '', 1, 0, 0, array(), 0, 'widthcentpercentminusx maxwidth400');
298 print '</td></tr>';
299
300 print '</table>';
301 print '<div class="center"><input type="submit" name="submit" class="button small reposition" value="'.$langs->trans("Refresh").'"></div>';
302 print '</form><br>';
303
304 print '<br>';
305
306
307 $param = '';
308 $param .= (GETPOSTISSET('id') ? '&id='.GETPOSTINT('id') : '&id='.$object->id).(($type != '' && $type != '-1') ? '&type='.((int) $type) : '').'&search_year='.((int) $search_year).($notab ? '&notab='.$notab : '');
309 if ($socid > 0) {
310 $param .= '&socid='.((int) $socid);
311 }
312 if (!empty($search_categ)) {
313 $param .= '&search_categ='.((int) $search_categ);
314 }
315
316 // Choice of stats mode (byunit or bynumber)
317
318 if (!empty($conf->dol_use_jmobile)) {
319 print "\n".'<div class="fichecenter"><div class="nowrap">'."\n";
320 }
321
322 if ($mode != 'byunit') {
323 print '<a class="a-mesure-disabled marginrightonly reposition" href="'.$_SERVER["PHP_SELF"].'?mode=byunit'.$param.'">';
324 } else {
325 print '<span class="a-mesure marginrightonly">';
326 }
327 if ($type == '0') {
328 print $langs->trans("StatsByNumberOfUnitsProducts");
329 } elseif ($type == '1') {
330 print $langs->trans("StatsByNumberOfUnitsServices");
331 } else {
332 print $langs->trans("StatsByNumberOfUnits");
333 }
334 if ($mode != 'byunit') {
335 print '</a>';
336 } else {
337 print '</span>';
338 }
339
340 if (!empty($conf->dol_use_jmobile)) {
341 print '</div>'."\n".'<div class="nowrap">'."\n";
342 }
343
344 if ($mode != 'bynumber') {
345 print '<a class="a-mesure-disabled marginleftonly marginrightonly reposition" href="'.$_SERVER["PHP_SELF"].'?mode=bynumber'.$param.'">';
346 } else {
347 print '<span class="a-mesure marginleftonly marginrightonly">';
348 }
349 print $langs->trans("StatsByNumberOfEntities");
350 if ($mode != 'bynumber') {
351 print '</a>';
352 } else {
353 print '</span>';
354 }
355
356 if (!empty($conf->dol_use_jmobile)) {
357 print '</div>'."\n".'<div class="nowrap">'."\n";
358 }
359
360 if ($mode != 'byamount') {
361 print '<a class="a-mesure-disabled marginleftonly marginrightonly reposition" href="'.$_SERVER["PHP_SELF"].'?mode=byamount'.$param.'">';
362 } else {
363 print '<span class="a-mesure marginleftonly marginrightonly">';
364 }
365 if ($type == '0') {
366 print $langs->trans("StatsByAmountProducts");
367 } elseif ($type == '1') {
368 print $langs->trans("StatsByAmountServices");
369 } else {
370 print $langs->trans("StatsByAmount");
371 }
372 if ($mode != 'byamount') {
373 print '</a>';
374 } else {
375 print '</span>';
376 }
377
378 // End of choices
379 if (!empty($conf->dol_use_jmobile)) {
380 print '</div></div>';
381 } else {
382 print '<br>';
383 }
384 print '<br>';
385
386 // Generation of graphs
387 $dir = (!empty($conf->product->multidir_temp[$conf->entity]) ? $conf->product->multidir_temp[$conf->entity] : $conf->service->multidir_temp[$conf->entity]);
388 if ($object->id > 0) { // We are on statistics for a dedicated product
389 if (!file_exists($dir.'/'.$object->id)) {
390 if (dol_mkdir($dir.'/'.$object->id) < 0) {
391 $mesg = $langs->trans("ErrorCanNotCreateDir", $dir);
392 $error++;
393 }
394 }
395 }
396
397 $arrayforlabel = array('byunit' => 'NumberOfUnits', 'bynumber' => 'NumberOf', 'byamount' => 'AmountIn');
398
399 if (isModEnabled('propal')) {
400 $langs->load("propal");
401 $graphfiles['propal'] = array('modulepart' => 'productstats_proposals',
402 'file' => $object->id.'/propal12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year > 0 ? '_year'.$search_year : '').'.png',
403 'label' => $langs->transnoentitiesnoconv($arrayforlabel[$mode], $langs->transnoentitiesnoconv("Proposals")));
404 }
405
406 if (isModEnabled('supplier_proposal')) {
407 $langs->load("supplier_proposal");
408 $graphfiles['proposalssuppliers'] = array('modulepart' => 'productstats_proposalssuppliers',
409 'file' => $object->id.'/proposalssuppliers12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year > 0 ? '_year'.$search_year : '').'.png',
410 'label' => $langs->transnoentitiesnoconv($arrayforlabel[$mode], $langs->transnoentitiesnoconv("SupplierProposals")));
411 }
412
413 if (isModEnabled('order')) {
414 $langs->load("orders");
415 $graphfiles['orders'] = array('modulepart' => 'productstats_orders',
416 'file' => $object->id.'/orders12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year > 0 ? '_year'.$search_year : '').'.png',
417 'label' => $langs->transnoentitiesnoconv($arrayforlabel[$mode], $langs->transnoentitiesnoconv("Orders")));
418 }
419
420 if (isModEnabled('supplier_order')) {
421 $langs->load("orders");
422 $graphfiles['orderssuppliers'] = array('modulepart' => 'productstats_orderssuppliers',
423 'file' => $object->id.'/orderssuppliers12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year > 0 ? '_year'.$search_year : '').'.png',
424 'label' => $langs->transnoentitiesnoconv($arrayforlabel[$mode], $langs->transnoentitiesnoconv("SuppliersOrders")));
425 }
426
427 if (isModEnabled('invoice')) {
428 $graphfiles['invoices'] = array('modulepart' => 'productstats_invoices',
429 'file' => $object->id.'/invoices12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year > 0 ? '_year'.$search_year : '').'.png',
430 'label' => $langs->transnoentitiesnoconv($arrayforlabel[$mode], $langs->transnoentitiesnoconv("Invoices")));
431 }
432
433 if (isModEnabled('supplier_invoice')) {
434 $graphfiles['invoicessuppliers'] = array('modulepart' => 'productstats_invoicessuppliers',
435 'file' => $object->id.'/invoicessuppliers12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year > 0 ? '_year'.$search_year : '').'.png',
436 'label' => $langs->transnoentitiesnoconv($arrayforlabel[$mode], $langs->transnoentitiesnoconv("SupplierInvoices")));
437 }
438
439 if (isModEnabled('contract')) {
440 $graphfiles['contracts'] = array('modulepart' => 'productstats_contracts',
441 'file' => $object->id.'/contracts12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year > 0 ? '_year'.$search_year : '').'.png',
442 'label' => $langs->transnoentitiesnoconv($arrayforlabel[$mode], $langs->transnoentitiesnoconv("Contracts")));
443 }
444
445 if (isModEnabled('mrp') && $mode != 'byamount') {
446 $graphfiles['mrp'] = array('modulepart' => 'productstats_mrp',
447 'file' => $object->id.'/mos12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year > 0 ? '_year'.$search_year : '').'.png',
448 'label' => $langs->transnoentitiesnoconv($arrayforlabel[$mode]."Mos"));
449 }
450
451 $px = new DolGraph();
452
453 if (!$error && count($graphfiles) > 0) {
454 $mesg = $px->isGraphKo();
455 if (!$mesg) {
456 foreach ($graphfiles as $key => $val) {
457 if (!$val['file']) { // @phpstan-ignore-line booleanNot.alwaysFalse
458 continue;
459 }
460
461 $graph_data = array();
462
463 if (dol_is_file($dir.'/'.$val['file'])) {
464 // TODO Load cachefile $graphfiles[$key]['file']
465 } else {
466 $morefilters = '';
467 if ($search_categ > 0) {
468 $categ = new Categorie($db);
469 $categ->fetch($search_categ);
470 $listofprodids = $categ->getObjectsInCateg('product', 1);
471 $morefilters = ' AND d.fk_product IN ('.$db->sanitize((is_array($listofprodids) && count($listofprodids)) ? implode(',', $listofprodids) : '0').')';
472 }
473 if ($search_categ == -2) {
474 $morefilters = ' AND NOT EXISTS (SELECT cp.fk_product FROM '.MAIN_DB_PREFIX.'categorie_product as cp WHERE d.fk_product = cp.fk_product)';
475 }
476
477 if ($key == 'propal') {
478 $graph_data = $object->get_nb_propal($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
479 }
480 if ($key == 'orders') {
481 $graph_data = $object->get_nb_order($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
482 }
483 if ($key == 'invoices') {
484 $graph_data = $object->get_nb_vente($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
485 }
486 if ($key == 'proposalssuppliers') {
487 $graph_data = $object->get_nb_propalsupplier($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
488 }
489 if ($key == 'invoicessuppliers') {
490 $graph_data = $object->get_nb_achat($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
491 }
492 if ($key == 'orderssuppliers') {
493 $graph_data = $object->get_nb_ordersupplier($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
494 }
495 if ($key == 'contracts') {
496 $graph_data = $object->get_nb_contract($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
497 }
498 if ($key == 'mrp') {
499 $graph_data = $object->get_nb_mos($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
500 }
501
502 // TODO Save cachefile $graphfiles[$key]['file']
503 }
504
505 if (is_array($graph_data)) {
506 $px->SetData($graph_data);
507 $px->SetYLabel($graphfiles[$key]['label']);
508 $px->SetMaxValue($px->GetCeilMaxValue() < 0 ? 0 : $px->GetCeilMaxValue());
509 $px->SetMinValue($px->GetFloorMinValue() > 0 ? 0 : $px->GetFloorMinValue());
510 $px->setShowLegend(0);
511 $px->SetWidth($WIDTH);
512 $px->SetHeight($HEIGHT);
513 $px->SetHorizTickIncrement(1);
514 $px->SetShading(3);
515 //print 'x '.$key.' '.$graphfiles[$key]['file'];
516
517 $url = DOL_URL_ROOT.'/viewimage.php?modulepart='.$val['modulepart'].'&entity='.((int) $object->entity).'&file='.urlencode($val['file']).($notab ? '&notab='.$notab : '');
518 $px->draw($dir."/".$val['file'], $url);
519
520 $graphfiles[$key]['total'] = $px->total();
521 $graphfiles[$key]['output'] = $px->show();
522 } else {
523 dol_print_error($db, 'Error for calculating graph on key='.$key.' - '.$object->error);
524 }
525 }
526
527 //setEventMessages($langs->trans("ChartGenerated"), null, 'mesgs');
528 }
529 }
530
531 // Show graphs
532 $i = 0;
533 if (count($graphfiles) > 0) {
534 foreach ($graphfiles as $key => $val) {
535 if (!$graphfiles[$key]['file']) { // @phpstan-ignore-line booleanNot.alwaysFalse
536 continue;
537 }
538
539 if ($key == 'propal' && !$user->hasRight('propal', 'lire')) {
540 continue;
541 }
542 if ($key == 'orders' && !$user->hasRight('commande', 'lire')) {
543 continue;
544 }
545 if ($key == 'invoices' && !$user->hasRight('facture', 'lire')) {
546 continue;
547 }
548 if ($key == 'proposalssuppliers' && !$user->hasRight('supplier_proposal', 'lire')) {
549 continue;
550 }
551 if ($key == 'invoicessuppliers' && !$user->hasRight('fournisseur', 'facture', 'lire')) {
552 continue;
553 }
554 if ($key == 'orderssuppliers' && !$user->hasRight('fournisseur', 'commande', 'lire')) {
555 continue;
556 }
557 if ($key == 'mrp' && !$user->hasRight('mrp', 'read')) {
558 continue;
559 }
560
561
562 if (($i % 2) == 0) {
563 print "\n".'<div class="fichecenter"><div class="fichehalfleft">'."\n";
564 } else {
565 print "\n".'<div class="fichehalfright">'."\n";
566 }
567
568 // Date generation
569 if ($graphfiles[$key]['output'] && !$px->isGraphKo()) {
570 if (file_exists($dir."/".$graphfiles[$key]['file']) && filemtime($dir."/".$graphfiles[$key]['file'])) {
571 $dategenerated = $langs->trans("GeneratedOn", dol_print_date(filemtime($dir."/".$graphfiles[$key]['file']), "dayhour"));
572 } else {
573 $dategenerated = $langs->trans("GeneratedOn", dol_print_date(dol_now(), "dayhour"));
574 }
575 } else {
576 $dategenerated = ($mesg ? '<span class="error">'.$mesg.'</span>' : $langs->trans("ChartNotGenerated"));
577 }
578 $linktoregenerate = '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?'.(GETPOSTISSET('id') ? 'id='.GETPOSTINT('id') : 'id='.$object->id).(((string) $type != '' && $type != '-1') ? '&type='.((int) $type) : '').'&action=recalcul&mode='.urlencode($mode).'&search_year='.((int) $search_year).($search_categ > 0 ? '&search_categ='.((int) $search_categ) : '').'">';
579 $linktoregenerate .= img_picto($langs->trans("ReCalculate").' ('.$dategenerated.')', 'refresh');
580 $linktoregenerate .= '</a>';
581
582
583 // Show graph
584 print '<div class="div-table-responsive-no-min">';
585 print '<table class="noborder centpercent">';
586 // Label
587 print '<tr class="liste_titre"><td>';
588 print $graphfiles[$key]['label'];
589 print ' <span class="opacitymedium">('.$graphfiles[$key]['total'].')</span></td>';
590 print '<td align="right">'.$linktoregenerate.'</td>';
591 print '</tr>';
592 // Image
593 print '<tr><td colspan="2" class="nohover" align="center">';
594 print $graphfiles[$key]['output'];
595 print '</td></tr>';
596 print '</table>';
597 print '</div>';
598
599 if ($i % 2 == 0) {
600 print "\n".'</div>'."\n";
601 } else {
602 print "\n".'</div></div>';
603 print '<div class="clear"><div class="fichecenter"><br></div></div>'."\n";
604 }
605
606 $i++;
607 }
608 }
609 // div not closed
610 if ($i % 2 == 1) {
611 print "\n".'<div class="fichehalfright">'."\n";
612 print "\n".'</div></div>';
613 print '<div class="clear"><div class="fichecenter"><br></div></div>'."\n";
614 }
615}
616
617if (!($id > 0)) {
618 print dol_get_fiche_end();
619}
620
621// End of page
622llxFooter();
623$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
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 manage categories.
Class to build graphs.
static getDefaultGraphSizeForStats($direction, $defaultsize='')
getDefaultGraphSizeForStats
Class to manage generation of HTML components Only common components must be here.
Class to help generate other html components Only common components are here.
Class to manage products or services.
const TYPE_PRODUCT
Regular product.
const TYPE_SERVICE
Service.
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_is_file($pathoffile)
Return if path is a file.
dol_now($mode='gmt')
Return date for now.
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)
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, $morecssdiv='')
Show tabs of a record.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
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).
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
isModEnabled($module)
Is Dolibarr module enabled.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
buildzip.php
product_prepare_head($object)
Prepare array with list of tabs.
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.