dolibarr 23.0.3
index.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2001-2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2020 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005-2017 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2011-2012 Juanjo Menent <jmenent@2byte.es>
6 * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
7 * Copyright (C) 2021-2025 Frédéric France <frederic.france@free.fr>
8 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
9 * Copyright (C) 2024-2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
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
31define('CSRFCHECK_WITH_TOKEN', 1); // We force need to use a token to login when making a POST
32
33require 'main.inc.php';
43require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
44
45// If not defined, we select menu "home"
46$_GET['mainmenu'] = GETPOST('mainmenu', 'aZ09') ? GETPOST('mainmenu', 'aZ09') : 'home'; // Keep this ?
47$action = GETPOST('action', 'aZ09');
48
49$hookmanager->initHooks(array('index'));
50
51require_once DOL_DOCUMENT_ROOT.'/core/redirect_if_setup_not_complete.inc.php';
52
53
54/*
55 * Actions
56 */
57
58if (GETPOST('addbox')) { // Add box (when submit is done from a form when ajax disabled)
59 require_once DOL_DOCUMENT_ROOT.'/core/class/infobox.class.php';
60 $zone = GETPOSTINT('areacode');
61 $userid = GETPOSTINT('userid');
62 $boxorder = GETPOST('boxorder', 'aZ09');
63 $boxorder .= GETPOST('boxcombo', 'aZ09');
64
65 $result = InfoBox::saveboxorder($db, $zone, $boxorder, $userid);
66 if ($result > 0) {
67 setEventMessages($langs->trans("BoxAdded"), null);
68 }
69}
70
71
72/*
73 * View
74 */
75
76if (!isset($form) || !is_object($form)) {
77 $form = new Form($db);
78}
79
80$appli = constant('DOL_APPLICATION_TITLE');
81$applicustom = getDolGlobalString('MAIN_APPLICATION_TITLE');
82if ($applicustom) {
83 $appli = (preg_match('/^\+/', $applicustom) ? $appli : '').$applicustom;
84} else {
85 $appli .= " ".DOL_VERSION;
86}
87
88// Title
89$title = $langs->trans("HomeArea").' - '.$appli;
90
91llxHeader('', $title);
92
93
94$resultboxes = FormOther::getBoxesArea($user, "0"); // Load $resultboxes (selectboxlist + boxactivated + boxlista + boxlistb)
95
96
97if (getDolGlobalString('MAIN_MOTD')) {
98 $conf->global->MAIN_MOTD = preg_replace('/<br(\s[\sa-zA-Z_="]*)?\/?>/i', '<br>', getDolGlobalString('MAIN_MOTD'));
99
100 $substitutionarray = getCommonSubstitutionArray($langs);
101 complete_substitutions_array($substitutionarray, $langs);
102 $texttoshow = make_substitutions(getDolGlobalString('MAIN_MOTD'), $substitutionarray, $langs);
103
104 print "\n<!-- Start of welcome text -->\n";
105 print '<table class="centpercent notopnoleftnoright"><tr><td>';
106 print dol_htmlentitiesbr($texttoshow);
107 print '</td></tr></table><br>';
108 print "\n<!-- End of welcome text -->\n";
109}
110
111/*
112 * Show specific warnings
113 */
114
115// Specific warning to propose to upgrade invoice situation to progressive mode
116/*
117if (getDolGlobalInt('INVOICE_USE_SITUATION') == 1) {
118 $langs->loadLangs(array("admin"));
119 print info_admin($langs->trans("WarningExperimentalFeatureInvoiceSituationNeedToUpgradeToProgressiveMode", 'https://partners.dolibarr.org'));
120 //print "<br>";
121}
122*/
123
124/*
125 * Show security warnings
126 */
127
128// Security warning if install.lock file is missing or if conf file is writable
129if (!getDolGlobalString('MAIN_REMOVE_INSTALL_WARNING')) {
130 $message = '';
131
132 // Check if install lock file is present
133 $lockfile = DOL_DATA_ROOT.'/install.lock';
134 if (!empty($lockfile) && !file_exists($lockfile) && is_dir(DOL_DOCUMENT_ROOT."/install")) {
135 $langs->load("errors");
136 //if (!empty($message)) $message.='<br>';
137 $message .= info_admin($langs->transnoentities("WarningLockFileDoesNotExists", DOL_DATA_ROOT).' '.$langs->transnoentities("WarningUntilDirRemoved", DOL_DOCUMENT_ROOT."/install"), 0, 0, '1', 'clearboth');
138 }
139
140 // Conf files must be in read only mode
141 if (is_writable($conffile)) {
142 // Try to remove automatically write permission
143 $currentPerm = fileperms($conffile);
144 $newPerm = $currentPerm & ~0222;
145 //print $conffile.' '.decoct($currentPerm).' '.(string) decoct($newPerm).' '.substr(decoct($newPerm), -4);
146 dolChmod($conffile, decoct($newPerm));
147
148 // @phpstan-ignore-next-line
149 if (is_writable($conffile)) {
150 $langs->load("errors");
151 $message .= info_admin($langs->transnoentities("WarningConfFileMustBeReadOnly").' '.$langs->transnoentities("WarningUntilDirRemoved", DOL_DOCUMENT_ROOT."/install"), 0, 0, '1', 'clearboth');
152 }
153 }
154
155 $object = new stdClass();
156 $parameters = array();
157 $reshook = $hookmanager->executeHooks('infoadmin', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
158 if ($reshook == 0) {
159 $message .= $hookmanager->resPrint;
160 }
161 if ($message) { // $message is an HTML string.
162 print '<!-- show security warning -->';
163 print dol_string_onlythesehtmltags($message, 1, 0, 0, 0, array('div', 'span', 'b'));
164 //print '<br>';
165 //print info_admin($langs->trans("WarningUntilDirRemoved",DOL_DOCUMENT_ROOT."/install"));
166 }
167}
168
169/*
170 * Dashboard Dolibarr statistics
171 * Hidden for external users
172 */
173
174print load_fiche_titre('&nbsp;', $resultboxes['selectboxlist'], '', 0, '', 'titleforhome');
175
176// Load translation files required by page
177$langs->loadLangs(array('commercial', 'bills', 'orders', 'contracts'));
178
179// Dolibarr Working Board with weather
180if (!getDolGlobalString('MAIN_DISABLE_GLOBAL_WORKBOARD') && getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER') < 2) {
181 $showweather = (!getDolGlobalString('MAIN_DISABLE_METEO') || getDolGlobalInt('MAIN_DISABLE_METEO') == 2) ? 1 : 0;
182
183 // Array that contains all WorkboardResponse classes to process them
184 $dashboardlines = array();
185
186 // Do not include sections without management permission
187 require_once DOL_DOCUMENT_ROOT.'/core/class/workboardresponse.class.php';
188
189 // Number of actions to do (late)
190 if (isModEnabled('agenda') && !getDolGlobalString('MAIN_DISABLE_BLOCK_AGENDA') && $user->hasRight('agenda', 'myactions', 'read')) {
191 include_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
192 $board = new ActionComm($db);
193 $dashboardlines[$board->element] = $board->load_board($user);
194 }
195
196 // Number of project opened
197 if (isModEnabled('project') && !getDolGlobalString('MAIN_DISABLE_BLOCK_PROJECT') && $user->hasRight('projet', 'lire')) {
198 include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
199 $board = new Project($db);
200 $dashboardlines[$board->element] = $board->load_board($user);
201 }
202
203 // Number of tasks to do (late)
204 if (isModEnabled('project') && !getDolGlobalString('MAIN_DISABLE_BLOCK_PROJECT') && !getDolGlobalString('PROJECT_HIDE_TASKS') && $user->hasRight('projet', 'lire')) {
205 include_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
206 $board = new Task($db);
207 $dashboardlines[$board->element] = $board->load_board($user);
208 }
209
210 // Number of commercial customer proposals open (expired)
211 if (isModEnabled('propal') && !getDolGlobalString('MAIN_DISABLE_BLOCK_CUSTOMER') && $user->hasRight('propal', 'read')) {
212 include_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
213 $board = new Propal($db);
214 $dashboardlines[$board->element.'_opened'] = $board->load_board($user, "opened");
215 // Number of commercial proposals CLOSED signed (billed)
216 $dashboardlines[$board->element.'_signed'] = $board->load_board($user, "signed");
217 }
218
219 // Number of supplier proposals open (expired)
220 if (isModEnabled('supplier_proposal') && !getDolGlobalString('MAIN_DISABLE_BLOCK_SUPPLIER') && $user->hasRight('supplier_proposal', 'lire')) {
221 $langs->load("supplier_proposal");
222 include_once DOL_DOCUMENT_ROOT.'/supplier_proposal/class/supplier_proposal.class.php';
223 $board = new SupplierProposal($db);
224 $dashboardlines[$board->element.'_opened'] = $board->load_board($user, "opened");
225 // Number of commercial proposals CLOSED signed (billed)
226 $dashboardlines[$board->element.'_signed'] = $board->load_board($user, "signed");
227 }
228
229 // Number of sales orders
230 if (isModEnabled('order') && !getDolGlobalString('MAIN_DISABLE_BLOCK_CUSTOMER') && $user->hasRight('commande', 'lire')) {
231 include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
232 $board = new Commande($db);
233 // Number of customer orders to be shipped (validated and in progress)
234 $dashboardlines[$board->element.'_toship'] = $board->load_board($user, 'toship');
235 // Number of customer orders to be billed (not visible by default, does not match a lot of organization).
236 if (getDolGlobalInt('ORDER_BILL_AFTER_VALIDATION')) {
237 $dashboardlines[$board->element.'_tobill'] = $board->load_board($user, 'tobill');
238 }
239 // Number of customer orders to be billed (delivered but not billed)
240 $dashboardlines[$board->element.'_shippedtobill'] = $board->load_board($user, 'shippedtobill');
241 }
242
243 // Number of suppliers orders
244 if (isModEnabled('supplier_order') && !getDolGlobalString('MAIN_DISABLE_BLOCK_SUPPLIER') && $user->hasRight('fournisseur', 'commande', 'lire')) {
245 include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
246 $board = new CommandeFournisseur($db);
247 $dashboardlines[$board->element.'_opened'] = $board->load_board($user, "opened");
248 $dashboardlines[$board->element.'_awaiting'] = $board->load_board($user, 'awaiting');
249 }
250
251 // Number of contract / services enabled (delayed)
252 if (isModEnabled('contract') && !getDolGlobalString('MAIN_DISABLE_BLOCK_CONTRACT') && $user->hasRight('contrat', 'lire')) {
253 include_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
254 $board = new Contrat($db);
255 $dashboardlines[$board->element.'_inactive'] = $board->load_board($user, "inactive");
256 // Number of active services (expired)
257 $dashboardlines[$board->element.'_active'] = $board->load_board($user, "active");
258 }
259
260 // Number of tickets open
261 if (isModEnabled('ticket') && !getDolGlobalString('MAIN_DISABLE_BLOCK_TICKET') && $user->hasRight('ticket', 'read')) {
262 include_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php';
263 $board = new Ticket($db);
264 $dashboardlines[$board->element.'_opened'] = $board->load_board($user, "opened");
265 // Number of active services (expired)
266 //$dashboardlines[$board->element.'_active'] = $board->load_board($user, "active");
267 }
268
269 // Number of invoices customers (paid)
270 if (isModEnabled('invoice') && !getDolGlobalString('MAIN_DISABLE_BLOCK_CUSTOMER') && $user->hasRight('facture', 'lire')) {
271 include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
272 $board = new Facture($db);
273 $dashboardlines[$board->element] = $board->load_board($user);
274 }
275
276 // Number of supplier invoices (paid)
277 if (isModEnabled('supplier_invoice') && !getDolGlobalString('MAIN_DISABLE_BLOCK_SUPPLIER') && $user->hasRight('fournisseur', 'facture', 'lire')) {
278 include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
279 $board = new FactureFournisseur($db);
280 $dashboardlines[$board->element] = $board->load_board($user);
281 }
282
283 // Number of transactions to conciliate
284 if (isModEnabled('bank') && !getDolGlobalString('MAIN_DISABLE_BLOCK_BANK') && $user->hasRight('banque', 'lire') && !$user->socid) {
285 include_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
286 $board = new Account($db);
287 $nb = $board->countAccountToReconcile(); // Get nb of account to reconciliate
288 if ($nb > 0) {
289 $dashboardlines[$board->element] = $board->load_board($user);
290 }
291 }
292
293
294 // Number of cheque to send
295 if (isModEnabled('bank') && !getDolGlobalString('MAIN_DISABLE_BLOCK_BANK') && $user->hasRight('banque', 'lire') && !$user->socid) {
296 if (!getDolGlobalString('BANK_DISABLE_CHECK_DEPOSIT')) {
297 include_once DOL_DOCUMENT_ROOT . '/compta/paiement/cheque/class/remisecheque.class.php';
298 $board = new RemiseCheque($db);
299 $dashboardlines[$board->element] = $board->load_board($user);
300 }
301 if (isModEnabled('prelevement')) {
302 include_once DOL_DOCUMENT_ROOT.'/compta/prelevement/class/bonprelevement.class.php';
303 $board = new BonPrelevement($db);
304 $dashboardlines[$board->element . '_direct_debit'] = $board->load_board($user, 'direct_debit');
305 }
306 if (isModEnabled('paymentbybanktransfer')) {
307 include_once DOL_DOCUMENT_ROOT.'/compta/prelevement/class/bonprelevement.class.php';
308 $board = new BonPrelevement($db);
309 $dashboardlines[$board->element . '_credit_transfer'] = $board->load_board($user, 'credit_transfer');
310 }
311 }
312
313 // Number of foundation members
314 if (isModEnabled('member') && !getDolGlobalString('MAIN_DISABLE_BLOCK_ADHERENT') && $user->hasRight('adherent', 'lire') && !$user->socid) {
315 include_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
316 $board = new Adherent($db);
317 $dashboardlines[$board->element.'_shift'] = $board->load_board($user, 'shift');
318 $dashboardlines[$board->element.'_expired'] = $board->load_board($user, 'expired');
319 }
320
321 // Number of expense reports to approve
322 if (isModEnabled('expensereport') && !getDolGlobalString('MAIN_DISABLE_BLOCK_EXPENSEREPORT') && $user->hasRight('expensereport', 'approve')) {
323 include_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
324 $board = new ExpenseReport($db);
325 $dashboardlines[$board->element.'_toapprove'] = $board->load_board($user, 'toapprove');
326 }
327
328 // Number of expense reports to pay
329 if (isModEnabled('expensereport') && !getDolGlobalString('MAIN_DISABLE_BLOCK_EXPENSEREPORT') && $user->hasRight('expensereport', 'to_paid')) {
330 include_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
331 $board = new ExpenseReport($db);
332 $dashboardlines[$board->element.'_topay'] = $board->load_board($user, 'topay');
333 }
334
335 // Number of holidays to approve
336 if (isModEnabled('holiday') && !getDolGlobalString('MAIN_DISABLE_BLOCK_HOLIDAY') && $user->hasRight('holiday', 'approve')) {
337 include_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php';
338 $board = new Holiday($db);
339 $dashboardlines[$board->element] = $board->load_board($user);
340 }
341
342 if (isModEnabled('mrp') && !getDolGlobalString('MAIN_DISABLE_BLOCK_MRP')) {
343 include_once DOL_DOCUMENT_ROOT.'/mrp/class/mo.class.php';
344 $board = new Mo($db);
345 $dashboardlines[$board->element] = $board->load_board($user);
346 }
347
348 $object = new stdClass();
349 $parameters = array();
350 $action = '';
351 $reshook = $hookmanager->executeHooks(
352 'addOpenElementsDashboardLine',
353 $parameters,
354 $object,
355 $action
356 ); // Note that $action and $object may have been modified by some hooks
357 if ($reshook == 0) {
358 $dashboardlines = array_merge($dashboardlines, $hookmanager->resArray);
359 }
360 /* Open object dashboard */
361 $dashboardgroup = array(
362 'action' =>
363 array(
364 'groupName' => 'Agenda',
365 'stats' => array('action'),
366 ),
367 'project' =>
368 array(
369 'groupName' => 'Projects',
370 'globalStatsKey' => 'projects',
371 'stats' => array('project', 'project_task'),
372 ),
373 'propal' =>
374 array(
375 'groupName' => 'Proposals',
376 'globalStatsKey' => 'proposals',
377 'stats' =>
378 array('propal_opened', 'propal_signed'),
379 ),
380 'commande' =>
381 array(
382 'groupName' => 'Orders',
383 'globalStatsKey' => 'orders',
384 'stats' =>
385 array('commande_toship', 'commande_tobill', 'commande_shippedtobill'),
386 ),
387 'facture' =>
388 array(
389 'groupName' => 'Invoices',
390 'globalStatsKey' => 'invoices',
391 'stats' =>
392 array('facture'),
393 ),
394 'supplier_proposal' =>
395 array(
396 'lang' => 'supplier_proposal',
397 'groupName' => 'SupplierProposals',
398 'globalStatsKey' => 'askprice',
399 'stats' =>
400 array('supplier_proposal_opened', 'supplier_proposal_signed'),
401 ),
402 'order_supplier' =>
403 array(
404 'groupName' => 'SuppliersOrders',
405 'globalStatsKey' => 'supplier_orders',
406 'stats' =>
407 array('order_supplier_opened', 'order_supplier_awaiting'),
408 ),
409 'invoice_supplier' =>
410 array(
411 'groupName' => 'BillsSuppliers',
412 'globalStatsKey' => 'supplier_invoices',
413 'stats' =>
414 array('invoice_supplier'),
415 ),
416 'contrat' =>
417 array(
418 'groupName' => 'Contracts',
419 'globalStatsKey' => 'Contracts',
420 'stats' =>
421 array('contrat_inactive', 'contrat_active'),
422 ),
423 'ticket' =>
424 array(
425 'groupName' => 'Tickets',
426 'globalStatsKey' => 'ticket',
427 'stats' =>
428 array('ticket_opened'),
429 ),
430 'bank_account' =>
431 array(
432 'groupName' => 'BankAccount',
433 'stats' =>
434 array('bank_account', 'chequereceipt', 'widthdraw_direct_debit', 'widthdraw_credit_transfer'),
435 ),
436 'member' =>
437 array(
438 'groupName' => 'Members',
439 'globalStatsKey' => 'members',
440 'stats' =>
441 array('member_shift', 'member_expired'),
442 ),
443 'expensereport' =>
444 array(
445 'groupName' => 'ExpenseReport',
446 'globalStatsKey' => 'expensereports',
447 'stats' =>
448 array('expensereport_toapprove', 'expensereport_topay'),
449 ),
450 'holiday' =>
451 array(
452 'groupName' => 'Holidays',
453 'globalStatsKey' => 'holidays',
454 'stats' =>
455 array('holiday'),
456 ),
457 'cubes' =>
458 array(
459 'groupName' => 'Mo',
460 'globalStatsKey' => 'mrp',
461 'stats' =>
462 array('mo'),
463 ),
464 );
465 $object = new stdClass();
466 $parameters = array(
467 'dashboardgroup' => $dashboardgroup
468 );
469 $reshook = $hookmanager->executeHooks('addOpenElementsDashboardGroup', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
470 if ($reshook == 0) {
471 $dashboardgroup = array_merge($dashboardgroup, $hookmanager->resArray);
472 }
473
474
475 // Calculate total nb of late
476 $totallate = $totaltodo = 0;
477
478 //Remove any invalid response
479 //load_board can return an integer if failed, or WorkboardResponse if OK
480 $valid_dashboardlines = array();
481 foreach ($dashboardlines as $workboardid => $tmp) {
482 if ($tmp instanceof WorkboardResponse) {
483 $tmp->id = $workboardid; // Complete the object to add its id into its name
484 $valid_dashboardlines[$workboardid] = $tmp;
485 }
486 }
487 // We calculate $totallate. Must be defined before start of next loop because it is show in first fetch on next loop
488 foreach ($valid_dashboardlines as $board) {
489 if (is_numeric($board->nbtodo) && is_numeric($board->nbtodolate) && $board->nbtodolate > 0) {
490 $totaltodo += $board->nbtodo;
491 $totallate += $board->nbtodolate;
492 }
493 }
494
495 $openedDashBoardSize = 'info-box-sm'; // use sm by default
496 foreach ($dashboardgroup as $dashbordelement) {
497 if (is_array($dashbordelement['stats']) && count($dashbordelement['stats']) > 2) {
498 $openedDashBoardSize = ''; // use default info box size : big
499 break;
500 }
501 }
502
503 $totalLateNumber = $totallate;
504 $totallatePercentage = ((!empty($totaltodo)) ? round($totallate / $totaltodo * 100, 2) : 0);
505 if (getDolGlobalString('MAIN_USE_METEO_WITH_PERCENTAGE')) {
506 $totallate = $totallatePercentage;
507 }
508
509 // Fill the content to show the tasks to do as a widget box (old version). Now this is no more used. Tasks to do ar in dedicated thumbs.
510 $boxwork = '';
511 $boxwork .= '<div class="box">';
512 $boxwork .= '<table summary="'.dol_escape_htmltag($langs->trans("WorkingBoard")).'" class="noborder boxtable boxtablenobottom boxworkingboard centpercent">'."\n";
513 $boxwork .= '<tr class="liste_titre">';
514 $boxwork .= '<th class="liste_titre"><div class="inline-block valignmiddle">'.$langs->trans("DolibarrWorkBoard").'</div>';
515 if ($showweather) {
516 if ($totallate > 0) {
517 $text = $langs->transnoentitiesnoconv("WarningYouHaveAtLeastOneTaskLate").' ('.$langs->transnoentitiesnoconv(
518 "NActionsLate",
519 $totallate.(getDolGlobalString('MAIN_USE_METEO_WITH_PERCENTAGE') ? '%' : '')
520 ).')';
521 } else {
522 $text = $langs->transnoentitiesnoconv("NoItemLate");
523 }
524 $text .= '. '.$langs->transnoentitiesnoconv("LateDesc");
525 //$text.=$form->textwithpicto('',$langs->trans("LateDesc"));
526 $options = 'height="24px" style="float: right"';
527 $boxwork .= showWeather($totallate, $text, $options, 'inline-block valignmiddle');
528 }
529 $boxwork .= '</th>';
530 $boxwork .= '</tr>'."\n";
531
532 // Show dashboard
533 $nbworkboardempty = 0;
534 $isIntopOpenedDashBoard = $globalStatInTopOpenedDashBoard = array();
535 $openedDashBoard = '';
536 if (!empty($valid_dashboardlines)) {
537 $boxwork .= '<tr class="nobottom nohover"><td class="tdboxstats nohover flexcontainer centpercent"><div style="display: flex: flex-wrap: wrap">';
538 foreach ($dashboardgroup as $groupKey => $groupElement) {
539 $boards = array();
540
541 // Scan $groupElement and save the one with 'stats' that must be used for the open objects dashboard
542 if (!getDolGlobalString('MAIN_DISABLE_NEW_OPENED_DASH_BOARD')) {
543 foreach ($groupElement['stats'] as $infoKey) {
544 if (!empty($valid_dashboardlines[$infoKey])) {
545 $boards[] = $valid_dashboardlines[$infoKey];
546 $isIntopOpenedDashBoard[] = $infoKey;
547 }
548 }
549 }
550
551
552 if (!empty($boards)) {
553 if (!empty($groupElement['lang'])) {
554 $langs->load($groupElement['lang']);
555 }
556 // @phan-suppress-next-line PhanTypePossiblyInvalidDimOffset
557 $groupName = $langs->trans($groupElement['groupName']);
558 $groupKeyLowerCase = strtolower($groupKey);
559
560 // global stats
561 $globalStatsKey = false;
562 if (!empty($groupElement['globalStatsKey']) && empty($groupElement['globalStats'])) { // can be filled by hook
563 $globalStatsKey = $groupElement['globalStatsKey'];
564 $groupElement['globalStats'] = array();
565 }
566
567 // Links
568 $arrayLinks = array(
569 'action' => dol_buildpath('/comm/action/card.php?action=create', 1),
570 'project' => dol_buildpath('/projet/card.php?action=create', 1),
571 'propal' => dol_buildpath('/comm/propal/card.php?action=create', 1),
572 'commande' => dol_buildpath('/commande/card.php?action=create', 1),
573 'facture' => dol_buildpath('/compta/facture/card.php?action=create', 1),
574 'supplier_proposal' => dol_buildpath('/supplier_proposal/card.php?action=create', 1),
575 'order_supplier' => dol_buildpath('/fourn/commande/card.php?action=create', 1),
576 'invoice_supplier' => dol_buildpath('/fourn/facture/card.php?action=create', 1),
577 'contrat' => dol_buildpath('/contrat/card.php?action=create', 1),
578 'ticket' => dol_buildpath('/ticket/card.php?action=create', 1),
579 'bank_account' => dol_buildpath('/compta/bank/card.php?action=create', 1),
580 'member' => dol_buildpath('/adherents/card.php?action=create', 1),
581 'expensereport' => dol_buildpath('/expensereport/card.php?action=create', 1),
582 'holiday' => dol_buildpath('/holiday/card.php?action=create', 1),
583 'cubes' => dol_buildpath('/mrp/mo_card.php?action=create', 1),
584
585 );
586 $infoboxMoreCss = '';
587 if (array_key_exists($groupKey, $arrayLinks)) {
588 $infoboxMoreCss = 'infobox-haslink';
589 }
590
591 $openedDashBoard .= '<div class="box-flex-item"><div class="box-flex-item-with-margin">'."\n";
592 $openedDashBoard .= ' <div class="info-box '.$openedDashBoardSize.' '.$infoboxMoreCss.'">'."\n";
593 $openedDashBoard .= ' <span class="info-box-icon bg-infobox-'.$groupKeyLowerCase.'">'."\n";
594 $openedDashBoard .= ' <i class="fa fa-dol-'.$groupKeyLowerCase.'"></i>'."\n";
595
596 // Show the span for the total of record. TODO This seems not used.
597 if (!empty($groupElement['globalStats'])) {
598 $globalStatInTopOpenedDashBoard[] = $globalStatsKey;
599 $openedDashBoard .= '<span class="info-box-icon-text" title="'.$groupElement['globalStats']['text'].'">'.$groupElement['globalStats']['nbTotal'].'</span>';
600 }
601
602 if (array_key_exists($groupKey, $arrayLinks)) {
603 $openedDashBoard .= ' <a href="'.$arrayLinks[$groupKey].'" class="info-box-createlink"><span class="fas fa-plus-circle"></span></a>'."\n";
604 }
605
606 $openedDashBoard .= '</span>'."\n";
607 $openedDashBoard .= '<div class="info-box-content">'."\n";
608
609 $openedDashBoard .= '<div class="info-box-title" title="'.dolPrintHTMLForAttribute($groupName).'">'.$groupName.'</div>'."\n";
610 $openedDashBoard .= '<div class="info-box-lines">'."\n";
611
612 foreach ($boards as $board) {
613 $openedDashBoard .= '<div class="info-box-line spanoverflow nowrap">';
614
615 if (!empty($board->labelShort)) {
616 $infoName = '<div class="marginrightonly inline-block valignmiddle info-box-line-text" title="'.$board->label.'">'.$board->labelShort.'</div>';
617 } else {
618 $infoName = '<div class="marginrightonly inline-block valignmiddle info-box-line-text">'.$board->label.'</div>';
619 }
620
621 $textLateTitle = $langs->trans("NActionsLate", $board->nbtodolate);
622
623 $dateOrder = '';
624 if ($board->id == 'mo') {
625 $dateOrder = $langs->trans("DateToday") . " > " . $langs->trans("DateReference");
626 } else {
627 $dateOrder = $langs->trans("DateReference") . " > " . $langs->trans("DateToday");
628 }
629 $warningDelay = ceil(empty($board->warning_delay) ? 0 : $board->warning_delay);
630 $sign = '';
631 if ($warningDelay >= 0) {
632 $sign = '+';
633 }
634
635 $textLateTitle .= " (" . $langs->trans("Late") . " = $dateOrder $sign$warningDelay " . $langs->trans("days") . ")";
636
637 if ($board->id == 'bank_account') {
638 $textLateTitle .= '<br><span class="opacitymedium">'.$langs->trans("IfYouDontReconcileDisableProperty", $langs->transnoentitiesnoconv("Conciliable")).'</span>';
639 }
640
641 $textLate = '';
642 if ($board->nbtodolate > 0) {
643 $textLate .= '<span title="'.dol_escape_htmltag($textLateTitle).'" class="classfortooltip badge badge-warning">';
644 $textLate .= '<i class="fa fa-exclamation-triangle hideonsmartphone"></i> '.$board->nbtodolate;
645 $textLate .= '</span>';
646 }
647
648 $nbtodClass = '';
649 if ($board->nbtodo > 0) {
650 $nbtodClass = 'badge badge-info';
651 } else {
652 $nbtodClass = 'opacitymedium';
653 }
654
655 // Forge the line to show into the open object box
656 $labeltoshow = $board->label.' ('.$board->nbtodo.')';
657 if ($board->total > 0) {
658 $labeltoshow .= ' - '.price($board->total, 0, $langs, 1, -1, -1, getDolCurrency());
659 }
660 $openedDashBoard .= '<a href="'.$board->url.'" class="info-box-text info-box-text-a">';
661 $openedDashBoard .= $infoName;
662 $openedDashBoard .= '</a>';
663 $openedDashBoard .= '<div class="inline-block nowraponall">';
664 $openedDashBoard .= '<a href="'.$board->url.'" class="info-box-text info-box-text-a">';
665 $openedDashBoard .= '<span class="classfortooltip'.($nbtodClass ? ' '.$nbtodClass : '').'" title="'.$labeltoshow.'">';
666 $openedDashBoard .= $board->nbtodo;
667 if ($board->total > 0 && getDolGlobalString('MAIN_WORKBOARD_SHOW_TOTAL_WO_TAX')) {
668 $openedDashBoard .= ' : '.price($board->total, 0, $langs, 1, -1, -1, getDolCurrency());
669 }
670 $openedDashBoard .= '</span>';
671 $openedDashBoard .= '</a>';
672
673 if ($textLate) {
674 if ($board->url_late) {
675 $openedDashBoard .= '</div>';
676 $openedDashBoard .= ' <div class="inline-block"><a href="'.$board->url_late.'" class="info-box-text info-box-text-a paddingleft">';
677 } else {
678 $openedDashBoard .= ' <span class="info-box-text info-box-text-a displaycontents">';
679 }
680 $openedDashBoard .= $textLate;
681 if ($board->url_late) {
682 $openedDashBoard .= '</a>';
683 } else {
684 $openedDashBoard .= '</span>';
685 }
686 }
687 $openedDashBoard .= '</div>'."\n";
688 //$openedDashBoard .= '</div>';
689 $openedDashBoard .= '</div>'."\n"; // info-box-line
690 }
691
692 // TODO Add hook here to add more "info-box-line"
693
694 $openedDashBoard .= ' </div><!-- /.info-box-lines --></div><!-- /.info-box-content -->'."\n";
695 $openedDashBoard .= ' </div><!-- /.info-box -->'."\n";
696 $openedDashBoard .= '</div><!-- /.box-flex-item-with-margin -->'."\n";
697 $openedDashBoard .= '</div><!-- /.box-flex-item -->'."\n";
698 $openedDashBoard .= "\n";
699 }
700 }
701
702 if ($showweather && !empty($isIntopOpenedDashBoard)) {
703 $appendClass = (getDolGlobalInt('MAIN_DISABLE_METEO') == 2 ? ' hideonsmartphone' : '');
704 $weather = getWeatherStatus($totallate);
705
706 $text = '';
707 if ($totallate > 0) {
708 $text = $langs->transnoentitiesnoconv("WarningYouHaveAtLeastOneTaskLate").' ('.$langs->transnoentitiesnoconv(
709 "NActionsLate",
710 $totallate.(getDolGlobalString('MAIN_USE_METEO_WITH_PERCENTAGE') ? '%' : '')
711 ).')';
712 } else {
713 $text = $langs->transnoentitiesnoconv("NoItemLate");
714 }
715 $text .= '. '.$langs->transnoentitiesnoconv("LateDesc");
716
717 $weatherDashBoard = '<div class="box-flex-item '.$appendClass.'"><div class="box-flex-item-with-margin">'."\n";
718 $weatherDashBoard .= ' <div class="info-box '.$openedDashBoardSize.' info-box-weather info-box-weather-level'.$weather->level.'">'."\n";
719 $weatherDashBoard .= ' <span class="info-box-icon">';
720 $weatherDashBoard .= img_weather('', $weather->level, '', 0, 'valignmiddle width50');
721 $weatherDashBoard .= ' </span>'."\n";
722 $weatherDashBoard .= ' <div class="info-box-content">'."\n";
723 $weatherDashBoard .= ' <div class="info-box-title">'.$langs->trans('GlobalOpenedElemView').'</div>'."\n";
724
725 if ($totallatePercentage > 0 && getDolGlobalString('MAIN_USE_METEO_WITH_PERCENTAGE')) {
726 $weatherDashBoard .= ' <span class="info-box-number">'.$langs->transnoentitiesnoconv(
727 "NActionsLate",
728 price($totallatePercentage).'%'
729 ).'</span>'."\n";
730 $weatherDashBoard .= ' <span class="progress-description">'.$langs->trans(
731 'NActionsLate',
732 $totalLateNumber
733 ).'</span>'."\n";
734 } else {
735 $weatherDashBoard .= ' <span class="info-box-number">'.$langs->transnoentitiesnoconv(
736 "NActionsLate",
737 (string) $totalLateNumber
738 ).'</span>'."\n";
739 if ($totallatePercentage > 0) {
740 $weatherDashBoard .= ' <span class="progress-description">'.$langs->trans(
741 'NActionsLate',
742 price($totallatePercentage).'%'
743 ).'</span>'."\n";
744 }
745 }
746
747 $weatherDashBoard .= ' </div><!-- /.info-box-content -->'."\n";
748 $weatherDashBoard .= ' </div><!-- /.info-box -->'."\n";
749 $weatherDashBoard .= '</div><!-- /.box-flex-item-with-margin -->'."\n";
750 $weatherDashBoard .= '</div><!-- /.box-flex-item -->'."\n";
751 $weatherDashBoard .= "\n";
752
753 $openedDashBoard = $weatherDashBoard.$openedDashBoard;
754 }
755
756 if (!empty($isIntopOpenedDashBoard)) {
757 for ($i = 1; $i <= 10; $i++) {
758 $openedDashBoard .= '<div class="box-flex-item filler"></div>';
759 }
760 }
761
762 $nbworkboardcount = 0;
763 foreach ($valid_dashboardlines as $infoKey => $board) {
764 if (in_array($infoKey, $isIntopOpenedDashBoard)) {
765 // skip if info is present on top
766 continue;
767 }
768
769 if (empty($board->nbtodo)) {
770 $nbworkboardempty++;
771 }
772 $nbworkboardcount++;
773
774
775 $textlate = $langs->trans("NActionsLate", $board->nbtodolate);
776 $textlate .= ' ('.$langs->trans("Late").' = '.$langs->trans("DateReference").' > '.$langs->trans("DateToday").' '.(ceil($board->warning_delay) >= 0 ? '+' : '').ceil($board->warning_delay).' '.$langs->trans("days").')';
777
778
779 $boxwork .= '<div class="boxstatsindicator thumbstat150 nobold nounderline"><div class="boxstats130 boxstatsborder">';
780 $boxwork .= '<div class="boxstatscontent">';
781 $boxwork .= '<span class="boxstatstext" title="'.dol_escape_htmltag($board->label).'">'.$board->img.' <span>'.$board->label.'</span></span><br>';
782 $boxwork .= '<a class="valignmiddle dashboardlineindicator" href="'.$board->url.'"><span class="dashboardlineindicator'.(($board->nbtodo == 0) ? ' dashboardlineok' : '').'">'.$board->nbtodo.'</span></a>';
783 if ($board->total > 0 && getDolGlobalString('MAIN_WORKBOARD_SHOW_TOTAL_WO_TAX')) {
784 $boxwork .= '&nbsp;/&nbsp;<a class="valignmiddle dashboardlineindicator" href="'.$board->url.'"><span class="dashboardlineindicator'.(($board->nbtodo == 0) ? ' dashboardlineok' : '').'">'.price($board->total).'</span></a>';
785 }
786 $boxwork .= '</div>';
787 if ($board->nbtodolate > 0) {
788 $boxwork .= '<div class="dashboardlinelatecoin nowrap">';
789 $boxwork .= '<a title="'.dol_escape_htmltag($textlate).'" class="valignmiddle dashboardlineindicatorlate'.($board->nbtodolate > 0 ? ' dashboardlineko' : ' dashboardlineok').'" href="'.((!$board->url_late) ? $board->url : $board->url_late).'">';
790 //$boxwork .= img_picto($textlate, "warning_white", 'class="valigntextbottom"');
791 $boxwork .= img_picto(
792 $textlate,
793 "warning_white",
794 'class="inline-block hideonsmartphone valigntextbottom"'
795 );
796 $boxwork .= '<span class="dashboardlineindicatorlate'.($board->nbtodolate > 0 ? ' dashboardlineko' : ' dashboardlineok').'">';
797 $boxwork .= $board->nbtodolate;
798 $boxwork .= '</span>';
799 $boxwork .= '</a>';
800 $boxwork .= '</div>';
801 }
802 $boxwork .= '</div></div>';
803 $boxwork .= "\n";
804 }
805
806 $boxwork .= '<div class="boxstatsindicator thumbstat150 nobold nounderline"><div class="boxstats150empty"></div></div>';
807 $boxwork .= '<div class="boxstatsindicator thumbstat150 nobold nounderline"><div class="boxstats150empty"></div></div>';
808 $boxwork .= '<div class="boxstatsindicator thumbstat150 nobold nounderline"><div class="boxstats150empty"></div></div>';
809 $boxwork .= '<div class="boxstatsindicator thumbstat150 nobold nounderline"><div class="boxstats150empty"></div></div>';
810
811 $boxwork .= '</div>';
812 $boxwork .= '</td></tr>';
813 } else {
814 $boxwork .= '<tr class="nohover">';
815 $boxwork .= '<td class="nohover valignmiddle opacitymedium">';
816 $boxwork .= $langs->trans("NoOpenedElementToProcess");
817 $boxwork .= '</td>';
818 $boxwork .= '</tr>';
819 }
820
821 $boxwork .= '</td></tr>';
822
823 $boxwork .= '</table>'; // End table array of working board
824 $boxwork .= '</div>';
825
826 if (!empty($isIntopOpenedDashBoard)) {
827 print '<div class="fichecenter">';
828 print '<div class="opened-dash-board-wrap"><div class="box-flex-container">'.$openedDashBoard.'</div></div>';
829 print '</div>';
830 }
831}
832
833
834print '<div class="clearboth"></div>';
835
836print '<div class="fichecenter fichecenterbis">';
837
838
839/*
840 * Show widgets (boxes)
841 */
842
843$boxlist = '<div class="twocolumns">';
844
845$boxlist .= '<div class="firstcolumn fichehalfleft boxhalfleft" id="boxhalfleft">';
846if (!empty($nbworkboardcount)) {
847 $boxlist .= $boxwork;
848}
849
850$boxlist .= $resultboxes['boxlista'];
851
852$boxlist .= '</div>';
853
854$boxlist .= '<div class="secondcolumn fichehalfright boxhalfright" id="boxhalfright">';
855
856$boxlist .= $resultboxes['boxlistb'];
857
858$boxlist .= '</div>';
859$boxlist .= "\n";
860
861$boxlist .= '</div>';
862
863
864print $boxlist;
865
866print '</div>';
867
868//print 'mem='.memory_get_usage().' - '.memory_get_peak_usage();
869
870// End of page
871llxFooter();
872$db->close();
873
874
885function showWeather($totallate, $text, $options, $morecss = '')
886{
887 global $conf;
888
889 $weather = getWeatherStatus($totallate);
890 return img_weather($text, $weather->picto, $options, 0, $morecss);
891}
892
893
900function getWeatherStatus($totallate)
901{
902 $weather = new stdClass();
903 $weather->picto = '';
904
905 $offset = 0;
906 $factor = 10; // By default
907
908 $used_conf = (getDolGlobalString('MAIN_USE_METEO_WITH_PERCENTAGE') ? 'MAIN_METEO_PERCENTAGE_LEVEL' : 'MAIN_METEO_LEVEL');
909
910 $weather->level = 0;
911 $level0 = $offset;
912 $level0 = getDolGlobalString($used_conf.'0', $level0);
913 $level1 = $offset + $factor;
914 $level1 = getDolGlobalString($used_conf.'1', $level1);
915 $level2 = $offset + 2 * $factor;
916 $level2 = getDolGlobalString($used_conf.'2', $level2);
917 $level3 = $offset + 3 * $factor;
918 $level3 = getDolGlobalString($used_conf.'3', $level3);
919
920 if ($totallate <= $level0) {
921 $weather->picto = 'weather-clear.png';
922 $weather->level = 0;
923 } elseif ($totallate <= $level1) {
924 $weather->picto = 'weather-few-clouds.png';
925 $weather->level = 1;
926 } elseif ($totallate <= $level2) {
927 $weather->picto = 'weather-clouds.png';
928 $weather->level = 2;
929 } elseif ($totallate <= $level3) {
930 $weather->picto = 'weather-many-clouds.png';
931 $weather->level = 3;
932 } else {
933 $weather->picto = 'weather-storm.png';
934 $weather->level = 4;
935 }
936
937 return $weather;
938}
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 bank accounts.
Class to manage agenda events (actions)
Class to manage members of a foundation.
Class to manage withdrawal receipts.
Class to manage predefined suppliers products.
Class to manage customers orders.
Class to manage Trips and Expenses.
Class to manage suppliers invoices.
Class to manage invoices.
Class to manage generation of HTML components Only common components must be here.
static getBoxesArea($user, $areacode)
Get array with HTML tabs with widgets/boxes of a particular area including personalized choices of us...
Class of the module paid holiday.
static saveboxorder($dbs, $zone, $boxorder, $userid=0)
Save order of boxes for area and user.
Class for Mo.
Definition mo.class.php:35
Class to manage projects.
Class to manage proposals.
Class to manage cheque delivery receipts.
Class to manage price ask supplier.
Class to manage tasks.
$conffile
img_weather($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $morecss='')
Show weather picto.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
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.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dolChmod($filepath, $newmask='')
Change mod of a file.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
getDolCurrency()
Return the main currency ('EUR', 'USD', ...)
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
dol_string_onlythesehtmltags($stringtoclean, $cleanalsosomestyles=1, $removeclassattribute=1, $cleanalsojavascript=0, $allowiframe=0, $allowed_tags=array(), $allowlink=0, $allowscript=0, $allowstyle=0, $allowphp=0)
Clean a string to keep only desirable HTML tags.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='')
Show information in HTML for admin users or standard users.
showWeather($totallate, $text, $options, $morecss='')
Show weather logo.
Definition index.php:885
getWeatherStatus($totallate)
get weather status for conf 'MAIN_METEO_LEVELx'
Definition index.php:900
Class to generate the form for creating a new ticket.