dolibarr 23.0.4
element.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-2010 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2012-2016 Juanjo Menent <jmenent@2byte.es>
6 * Copyright (C) 2015-2021 Alexandre Spangaro <aspangaro@open-dsi.fr>
7 * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
8 * Copyright (C) 2016 Josep Lluís Amador <joseplluis@lliuretic.cat>
9 * Copyright (C) 2021-2023 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
10 * Copyright (C) 2021 Noé Cendrier <noe.cendrier@altairis.fr>
11 * Copyright (C) 2023-2025 Frédéric France <frederic.france@free.fr>
12 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
13 * Copyright (C) 2025 Günter Lukas <github@gl.co.at>
14 * Copyright (C) 2026 Joachim Kueter <git-jk@bloxera.com>
15 * Copyright (C) 2026 Ferran Marcet <fmarcet@2byte.es>
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 3 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program. If not, see <https://www.gnu.org/licenses/>.
29 */
30
37// Load Dolibarr environment
38require '../main.inc.php';
48require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
49require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
50require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
51require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
52require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
53require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
54require_once DOL_DOCUMENT_ROOT.'/core/class/timespent.class.php';
55
56if (isModEnabled('agenda')) {
57 require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
58}
59if (isModEnabled('bank')) {
60 require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/paymentvarious.class.php';
61}
62if (isModEnabled('category')) {
63 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
64}
65if (isModEnabled('order')) {
66 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
67}
68if (isModEnabled('contract')) {
69 require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
70}
71if (isModEnabled('deplacement')) {
72 require_once DOL_DOCUMENT_ROOT.'/compta/deplacement/class/deplacement.class.php';
73}
74if (isModEnabled('don')) {
75 require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php';
76}
77if (isModEnabled('shipping')) {
78 require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
79}
80if (isModEnabled('expensereport')) {
81 require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
82}
83if (isModEnabled('invoice')) {
84 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
85 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture-rec.class.php';
86}
87if (isModEnabled('intervention')) {
88 require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
89}
90if (isModEnabled('loan')) {
91 require_once DOL_DOCUMENT_ROOT.'/loan/class/loan.class.php';
92 require_once DOL_DOCUMENT_ROOT.'/loan/class/loanschedule.class.php';
93}
94if (isModEnabled('mrp')) {
95 require_once DOL_DOCUMENT_ROOT.'/mrp/class/mo.class.php';
96}
97if (isModEnabled('propal')) {
98 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
99}
100if (isModEnabled('salaries')) {
101 require_once DOL_DOCUMENT_ROOT.'/salaries/class/salary.class.php';
102}
103if (isModEnabled('stock')) {
104 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
105 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
106}
107if (isModEnabled('supplier_invoice')) {
108 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
109}
110if (isModEnabled('supplier_order')) {
111 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
112}
113if (isModEnabled('supplier_proposal')) {
114 require_once DOL_DOCUMENT_ROOT.'/supplier_proposal/class/supplier_proposal.class.php';
115}
116if (isModEnabled('tax')) {
117 require_once DOL_DOCUMENT_ROOT.'/compta/sociales/class/chargesociales.class.php';
118}
119if (isModEnabled('stocktransfer')) {
120 require_once DOL_DOCUMENT_ROOT.'/product/stock/stocktransfer/class/stocktransfer.class.php';
121 require_once DOL_DOCUMENT_ROOT.'/product/stock/stocktransfer/class/stocktransferline.class.php';
122}
123
124// Load translation files required by the page
125$langs->loadLangs(array('projects', 'companies', 'suppliers', 'compta'));
126if (isModEnabled('invoice')) {
127 $langs->load("bills");
128}
129if (isModEnabled('order')) {
130 $langs->load("orders");
131}
132if (isModEnabled("propal")) {
133 $langs->load("propal");
134}
135if (isModEnabled('intervention')) {
136 $langs->load("interventions");
137}
138if (isModEnabled('deplacement')) {
139 $langs->load("trips");
140}
141if (isModEnabled('expensereport')) {
142 $langs->load("trips");
143}
144if (isModEnabled('don')) {
145 $langs->load("donations");
146}
147if (isModEnabled('loan')) {
148 $langs->load("loan");
149}
150if (isModEnabled('salaries')) {
151 $langs->load("salaries");
152}
153if (isModEnabled('mrp')) {
154 $langs->load("mrp");
155}
156if (isModEnabled('eventorganization')) {
157 $langs->load("eventorganization");
158}
159
160$id = GETPOSTINT('id');
161$ref = GETPOST('ref', 'alpha');
162$action = GETPOST('action', 'aZ09');
163$datesrfc = GETPOST('datesrfc'); // deprecated
164$dateerfc = GETPOST('dateerfc'); // deprecated
165$dates = dol_mktime(0, 0, 0, GETPOSTINT('datesmonth'), GETPOSTINT('datesday'), GETPOSTINT('datesyear'));
166$datee = dol_mktime(23, 59, 59, GETPOSTINT('dateemonth'), GETPOSTINT('dateeday'), GETPOSTINT('dateeyear'));
167if (empty($dates) && !empty($datesrfc)) { // deprecated
168 $dates = dol_stringtotime($datesrfc);
169}
170if (empty($datee) && !empty($dateerfc)) { // deprecated
171 $datee = dol_stringtotime($dateerfc);
172}
173if (!GETPOSTISSET('datesrfc') && !GETPOSTISSET('datesday') && getDolGlobalString('PROJECT_LINKED_ELEMENT_DEFAULT_FILTER_YEAR')) {
174 $new = dol_now();
175 $tmp = dol_getdate($new);
176 //$datee=$now
177 //$dates=dol_time_plus_duree($datee, -1, 'y');
178 $dates = dol_get_first_day($tmp['year'], 1);
179}
180if ($id == '' && $ref == '') {
181 setEventMessage($langs->trans('ErrorBadParameters'), 'errors');
182 header('Location: list.php');
183 exit();
184}
185
186$mine = GETPOST('mode') == 'mine' ? 1 : 0;
187
188$object = new Project($db);
189
190include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be 'include', not 'include_once'
191if (getDolGlobalString('PROJECT_ALLOW_COMMENT_ON_PROJECT') && method_exists($object, 'fetchComments') && empty($object->comments)) {
192 $object->fetchComments();
193}
194
195// Security check
196$socid = $object->socid;
197
198$hookmanager->initHooks(array('projectOverview'));
199
200//if ($user->socid > 0) $socid = $user->socid; // For external user, no check is done on company because readability is managed by public status of project and assignment.
201$result = restrictedArea($user, 'projet', $object->id, 'projet&project');
202
203// Check if user has access to any financial module (not just project time)
204$canSeeFinancials = (
205 (isModEnabled('invoice') && $user->hasRight('facture', 'lire'))
206 || (isModEnabled('supplier_invoice') && ($user->hasRight('fournisseur', 'facture', 'lire') || $user->hasRight('supplier_invoice', 'lire')))
207 || (isModEnabled('salaries') && $user->hasRight('salaries', 'read'))
208 || (isModEnabled('expensereport') && $user->hasRight('expensereport', 'lire'))
209 || (isModEnabled('don') && $user->hasRight('don', 'lire'))
210 || (isModEnabled('tax') && $user->hasRight('tax', 'charges', 'lire'))
211 || (isModEnabled('bank') && $user->hasRight('banque', 'lire'))
212);
213
214$total_duration = 0;
215$total_ttc_by_line = 0;
216$total_ht_by_line = 0;
217$expensereport = null;
218$othermessage = '';
219$tmpprojtime = array();
220$nbAttendees = 0;
221
222$permissiontoadd = $user->hasRight('projet', 'creer');
223$permissiontodelete = $user->hasRight('projet', 'supprimer');
224$permissiondellink = $user->hasRight('projet', 'creer'); // Used by the include of actions_dellink.inc.php
225$permissiontoeditextra = $permissiontoadd;
226if (GETPOST('attribute', 'aZ09') && isset($extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')])) {
227 // For action 'update_extras', is there a specific permission set for the attribute to update
228 $permissiontoeditextra = dol_eval($extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')]);
229}
230
231/*
232 * Actions
233 */
234
235// Quick edit for extrafields
236if ($action == 'update_extras' && $permissiontoeditextra) {
237 $error = 0;
238 $object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
239
240 $attribute_name = GETPOST('attribute', 'aZ09');
241
242 // Fill array 'array_options' with data from update form
243 $ret = $extrafields->setOptionalsFromPost(null, $object, $attribute_name);
244 if ($ret < 0) {
245 $error++;
246 }
247
248 if (!$error) {
249 $result = $object->updateExtraField($attribute_name, 'PROJECT_MODIFY');
250 if ($result < 0) {
251 setEventMessages($object->error, $object->errors, 'errors');
252 $error++;
253 }
254 }
255
256 if ($error) {
257 $action = 'edit_extras';
258 }
259}
260if (($action == 'updateundefinedwithlasthourlyrate' || $action == 'updateallwithlasthourlyrate') && $permissiontoadd) {
261 $error = 0;
262 if (!GETPOSTISSET('taskid')) {
263 $error++;
264 }
265 if (!$error) {
266 $taskid = GETPOSTINT("taskid");
267
268 $sql = "SELECT et.rowid as id, u.thm as thmuser";
269 $sql .= " FROM ".MAIN_DB_PREFIX."element_time as et";
270 $sql .= " INNER JOIN ".MAIN_DB_PREFIX."user as u ON u.rowid = et.fk_user";
271 $sql .= " WHERE et.elementtype = 'task'";
272 $sql .= " AND et.fk_element = ".((int) $taskid);
273 if ($action == 'updateundefinedwithlasthourlyrate') { // Test on permission already done
274 $sql .= " AND et.thm IS NULL"; // Note: If 0, it is defined, we won't update it.
275 }
276
277 $resql = $db->query($sql);
278 if ($resql) {
279 $num = $db->num_rows($resql);
280 $i = 0;
281 while ($i < $num) {
282 $obj = $db->fetch_object($resql);
283 if (empty($obj->thmuser)) {
284 $error++;
285 break;
286 }
287 $timespent = new TimeSpent($db);
288 $res = $timespent->fetch($obj->id);
289 if ($res <= 0) {
290 setEventMessages($timespent->error, $timespent->errors, 'errors');
291 $error++;
292 break;
293 }
294 $timespent->thm = $obj->thmuser;
295 $res = $timespent->update($user);
296 if ($res <= 0) {
297 setEventMessages($timespent->error, $timespent->errors, 'errors');
298 $error++;
299 break;
300 }
301 $i++;
302 }
303 } else {
304 dol_print_error($db);
305 $error++;
306 }
307 }
308 if (!$error) {
309 $db->commit();
310 setEventMessages($langs->trans("TaskHourlyRateUpdated"), null);
311 $action = '';
312 } else {
313 $db->rollback();
314 }
315}
316
317
318/*
319 * View
320 */
321
322$title = $langs->trans('ProjectReferers').' - '.$object->ref.' '.$object->name;
323if (getDolGlobalString('MAIN_HTML_TITLE') && preg_match('/projectnameonly/', getDolGlobalString('MAIN_HTML_TITLE')) && $object->name) {
324 $title = $object->ref.' '.$object->name.' - '.$langs->trans('ProjectReferers');
325}
326
327$help_url = 'EN:Module_Projects|FR:Module_Projets|ES:M&oacute;dulo_Proyectos|DE:Modul_Projekte';
328
329llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-project page-card_element');
330
331$form = new Form($db);
332$formproject = new FormProjets($db);
333$formfile = new FormFile($db);
334
335$userstatic = new User($db);
336
337// To verify role of users
338$userAccess = $object->restrictedProjectArea($user);
339
340$head = project_prepare_head($object);
341print dol_get_fiche_head($head, 'element', $langs->trans("Project"), -1, ($object->public ? 'projectpub' : 'project'));
342
343
344// Project card
345
346if (!empty($_SESSION['pageforbacktolist']) && !empty($_SESSION['pageforbacktolist']['project'])) {
347 $tmpurl = $_SESSION['pageforbacktolist']['project'];
348 $tmpurl = preg_replace('/__SOCID__/', (string) $object->socid, $tmpurl);
349 $linkback = '<a href="'.$tmpurl.(preg_match('/\?/', $tmpurl) ? '&' : '?'). 'restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
350} else {
351 $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
352}
353
354$morehtmlref = '<div class="refidno">';
355// Title
356$morehtmlref .= $object->title;
357// Thirdparty
358if (!empty($object->thirdparty->id) && $object->thirdparty->id > 0) {
359 $morehtmlref .= '<br>'.$object->thirdparty->getNomUrl(1, 'project');
360}
361$morehtmlref .= '</div>';
362
363// Define a complementary filter for search of next/prev ref.
364if (!$user->hasRight('projet', 'all', 'lire')) {
365 $objectsListId = $object->getProjectsAuthorizedForUser($user, 0, 0);
366 $object->next_prev_filter = "te.rowid:IN:".$db->sanitize(count($objectsListId) ? implode(',', array_keys($objectsListId)) : '0');
367}
368
369dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
370
371
372print '<div class="fichecenter">';
373print '<div class="fichehalfleft">';
374print '<div class="underbanner clearboth"></div>';
375
376print '<table class="border tableforfield centpercent">';
377
378// Usage
379if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES') || !getDolGlobalString('PROJECT_HIDE_TASKS') || isModEnabled('eventorganization')) {
380 print '<tr><td class="tdtop">';
381 print $langs->trans("Usage");
382 print '</td>';
383 print '<td>';
384 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
385 print '<input type="checkbox" disabled name="usage_opportunity"'.(GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_opportunity ? ' checked="checked"' : '')).'"> ';
386 $htmltext = $langs->trans("ProjectFollowOpportunity");
387 print $form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext);
388 print '<br>';
389 }
390 if (!getDolGlobalString('PROJECT_HIDE_TASKS')) {
391 print '<input type="checkbox" disabled name="usage_task"'.(GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_task ? ' checked="checked"' : '')).'"> ';
392 $htmltext = $langs->trans("ProjectFollowTasks");
393 print $form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext);
394 print '<br>';
395 }
396 if (!getDolGlobalString('PROJECT_HIDE_TASKS') && getDolGlobalString('PROJECT_BILL_TIME_SPENT')) {
397 print '<input type="checkbox" disabled name="usage_bill_time"'.(GETPOSTISSET('usage_bill_time') ? (GETPOST('usage_bill_time', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_bill_time ? ' checked="checked"' : '')).'"> ';
398 $htmltext = $langs->trans("ProjectBillTimeDescription");
399 print $form->textwithpicto($langs->trans("BillTime"), $htmltext);
400 print '<br>';
401 }
402 if (isModEnabled('eventorganization')) {
403 print '<input type="checkbox" disabled name="usage_organize_event"'.(GETPOSTISSET('usage_organize_event') ? (GETPOST('usage_organize_event', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_organize_event ? ' checked="checked"' : '')).'"> ';
404 $htmltext = $langs->trans("EventOrganizationDescriptionLong");
405 print $form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext);
406 }
407 print '</td></tr>';
408}
409
410if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES') && !empty($object->usage_opportunity)) {
411 // Opportunity status
412 print '<tr><td>'.$langs->trans("OpportunityStatus").'</td><td>';
413 $code = dol_getIdFromCode($db, $object->opp_status, 'c_lead_status', 'rowid', 'code');
414 if ($code) {
415 print $langs->trans("OppStatus".$code);
416 }
417
418 // Opportunity percent
419 print ' <span title="'.$langs->trans("OpportunityProbability").'"> / ';
420 if (strcmp($object->opp_percent, '')) {
421 print price($object->opp_percent, 0, $langs, 1, 0).' %';
422 }
423 print '</span></td></tr>';
424
425 // Opportunity Amount
426 print '<tr><td>'.$langs->trans("OpportunityAmount").'</td><td>';
427 if (!is_null($object->opp_amount) && strcmp($object->opp_amount, '')) {
428 print '<span class="amount">'.price($object->opp_amount, 0, $langs, 1, 0, 0, $conf->currency).'</span>';
429 if (strcmp($object->opp_percent, '')) {
430 print ' &nbsp; &nbsp; &nbsp; <span title="'.dol_escape_htmltag($langs->trans('OpportunityWeightedAmount')).'"><span class="opacitymedium">'.$langs->trans("OpportunityWeightedAmountShort").'</span>: <span class="amount">'.price($object->opp_amount * $object->opp_percent / 100, 0, $langs, 1, 0, -1, $conf->currency).'</span></span>';
431 }
432 }
433 print '</td></tr>';
434}
435
436// Budget
437print '<tr><td>'.$langs->trans("Budget").'</td><td>';
438if (!is_null($object->budget_amount) && strcmp($object->budget_amount, '')) {
439 print '<span class="amount">'.price($object->budget_amount, 0, $langs, 1, 0, 0, $conf->currency).'</span>';
440}
441print '</td></tr>';
442
443// Date start - end project
444print '<tr><td>'.$langs->trans("Dates").'</td><td>';
445$start = dol_print_date($object->date_start, 'day');
446print($start ? $start : '?');
447$end = dol_print_date($object->date_end, 'day');
448print ' - ';
449print($end ? $end : '?');
450if ($object->hasDelay()) {
451 print img_warning("Late");
452}
453print '</td></tr>';
454
455// Visibility
456print '<tr><td class="titlefield">'.$langs->trans("Visibility").'</td><td>';
457if ($object->public) {
458 print img_picto($langs->trans('SharedProject'), 'world', 'class="paddingrightonly"');
459 print $langs->trans('SharedProject');
460} else {
461 print img_picto($langs->trans('PrivateProject'), 'private', 'class="paddingrightonly"');
462 print $langs->trans('PrivateProject');
463}
464print '</td></tr>';
465
466// Other attributes
467$cols = 2;
468include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
469
470print '</table>';
471
472print '</div>';
473print '<div class="fichehalfright">';
474print '<div class="underbanner clearboth"></div>';
475
476print '<table class="border tableforfield centpercent">';
477
478// Categories
479if (isModEnabled('category')) {
480 print '<tr><td class="valignmiddle">'.$langs->trans("Categories").'</td><td>';
481 print $form->showCategories($object->id, Categorie::TYPE_PROJECT, 1);
482 print "</td></tr>";
483}
484
485// Description
486print '<tr><td class="titlefield'.($object->description ? ' noborderbottom' : '').'" colspan="2">'.$langs->trans("Description").'</td></tr>';
487if ($object->description) {
488 print '<tr><td class="nottitleforfield" colspan="2">';
489 print '<div class="longmessagecut">';
490 print dolPrintHTML($object->description);
491 print '</div>';
492 print '</td></tr>';
493}
494
495print '</table>';
496
497print '</div>';
498print '</div>';
499
500print '<div class="clearboth"></div>';
501
502print dol_get_fiche_end();
503
504print '<br>';
505
506/*
507 * Referrer types
508 */
509
510$listofreferent = array(
511 'entrepot' => array(
512 'name' => "Warehouse",
513 'title' => "ListWarehouseAssociatedProject",
514 'class' => 'Entrepot',
515 'table' => 'entrepot',
516 'datefieldname' => 'date_entrepot',
517 'urlnew' => DOL_URL_ROOT.'/product/stock/card.php?action=create&projectid='.$id.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
518 'lang' => 'entrepot',
519 'buttonnew' => 'AddWarehouse',
520 'project_field' => 'fk_project',
521 'testnew' => $user->hasRight('stock', 'creer'),
522 'test' => isModEnabled('stock') && $user->hasRight('stock', 'lire') && getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_PROJECT')
523 ),
524 'propal' => array(
525 'name' => "Proposals",
526 'title' => "ListProposalsAssociatedProject",
527 'class' => 'Propal',
528 'table' => 'propal',
529 'datefieldname' => 'datep',
530 'urlnew' => DOL_URL_ROOT.'/comm/propal/card.php?action=create&origin=project&originid='.$id.'&socid='.$socid.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
531 'lang' => 'propal',
532 'buttonnew' => 'AddProp',
533 'testnew' => $user->hasRight('propal', 'creer'),
534 'test' => isModEnabled('propal') && $user->hasRight('propal', 'lire')
535 ),
536 'order' => array(
537 'name' => "CustomersOrders",
538 'title' => "ListOrdersAssociatedProject",
539 'class' => 'Commande',
540 'table' => 'commande',
541 'datefieldname' => 'date_commande',
542 'urlnew' => DOL_URL_ROOT.'/commande/card.php?action=create&projectid='.$id.'&socid='.$socid.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
543 'lang' => 'orders',
544 'buttonnew' => 'CreateOrder',
545 'testnew' => $user->hasRight('commande', 'creer'),
546 'test' => isModEnabled('order') && $user->hasRight('commande', 'lire')
547 ),
548 'invoice' => array(
549 'name' => "CustomersInvoices",
550 'title' => "ListInvoicesAssociatedProject",
551 'class' => 'Facture',
552 'margin' => 'add',
553 'table' => 'facture',
554 'datefieldname' => 'datef',
555 'urlnew' => DOL_URL_ROOT.'/compta/facture/card.php?action=create&projectid='.$id.'&socid='.$socid.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
556 'lang' => 'bills',
557 'buttonnew' => 'CreateBill',
558 'testnew' => $user->hasRight('facture', 'creer'),
559 'test' => isModEnabled('invoice') && $user->hasRight('facture', 'lire')
560 ),
561 'invoice_predefined' => array(
562 'name' => "PredefinedInvoices",
563 'title' => "ListPredefinedInvoicesAssociatedProject",
564 'class' => 'FactureRec',
565 'table' => 'facture_rec',
566 'datefieldname' => 'datec',
567 'urlnew' => DOL_URL_ROOT.'/compta/facture/card.php?action=create&projectid='.$id.'&socid='.$socid.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
568 'lang' => 'bills',
569 'buttonnew' => 'CreateBill',
570 'testnew' => $user->hasRight('facture', 'creer'),
571 'test' => isModEnabled('invoice') && $user->hasRight('facture', 'lire')
572 ),
573 'proposal_supplier' => array(
574 'name' => "SupplierProposals",
575 'title' => "ListSupplierProposalsAssociatedProject",
576 'class' => 'SupplierProposal',
577 'table' => 'supplier_proposal',
578 'datefieldname' => 'date_valid',
579 'urlnew' => DOL_URL_ROOT.'/supplier_proposal/card.php?action=create&projectid='.$id.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id), // No socid parameter here, the socid is often the customer and we create a supplier object
580 'lang' => 'supplier_proposal',
581 'buttonnew' => 'AddSupplierProposal',
582 'testnew' => $user->hasRight('supplier_proposal', 'creer'),
583 'test' => isModEnabled('supplier_proposal') && $user->hasRight('supplier_proposal', 'lire')
584 ),
585 'order_supplier' => array(
586 'name' => "SuppliersOrders",
587 'title' => "ListSupplierOrdersAssociatedProject",
588 'class' => 'CommandeFournisseur',
589 'table' => 'commande_fournisseur',
590 'datefieldname' => 'date_commande',
591 'urlnew' => DOL_URL_ROOT.'/fourn/commande/card.php?action=create&projectid='.$id.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id), // No socid parameter here, the socid is often the customer and we create a supplier object
592 'lang' => 'suppliers',
593 'buttonnew' => 'AddSupplierOrder',
594 'testnew' => $user->hasRight('fournisseur', 'commande', 'creer') || $user->hasRight('supplier_order', 'creer'),
595 'test' => isModEnabled('supplier_order') && $user->hasRight('fournisseur', 'commande', 'lire') || $user->hasRight('supplier_order', 'lire')
596 ),
597 'invoice_supplier' => array(
598 'name' => "BillsSuppliers",
599 'title' => "ListSupplierInvoicesAssociatedProject",
600 'class' => 'FactureFournisseur',
601 'margin' => 'minus',
602 'table' => 'facture_fourn',
603 'datefieldname' => 'datef',
604 'urlnew' => DOL_URL_ROOT.'/fourn/facture/card.php?action=create&projectid='.$id.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id), // No socid parameter here, the socid is often the customer and we create a supplier object
605 'lang' => 'suppliers',
606 'buttonnew' => 'AddSupplierInvoice',
607 'testnew' => $user->hasRight('fournisseur', 'facture', 'creer') || $user->hasRight('supplier_invoice', 'creer'),
608 'test' => isModEnabled('supplier_invoice') && $user->hasRight('fournisseur', 'facture', 'lire') || $user->hasRight('supplier_invoice', 'lire')
609 ),
610 'contract' => array(
611 'name' => "Contracts",
612 'title' => "ListContractAssociatedProject",
613 'class' => 'Contrat',
614 'table' => 'contrat',
615 'datefieldname' => 'date_contrat',
616 'urlnew' => DOL_URL_ROOT.'/contrat/card.php?action=create&projectid='.$id.'&socid='.$socid.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
617 'lang' => 'contracts',
618 'buttonnew' => 'AddContract',
619 'testnew' => $user->hasRight('contrat', 'creer'),
620 'test' => isModEnabled('contract') && $user->hasRight('contrat', 'lire')
621 ),
622 'intervention' => array(
623 'name' => "Interventions",
624 'title' => "ListFichinterAssociatedProject",
625 'class' => 'Fichinter',
626 'table' => 'fichinter',
627 'datefieldname' => 'date_valid',
628 'disableamount' => 0,
629 'margin' => '',
630 'urlnew' => DOL_URL_ROOT.'/fichinter/card.php?action=create&origin=project&originid='.$id.'&socid='.$socid.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
631 'lang' => 'interventions',
632 'buttonnew' => 'AddIntervention',
633 'testnew' => $user->hasRight('ficheinter', 'creer'),
634 'test' => isModEnabled('intervention') && $user->hasRight('ficheinter', 'lire')
635 ),
636 'shipping' => array(
637 'name' => "Shippings",
638 'title' => "ListShippingAssociatedProject",
639 'class' => 'Expedition',
640 'table' => 'expedition',
641 'datefieldname' => 'date_valid',
642 'urlnew' => DOL_URL_ROOT.'/expedition/card.php?action=create&origin=project&originid='.$id.'&socid='.$socid.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
643 'lang' => 'sendings',
644 'buttonnew' => 'CreateShipment',
645 'testnew' => 0,
646 'test' => isModEnabled('shipping') && $user->hasRight('expedition', 'lire')
647 ),
648 'mrp' => array(
649 'name' => "MO",
650 'title' => "ListMOAssociatedProject",
651 'class' => 'Mo',
652 'table' => 'mrp_mo',
653 'datefieldname' => 'date_valid',
654 'urlnew' => DOL_URL_ROOT.'/mrp/mo_card.php?action=create&origin=project&originid='.$id.'&socid='.$socid.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
655 'lang' => 'mrp',
656 'buttonnew' => 'CreateMO',
657 'testnew' => $user->hasRight('mrp', 'write'),
658 'project_field' => 'fk_project',
659 'nototal' => 1,
660 'test' => isModEnabled('mrp') && $user->hasRight('mrp', 'read')
661 ),
662 'trip' => array(
663 'name' => "TripsAndExpenses",
664 'title' => "ListExpenseReportsAssociatedProject",
665 'class' => 'Deplacement',
666 'table' => 'deplacement',
667 'datefieldname' => 'dated',
668 'margin' => 'minus',
669 'disableamount' => 1,
670 'urlnew' => DOL_URL_ROOT.'/deplacement/card.php?action=create&projectid='.$id.'&socid='.$socid.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
671 'lang' => 'trips',
672 'buttonnew' => 'AddTrip',
673 'testnew' => $user->hasRight('deplacement', 'creer'),
674 'test' => isModEnabled('deplacement') && $user->hasRight('deplacement', 'lire')
675 ),
676 'expensereport' => array(
677 'name' => "ExpenseReports",
678 'title' => "ListExpenseReportsAssociatedProject",
679 'class' => 'ExpenseReportLine',
680 'table' => 'expensereport_det',
681 'datefieldname' => 'date',
682 'margin' => 'minus',
683 'disableamount' => 0,
684 'urlnew' => DOL_URL_ROOT.'/expensereport/card.php?action=create&projectid='.$id.'&socid='.$socid.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
685 'lang' => 'trips',
686 'buttonnew' => 'AddTrip',
687 'testnew' => $user->hasRight('expensereport', 'creer'),
688 'test' => isModEnabled('expensereport') && $user->hasRight('expensereport', 'lire')
689 ),
690 'donation' => array(
691 'name' => "Donation",
692 'title' => "ListDonationsAssociatedProject",
693 'class' => 'Don',
694 'margin' => 'add',
695 'table' => 'don',
696 'datefieldname' => 'datedon',
697 'disableamount' => 0,
698 'urlnew' => DOL_URL_ROOT.'/don/card.php?action=create&projectid='.$id.'&socid='.$socid.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
699 'lang' => 'donations',
700 'buttonnew' => 'AddDonation',
701 'testnew' => $user->hasRight('don', 'creer'),
702 'test' => isModEnabled('don') && $user->hasRight('don', 'lire')
703 ),
704 'loan' => array(
705 'name' => "Loan",
706 'title' => "ListLoanAssociatedProject",
707 'class' => 'Loan',
708 'margin' => '',
709 'table' => 'loan',
710 'datefieldname' => 'datestart',
711 'disableamount' => 0,
712 'urlnew' => DOL_URL_ROOT.'/loan/card.php?action=create&projectid='.$id.'&socid='.$socid.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
713 'lang' => 'loan',
714 'buttonnew' => 'AddLoan',
715 'testnew' => $user->hasRight('loan', 'write'),
716 'test' => isModEnabled('loan') && $user->hasRight('loan', 'read')
717 ),
718 'chargesociales' => array(
719 'name' => "SocialContribution",
720 'title' => "ListSocialContributionAssociatedProject",
721 'class' => 'ChargeSociales',
722 'margin' => 'minus',
723 'table' => 'chargesociales',
724 'datefieldname' => 'date_ech',
725 'disableamount' => 0,
726 'urlnew' => DOL_URL_ROOT.'/compta/sociales/card.php?action=create&projectid='.$id.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
727 'lang' => 'compta',
728 'buttonnew' => 'AddSocialContribution',
729 'testnew' => $user->hasRight('tax', 'charges', 'lire'),
730 'test' => isModEnabled('tax') && $user->hasRight('tax', 'charges', 'lire')
731 ),
732 'project_task' => array(
733 'name' => "TaskTimeSpent",
734 'title' => "ListTaskTimeUserProject",
735 'class' => 'Task',
736 'margin' => 'minus',
737 'table' => 'projet_task',
738 'datefieldname' => 'element_date',
739 'disableamount' => ($canSeeFinancials ? 0 : 1),
740 'urlnew' => DOL_URL_ROOT.'/projet/tasks/time.php?withproject=1&action=createtime&projectid='.$id.'&token='.newToken().'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
741 'buttonnew' => 'AddTimeSpent',
742 'testnew' => $user->hasRight('project', 'creer'),
743 'test' => isModEnabled('project') && $user->hasRight('projet', 'lire') && !getDolGlobalString('PROJECT_HIDE_TASKS')
744 ),
745 'stocktransfer' => array(
746 'name' => "StockTransfer",
747 'title' => "ListStockTransferProject",
748 'class' => 'StockTransfer',
749 'table' => 'stocktransfer_stocktransfer',
750 'datefieldname' => 'datem',
751 'margin' => '',
752 'project_field' => 'fk_project',
753 'disableamount' => 1,
754 'urlnew' => DOL_URL_ROOT.'/product/stock/stocktransfer/stocktransfer_card.php?action=create&projectid='.$id.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
755 'lang' => 'stocks',
756 'buttonnew' => 'StockTransferNew',
757 'testnew' => $user->hasRight('stocktransfer', 'stocktransfer', 'write'),
758 'test' => isModEnabled('stocktransfer') && $user->hasRight('stocktransfer', 'stocktransfer', 'read')
759 ),
760 'stock_mouvement' => array(
761 'name' => "MouvementStockAssociated",
762 'title' => "ListMouvementStockProject",
763 'class' => 'MouvementStock',
764 'table' => 'stock_mouvement',
765 'datefieldname' => 'datem',
766 'margin' => 'minus',
767 'project_field' => 'fk_project',
768 'disableamount' => 0,
769 'test' => isModEnabled('stock') && $user->hasRight('stock', 'mouvement', 'lire') && getDolGlobalString('STOCK_MOVEMENT_INTO_PROJECT_OVERVIEW')
770 ),
771 'salaries' => array(
772 'name' => "Salaries",
773 'title' => "ListSalariesAssociatedProject",
774 'class' => 'Salary',
775 'table' => 'salary',
776 'datefieldname' => 'datesp',
777 'margin' => 'minus',
778 'disableamount' => 0,
779 'urlnew' => DOL_URL_ROOT.'/salaries/card.php?action=create&projectid='.$id.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
780 'lang' => 'salaries',
781 'buttonnew' => 'AddSalary',
782 'testnew' => $user->hasRight('salaries', 'write'),
783 'test' => isModEnabled('salaries') && $user->hasRight('salaries', 'read')
784 ),
785 'variouspayment' => array(
786 'name' => "VariousPayments",
787 'title' => "ListVariousPaymentsAssociatedProject",
788 'class' => 'PaymentVarious',
789 'table' => 'payment_various',
790 'datefieldname' => 'datev',
791 'margin' => 'minus',
792 'disableamount' => 0,
793 'urlnew' => DOL_URL_ROOT.'/compta/bank/various_payment/card.php?action=create&projectid='.$id.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
794 'lang' => 'banks',
795 'buttonnew' => 'AddVariousPayment',
796 'testnew' => $user->hasRight('banque', 'modifier'),
797 'test' => isModEnabled("bank") && $user->hasRight('banque', 'lire') && !getDolGlobalString('BANK_USE_OLD_VARIOUS_PAYMENT')
798 ),
799 /* No need for this, available on dedicated tab "Agenda/Events"
800 'agenda'=>array(
801 'name'=>"Agenda",
802 'title'=>"ListActionsAssociatedProject",
803 'class'=>'ActionComm',
804 'table'=>'actioncomm',
805 'datefieldname'=>'datep',
806 'disableamount'=>1,
807 'urlnew'=>DOL_URL_ROOT.'/comm/action/card.php?action=create&projectid='.$id.'&socid='.$socid.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
808 'lang'=>'agenda',
809 'buttonnew'=>'AddEvent',
810 'testnew'=>$user->rights->agenda->myactions->create,
811 'test'=> isModEnabled('agenda') && $user->hasRight('agenda', 'myactions', 'read')),
812 */
813);
814
815// Change rules for profit/benefit calculation
816if (getDolGlobalString('PROJECT_ELEMENTS_FOR_PLUS_MARGIN')) {
817 foreach ($listofreferent as $key => $element) {
818 if ($listofreferent[$key]['margin'] == 'add') {
819 unset($listofreferent[$key]['margin']);
820 }
821 }
822 $newelementforplusmargin = explode(',', getDolGlobalString('PROJECT_ELEMENTS_FOR_PLUS_MARGIN'));
823 foreach ($newelementforplusmargin as $value) {
824 $listofreferent[trim($value)]['margin'] = 'add';
825 }
826}
827if (getDolGlobalString('PROJECT_ELEMENTS_FOR_MINUS_MARGIN')) {
828 foreach ($listofreferent as $key => $element) {
829 if ($listofreferent[$key]['margin'] == 'minus') {
830 unset($listofreferent[$key]['margin']);
831 }
832 }
833 $newelementforminusmargin = explode(',', getDolGlobalString('PROJECT_ELEMENTS_FOR_MINUS_MARGIN'));
834 foreach ($newelementforminusmargin as $value) {
835 $listofreferent[trim($value)]['margin'] = 'minus';
836 }
837}
838
839
840$parameters = array('listofreferent' => $listofreferent);
841$resHook = $hookmanager->executeHooks('completeListOfReferent', $parameters, $object, $action);
842
843if (!empty($hookmanager->resArray)) {
844 $listofreferent = array_merge($listofreferent, $hookmanager->resArray);
845} elseif ($resHook > 0 && !empty($hookmanager->resPrint)) {
846 $listofreferent = $hookmanager->resPrint;
847}
848
849if (in_array($action, ['addelement', 'unlink'])) {
850 // Only an element type listed (and allowed) on this page can be linked or unlinked, using the project field it declares
851 $tablename = GETPOST("tablename", "aZ09");
852 $projectField = '';
853 $excludeselect = ['payment_various'];
854 foreach ($listofreferent as $value) {
855 if (!empty($value['test']) && isset($value['table']) && $value['table'] === $tablename) {
856 $projectField = empty($value['project_field']) ? 'fk_projet' : $value['project_field'];
857 if (!empty($value['exclude_select_element'])) {
858 $excludeselect[] = $value['exclude_select_element'];
859 }
860 break;
861 }
862 }
863 if (!$permissiontoadd || $projectField === ''
864 || ($action == 'addelement' && (getDolGlobalString('PROJECT_LINK_ON_OVERWIEW_DISABLED') || in_array($tablename, $excludeselect)))
865 || ($action == 'unlink' && (in_array($tablename, ['projet_task', 'stock_mouvement']) || (getDolGlobalString('PROJECT_DISABLE_UNLINK_FROM_OVERVIEW') && !$user->admin)))) {
866 accessforbidden('', 0, 0);
867 }
868
869 $elementselectid = GETPOSTINT("elementselect");
870 if ($action == "addelement") {
871 $result = $object->update_element($tablename, $elementselectid);
872 } else {
873 $result = $object->remove_element($tablename, $elementselectid, $projectField);
874 }
875 if ($result < 0) {
876 setEventMessages($object->error, $object->errors, 'errors');
877 }
878}
879
880$elementuser = new User($db);
881
882
883
884$showdatefilter = 0;
885// Show the filter on date on top of element list
886if (!$showdatefilter) {
887 print '<div class="center centpercent">';
888 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">';
889 print '<input type="hidden" name="token" value="'.newToken().'">';
890 print '<input type="hidden" name="tablename" value="'.(empty($tablename) ? '' : $tablename).'">';
891 print '<input type="hidden" name="action" value="view">';
892 print '<div class="inline-block">';
893 print $form->selectDate($dates, 'dates', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From"));
894 print '</div>';
895 print '<div class="inline-block">';
896 print $form->selectDate($datee, 'datee', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"));
897 print '</div>';
898 print '<div class="inline-block">';
899 print '<input type="submit" name="refresh" value="'.$langs->trans("Refresh").'" class="button small">';
900 print '</div>';
901 print '</form>';
902 print '</div>';
903
904 $showdatefilter++;
905}
906
907
908
909// Show balance for whole project
910
911$langs->loadLangs(array("suppliers", "bills", "orders", "proposals", "margins"));
912
913if (isModEnabled('stock')) {
914 $langs->load('stocks');
915}
916
917print '<!-- Begin PROFIT table -->';
918print load_fiche_titre($langs->trans("Profit"), '', 'title_accountancy');
919
920print '<div class="div-table-responsive">';
921print '<table class="noborder centpercent">';
922print '<tr class="liste_titre">';
923print '<td class="left" width="200">';
924$tooltiponprofit = $langs->trans("ProfitIsCalculatedWith")."<br>\n";
925$tooltiponprofitplus = $tooltiponprofitminus = '';
926foreach ($listofreferent as $key => $value) {
927 if (!empty($value['lang'])) {
928 $langs->load($value['lang']);
929 }
930 $name = $langs->trans($value['name']);
931 $qualified = $value['test'];
932 $margin = empty($value['margin']) ? '' : $value['margin'];
933 if ($qualified && $margin) { // If this element must be included into profit calculation ($margin is 'minus' or 'add')
934 if ($margin === 'add') {
935 $tooltiponprofitplus .= ' &gt; '.$name." (+)<br>\n";
936 } elseif ($margin === 'minus') {
937 $tooltiponprofitminus .= ' &gt; '.$name." (-)<br>\n";
938 }
939 }
940}
941$tooltiponprofit .= $tooltiponprofitplus;
942$tooltiponprofit .= $tooltiponprofitminus;
943print $form->textwithpicto($langs->trans("Element"), $tooltiponprofit);
944print '</td>';
945print '<td class="right" width="100">'.$langs->trans("Number").'</td>';
946print '<td class="right" width="100">'.$langs->trans("AmountHT").'</td>';
947print '<td class="right" width="100">'.$langs->trans("AmountTTC").'</td>';
948print '</tr>';
949
950$total_revenue_ht = 0;
951$balance_ht = 0;
952$balance_ttc = 0;
953
954// Loop on each element type (proposal, sale order, invoices, ...)
955foreach ($listofreferent as $key => $value) {
956 $parameters = array(
957 'total_revenue_ht' => & $total_revenue_ht,
958 'balance_ht' => & $balance_ht,
959 'balance_ttc' => & $balance_ttc,
960 'key' => $key,
961 'value' => & $value,
962 'dates' => $dates,
963 'datee' => $datee
964 );
965 $reshook = $hookmanager->executeHooks('printOverviewProfit', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
966 if ($reshook < 0) {
967 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
968 } elseif ($reshook > 0) {
969 print $hookmanager->resPrint;
970 continue;
971 }
972
973 $name = $langs->trans($value['name']);
974 $title = $value['title'];
975 $classname = $value['class'];
976 $tablename = $value['table'];
977 $datefieldname = $value['datefieldname'];
978 $qualified = $value['test'];
979 // Hide project_task amounts in profit section for users without financial access
980 if ($key === 'project_task' && !$canSeeFinancials) {
981 $qualified = false;
982 }
983 $margin = empty($value['margin']) ? 0 : $value['margin'];
984 $project_field = empty($value['project_field']) ? '' : $value['project_field'];
985 if ($qualified) { // If this element must be included into profit summary table ($margin is '', 'minus' or 'add')
986 $element = new $classname($db);
987
988 $elementarray = $object->get_element_list($key, $tablename, $datefieldname, $dates, $datee, !empty($project_field) ? $project_field : 'fk_projet');
989
990 if (is_array($elementarray) && count($elementarray) > 0) {
991 $total_ht = 0;
992 $total_ttc = 0;
993 $i = 0;
994
995 // Loop on each object for the current element type
996 $num = count($elementarray);
997 for ($i = 0; $i < $num; $i++) {
998 $tmp = explode('_', $elementarray[$i]);
999 $idofelement = (int) $tmp[0];
1000 $idofelementuser = !empty($tmp[1]) ? (int) $tmp[1] : 0;
1001
1002 $element->fetch($idofelement);
1003 if ($idofelementuser) {
1004 $elementuser->fetch($idofelementuser);
1005 }
1006
1007 // Define if record must be used for total or not
1008 $qualifiedfortotal = true;
1009 if ($key == 'invoice') {
1010 if (!empty($element->close_code) && $element->close_code == 'replaced') {
1011 $qualifiedfortotal = false; // Replacement invoice, do not include into total
1012 }
1013 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS') && $element->type == Facture::TYPE_DEPOSIT) {
1014 $qualifiedfortotal = false; // If hidden option to use deposits as payment (deprecated, not recommended to use this), deposits are not included
1015 }
1016 }
1017 if ($key == 'propal') {
1018 if ($element->status != Propal::STATUS_SIGNED && $element->status != Propal::STATUS_BILLED) {
1019 $qualifiedfortotal = false; // Only signed proposal must not be included in total
1020 }
1021 }
1022
1023 if ($tablename != 'expensereport_det' && method_exists($element, 'fetch_thirdparty')) {
1024 $element->fetch_thirdparty();
1025 }
1026
1027 // Define $total_ht_by_line
1028 if ($tablename == 'don' || $tablename == 'chargesociales' || $tablename == 'payment_various' || $tablename == 'salary') {
1029 '@phan-var-force ChargeSociales|PaymentVarious|Salary $element';
1030 $total_ht_by_line = $element->amount;
1031 } elseif ($tablename == 'fichinter') {
1032 '@phan-var-force Fichinter $element';
1033 $total_ht_by_line = $element->getAmount();
1034 } elseif ($tablename == 'stock_mouvement') {
1035 '@phan-var-force MouvementStock $element';
1036 $total_ht_by_line = $element->price * abs($element->qty);
1037 } elseif ($tablename == 'projet_task') {
1038 '@phan-var-force Task $element';
1039 $tmp = $element->getSumOfAmount($idofelementuser ? $elementuser : '', (string) $dates, (string) $datee);
1040 $total_ht_by_line = price2num($tmp['amount'], 'MT');
1041 } elseif ($key == 'loan') {
1042 '@phan-var-force Loan $element';
1043 if ((empty($dates) && empty($datee)) || (intval($dates) <= $element->datestart && intval($datee) >= $element->dateend)) {
1044 // Get total loan
1045 $total_ht_by_line = -$element->capital;
1046 } else {
1047 // Get loan schedule according to date filter
1048 $total_ht_by_line = 0;
1049 $loanScheduleStatic = new LoanSchedule($element->db);
1050 $loanScheduleStatic->fetchAll($element->id);
1051 if (!empty($loanScheduleStatic->lines)) {
1052 foreach ($loanScheduleStatic->lines as $loanSchedule) {
1056 if (($loanSchedule->datep >= $dates && $loanSchedule->datep <= $datee) // dates filter is defined
1057 || !empty($dates) && empty($datee) && $loanSchedule->datep >= $dates && $loanSchedule->datep <= dol_now()
1058 || empty($dates) && !empty($datee) && $loanSchedule->datep <= $datee
1059 ) {
1060 $total_ht_by_line -= $loanSchedule->amount_capital;
1061 }
1062 }
1063 }
1064 }
1065 } else {
1066 $total_ht_by_line = $element->total_ht;
1067 }
1068
1069 // Define $total_ttc_by_line
1070 if ($tablename == 'don' || $tablename == 'chargesociales' || $tablename == 'payment_various' || $tablename == 'salary') {
1071 '@phan-var-force ChargeSociales|PaymentVarious|Salary $element';
1072 $total_ttc_by_line = $element->amount;
1073 } elseif ($tablename == 'fichinter') {
1074 '@phan-var-force Fichinter $element';
1075 $total_ttc_by_line = $element->getAmount();
1076 } elseif ($tablename == 'stock_mouvement') {
1077 '@phan-var-force MouvementStock $element';
1078 $total_ttc_by_line = $element->price * abs($element->qty);
1079 } elseif ($tablename == 'projet_task') {
1080 '@phan-var-force Task $element';
1081 $defaultvat = get_default_tva($mysoc, $mysoc);
1082 $reg = array();
1083 if (preg_replace('/^(\d+\.)\s\‍(.*\‍)/', $defaultvat, $reg)) {
1084 // @phan-suppress-next-line PhanTypeInvalidDimOffset
1085 $defaultvat = $reg[1];
1086 }
1087 $total_ttc_by_line = price2num($total_ht_by_line * (1 + ((float) $defaultvat / 100)), 'MT');
1088 } elseif ($key == 'loan') {
1089 $total_ttc_by_line = $total_ht_by_line; // For loan there is actually no taxe managed in Dolibarr
1090 } else {
1091 $total_ttc_by_line = $element->total_ttc;
1092 }
1093
1094 // Change sign of $total_ht_by_line and $total_ttc_by_line for various payments
1095 if ($tablename == 'payment_various') {
1096 if ($element->sens == 1) {
1097 $total_ht_by_line = -$total_ht_by_line;
1098 $total_ttc_by_line = -$total_ttc_by_line;
1099 }
1100 }
1101
1102 // Change sign of $total_ht_by_line and $total_ttc_by_line for supplier proposal and supplier order.
1103 // Skip when the element already participates to the margin computation via margin='minus'
1104 // (line 1095 below will revert sign too, and double-negation would silently flip the value
1105 // back to positive - see PROJECT_ELEMENTS_FOR_MINUS_MARGIN=order_supplier in #34684).
1106 if (($tablename == 'commande_fournisseur' || $tablename == 'supplier_proposal') && $margin !== 'minus') {
1107 $total_ht_by_line = -$total_ht_by_line;
1108 $total_ttc_by_line = -$total_ttc_by_line;
1109 }
1110
1111 // Add total if we have to
1112 if ($qualifiedfortotal) {
1113 $total_ht += $total_ht_by_line;
1114 $total_ttc += $total_ttc_by_line;
1115 }
1116 }
1117
1118 // Each element with at least one line is output
1119
1120 // Calculate margin
1121 if ($margin) {
1122 if ($margin === 'add') {
1123 $total_revenue_ht += $total_ht;
1124 }
1125
1126 if ($margin === "minus") { // Revert sign
1127 $total_ht = -$total_ht;
1128 $total_ttc = -$total_ttc;
1129 }
1130
1131 $balance_ht += $total_ht;
1132 $balance_ttc += $total_ttc;
1133 }
1134
1135 print '<tr class="oddeven">';
1136 // Module
1137 print '<!-- // Module '.$name.' with tablename '.$tablename.' -->';
1138 print '<td class="left"><a href="#table_'.$tablename.'">'.$name.'</a></td>';
1139 // Nb
1140 print '<td class="right">'.$i.'</td>';
1141 // Amount HT
1142 print '<td class="right">';
1143 if ($key == 'intervention' && !$margin) {
1144 print '<span class="opacitymedium">'.$form->textwithpicto($langs->trans("NA"), $langs->trans("AmountOfInteventionNotIncludedByDefault")).'</span>';
1145 } else {
1146 if ($key == 'propal') {
1147 print '<span class="opacitymedium">'.$form->textwithpicto('', $langs->trans("SignedOnly")).'</span>';
1148 }
1149 print price($total_ht);
1150 }
1151 print '</td>';
1152 // Amount TTC
1153 print '<td class="right">';
1154 if ($key == 'intervention' && !$margin) {
1155 print '<span class="opacitymedium">'.$form->textwithpicto($langs->trans("NA"), $langs->trans("AmountOfInteventionNotIncludedByDefault")).'</span>';
1156 } else {
1157 if ($key == 'propal') {
1158 print '<span class="opacitymedium">'.$form->textwithpicto('', $langs->trans("SignedOnly")).'</span>';
1159 }
1160 print price($total_ttc);
1161 }
1162 print '</td>';
1163 print '</tr>';
1164 }
1165 }
1166}
1167// and the final balance
1168print '<tr class="liste_total">';
1169print '<td class="right" colspan="2">'.$langs->trans("Profit").'</td>';
1170print '<td class="right">'.price(price2num($balance_ht, 'MT')).'</td>';
1171print '<td class="right">'.price(price2num($balance_ttc, 'MT')).'</td>';
1172print '</tr>';
1173
1174// and the cost per attendee
1175if ($object->usage_organize_event) {
1176 require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorboothattendee.class.php';
1177 $conforboothattendee = new ConferenceOrBoothAttendee($db);
1178 $result = $conforboothattendee->fetchAll('', '', 0, 0, '(t.fk_project:=:'.((int) $object->id).') AND (t.status:=:'.ConferenceOrBoothAttendee::STATUS_VALIDATED.')');
1179
1180 if (!is_array($result) && $result < 0) {
1181 setEventMessages($conforboothattendee->error, $conforboothattendee->errors, 'errors');
1182 } else {
1183 $nbAttendees = count($result);
1184 }
1185
1186 if ($nbAttendees >= 2) {
1187 $costperattendee_ht = $balance_ht / $nbAttendees;
1188 $costperattendee_ttc = $balance_ttc / $nbAttendees;
1189 print '<tr class="liste_total">';
1190 print '<td class="right" colspan="2">'.$langs->trans("ProfitPerValidatedAttendee").'</td>';
1191 print '<td class="right">'.price(price2num($costperattendee_ht, 'MT')).'</td>';
1192 print '<td class="right">'.price(price2num($costperattendee_ttc, 'MT')).'</td>';
1193 print '</tr>';
1194 }
1195}
1196
1197// and the margin (profit / revenues)
1198if ($total_revenue_ht) {
1199 print '<tr class="liste_total">';
1200 print '<td class="right" colspan="2">'.$langs->trans("Margin").'</td>';
1201 print '<td class="right">'.round(100 * $balance_ht / $total_revenue_ht, 1).'%</td>';
1202 print '<td class="right"></td>';
1203 print '</tr>';
1204}
1205
1206print "</table>";
1207print '</div>';
1208print '<!-- End PROFIT table -->';
1209
1210
1211print '<br><br>';
1212print '<br>';
1213
1214
1215$total_time = 0;
1216
1217// Detail
1218foreach ($listofreferent as $key => $value) {
1219 $parameters = array(
1220 'key' => $key,
1221 'value' => & $value,
1222 'dates' => $dates,
1223 'datee' => $datee
1224 );
1225 $reshook = $hookmanager->executeHooks('printOverviewDetail', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1226 if ($reshook < 0) {
1227 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1228 } elseif ($reshook > 0) {
1229 print $hookmanager->resPrint;
1230 continue;
1231 }
1232
1233 $title = $value['title'];
1234 $classname = $value['class'];
1235 $tablename = $value['table'];
1236 $datefieldname = $value['datefieldname'];
1237 $qualified = $value['test'];
1238 $urlnew = empty($value['urlnew']) ? '' : $value['urlnew'];
1239 $buttonnew = empty($value['buttonnew']) ? '' : $value['buttonnew'];
1240 $testnew = empty($value['testnew']) ? '' : $value['testnew'];
1241 $project_field = empty($value['project_field']) ? '' : $value['project_field'];
1242 $nototal = empty($value['nototal']) ? 0 : 1;
1243
1244 $exclude_select_element = array('payment_various');
1245 if (!empty($value['exclude_select_element'])) {
1246 $exclude_select_element[] = $value['exclude_select_element'];
1247 }
1248
1249 if ($qualified && $tablename !== null) {
1250 // If we want the project task array to have details of users
1251 //if ($key == 'project_task') $key = 'project_task_time';
1252
1253 $element = new $classname($db);
1254
1255 $addform = '';
1256
1257 $idtofilterthirdparty = 0;
1258 $array_of_element_linkable_with_different_thirdparty = array('facture_fourn', 'commande_fournisseur');
1259 if (!in_array($tablename, $array_of_element_linkable_with_different_thirdparty)) {
1260 $idtofilterthirdparty = empty($object->thirdparty->id) ? 0 : $object->thirdparty->id;
1261 if (getDolGlobalString('PROJECT_OTHER_THIRDPARTY_ID_TO_ADD_ELEMENTS')) {
1262 $idtofilterthirdparty .= ',' . getDolGlobalString('PROJECT_OTHER_THIRDPARTY_ID_TO_ADD_ELEMENTS');
1263 }
1264 }
1265
1266 $elementarray = $object->get_element_list($key, $tablename, $datefieldname, $dates, $datee, !empty($project_field) ? $project_field : 'fk_projet');
1267
1268
1269 if ($permissiontoadd && !getDolGlobalString('PROJECT_LINK_ON_OVERWIEW_DISABLED') && $idtofilterthirdparty && !in_array($tablename, $exclude_select_element)) {
1270 $selectList = $formproject->select_element($tablename, $idtofilterthirdparty, 'minwidth300 minwidth75imp', -2, empty($project_field) ? 'fk_projet' : $project_field, $langs->trans("SelectElement"));
1271 if ((int) $selectList < 0) { // cast to int because ''<0 is true.
1272 setEventMessages($formproject->error, $formproject->errors, 'errors');
1273 } elseif ($selectList) {
1274 // Define form with the combo list of elements to link
1275 $addform .= '<div class="inline-block valignmiddle">';
1276 $addform .= '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
1277 $addform .= '<input type="hidden" name="token" value="'.newToken().'">';
1278 $addform .= '<input type="hidden" name="tablename" value="'.$tablename.'">';
1279 $addform .= '<input type="hidden" name="action" value="addelement">';
1280 $addform .= '<input type="hidden" name="datesrfc" value="'.dol_print_date($dates, 'dayhourrfc').'">';
1281 $addform .= '<input type="hidden" name="dateerfc" value="'.dol_print_date($datee, 'dayhourrfc').'">';
1282 $addform .= '<table><tr>';
1283 //$addform .= '<td><span class="hideonsmartphone opacitymedium">'.$langs->trans("SelectElement").'</span></td>';
1284 $addform .= '<td>'.$selectList.'</td>';
1285 $addform .= '<td><input type="submit" class="button button-linkto smallpaddingimp" value="'.dol_escape_htmltag($langs->trans("LinkToElementShort")).'"></td>';
1286 $addform .= '</tr></table>';
1287 $addform .= '</form>';
1288 $addform .= '</div>';
1289 }
1290 }
1291 if (!getDolGlobalString('PROJECT_CREATE_ON_OVERVIEW_DISABLED') && $urlnew) {
1292 $addform .= '<div class="inline-block valignmiddle">';
1293 if ($testnew) {
1294 $addform .= '<a class="buttonxxx marginleftonly" href="'.$urlnew.'" title="'.dol_escape_htmltag($langs->trans($buttonnew)).'"><span class="fa fa-plus-circle valignmiddle paddingleft"></span></a>';
1295 } elseif (!getDolGlobalString('MAIN_BUTTON_HIDE_UNAUTHORIZED')) {
1296 $addform .= '<span title="'.dol_escape_htmltag($langs->trans($buttonnew)).'"><a class="buttonxxx marginleftonly buttonRefused" disabled="disabled" href="#"><span class="fa fa-plus-circle valignmiddle paddingleft"></span></a></span>';
1297 }
1298 $addform .= '<div>';
1299 }
1300
1301 if (is_array($elementarray) && count($elementarray) > 0 && $key == "order_supplier") {
1302 $addform .= '<div class="inline-block valignmiddle"><a id="btnShow" class="buttonxxx marginleftonly" href="#" onClick="return false;">
1303 <span id="textBtnShow" class="valignmiddle text-plus-circle hideonsmartphone">'.$langs->trans("CanceledShown").'</span><span id="minus-circle" class="fa fa-eye valignmiddle paddingleft"></span>
1304 </a>
1305 <script>
1306 $("#btnShow").on("click", function () {
1307 console.log("We click to show or hide the canceled lines");
1308 var attr = $(this).attr("data-canceledarehidden");
1309 if (typeof attr !== "undefined" && attr !== false) {
1310 console.log("Show canceled");
1311 $(".tr_canceled").show();
1312 $("#textBtnShow").text("'.dol_escape_js($langs->transnoentitiesnoconv("CanceledShown")).'");
1313 $("#btnShow").removeAttr("data-canceledarehidden");
1314 $("#minus-circle").removeClass("fa-eye-slash").addClass("fa-eye");
1315 } else {
1316 console.log("Hide canceled");
1317 $(".tr_canceled").hide();
1318 $("#textBtnShow").text("'.dol_escape_js($langs->transnoentitiesnoconv("CanceledHidden")).'");
1319 $("#btnShow").attr("data-canceledarehidden", 1);
1320 $("#minus-circle").removeClass("fa-eye").addClass("fa-eye-slash");
1321 }
1322 });
1323 </script></div>';
1324
1325 $addform .= '<div class="inline-block valignmiddle"><a id="btnShowPaid" class="buttonxxx marginleftonly" href="#" onClick="return false;">
1326 <span id="textBtnShowPaid" class="valignmiddle text-plus-circle hideonsmartphone">'.$langs->trans("PaidShown").'</span><span id="minus-circle-paid" class="fa fa-eye valignmiddle paddingleft"></span>
1327 </a>
1328 <script>
1329 $("#btnShowPaid").on("click", function () {
1330 console.log("We click to show or hide the paid lines");
1331 var attr = $(this).attr("data-paidarehidden");
1332 if (typeof attr !== "undefined" && attr !== false) {
1333 console.log("Show paid");
1334 $(".tr_paid").show();
1335 $("#textBtnShowPaid").text("'.dol_escape_js($langs->transnoentitiesnoconv("PaidShown")).'");
1336 $("#btnShowPaid").removeAttr("data-paidarehidden");
1337 $("#minus-circle-paid").removeClass("fa-eye-slash").addClass("fa-eye");
1338 } else {
1339 console.log("Hide paid");
1340 $(".tr_paid").hide();
1341 $("#textBtnShowPaid").text("'.dol_escape_js($langs->transnoentitiesnoconv("PaidHidden")).'");
1342 $("#btnShowPaid").attr("data-paidarehidden", 1);
1343 $("#minus-circle-paid").removeClass("fa-eye").addClass("fa-eye-slash");
1344 }
1345 });
1346 </script></div>';
1347 }
1348
1349 print '<a id="table_'.$tablename.'"></a>';
1350 print load_fiche_titre($langs->trans($title), $addform, '');
1351
1352 print "\n".'<!-- Table for tablename = '.$tablename.' -->'."\n";
1353 print '<div class="div-table-responsive">';
1354 print '<table class="noborder centpercent">';
1355
1356 print '<tr class="liste_titre">';
1357 // Remove link column
1358 print '<td style="width: 24px"></td>';
1359 // Ref
1360 print '<td'.(($tablename != 'actioncomm' && $tablename != 'projet_task') ? ' style="width: 200px"' : '').'>'.$langs->trans("Ref").'</td>';
1361 // Product and qty on stock_movement
1362 if ('MouvementStock' == $classname) {
1363 print '<td style="width: 200px">'.$langs->trans("Product").'</td>';
1364 print '<td style="width: 50px">'.$langs->trans("Qty").'</td>';
1365 }
1366 // Date
1367 print '<td'.(($tablename != 'actioncomm' && $tablename != 'projet_task') ? ' style="width: 200px"' : '').' class="center">';
1368 if (in_array($tablename, array('projet_task'))) {
1369 print $langs->trans("TimeSpent");
1370 }
1371 if (!in_array($tablename, array('projet_task'))) {
1372 print $langs->trans("Date");
1373 }
1374 print '</td>';
1375 // Thirdparty or user
1376 print '<td>';
1377 if (in_array($tablename, array('projet_task')) && $key == 'project_task') {
1378 print ''; // if $key == 'project_task', we don't want details per user
1379 } elseif (in_array($tablename, array('payment_various'))) {
1380 print $langs->trans("Label"); // complementary info about the payment
1381 } elseif (in_array($tablename, array('expensereport_det', 'don', 'projet_task', 'stock_mouvement', 'salary'))) {
1382 print $langs->trans("User");
1383 } else {
1384 print $langs->trans("ThirdParty");
1385 }
1386 print '</td>';
1387 // Duration of intervention
1388 if ($tablename == 'fichinter') {
1389 print '<td>';
1390 print $langs->trans("TotalDuration");
1391 $total_duration = 0;
1392 print '</td>';
1393 }
1394 // Type from Expense Report
1395 if ($tablename == 'expensereport_det') {
1396 print '<td id="expensereport_type">';
1397 print $langs->trans("Type");
1398 print '</td>';
1399 }
1400 // Description from Expense Report
1401 if ($tablename == 'expensereport_det') {
1402 print '<td id="expensereport_description">';
1403 print $langs->trans("Description");
1404 print '</td>';
1405 }
1406
1407
1408 // Amount HT
1409 //if (empty($value['disableamount']) && ! in_array($tablename, array('projet_task'))) print '<td class="right" width="120">'.$langs->trans("AmountHT").'</td>';
1410 //elseif (empty($value['disableamount']) && in_array($tablename, array('projet_task'))) print '<td class="right" width="120">'.$langs->trans("Amount").'</td>';
1411 if ($key == 'loan') {
1412 print '<td class="right" width="120">'.$langs->trans("LoanCapital").'</td>';
1413 } elseif (empty($value['disableamount'])) {
1414 print '<td class="right" width="120">'.$langs->trans("AmountHT").'</td>';
1415 } else {
1416 print '<td width="120"></td>';
1417 }
1418 // Amount TTC
1419 //if (empty($value['disableamount']) && ! in_array($tablename, array('projet_task'))) print '<td class="right" width="120">'.$langs->trans("AmountTTC").'</td>';
1420 if ($key == 'loan') {
1421 print '<td class="right" width="120">'.$langs->trans("RemainderToPay").'</td>';
1422 } elseif (empty($value['disableamount'])) {
1423 print '<td class="right" width="120">'.$langs->trans("AmountTTC").'</td>';
1424 } else {
1425 print '<td width="120"></td>';
1426 }
1427 // Status
1428 if (in_array($tablename, array('projet_task'))) {
1429 print '<td class="right" width="200">'.$langs->trans("ProgressDeclared").'</td>';
1430 } else {
1431 print '<td class="right" width="200">'.$langs->trans("Status").'</td>';
1432 }
1433 print '</tr>';
1434
1435 if (is_array($elementarray) && count($elementarray) > 0) {
1436 $total_ht = 0;
1437 $total_ttc = 0;
1438 $i = 0;
1439
1440 $total_ht_by_third = 0;
1441 $total_ttc_by_third = 0;
1442
1443 $saved_third_id = 0;
1444 $breakline = '';
1445
1446 if (canApplySubtotalOn($tablename)) {
1447 // Sort
1448 $elementarray = sortElementsByClientName($elementarray);
1449 }
1450
1451 $num = count($elementarray);
1452 $total_time = 0;
1453 for ($i = 0; $i < $num; $i++) {
1454 $tmp = explode('_', $elementarray[$i]);
1455 $idofelement = (int) $tmp[0];
1456 $idofelementuser = isset($tmp[1]) ? (int) $tmp[1] : 0;
1457
1458 $element->fetch($idofelement);
1459 if ($idofelementuser) {
1460 $elementuser->fetch($idofelementuser);
1461 }
1462
1463 // Special cases
1464 if ($tablename != 'expensereport_det') {
1465 if (method_exists($element, 'fetch_thirdparty')) {
1466 $element->fetch_thirdparty();
1467 }
1468 } else {
1469 $expensereport = new ExpenseReport($db);
1470 $expensereport->fetch($element->fk_expensereport);
1471 }
1472
1473 //print 'xxx'.$tablename.'yyy'.$classname;
1474
1475 if ($breakline && $saved_third_id != $element->thirdparty->id) {
1476 print $breakline;
1477
1478 $saved_third_id = $element->thirdparty->id;
1479 $breakline = '';
1480
1481 $total_ht_by_third = 0;
1482 $total_ttc_by_third = 0;
1483 }
1484
1485 $saved_third_id = empty($element->thirdparty->id) ? 0 : $element->thirdparty->id;
1486
1487 $qualifiedfortotal = true;
1488 if ($key == 'invoice') {
1489 if (!empty($element->close_code) && $element->close_code == 'replaced') {
1490 $qualifiedfortotal = false; // Replacement invoice, do not include into total
1491 }
1492 } elseif ($key == 'order_supplier' && ($element->status == 6 || $element->status == 7)) {
1493 $qualifiedfortotal = false; // It makes no sense to include canceled orders in the total
1494 }
1495
1496 if ($key == "order_supplier" && ($element->status == 6 || $element->status == 7)) {
1497 print '<tr class="oddeven tr_canceled">';
1498 } elseif ($key == "order_supplier" && ($element->billed)) {
1499 print '<tr class="oddeven tr_paid">';
1500 } else {
1501 print '<tr class="oddeven" >';
1502 }
1503
1504
1505 // Remove link
1506 print '<td style="width: 24px">';
1507 if ($tablename != 'projet_task' && $tablename != 'stock_mouvement') {
1508 if ($permissiontoadd && (!getDolGlobalString('PROJECT_DISABLE_UNLINK_FROM_OVERVIEW') || $user->admin)) { // PROJECT_DISABLE_UNLINK_FROM_OVERVIEW is empty by default, so this test true
1509 print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=unlink&tablename='.$tablename.'&elementselect='.$element->id.($project_field ? '&projectfield='.$project_field : '').'" class="reposition">';
1510 print img_picto($langs->trans('Unlink'), 'unlink');
1511 print '</a>';
1512 }
1513 }
1514 print "</td>\n";
1515
1516 // Ref
1517 print '<td class="left nowraponall">';
1518 if ($tablename == 'expensereport_det') {
1519 print $expensereport->getNomUrl(1);
1520 } else {
1521 print '<table><tr><td style="border-bottom: none;">';
1522 // Show ref with link
1523 if ($element instanceof Task) {
1524 print $element->getNomUrl(1, 'withproject', 'time');
1525 print ' - '.dol_trunc($element->label, 48);
1526 } elseif ($key == 'loan') {
1527 print $element->getNomUrl(1);
1528 print ' - '.dol_trunc($element->label, 48);
1529 } else {
1530 print $element->getNomUrl(1);
1531 }
1532
1533 $element_doc = $element->element;
1534 $filename = dol_sanitizeFileName($element->ref);
1535 if (!empty($conf->$element_doc)) {
1536 $confelementdoc = $conf->$element_doc;
1537 $filedir = $confelementdoc->multidir_output[$element->entity ?? $conf->entity].'/'.dol_sanitizeFileName($element->ref);
1538 } else {
1539 $filedir = '';
1540 }
1541
1542 if ($element_doc === 'order_supplier') {
1543 $element_doc = 'commande_fournisseur';
1544 $filedir = $conf->fournisseur->commande->multidir_output[$element->entity ?? $conf->entity].'/'.dol_sanitizeFileName($element->ref);
1545 } elseif ($element_doc === 'invoice_supplier') {
1546 $element_doc = 'facture_fournisseur';
1547 $filename = get_exdir($element->id, 2, 0, 0, $element, 'invoice_supplier').dol_sanitizeFileName($element->ref);
1548 $filedir = $conf->fournisseur->facture->multidir_output[$element->entity ?? $conf->entity].'/'.$filename;
1549 }
1550
1551 print '<div class="inline-block valignmiddle">';
1552 if ($filedir) {
1553 print $formfile->getDocumentsLink($element_doc, $filename, $filedir);
1554 }
1555 print '</div>';
1556
1557 print '</td>';
1558
1559 print '<td class="tdoverflowmax250" style="border-bottom: none;">';
1560
1561 // Show supplier ref
1562 if (!empty($element->ref_supplier)) {
1563 print ' - '.$element->ref_supplier;
1564 }
1565 // Show customer ref
1566 if (!empty($element->ref_customer)) {
1567 print ' - '.$element->ref_customer;
1568 }
1569 // Compatibility propale
1570 if (empty($element->ref_customer) && !empty($element->ref_client)) {
1571 print ' - '.$element->ref_client;
1572 }
1573
1574 print '</td></tr></table>';
1575 }
1576 print "</td>\n";
1577 // Product and qty on stock movement
1578 if ('MouvementStock' == $classname) {
1579 '@phan-var-force MouvementStock $element';
1580 $mvsProd = new Product($element->db);
1581 $mvsProd->fetch($element->product_id);
1582 print '<td>'.$mvsProd->getNomUrl(1).'</td>';
1583 print '<td>'.$element->qty.'</td>';
1584 }
1585 // Date or TimeSpent
1586 $date = '';
1587 $total_time_by_line = 0;
1588 if ($tablename == 'expensereport_det') {
1589 '@phan-var-force ExpenseReportLine $element';
1590 $date = $element->date; // No draft status on lines
1591 } elseif ($tablename == 'stock_mouvement') {
1592 '@phan-var-force MouvementStock $element';
1593 $date = $element->datem;
1594 } elseif ($tablename == 'salary') {
1595 '@phan-var-force Salary $element';
1596 $date = $element->datesp;
1597 } elseif ($tablename == 'payment_various') {
1598 '@phan-var-force PaymentVarious $element';
1599 $date = $element->datev;
1600 } elseif ($tablename == 'chargesociales') {
1601 '@phan-var-force ChargeSociales $element';
1602 $date = $element->date_ech;
1603 } elseif (!empty($element->status) || !empty($element->statut) || !empty($element->fk_status)) {
1604 if ($tablename == 'don') {
1605 '@phan-var-force Don $element';
1606 $date = $element->date;
1607 }
1608 if ($tablename == 'commande_fournisseur' || $tablename == 'supplier_order') {
1609 '@phan-var-force CommandeFournisseur $element';
1610 $date = ($element->date_commande ? $element->date_commande : $element->date_valid);
1611 } elseif ($tablename == 'supplier_proposal') {
1612 '@phan-var-force SupplierProposal $element';
1613 $date = $element->date_validation; // There is no other date for this
1614 } elseif ($tablename == 'fichinter') {
1615 '@phan-var-force Fichinter $element';
1616 $date = $element->datev; // There is no other date for this
1617 } elseif ($tablename == 'projet_task') {
1618 '@phan-var-force Task $element';
1619 $date = ''; // We show no date. Showing date of beginning of task make user think it is date of time consumed
1620 } else {
1621 $date = $element->date; // invoice, ...
1622 if (empty($date)) {
1623 $date = $element->date_contrat;
1624 }
1625 if (empty($date)) {
1626 $date = $element->datev;
1627 }
1628 if (empty($date) && !empty($datefieldname)) {
1629 // @phan-suppress-next-line PhanUndeclaredProperty
1630 $date = $element->$datefieldname;
1631 }
1632 }
1633 } elseif ($key == 'loan') {
1634 '@phan-var-force Loan $element';
1635 $date = $element->datestart;
1636 }
1637
1638 print '<td class="center">';
1639 if ($tablename == 'actioncomm') {
1640 '@phan-var-force ActionComm $element';
1641 print dol_print_date($element->datep, 'dayhour');
1642 if ($element->datef && $element->datef > $element->datep) {
1643 print " - ".dol_print_date($element->datef, 'dayhour');
1644 }
1645 } elseif (in_array($tablename, array('projet_task'))) {
1646 '@phan-var-force Task $element';
1647 $tmpprojtime = $element->getSumOfAmount($idofelementuser ? $elementuser : '', (string) $dates, (string) $datee); // $element is a task. $elementuser may be empty
1648 print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$idofelement.'&withproject=1">';
1649 print convertSecondToTime($tmpprojtime['nbseconds'], 'allhourmin');
1650 print '</a>';
1651 $total_time_by_line = $tmpprojtime['nbseconds'];
1652 } else {
1653 print dol_print_date($date, 'day');
1654 }
1655 print '</td>';
1656
1657 // Third party or user
1658 print '<td class="tdoverflowmax150">';
1659 if (is_object($element->thirdparty)) {
1660 print $element->thirdparty->getNomUrl(1, '', 48);
1661 } elseif ($tablename == 'expensereport_det') {
1662 $tmpuser = new User($db);
1663 $tmpuser->fetch($expensereport->fk_user_author);
1664 print $tmpuser->getNomUrl(1, '', 48);
1665 } elseif ($tablename == 'salary') {
1666 $tmpuser = new User($db);
1667 $tmpuser->fetch($element->fk_user);
1668 print $tmpuser->getNomUrl(1, '', 48);
1669 } elseif ($tablename == 'don' || $tablename == 'stock_mouvement') {
1670 '@phan-var-force Don|MouvementStock $element';
1671 if ($element->fk_user_author > 0) {
1672 $tmpuser2 = new User($db);
1673 $tmpuser2->fetch($element->fk_user_author);
1674 print $tmpuser2->getNomUrl(1, '', 48);
1675 }
1676 } elseif ($tablename == 'projet_task' && $key == 'element_time') { // if $key == 'project_task', we don't want details per user
1677 print $elementuser->getNomUrl(1);
1678 } elseif ($tablename == 'payment_various') { // payment label
1679 '@phan-var-force PaymentVarious $element';
1680 print $element->label;
1681 }
1682 print '</td>';
1683
1684 // Add duration and store it in counter for fichinter
1685 if ($tablename == 'fichinter') {
1686 '@phan-var-force FichInter $element';
1687 print '<td>';
1688 print convertSecondToTime($element->duration, 'all', $conf->global->MAIN_DURATION_OF_WORKDAY);
1689 $total_duration += $element->duration;
1690 print '</td>';
1691 }
1692
1693 // Type from Expense Report
1694 if ($tablename == 'expensereport_det') {
1695 print '<td class="left linecoltype">';
1696 $labeltype = ($langs->trans(($element->type_fees_code)) == $element->type_fees_code ? $element->type_fees_libelle : $langs->trans($element->type_fees_code));
1697 print (string) $labeltype;
1698 print '</td>';
1699 }
1700 // Description from Expense Report
1701 if ($tablename == 'expensereport_det') {
1702 print '<td class="left linecolcomment">';
1703 print (string) $element->comments;
1704 print '</td>';
1705 }
1706
1707
1708 // Amount without tax
1709 $warning = '';
1710 if (empty($value['disableamount'])) {
1711 $total_ht_by_line = null;
1712 $othermessage = '';
1713 if ($tablename == 'don' || $tablename == 'chargesociales' || $tablename == 'payment_various' || $tablename == 'salary') {
1714 '@phan-var-force Don|ChargeSociales|PaymentVarious|Salary $element';
1715 $total_ht_by_line = $element->amount;
1716 } elseif ($tablename == 'fichinter') {
1717 '@phan-var-force FichInter $element';
1718 $total_ht_by_line = $element->getAmount();
1719 } elseif ($tablename == 'stock_mouvement') {
1720 '@phan-var-force MouvementStock $element';
1721 $total_ht_by_line = $element->price * abs($element->qty);
1722 } elseif (in_array($tablename, array('projet_task'))) {
1723 if (isModEnabled('salaries')) {
1724 // TODO Permission to read daily rate to show value
1725 $total_ht_by_line = price2num($tmpprojtime['amount'], 'MT');
1726 if (isset($tmpprojtime['nblinesnull']) && ($tmpprojtime['nblinesnull'] > 0)) {
1727 $langs->load("errors");
1728 $warning = $langs->trans("WarningSomeLinesWithNullHourlyRate", $conf->currency);
1729 }
1730 } else {
1731 $othermessage = $form->textwithpicto($langs->trans("NotAvailable"), $langs->trans("ModuleSalaryToDefineHourlyRateMustBeEnabled"));
1732 }
1733 } elseif ($key == 'loan') {
1734 '@phan-var-force Loan $element';
1735 $total_ht_by_line = $element->capital;
1736 } else {
1737 $total_ht_by_line = $element->total_ht;
1738 }
1739
1740 // Change sign of $total_ht_by_line and $total_ttc_by_line for some cases
1741 if ($tablename == 'payment_various') {
1742 if ($element->sens == 0) {
1743 $total_ht_by_line = -$total_ht_by_line;
1744 }
1745 }
1746
1747 print '<td class="right">';
1748 if ($othermessage) {
1749 print '<span class="opacitymedium">'.$othermessage.'</span>';
1750 }
1751 if (isset($total_ht_by_line)) {
1752 if (!$qualifiedfortotal) {
1753 print '<strike>';
1754 }
1755 print '<span class="amount">'.price($total_ht_by_line).'</span>';
1756 if (!$qualifiedfortotal) {
1757 print '</strike>';
1758 }
1759 }
1760 if ($warning) {
1761 print ' '.img_warning($warning);
1762 }
1763 if (isset($tmpprojtime['nblinesnull']) && ($tmpprojtime['nblinesnull'] > 0)) {
1764 if ($tmpprojtime['nbuserthmnull'] > 0) {
1765 $title = $langs->trans("EnterUsersHourlyRateFirst");
1766 print ' '.img_picto($title, "sync", '', 0, 0, 0, '', 'opacitymedium');
1767 } else {
1768 $title = $langs->trans("UpdateUndefinedWithLastHourlyRate");
1769 print ' <a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$id.'&action=updateundefinedwithlasthourlyrate&taskid='.$idofelement.'&token='.currentToken().'">'.img_picto($title, "sync", '', 0, 0, 0, '', 'warning').'</a>';
1770 }
1771 }
1772 if (getDolGlobalString('PROJECT_CAN_OVERWRITE_TIMESTPENT_HOURLY_RATE_WITH_LASTONE')) {
1773 $title = $langs->trans("UpdateWithLastHourlyRate");
1774 print ' <a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$id.'&action=updateallwithlasthourlyrate&taskid='.$idofelement.'&token='.currentToken().'">'.img_picto($title, "sync", '', 0, 0, 0, '', '').'</a>';
1775 }
1776 print '</td>';
1777 } else {
1778 print '<td></td>';
1779 }
1780
1781 // Amount inc tax
1782 if (empty($value['disableamount'])) {
1783 $total_ttc_by_line = null;
1784 if ($tablename == 'don' || $tablename == 'chargesociales' || $tablename == 'payment_various' || $tablename == 'salary') {
1785 '@phan-var-force Don|ChargeSociales|PaymentVarious $element';
1786 $total_ttc_by_line = $element->amount;
1787 } elseif ($tablename == 'fichinter') {
1788 '@phan-var-force Fichinter $element';
1789 $total_ttc_by_line = $element->getAmount();
1790 } elseif ($tablename == 'stock_mouvement') {
1791 '@phan-var-force MouvementStock $element';
1792 $total_ttc_by_line = $element->price * abs($element->qty);
1793 } elseif ($tablename == 'projet_task') {
1794 if (isModEnabled('salaries')) {
1795 // TODO Permission to read daily rate
1796 $defaultvat = get_default_tva($mysoc, $mysoc);
1797 $total_ttc_by_line = price2num($total_ht_by_line * (1 + ($defaultvat / 100)), 'MT');
1798 } else {
1799 $othermessage = $form->textwithpicto($langs->trans("NotAvailable"), $langs->trans("ModuleSalaryToDefineHourlyRateMustBeEnabled"));
1800 }
1801 } elseif ($key == 'loan') {
1802 '@phan-var-force Loan $element';
1803 $total_ttc_by_line = $element->capital - $element->getSumPayment();
1804 } else {
1805 $total_ttc_by_line = $element->total_ttc;
1806 }
1807
1808 // Change sign of $total_ht_by_line and $total_ttc_by_line for some cases
1809 if ($tablename == 'payment_various') {
1810 if ($element->sens == 0) {
1811 $total_ttc_by_line = -$total_ttc_by_line;
1812 }
1813 }
1814
1815 print '<td class="right">';
1816 if ($othermessage) {
1817 print $othermessage;
1818 }
1819 if (isset($total_ttc_by_line)) {
1820 if (!$qualifiedfortotal) {
1821 print '<strike>';
1822 }
1823 print '<span class="amount">'.price($total_ttc_by_line).'</span>';
1824 if (!$qualifiedfortotal) {
1825 print '</strike>';
1826 }
1827 }
1828 if ($warning) {
1829 print ' '.img_warning($warning);
1830 }
1831 if (isset($tmpprojtime['nblinesnull']) && ($tmpprojtime['nblinesnull'] > 0)) {
1832 if ($tmpprojtime['nbuserthmnull'] > 0) {
1833 $title = $langs->trans("EnterUsersHourlyRateFirst");
1834 print ' '.img_picto($title, "sync", '', 0, 0, 0, '', 'opacitymedium');
1835 } else {
1836 $title = $langs->trans("UpdateUndefinedWithLastHourlyRate");
1837 print ' <a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$id.'&action=updateundefinedwithlasthourlyrate&taskid='.$idofelement.'&token='.currentToken().'">'.img_picto($title, "sync", '', 0, 0, 0, '', 'warning').'</a>';
1838 }
1839 }
1840 if (getDolGlobalString('PROJECT_CAN_OVERWRITE_TIMESTPENT_HOURLY_RATE_WITH_LASTONE')) {
1841 $title = $langs->trans("UpdateWithLastHourlyRate");
1842 print ' <a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$id.'&action=updateallwithlasthourlyrate&taskid='.$idofelement.'&token='.currentToken().'">'.img_picto($title, "sync").'</a>';
1843 }
1844 print '</td>';
1845 } else {
1846 print '<td></td>';
1847 }
1848
1849 // Status
1850 print '<td class="right">';
1851 if ($tablename == 'expensereport_det') {
1852 print $expensereport->getLibStatut(5);
1853 } elseif ($element instanceof CommonInvoice) {
1854 //This applies for Facture and FactureFournisseur
1855 print $element->getLibStatut(5, $element->getSommePaiement());
1856 } elseif ($element instanceof Task) {
1857 if ($element->progress != '') {
1858 print $element->progress.' %';
1859 }
1860 } elseif ($tablename == 'stock_mouvement') {
1861 '@phan-var-force MouvementStock $element';
1862 print $element->getLibStatut(3);
1863 } else {
1864 print $element->getLibStatut(5);
1865 }
1866 print '</td>';
1867
1868 print '</tr>';
1869
1870 if ($qualifiedfortotal) {
1871 $total_ht += $total_ht_by_line;
1872 $total_ttc += $total_ttc_by_line;
1873
1874 $total_ht_by_third += $total_ht_by_line;
1875 $total_ttc_by_third += $total_ttc_by_line;
1876
1877 if (!isset($total_time)) {
1878 $total_time = $total_time_by_line;
1879 } else {
1880 $total_time += $total_time_by_line;
1881 }
1882 }
1883
1884 if (canApplySubtotalOn($tablename)) {
1885 $breakline = '<tr class="liste_total liste_sub_total">';
1886 $breakline .= '<td colspan="2">';
1887 $breakline .= '</td>';
1888 $breakline .= '<td>';
1889 $breakline .= '</td>';
1890 $breakline .= '<td class="right">';
1891 $breakline .= $langs->trans('SubTotal').' : ';
1892 if (is_object($element->thirdparty)) {
1893 $breakline .= $element->thirdparty->getNomUrl(0, '', 48);
1894 }
1895 $breakline .= '</td>';
1896 $breakline .= '<td class="right">'.price($total_ht_by_third).'</td>';
1897 $breakline .= '<td class="right">'.price($total_ttc_by_third).'</td>';
1898 $breakline .= '<td></td>';
1899 $breakline .= '</tr>';
1900 }
1901
1902 //var_dump($element->thirdparty->name.' - '.$saved_third_id.' - '.$element->thirdparty->id);
1903 }
1904
1905 if ($breakline) {
1906 print $breakline;
1907 }
1908
1909 // Total
1910 if (empty($nototal)) {
1911 $colspan = 4;
1912 if (in_array($tablename, array('projet_task'))) {
1913 $colspan = 2;
1914 }
1915
1916 print '<tr class="liste_total"><td colspan="'.$colspan.'">'.$langs->trans("Number").': '.$i.'</td>';
1917 if (in_array($tablename, array('projet_task'))) {
1918 print '<td class="center">';
1919 print convertSecondToTime((int) $total_time, 'allhourmin');
1920 print '</td>';
1921 print '<td>';
1922 print '</td>';
1923 }
1924 //if (empty($value['disableamount']) && ! in_array($tablename, array('projet_task'))) print '<td class="right" width="100">'.$langs->trans("TotalHT").' : '.price($total_ht).'</td>';
1925 //elseif (empty($value['disableamount']) && in_array($tablename, array('projet_task'))) print '<td class="right" width="100">'.$langs->trans("Total").' : '.price($total_ht).'</td>';
1926 // If fichinter add the total_duration
1927 if ($tablename == 'fichinter') {
1928 print '<td class="left">'.convertSecondToTime($total_duration, 'all', $conf->global->MAIN_DURATION_OF_WORKDAY).'</td>';
1929 }
1930 print '<td class="right">';
1931 if (empty($value['disableamount'])) {
1932 if ($key == 'loan') {
1933 print $langs->trans("Total").' '.$langs->trans("LoanCapital").' : '.price($total_ttc);
1934 } elseif ($tablename != 'projet_task' || isModEnabled('salaries')) {
1935 print ''.$langs->trans("TotalHT").' : '.price($total_ht);
1936 }
1937 }
1938 print '</td>';
1939 //if (empty($value['disableamount']) && ! in_array($tablename, array('projet_task'))) print '<td class="right" width="100">'.$langs->trans("TotalTTC").' : '.price($total_ttc).'</td>';
1940 //elseif (empty($value['disableamount']) && in_array($tablename, array('projet_task'))) print '<td class="right" width="100"></td>';
1941 print '<td class="right">';
1942 if (empty($value['disableamount'])) {
1943 if ($key == 'loan') {
1944 print $langs->trans("Total").' '.$langs->trans("RemainderToPay").' : '.price($total_ttc);
1945 } elseif ($tablename != 'projet_task' || isModEnabled('salaries')) {
1946 print $langs->trans("TotalTTC").' : '.price($total_ttc);
1947 }
1948 }
1949 print '</td>';
1950 print '<td>&nbsp;</td>';
1951 // Because of the added Type and Description columns to Expense Reports
1952 if ($tablename == 'expensereport_det') {
1953 print '<td>&nbsp;</td>';
1954 print '<td>&nbsp;</td>';
1955 }
1956 print '</tr>';
1957 }
1958 } else {
1959 if (!is_array($elementarray)) { // error
1960 print '<tr><td>'.$elementarray.'</td></tr>';
1961 } else {
1962 $colspan = 7;
1963 if ($tablename == 'fichinter') {
1964 $colspan++;
1965 }
1966 print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("None").'</td></tr>';
1967 }
1968 }
1969 print "</table>";
1970 print '</div>';
1971 print "<br>\n";
1972 }
1973}
1974
1975// Enhance with select2
1976if ($conf->use_javascript_ajax) {
1977 include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
1978 $comboenhancement = ajax_combobox('.elementselect');
1979
1980 print $comboenhancement;
1981}
1982
1983// End of page
1984llxFooter();
1985$db->close();
1986
1987
1988
1995function canApplySubtotalOn($tablename)
1996{
1997 global $conf;
1998
1999 if (!getDolGlobalString('PROJECT_ADD_SUBTOTAL_LINES')) {
2000 return false;
2001 }
2002 return in_array($tablename, array('facture_fourn', 'commande_fournisseur'));
2003}
2004
2011function sortElementsByClientName($elementarray)
2012{
2013 global $db, $classname;
2014 '@phan-var-force string $classname';
2015
2016 $element = new $classname($db);
2017 '@phan-var-force CommonObject $element';
2018
2019 $clientname = array();
2020 foreach ($elementarray as $key => $id) { // id = id of object
2021 if (empty($clientname[$id])) {
2022 $element->fetch($id);
2023 $element->fetch_thirdparty();
2024
2025 $clientname[$id] = $element->thirdparty->name;
2026 }
2027 }
2028
2029 //var_dump($clientname);
2030 asort($clientname); // sort on name
2031
2032 $elementarray = array();
2033 foreach ($clientname as $id => $name) {
2034 $elementarray[] = $id;
2035 }
2036
2037 return $elementarray;
2038}
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='')
Convert a html select field into an ajax combobox.
Definition ajax.lib.php:475
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
Superclass for invoice classes.
Class for ConferenceOrBoothAttendee.
Class to manage Trips and Expenses.
const TYPE_DEPOSIT
Deposit invoice.
Class to offer components to list and upload files.
Class to manage generation of HTML components Only common components must be here.
Class to manage building of HTML components.
Class to manage Schedule of loans.
Class to manage products or services.
Class to manage projects.
const STATUS_SIGNED
Signed quote.
const STATUS_BILLED
Billed or processed quote.
Class to manage tasks.
Class for TimeSpent.
Class to manage Dolibarr users.
global $mysoc
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
Definition date.lib.php:618
convertSecondToTime($iSecond, $format='all', $lengthOfDay=86400, $lengthOfWeek=7)
Return, in clear text, value of a number of seconds in days, hours and minutes.
Definition date.lib.php:262
dol_stringtotime($string, $gm=1)
Convert a string date into a GM Timestamps date Warning: YYYY-MM-DDTHH:MM:SS+02:00 (RFC3339) is not s...
Definition date.lib.php:449
sortElementsByClientName($elementarray)
sortElementsByClientName
Definition element.php:2011
canApplySubtotalOn($tablename)
Return if we should do a group by customer with sub-total.
Definition element.php:1995
dol_now($mode='gmt')
Return date for now.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='', $useCache=true)
Return an id or code from a code or id.
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)
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
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.
dolPrintHTML($s, $allowiframe=0)
Return a string (that can be on several lines) ready to be output on a HTML page.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
currentToken()
Return the value of token currently saved into session with name 'token'.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
dol_eval($s, $returnvalue=1, $hideerrors=1, $onlysimplestring='1')
Replace eval function to add more security.
setEventMessage($mesgs, $style='mesgs', $noduplicate=0, $attop=0)
Set event message in dol_events session object.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
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.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_clone($srcobject, $native=2)
Create a clone of instance of object (new instance with same value for each properties) With native =...
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...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that return vat rate of a product line (according to seller, buyer and product vat rate) VAT...
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart='')
Return a path to have a the directory according to object where files are stored.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
project_prepare_head(Project $project, $moreparam='')
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.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.