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