dolibarr 24.0.2
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('don')) {
72 require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php';
73}
74if (isModEnabled('shipping')) {
75 require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
76}
77if (isModEnabled('expensereport')) {
78 require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
79}
80if (isModEnabled('invoice')) {
81 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
82 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture-rec.class.php';
83}
84if (isModEnabled('intervention')) {
85 require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
86}
87if (isModEnabled('loan')) {
88 require_once DOL_DOCUMENT_ROOT.'/loan/class/loan.class.php';
89 require_once DOL_DOCUMENT_ROOT.'/loan/class/loanschedule.class.php';
90}
91if (isModEnabled('mrp')) {
92 require_once DOL_DOCUMENT_ROOT.'/mrp/class/mo.class.php';
93}
94if (isModEnabled('propal')) {
95 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
96}
97if (isModEnabled('salaries')) {
98 require_once DOL_DOCUMENT_ROOT.'/salaries/class/salary.class.php';
99}
100if (isModEnabled('stock')) {
101 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
102 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
103}
104if (isModEnabled('supplier_invoice')) {
105 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
106}
107if (isModEnabled('supplier_order')) {
108 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
109}
110if (isModEnabled('supplier_proposal')) {
111 require_once DOL_DOCUMENT_ROOT.'/supplier_proposal/class/supplier_proposal.class.php';
112}
113if (isModEnabled('tax')) {
114 require_once DOL_DOCUMENT_ROOT.'/compta/sociales/class/chargesociales.class.php';
115}
116if (isModEnabled('stocktransfer')) {
117 require_once DOL_DOCUMENT_ROOT.'/product/stock/stocktransfer/class/stocktransfer.class.php';
118 require_once DOL_DOCUMENT_ROOT.'/product/stock/stocktransfer/class/stocktransferline.class.php';
119}
120
121// Load translation files required by the page
122$langs->loadLangs(array('projects', 'companies', 'suppliers', 'compta'));
123if (isModEnabled('invoice')) {
124 $langs->load("bills");
125}
126if (isModEnabled('order')) {
127 $langs->load("orders");
128}
129if (isModEnabled("propal")) {
130 $langs->load("propal");
131}
132if (isModEnabled('intervention')) {
133 $langs->load("interventions");
134}
135if (isModEnabled('deplacement')) {
136 $langs->load("trips");
137}
138if (isModEnabled('expensereport')) {
139 $langs->load("trips");
140}
141if (isModEnabled('don')) {
142 $langs->load("donations");
143}
144if (isModEnabled('loan')) {
145 $langs->load("loan");
146}
147if (isModEnabled('salaries')) {
148 $langs->load("salaries");
149}
150if (isModEnabled('mrp')) {
151 $langs->load("mrp");
152}
153if (isModEnabled('eventorganization')) {
154 $langs->load("eventorganization");
155}
156
157$id = GETPOSTINT('id');
158$ref = GETPOST('ref', 'alpha');
159$action = GETPOST('action', 'aZ09');
160$datesrfc = GETPOST('datesrfc'); // deprecated
161$dateerfc = GETPOST('dateerfc'); // deprecated
162$dates = dol_mktime(0, 0, 0, GETPOSTINT('datesmonth'), GETPOSTINT('datesday'), GETPOSTINT('datesyear'));
163$datee = dol_mktime(23, 59, 59, GETPOSTINT('dateemonth'), GETPOSTINT('dateeday'), GETPOSTINT('dateeyear'));
164if (empty($dates) && !empty($datesrfc)) { // deprecated
165 $dates = dol_stringtotime($datesrfc);
166}
167if (empty($datee) && !empty($dateerfc)) { // deprecated
168 $datee = dol_stringtotime($dateerfc);
169}
170if (!GETPOSTISSET('datesrfc') && !GETPOSTISSET('datesday') && getDolGlobalString('PROJECT_LINKED_ELEMENT_DEFAULT_FILTER_YEAR')) {
171 $new = dol_now();
172 $tmp = dol_getdate($new);
173 //$datee=$now
174 //$dates=dol_time_plus_duree($datee, -1, 'y');
175 $dates = dol_get_first_day($tmp['year'], 1);
176}
177if ($id == '' && $ref == '') {
178 setEventMessage($langs->trans('ErrorBadParameters'), 'errors');
179 header('Location: list.php');
180 exit();
181}
182
183$mine = GETPOST('mode') == 'mine' ? 1 : 0;
184
185$object = new Project($db);
186
187include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be 'include', not 'include_once'
188if (getDolGlobalString('PROJECT_ALLOW_COMMENT_ON_PROJECT') && method_exists($object, 'fetchComments') && empty($object->comments)) {
189 $object->fetchComments();
190}
191
192// Security check
193$socid = $object->socid;
194
195$hookmanager->initHooks(array('projectOverview'));
196
197//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.
198$result = restrictedArea($user, 'projet', $object->id, 'projet&project');
199
200// Check if user has access to any financial module (not just project time)
201$canSeeFinancials = (
202 (isModEnabled('invoice') && $user->hasRight('facture', 'lire'))
203 || (isModEnabled('supplier_invoice') && ($user->hasRight('fournisseur', 'facture', 'lire') || $user->hasRight('supplier_invoice', 'lire')))
204 || (isModEnabled('salaries') && $user->hasRight('salaries', 'read'))
205 || (isModEnabled('expensereport') && $user->hasRight('expensereport', 'lire'))
206 || (isModEnabled('don') && $user->hasRight('don', 'lire'))
207 || (isModEnabled('tax') && $user->hasRight('tax', 'charges', 'lire'))
208 || (isModEnabled('bank') && $user->hasRight('banque', 'lire'))
209);
210
211$total_duration = 0;
212$total_ttc_by_line = 0;
213$total_ht_by_line = 0;
214$expensereport = null;
215$othermessage = '';
216$tmpprojtime = array();
217$nbAttendees = 0;
218
219$extrafields->fetch_name_optionals_label($object->table_element);
220$object->fetch_optionals();
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 {
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 'expensereport' => array(
663 'name' => "ExpenseReports",
664 'title' => "ListExpenseReportsAssociatedProject",
665 'class' => 'ExpenseReportLine',
666 'table' => 'expensereport_det',
667 'datefieldname' => 'date',
668 'margin' => 'minus',
669 'disableamount' => 0,
670 'urlnew' => DOL_URL_ROOT.'/expensereport/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('expensereport', 'creer'),
674 'test' => isModEnabled('expensereport') && $user->hasRight('expensereport', 'lire')
675 ),
676 'donation' => array(
677 'name' => "Donation",
678 'title' => "ListDonationsAssociatedProject",
679 'class' => 'Don',
680 'margin' => 'add',
681 'table' => 'don',
682 'datefieldname' => 'datedon',
683 'disableamount' => 0,
684 'urlnew' => DOL_URL_ROOT.'/don/card.php?action=create&projectid='.$id.'&socid='.$socid.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
685 'lang' => 'donations',
686 'buttonnew' => 'AddDonation',
687 'testnew' => $user->hasRight('don', 'creer'),
688 'test' => isModEnabled('don') && $user->hasRight('don', 'lire')
689 ),
690 'loan' => array(
691 'name' => "Loan",
692 'title' => "ListLoanAssociatedProject",
693 'class' => 'Loan',
694 'margin' => '',
695 'table' => 'loan',
696 'datefieldname' => 'datestart',
697 'disableamount' => 0,
698 'urlnew' => DOL_URL_ROOT.'/loan/card.php?action=create&projectid='.$id.'&socid='.$socid.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
699 'lang' => 'loan',
700 'buttonnew' => 'AddLoan',
701 'testnew' => $user->hasRight('loan', 'write'),
702 'test' => isModEnabled('loan') && $user->hasRight('loan', 'read')
703 ),
704 'chargesociales' => array(
705 'name' => "SocialContribution",
706 'title' => "ListSocialContributionAssociatedProject",
707 'class' => 'ChargeSociales',
708 'margin' => 'minus',
709 'table' => 'chargesociales',
710 'datefieldname' => 'date_ech',
711 'disableamount' => 0,
712 'urlnew' => DOL_URL_ROOT.'/compta/sociales/card.php?action=create&projectid='.$id.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
713 'lang' => 'compta',
714 'buttonnew' => 'AddSocialContribution',
715 'testnew' => $user->hasRight('tax', 'charges', 'lire'),
716 'test' => isModEnabled('tax') && $user->hasRight('tax', 'charges', 'lire')
717 ),
718 'project_task' => array(
719 'name' => "TaskTimeSpent",
720 'title' => "ListTaskTimeUserProject",
721 'class' => 'Task',
722 'margin' => 'minus',
723 'table' => 'projet_task',
724 'datefieldname' => 'element_date',
725 'disableamount' => ($canSeeFinancials ? 0 : 1),
726 'urlnew' => DOL_URL_ROOT.'/projet/tasks/time.php?withproject=1&action=createtime&projectid='.$id.'&token='.newToken().'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
727 'buttonnew' => 'AddTimeSpent',
728 'testnew' => $user->hasRight('project', 'creer'),
729 'test' => isModEnabled('project') && $user->hasRight('projet', 'lire') && !getDolGlobalString('PROJECT_HIDE_TASKS')
730 ),
731 'stocktransfer' => array(
732 'name' => "StockTransfer",
733 'title' => "ListStockTransferProject",
734 'class' => 'StockTransfer',
735 'table' => 'stocktransfer_stocktransfer',
736 'datefieldname' => 'datem',
737 'margin' => '',
738 'project_field' => 'fk_project',
739 'disableamount' => 1,
740 'urlnew' => DOL_URL_ROOT.'/product/stock/stocktransfer/stocktransfer_card.php?action=create&projectid='.$id.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
741 'lang' => 'stocks',
742 'buttonnew' => 'StockTransferNew',
743 'testnew' => $user->hasRight('stocktransfer', 'stocktransfer', 'write'),
744 'test' => isModEnabled('stocktransfer') && $user->hasRight('stocktransfer', 'stocktransfer', 'read')
745 ),
746 'stock_mouvement' => array(
747 'name' => "MouvementStockAssociated",
748 'title' => "ListMouvementStockProject",
749 'class' => 'MouvementStock',
750 'table' => 'stock_mouvement',
751 'datefieldname' => 'datem',
752 'margin' => 'minus',
753 'project_field' => 'fk_project',
754 'disableamount' => 0,
755 'test' => isModEnabled('stock') && $user->hasRight('stock', 'mouvement', 'lire') && getDolGlobalString('STOCK_MOVEMENT_INTO_PROJECT_OVERVIEW')
756 ),
757 'salaries' => array(
758 'name' => "Salaries",
759 'title' => "ListSalariesAssociatedProject",
760 'class' => 'Salary',
761 'table' => 'salary',
762 'datefieldname' => 'datesp',
763 'margin' => 'minus',
764 'disableamount' => 0,
765 'urlnew' => DOL_URL_ROOT.'/salaries/card.php?action=create&projectid='.$id.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
766 'lang' => 'salaries',
767 'buttonnew' => 'AddSalary',
768 'testnew' => $user->hasRight('salaries', 'write'),
769 'test' => isModEnabled('salaries') && $user->hasRight('salaries', 'read')
770 ),
771 'variouspayment' => array(
772 'name' => "VariousPayments",
773 'title' => "ListVariousPaymentsAssociatedProject",
774 'class' => 'PaymentVarious',
775 'table' => 'payment_various',
776 'datefieldname' => 'datev',
777 'margin' => 'minus',
778 'disableamount' => 0,
779 'urlnew' => DOL_URL_ROOT.'/compta/bank/various_payment/card.php?action=create&projectid='.$id.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
780 'lang' => 'banks',
781 'buttonnew' => 'AddVariousPayment',
782 'testnew' => $user->hasRight('banque', 'modifier'),
783 'test' => isModEnabled("bank") && $user->hasRight('banque', 'lire') && !getDolGlobalString('BANK_USE_OLD_VARIOUS_PAYMENT')
784 ),
785 /* No need for this, available on dedicated tab "Agenda/Events"
786 'agenda'=>array(
787 'name'=>"Agenda",
788 'title'=>"ListActionsAssociatedProject",
789 'class'=>'ActionComm',
790 'table'=>'actioncomm',
791 'datefieldname'=>'datep',
792 'disableamount'=>1,
793 'urlnew'=>DOL_URL_ROOT.'/comm/action/card.php?action=create&projectid='.$id.'&socid='.$socid.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
794 'lang'=>'agenda',
795 'buttonnew'=>'AddEvent',
796 'testnew'=>$user->rights->agenda->myactions->create,
797 'test'=> isModEnabled('agenda') && $user->hasRight('agenda', 'myactions', 'read')),
798 */
799);
800
801// Change rules for profit/benefit calculation
802if (getDolGlobalString('PROJECT_ELEMENTS_FOR_PLUS_MARGIN')) {
803 foreach ($listofreferent as $key => $element) {
804 if ($listofreferent[$key]['margin'] == 'add') {
805 unset($listofreferent[$key]['margin']);
806 }
807 }
808 $newelementforplusmargin = explode(',', getDolGlobalString('PROJECT_ELEMENTS_FOR_PLUS_MARGIN'));
809 foreach ($newelementforplusmargin as $value) {
810 $listofreferent[trim($value)]['margin'] = 'add';
811 }
812}
813if (getDolGlobalString('PROJECT_ELEMENTS_FOR_MINUS_MARGIN')) {
814 foreach ($listofreferent as $key => $element) {
815 if ($listofreferent[$key]['margin'] == 'minus') {
816 unset($listofreferent[$key]['margin']);
817 }
818 }
819 $newelementforminusmargin = explode(',', getDolGlobalString('PROJECT_ELEMENTS_FOR_MINUS_MARGIN'));
820 foreach ($newelementforminusmargin as $value) {
821 $listofreferent[trim($value)]['margin'] = 'minus';
822 }
823}
824
825
826$parameters = array('listofreferent' => $listofreferent);
827$resHook = $hookmanager->executeHooks('completeListOfReferent', $parameters, $object, $action);
828
829if (!empty($hookmanager->resArray)) {
830 $listofreferent = array_merge($listofreferent, $hookmanager->resArray);
831} elseif ($resHook > 0 && !empty($hookmanager->resPrint)) {
832 $listofreferent = $hookmanager->resPrint;
833}
834
835if (in_array($action, ['addelement', 'unlink'])) {
836 // Only an element type listed (and allowed) on this page can be linked or unlinked, using the project field it declares
837 $tablename = GETPOST("tablename", "aZ09");
838 $projectField = '';
839 $excludeselect = ['payment_various'];
840 foreach ($listofreferent as $value) {
841 if (!empty($value['test']) && isset($value['table']) && $value['table'] === $tablename) {
842 $projectField = empty($value['project_field']) ? 'fk_projet' : $value['project_field'];
843 if (!empty($value['exclude_select_element'])) {
844 $excludeselect[] = $value['exclude_select_element'];
845 }
846 break;
847 }
848 }
849 if (!$permissiontoadd || $projectField === ''
850 || ($action == 'addelement' && (getDolGlobalString('PROJECT_LINK_ON_OVERWIEW_DISABLED') || in_array($tablename, $excludeselect)))
851 || ($action == 'unlink' && (in_array($tablename, ['projet_task', 'stock_mouvement']) || (getDolGlobalString('PROJECT_DISABLE_UNLINK_FROM_OVERVIEW') && !$user->admin)))) {
852 accessforbidden('', 0, 0);
853 }
854
855 $elementselectid = GETPOSTINT("elementselect");
856 if ($action == "addelement") {
857 $result = $object->update_element($tablename, $elementselectid);
858 } else {
859 $result = $object->remove_element($tablename, $elementselectid, $projectField);
860 }
861 if ($result < 0) {
862 setEventMessages($object->error, $object->errors, 'errors');
863 }
864}
865
866$elementuser = new User($db);
867
868
869
870$showdatefilter = 0;
871// Show the filter on date on top of element list
872if (!$showdatefilter) {
873 print '<div class="center centpercent">';
874 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">';
875 print '<input type="hidden" name="token" value="'.newToken().'">';
876 print '<input type="hidden" name="tablename" value="'.(empty($tablename) ? '' : $tablename).'">';
877 print '<input type="hidden" name="action" value="view">';
878 print '<div class="inline-block">';
879 print $form->selectDate($dates, 'dates', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From"));
880 print '</div>';
881 print '<div class="inline-block">';
882 print $form->selectDate($datee, 'datee', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"));
883 print '</div>';
884 print '<div class="inline-block">';
885 print '<input type="submit" name="refresh" value="'.$langs->trans("Refresh").'" class="button small">';
886 print '</div>';
887 print '</form>';
888 print '</div>';
889
890 $showdatefilter++;
891}
892
893
894
895// Show balance for whole project
896
897$langs->loadLangs(array("suppliers", "bills", "orders", "proposals", "margins"));
898
899if (isModEnabled('stock') || isModEnabled('stocktransfer')) {
900 $langs->load('stocks');
901}
902
903print '<!-- Begin PROFIT table -->';
904print load_fiche_titre($langs->trans("Profit"), '', 'title_accountancy');
905
906print '<div class="div-table-responsive">';
907print '<table class="noborder centpercent">';
908print '<tr class="liste_titre">';
909print '<td class="left" width="200">';
910$tooltiponprofit = $langs->trans("ProfitIsCalculatedWith")."<br>\n";
911$tooltiponprofitplus = $tooltiponprofitminus = '';
912foreach ($listofreferent as $key => $value) {
913 if (!empty($value['lang'])) {
914 $langs->load($value['lang']);
915 }
916 $name = $langs->trans($value['name']);
917 $qualified = $value['test'];
918 $margin = empty($value['margin']) ? '' : $value['margin'];
919 if ($qualified && $margin) { // If this element must be included into profit calculation ($margin is 'minus' or 'add')
920 if ($margin === 'add') {
921 $tooltiponprofitplus .= ' &gt; '.$name." (+)<br>\n";
922 } elseif ($margin === 'minus') {
923 $tooltiponprofitminus .= ' &gt; '.$name." (-)<br>\n";
924 }
925 }
926}
927$tooltiponprofit .= $tooltiponprofitplus;
928$tooltiponprofit .= $tooltiponprofitminus;
929print $form->textwithpicto($langs->trans("Element"), $tooltiponprofit);
930print '</td>';
931print '<td class="right" width="100">'.$langs->trans("Number").'</td>';
932print '<td class="right" width="100">'.$langs->trans("AmountHT").'</td>';
933print '<td class="right" width="100">'.$langs->trans("AmountTTC").'</td>';
934print '</tr>';
935
936$total_revenue_ht = 0;
937$balance_ht = 0;
938$balance_ttc = 0;
939
940// Loop on each element type (proposal, sale order, invoices, ...)
941foreach ($listofreferent as $key => $value) {
942 $parameters = array(
943 'total_revenue_ht' => & $total_revenue_ht,
944 'balance_ht' => & $balance_ht,
945 'balance_ttc' => & $balance_ttc,
946 'key' => $key,
947 'value' => & $value,
948 'dates' => $dates,
949 'datee' => $datee
950 );
951 $reshook = $hookmanager->executeHooks('printOverviewProfit', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
952 if ($reshook < 0) {
953 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
954 } elseif ($reshook > 0) {
955 print $hookmanager->resPrint;
956 continue;
957 }
958
959 $name = $langs->trans($value['name']);
960 $title = $value['title'];
961 $classname = $value['class'];
962 $tablename = $value['table'];
963 $datefieldname = $value['datefieldname'];
964 $qualified = $value['test'];
965 // Hide project_task amounts in profit section for users without financial access
966 if ($key === 'project_task' && !$canSeeFinancials) {
967 $qualified = false;
968 }
969 $margin = empty($value['margin']) ? 0 : $value['margin'];
970 $project_field = empty($value['project_field']) ? '' : $value['project_field'];
971 if ($qualified) { // If this element must be included into profit summary table ($margin is '', 'minus' or 'add')
972 $element = new $classname($db);
973
974 $elementarray = $object->get_element_list($key, $tablename, $datefieldname, $dates, $datee, !empty($project_field) ? $project_field : 'fk_projet');
975
976 if (is_array($elementarray) && count($elementarray) > 0) {
977 $total_ht = 0;
978 $total_ttc = 0;
979 $i = 0;
980
981 // Loop on each object for the current element type
982 $num = count($elementarray);
983 for ($i = 0; $i < $num; $i++) {
984 $tmp = explode('_', $elementarray[$i]);
985 $idofelement = (int) $tmp[0];
986 $idofelementuser = !empty($tmp[1]) ? (int) $tmp[1] : 0;
987
988 $element->fetch($idofelement);
989 if ($idofelementuser) {
990 $elementuser->fetch($idofelementuser);
991 }
992
993 // Define if record must be used for total or not
994 $qualifiedfortotal = true;
995 if ($key == 'invoice') {
996 if (!empty($element->close_code) && $element->close_code == 'replaced') {
997 $qualifiedfortotal = false; // Replacement invoice, do not include into total
998 }
999 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS') && $element->type == Facture::TYPE_DEPOSIT) {
1000 $qualifiedfortotal = false; // If hidden option to use deposits as payment (deprecated, not recommended to use this), deposits are not included
1001 }
1002 if (getDolGlobalString('PROJECT_ONLY_PAYED_INVOICE_ON_PROFIT') && $element->status != Facture::STATUS_CLOSED) {
1003 $qualifiedfortotal = false; // Only paid invoices qualify
1004 }
1005 }
1006 if ($key == 'propal') {
1007 if ($element->status != Propal::STATUS_SIGNED && $element->status != Propal::STATUS_BILLED) {
1008 $qualifiedfortotal = false; // Only signed proposal must not be included in total
1009 }
1010 }
1011
1012 if ($tablename != 'expensereport_det' && method_exists($element, 'fetch_thirdparty')) {
1013 $element->fetch_thirdparty();
1014 }
1015
1016 // Define $total_ht_by_line
1017 if ($tablename == 'don' || $tablename == 'chargesociales' || $tablename == 'payment_various' || $tablename == 'salary') {
1018 '@phan-var-force ChargeSociales|PaymentVarious|Salary $element';
1019 $total_ht_by_line = $element->amount;
1020 } elseif ($tablename == 'fichinter') {
1021 '@phan-var-force Fichinter $element';
1022 $total_ht_by_line = $element->getAmount();
1023 } elseif ($tablename == 'stock_mouvement') {
1024 '@phan-var-force MouvementStock $element';
1025 $total_ht_by_line = $element->price * abs($element->qty);
1026 } elseif ($tablename == 'projet_task') {
1027 '@phan-var-force Task $element';
1028 $tmp = $element->getSumOfAmount($idofelementuser ? $elementuser : '', (string) $dates, (string) $datee);
1029 $total_ht_by_line = price2num($tmp['amount'], 'MT');
1030 } elseif ($key == 'loan') {
1031 '@phan-var-force Loan $element';
1032 if ((empty($dates) && empty($datee)) || (intval($dates) <= $element->datestart && intval($datee) >= $element->dateend)) {
1033 // Get total loan
1034 $total_ht_by_line = -$element->capital;
1035 } else {
1036 // Get loan schedule according to date filter
1037 $total_ht_by_line = 0;
1038 $loanScheduleStatic = new LoanSchedule($element->db);
1039 $loanScheduleStatic->fetchAll($element->id);
1040 if (!empty($loanScheduleStatic->lines)) {
1041 foreach ($loanScheduleStatic->lines as $loanSchedule) {
1045 if (($loanSchedule->datep >= $dates && $loanSchedule->datep <= $datee) // dates filter is defined
1046 || !empty($dates) && empty($datee) && $loanSchedule->datep >= $dates && $loanSchedule->datep <= dol_now()
1047 || empty($dates) && !empty($datee) && $loanSchedule->datep <= $datee
1048 ) {
1049 $total_ht_by_line -= $loanSchedule->amount_capital;
1050 }
1051 }
1052 }
1053 }
1054 } else {
1055 $total_ht_by_line = $element->total_ht;
1056 }
1057
1058 // Define $total_ttc_by_line
1059 if ($tablename == 'don' || $tablename == 'chargesociales' || $tablename == 'payment_various' || $tablename == 'salary') {
1060 '@phan-var-force ChargeSociales|PaymentVarious|Salary $element';
1061 $total_ttc_by_line = $element->amount;
1062 } elseif ($tablename == 'fichinter') {
1063 '@phan-var-force Fichinter $element';
1064 $total_ttc_by_line = $element->getAmount();
1065 } elseif ($tablename == 'stock_mouvement') {
1066 '@phan-var-force MouvementStock $element';
1067 $total_ttc_by_line = $element->price * abs($element->qty);
1068 } elseif ($tablename == 'projet_task') {
1069 '@phan-var-force Task $element';
1070 $defaultvat = get_default_tva($mysoc, $mysoc);
1071 $reg = array();
1072 if (preg_replace('/^(\d+\.)\s\‍(.*\‍)/', $defaultvat, $reg)) {
1073 // @phan-suppress-next-line PhanTypeInvalidDimOffset
1074 $defaultvat = $reg[1];
1075 }
1076 $total_ttc_by_line = price2num($total_ht_by_line * (1 + ((float) $defaultvat / 100)), 'MT');
1077 } elseif ($key == 'loan') {
1078 $total_ttc_by_line = $total_ht_by_line; // For loan there is actually no taxe managed in Dolibarr
1079 } else {
1080 $total_ttc_by_line = $element->total_ttc;
1081 }
1082
1083 // Change sign of $total_ht_by_line and $total_ttc_by_line for various payments
1084 if ($tablename == 'payment_various') {
1085 if ($element->sens == 1) {
1086 $total_ht_by_line = -$total_ht_by_line;
1087 $total_ttc_by_line = -$total_ttc_by_line;
1088 }
1089 }
1090
1091 // Change sign of $total_ht_by_line and $total_ttc_by_line for supplier proposal and supplier order.
1092 // Skip when the element already participates to the margin computation via margin='minus'
1093 // (line 1095 below will revert sign too, and double-negation would silently flip the value
1094 // back to positive - see PROJECT_ELEMENTS_FOR_MINUS_MARGIN=order_supplier in #34684).
1095 if (($tablename == 'commande_fournisseur' || $tablename == 'supplier_proposal') && $margin !== 'minus') {
1096 $total_ht_by_line = -$total_ht_by_line;
1097 $total_ttc_by_line = -$total_ttc_by_line;
1098 }
1099
1100 // Add total if we have to
1101 if ($qualifiedfortotal) {
1102 $total_ht += $total_ht_by_line;
1103 $total_ttc += $total_ttc_by_line;
1104 }
1105 }
1106
1107 // Each element with at least one line is output
1108
1109 // Calculate margin
1110 if ($margin) {
1111 if ($margin === 'add') {
1112 $total_revenue_ht += $total_ht;
1113 }
1114
1115 if ($margin === "minus") { // Revert sign
1116 $total_ht = -$total_ht;
1117 $total_ttc = -$total_ttc;
1118 }
1119
1120 $balance_ht += $total_ht;
1121 $balance_ttc += $total_ttc;
1122 }
1123
1124 print '<tr class="oddeven">';
1125 // Module
1126 print '<!-- // Module '.$name.' with tablename '.$tablename.' -->';
1127 print '<td class="left"><a href="#table_'.$tablename.'">'.$name.'</a></td>';
1128 // Nb
1129 print '<td class="right">'.$i.'</td>';
1130 // Amount HT
1131 print '<td class="right">';
1132 if ($key == 'intervention' && !$margin) {
1133 print '<span class="opacitymedium">'.$form->textwithpicto($langs->trans("NA"), $langs->trans("AmountOfInteventionNotIncludedByDefault")).'</span>';
1134 } elseif ($key == 'stocktransfer') {
1135 print '<span class="opacitymedium">'.$form->textwithpicto($langs->trans("NA"), $langs->trans("NoAmountforStockTransfer")).'</span>';
1136 } else {
1137 if ($key == 'propal') {
1138 print '<span class="opacitymedium">'.$form->textwithpicto('', $langs->trans("SignedOnly")).'</span>';
1139 }
1140 print price($total_ht);
1141 }
1142 print '</td>';
1143 // Amount TTC
1144 print '<td class="right">';
1145 if ($key == 'intervention' && !$margin) {
1146 print '<span class="opacitymedium">'.$form->textwithpicto($langs->trans("NA"), $langs->trans("AmountOfInteventionNotIncludedByDefault")).'</span>';
1147 } elseif ($key == 'stocktransfer') {
1148 print '<span class="opacitymedium">'.$form->textwithpicto($langs->trans("NA"), $langs->trans("NoAmountforStockTransfer")).'</span>';
1149 } else {
1150 if ($key == 'propal') {
1151 print '<span class="opacitymedium">'.$form->textwithpicto('', $langs->trans("SignedOnly")).'</span>';
1152 }
1153 print price($total_ttc);
1154 }
1155 print '</td>';
1156 print '</tr>';
1157 }
1158 }
1159}
1160// and the final balance
1161print '<tr class="liste_total">';
1162print '<td class="right" colspan="2">'.$langs->trans("Profit").'</td>';
1163print '<td class="right">'.price(price2num($balance_ht, 'MT')).'</td>';
1164print '<td class="right">'.price(price2num($balance_ttc, 'MT')).'</td>';
1165print '</tr>';
1166
1167// and the cost per attendee
1168if ($object->usage_organize_event) {
1169 require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorboothattendee.class.php';
1170 $conforboothattendee = new ConferenceOrBoothAttendee($db);
1171 $result = $conforboothattendee->fetchAll('', '', 0, 0, '(t.fk_project:=:'.((int) $object->id).') AND (t.status:=:'.ConferenceOrBoothAttendee::STATUS_VALIDATED.')');
1172
1173 if (!is_array($result) && $result < 0) {
1174 setEventMessages($conforboothattendee->error, $conforboothattendee->errors, 'errors');
1175 } else {
1176 $nbAttendees = count($result);
1177 }
1178
1179 if ($nbAttendees >= 2) {
1180 $costperattendee_ht = $balance_ht / $nbAttendees;
1181 $costperattendee_ttc = $balance_ttc / $nbAttendees;
1182 print '<tr class="liste_total">';
1183 print '<td class="right" colspan="2">'.$langs->trans("ProfitPerValidatedAttendee").'</td>';
1184 print '<td class="right">'.price(price2num($costperattendee_ht, 'MT')).'</td>';
1185 print '<td class="right">'.price(price2num($costperattendee_ttc, 'MT')).'</td>';
1186 print '</tr>';
1187 }
1188}
1189
1190// and the margin (profit / revenues)
1191if ($total_revenue_ht) {
1192 print '<tr class="liste_total">';
1193 print '<td class="right" colspan="2">'.$langs->trans("Margin").'</td>';
1194 print '<td class="right">'.round(100 * $balance_ht / $total_revenue_ht, 1).'%</td>';
1195 print '<td class="right"></td>';
1196 print '</tr>';
1197}
1198
1199print "</table>";
1200print '</div>';
1201print '<!-- End PROFIT table -->';
1202
1203
1204print '<br><br>';
1205print '<br>';
1206
1207
1208$total_time = 0;
1209
1210// Detail
1211foreach ($listofreferent as $key => $value) {
1212 $parameters = array(
1213 'key' => $key,
1214 'value' => & $value,
1215 'dates' => $dates,
1216 'datee' => $datee
1217 );
1218 $reshook = $hookmanager->executeHooks('printOverviewDetail', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1219 if ($reshook < 0) {
1220 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1221 } elseif ($reshook > 0) {
1222 print $hookmanager->resPrint;
1223 continue;
1224 }
1225
1226 $title = $value['title'];
1227 $classname = $value['class'];
1228 $tablename = $value['table'];
1229 $datefieldname = $value['datefieldname'];
1230 $qualified = $value['test'];
1231 $urlnew = empty($value['urlnew']) ? '' : $value['urlnew'];
1232 $buttonnew = empty($value['buttonnew']) ? '' : $value['buttonnew'];
1233 $testnew = empty($value['testnew']) ? '' : $value['testnew'];
1234 $project_field = empty($value['project_field']) ? '' : $value['project_field'];
1235 $nototal = empty($value['nototal']) ? 0 : 1;
1236
1237 $exclude_select_element = array('payment_various');
1238 if (!empty($value['exclude_select_element'])) {
1239 $exclude_select_element[] = $value['exclude_select_element'];
1240 }
1241
1242 if ($qualified && $tablename !== null) {
1243 // If we want the project task array to have details of users
1244 //if ($key == 'project_task') $key = 'project_task_time';
1245
1246 $element = new $classname($db);
1247
1248 $addform = '';
1249
1250 $idtofilterthirdparty = 0;
1251 $array_of_element_linkable_with_different_thirdparty = array('facture_fourn', 'commande_fournisseur');
1252 if (!in_array($tablename, $array_of_element_linkable_with_different_thirdparty)) {
1253 $idtofilterthirdparty = empty($object->thirdparty->id) ? 0 : $object->thirdparty->id;
1254 if (getDolGlobalString('PROJECT_OTHER_THIRDPARTY_ID_TO_ADD_ELEMENTS')) {
1255 $idtofilterthirdparty .= ',' . getDolGlobalString('PROJECT_OTHER_THIRDPARTY_ID_TO_ADD_ELEMENTS');
1256 }
1257 }
1258
1259 $elementarray = $object->get_element_list($key, $tablename, $datefieldname, $dates, $datee, !empty($project_field) ? $project_field : 'fk_projet');
1260
1261
1262 if ($permissiontoadd && !getDolGlobalString('PROJECT_LINK_ON_OVERWIEW_DISABLED') && $idtofilterthirdparty && !in_array($tablename, $exclude_select_element)) {
1263 $selectList = $formproject->select_element($tablename, $idtofilterthirdparty, 'minwidth300 minwidth75imp', -2, empty($project_field) ? 'fk_projet' : $project_field, $langs->trans("SelectElement"));
1264 if ((int) $selectList < 0) { // cast to int because ''<0 is true.
1265 setEventMessages($formproject->error, $formproject->errors, 'errors');
1266 } elseif ($selectList) {
1267 // Define form with the combo list of elements to link
1268 $addform .= '<div class="inline-block valignmiddle">';
1269 $addform .= '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
1270 $addform .= '<input type="hidden" name="token" value="'.newToken().'">';
1271 $addform .= '<input type="hidden" name="tablename" value="'.$tablename.'">';
1272 $addform .= '<input type="hidden" name="action" value="addelement">';
1273 $addform .= '<input type="hidden" name="datesrfc" value="'.dol_print_date($dates, 'dayhourrfc').'">';
1274 $addform .= '<input type="hidden" name="dateerfc" value="'.dol_print_date($datee, 'dayhourrfc').'">';
1275 $addform .= '<table><tr>';
1276 //$addform .= '<td><span class="hideonsmartphone opacitymedium">'.$langs->trans("SelectElement").'</span></td>';
1277 $addform .= '<td>'.$selectList.'</td>';
1278 $addform .= '<td><input type="submit" class="button button-linkto smallpaddingimp" value="'.dol_escape_htmltag($langs->trans("LinkToElementShort")).'"></td>';
1279 $addform .= '</tr></table>';
1280 $addform .= '</form>';
1281 $addform .= '</div>';
1282 }
1283 }
1284 if (!getDolGlobalString('PROJECT_CREATE_ON_OVERVIEW_DISABLED') && $urlnew) {
1285 $addform .= '<div class="inline-block valignmiddle">';
1286 if ($testnew) {
1287 $addform .= '<a class="buttonxxx marginleftonly" href="'.$urlnew.'" title="'.dol_escape_htmltag($langs->trans($buttonnew)).'"><span class="fa fa-plus-circle valignmiddle paddingleft"></span></a>';
1288 } elseif (!getDolGlobalString('MAIN_BUTTON_HIDE_UNAUTHORIZED')) {
1289 $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>';
1290 }
1291 $addform .= '<div>';
1292 }
1293
1294 if (is_array($elementarray) && count($elementarray) > 0 && $key == "order_supplier") {
1295 $addform .= '<div class="inline-block valignmiddle"><a id="btnShow" class="buttonxxx marginleftonly" href="#" onClick="return false;">
1296 <span id="textBtnShow" class="valignmiddle text-plus-circle hideonsmartphone">'.$langs->trans("CanceledShown").'</span><span id="minus-circle" class="fa fa-eye valignmiddle paddingleft"></span>
1297 </a>
1298 <script>
1299 $("#btnShow").on("click", function () {
1300 console.log("We click to show or hide the canceled lines");
1301 var attr = $(this).attr("data-canceledarehidden");
1302 if (typeof attr !== "undefined" && attr !== false) {
1303 console.log("Show canceled");
1304 $(".tr_canceled").show();
1305 $("#textBtnShow").text("'.dol_escape_js($langs->transnoentitiesnoconv("CanceledShown")).'");
1306 $("#btnShow").removeAttr("data-canceledarehidden");
1307 $("#minus-circle").removeClass("fa-eye-slash").addClass("fa-eye");
1308 } else {
1309 console.log("Hide canceled");
1310 $(".tr_canceled").hide();
1311 $("#textBtnShow").text("'.dol_escape_js($langs->transnoentitiesnoconv("CanceledHidden")).'");
1312 $("#btnShow").attr("data-canceledarehidden", 1);
1313 $("#minus-circle").removeClass("fa-eye").addClass("fa-eye-slash");
1314 }
1315 });
1316 </script></div>';
1317
1318 $addform .= '<div class="inline-block valignmiddle"><a id="btnShowPaid" class="buttonxxx marginleftonly" href="#" onClick="return false;">
1319 <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>
1320 </a>
1321 <script>
1322 $("#btnShowPaid").on("click", function () {
1323 console.log("We click to show or hide the paid lines");
1324 var attr = $(this).attr("data-paidarehidden");
1325 if (typeof attr !== "undefined" && attr !== false) {
1326 console.log("Show paid");
1327 $(".tr_paid").show();
1328 $("#textBtnShowPaid").text("'.dol_escape_js($langs->transnoentitiesnoconv("PaidShown")).'");
1329 $("#btnShowPaid").removeAttr("data-paidarehidden");
1330 $("#minus-circle-paid").removeClass("fa-eye-slash").addClass("fa-eye");
1331 } else {
1332 console.log("Hide paid");
1333 $(".tr_paid").hide();
1334 $("#textBtnShowPaid").text("'.dol_escape_js($langs->transnoentitiesnoconv("PaidHidden")).'");
1335 $("#btnShowPaid").attr("data-paidarehidden", 1);
1336 $("#minus-circle-paid").removeClass("fa-eye").addClass("fa-eye-slash");
1337 }
1338 });
1339 </script></div>';
1340 }
1341
1342 print '<a id="table_'.$tablename.'"></a>';
1343 print load_fiche_titre($langs->trans($title), $addform, '');
1344
1345 print "\n".'<!-- Table for tablename = '.$tablename.' -->'."\n";
1346 print '<div class="div-table-responsive">';
1347 print '<table class="noborder centpercent">';
1348
1349 print '<tr class="liste_titre">';
1350 $stocktransfercolstyle = ($key == 'stocktransfer' ? ' style="width: 9%"' : '');
1351 // Remove link column
1352 print '<td style="width: 24px"></td>';
1353 // Ref
1354 if ($key == 'stocktransfer') {
1355 print '<td'.$stocktransfercolstyle.'>'.$langs->trans("Ref").'</td>';
1356 } else {
1357 print '<td'.(($tablename != 'actioncomm' && $tablename != 'projet_task') ? ' style="width: 200px"' : '').'>'.$langs->trans("Ref").'</td>';
1358 }
1359 // Product and qty on stock_movement
1360 if ('MouvementStock' == $classname) {
1361 print '<td style="width: 200px">'.$langs->trans("Product").'</td>';
1362 print '<td style="width: 50px">'.$langs->trans("Qty").'</td>';
1363 }
1364 // Date
1365 if ($key != 'stocktransfer') {
1366 print '<td'.(($tablename != 'actioncomm' && $tablename != 'projet_task') ? ' style="width: 200px"' : '').' class="center">';
1367 if (in_array($tablename, array('projet_task'))) {
1368 print $langs->trans("TimeSpent");
1369 }
1370 if (!in_array($tablename, array('projet_task'))) {
1371 print $langs->trans("Date");
1372 }
1373 print '</td>';
1374 }
1375 if ($key == 'stocktransfer') {
1376 print '<td'.$stocktransfercolstyle.'>'.$langs->trans("WarehouseSource").'</td>';
1377 print '<td'.$stocktransfercolstyle.'>'.$langs->trans("WarehouseDestination").'</td>';
1378 print '<td class="center"'.$stocktransfercolstyle.'>'.$langs->trans("DatePrevueDepart").'</td>';
1379 print '<td class="center"'.$stocktransfercolstyle.'>'.$langs->trans("DateReelleDepart").'</td>';
1380 print '<td class="center"'.$stocktransfercolstyle.'>'.$langs->trans("DatePrevueArrivee").'</td>';
1381 print '<td class="center"'.$stocktransfercolstyle.'>'.$langs->trans("DateReelleArrivee").'</td>';
1382 }
1383 // Thirdparty or user
1384 print '<td'.($key == 'stocktransfer' ? $stocktransfercolstyle : '').'>';
1385 if (in_array($tablename, array('projet_task')) && $key == 'project_task') {
1386 print ''; // if $key == 'project_task', we don't want details per user
1387 } elseif (in_array($tablename, array('payment_various'))) {
1388 print $langs->trans("Label"); // complementary info about the payment
1389 } elseif (in_array($tablename, array('expensereport_det', 'don', 'projet_task', 'stock_mouvement', 'salary'))) {
1390 print $langs->trans("User");
1391 } else {
1392 print $langs->trans("ThirdParty");
1393 }
1394 print '</td>';
1395 // Duration of intervention
1396 if ($tablename == 'fichinter') {
1397 print '<td>';
1398 print $langs->trans("TotalDuration");
1399 $total_duration = 0;
1400 print '</td>';
1401 }
1402 // Type from Expense Report
1403 if ($tablename == 'expensereport_det') {
1404 print '<td id="expensereport_type">';
1405 print $langs->trans("Type");
1406 print '</td>';
1407 }
1408 // Description from Expense Report
1409 if ($tablename == 'expensereport_det') {
1410 print '<td id="expensereport_description">';
1411 print $langs->trans("Description");
1412 print '</td>';
1413 }
1414
1415
1416 // Amount HT
1417 //if (empty($value['disableamount']) && ! in_array($tablename, array('projet_task'))) print '<td class="right" width="120">'.$langs->trans("AmountHT").'</td>';
1418 //elseif (empty($value['disableamount']) && in_array($tablename, array('projet_task'))) print '<td class="right" width="120">'.$langs->trans("Amount").'</td>';
1419 if ($key == 'loan') {
1420 print '<td class="right" width="120">'.$langs->trans("LoanCapital").'</td>';
1421 } elseif (empty($value['disableamount'])) {
1422 if ($key == 'stocktransfer') {
1423 print '<td class="right"'.$stocktransfercolstyle.'>'.$langs->trans("AmountHT").'</td>';
1424 } else {
1425 print '<td class="right" width="120">'.$langs->trans("AmountHT").'</td>';
1426 }
1427 } else {
1428 if ($key == 'stocktransfer') {
1429 print '<td'.$stocktransfercolstyle.'></td>';
1430 } else {
1431 print '<td width="120"></td>';
1432 }
1433 }
1434 // Amount TTC
1435 //if (empty($value['disableamount']) && ! in_array($tablename, array('projet_task'))) print '<td class="right" width="120">'.$langs->trans("AmountTTC").'</td>';
1436 if ($key == 'loan') {
1437 print '<td class="right" width="120">'.$langs->trans("RemainderToPay").'</td>';
1438 } elseif (empty($value['disableamount'])) {
1439 if ($key == 'stocktransfer') {
1440 print '<td class="right"'.$stocktransfercolstyle.'>'.$langs->trans("AmountTTC").'</td>';
1441 } else {
1442 print '<td class="right" width="120">'.$langs->trans("AmountTTC").'</td>';
1443 }
1444 } else {
1445 if ($key == 'stocktransfer') {
1446 print '<td'.$stocktransfercolstyle.'></td>';
1447 } else {
1448 print '<td width="120"></td>';
1449 }
1450 }
1451 // Status
1452 if (in_array($tablename, array('projet_task'))) {
1453 print '<td class="right" width="200">'.$langs->trans("ProgressDeclared").'</td>';
1454 } else {
1455 if ($key == 'stocktransfer') {
1456 print '<td class="right"'.$stocktransfercolstyle.'>'.$langs->trans("Status").'</td>';
1457 } else {
1458 print '<td class="right" width="200">'.$langs->trans("Status").'</td>';
1459 }
1460 }
1461 print '</tr>';
1462
1463 if (is_array($elementarray) && count($elementarray) > 0) {
1464 $total_ht = 0;
1465 $total_ttc = 0;
1466 $i = 0;
1467
1468 $total_ht_by_third = 0;
1469 $total_ttc_by_third = 0;
1470
1471 $saved_third_id = 0;
1472 $breakline = '';
1473
1474 if (canApplySubtotalOn($tablename)) {
1475 // Sort
1476 $elementarray = sortElementsByClientName($elementarray);
1477 }
1478
1479 $num = count($elementarray);
1480 $total_time = 0;
1481 for ($i = 0; $i < $num; $i++) {
1482 $tmp = explode('_', $elementarray[$i]);
1483 $idofelement = (int) $tmp[0];
1484 $idofelementuser = isset($tmp[1]) ? (int) $tmp[1] : 0;
1485
1486 $element->fetch($idofelement);
1487 if ($idofelementuser) {
1488 $elementuser->fetch($idofelementuser);
1489 }
1490
1491 // Special cases
1492 if ($tablename != 'expensereport_det') {
1493 if (method_exists($element, 'fetch_thirdparty')) {
1494 $element->fetch_thirdparty();
1495 }
1496 } else {
1497 $expensereport = new ExpenseReport($db);
1498 $expensereport->fetch($element->fk_expensereport);
1499 }
1500
1501 //print 'xxx'.$tablename.'yyy'.$classname;
1502
1503 if ($breakline && $saved_third_id != $element->thirdparty->id) {
1504 print $breakline;
1505
1506 $saved_third_id = $element->thirdparty->id;
1507 $breakline = '';
1508
1509 $total_ht_by_third = 0;
1510 $total_ttc_by_third = 0;
1511 }
1512
1513 $saved_third_id = empty($element->thirdparty->id) ? 0 : $element->thirdparty->id;
1514
1515 $qualifiedfortotal = true;
1516 if ($key == 'invoice') {
1517 if (!empty($element->close_code) && $element->close_code == 'replaced') {
1518 $qualifiedfortotal = false; // Replacement invoice, do not include into total
1519 }
1520 } elseif ($key == 'order_supplier' && ($element->status == 6 || $element->status == 7)) {
1521 $qualifiedfortotal = false; // It makes no sense to include canceled orders in the total
1522 }
1523
1524 if ($key == "order_supplier" && ($element->status == 6 || $element->status == 7)) {
1525 print '<tr class="oddeven tr_canceled">';
1526 } elseif ($key == "order_supplier" && ($element->billed)) {
1527 print '<tr class="oddeven tr_paid">';
1528 } else {
1529 print '<tr class="oddeven" >';
1530 }
1531
1532
1533 // Remove link
1534 print '<td style="width: 24px">';
1535 if ($tablename != 'projet_task' && $tablename != 'stock_mouvement') {
1536 if ($permissiontoadd && (!getDolGlobalString('PROJECT_DISABLE_UNLINK_FROM_OVERVIEW') || $user->admin)) { // PROJECT_DISABLE_UNLINK_FROM_OVERVIEW is empty by default, so this test true
1537 print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=unlink&token='.newToken().'&tablename='.$tablename.'&elementselect='.$element->id.($project_field ? '&projectfield='.$project_field : '').'" class="reposition">';
1538 print img_picto($langs->trans('Unlink'), 'unlink');
1539 print '</a>';
1540 }
1541 }
1542 print "</td>\n";
1543
1544 // Ref
1545 print '<td class="left nowraponall">';
1546 if ($tablename == 'expensereport_det') {
1547 print $expensereport->getNomUrl(1);
1548 } else {
1549 print '<table><tr><td style="border-bottom: none;">';
1550 // Show ref with link
1551 if ($element instanceof Task) {
1552 print $element->getNomUrl(1, 'withproject', 'time');
1553 print ' - '.dol_trunc($element->label, 48);
1554 } elseif ($key == 'loan') {
1555 print $element->getNomUrl(1);
1556 print ' - '.dol_trunc($element->label, 48);
1557 } else {
1558 print $element->getNomUrl(1);
1559 }
1560
1561 $element_doc = $element->element;
1562 $filename = dol_sanitizeFileName($element->ref);
1563 if (!empty($conf->$element_doc)) {
1564 $confelementdoc = $conf->$element_doc;
1565 $filedir = $confelementdoc->multidir_output[$element->entity ?? $conf->entity].'/'.dol_sanitizeFileName($element->ref);
1566 } else {
1567 $filedir = '';
1568 }
1569
1570 if ($element_doc === 'order_supplier') {
1571 $element_doc = 'commande_fournisseur';
1572 $filedir = $conf->fournisseur->commande->multidir_output[$element->entity ?? $conf->entity].'/'.dol_sanitizeFileName($element->ref);
1573 } elseif ($element_doc === 'invoice_supplier') {
1574 $element_doc = 'facture_fournisseur';
1575 $filename = get_exdir($element->id, 2, 0, 0, $element, 'invoice_supplier').dol_sanitizeFileName($element->ref);
1576 $filedir = $conf->fournisseur->facture->multidir_output[$element->entity ?? $conf->entity].'/'.$filename;
1577 }
1578
1579 print '<div class="inline-block valignmiddle">';
1580 if ($filedir) {
1581 print $formfile->getDocumentsLink($element_doc, $filename, $filedir);
1582 }
1583 print '</div>';
1584
1585 print '</td>';
1586
1587 print '<td class="tdoverflowmax250" style="border-bottom: none;">';
1588
1589 // Show supplier ref
1590 if (!empty($element->ref_supplier)) {
1591 print ' - '.$element->ref_supplier;
1592 }
1593 // Show customer ref
1594 if (!empty($element->ref_customer)) {
1595 print ' - '.$element->ref_customer;
1596 }
1597 // Compatibility propale
1598 if (empty($element->ref_customer) && !empty($element->ref_client)) {
1599 print ' - '.$element->ref_client;
1600 }
1601
1602 print '</td></tr></table>';
1603 }
1604 print "</td>\n";
1605 // Product and qty on stock movement
1606 if ('MouvementStock' == $classname) {
1607 '@phan-var-force MouvementStock $element';
1608 $mvsProd = new Product($element->db);
1609 $mvsProd->fetch($element->product_id);
1610 print '<td>'.$mvsProd->getNomUrl(1).'</td>';
1611 print '<td>'.$element->qty.'</td>';
1612 }
1613 // Date or TimeSpent
1614 $date = '';
1615 $total_time_by_line = 0;
1616 if ($tablename == 'expensereport_det') {
1617 '@phan-var-force ExpenseReportLine $element';
1618 $date = $element->date; // No draft status on lines
1619 } elseif ($tablename == 'stock_mouvement') {
1620 '@phan-var-force MouvementStock $element';
1621 $date = $element->datem;
1622 } elseif ($tablename == 'salary') {
1623 '@phan-var-force Salary $element';
1624 $date = $element->datesp;
1625 } elseif ($tablename == 'payment_various') {
1626 '@phan-var-force PaymentVarious $element';
1627 $date = $element->datev;
1628 } elseif ($tablename == 'chargesociales') {
1629 '@phan-var-force ChargeSociales $element';
1630 $date = $element->date_ech;
1631 } elseif (!empty($element->status) || !empty($element->statut) || !empty($element->fk_status)) {
1632 if ($tablename == 'don') {
1633 '@phan-var-force Don $element';
1634 $date = $element->date;
1635 }
1636 if ($tablename == 'commande_fournisseur' || $tablename == 'supplier_order') {
1637 '@phan-var-force CommandeFournisseur $element';
1638 $date = ($element->date_commande ? $element->date_commande : $element->date_valid);
1639 } elseif ($tablename == 'supplier_proposal') {
1640 '@phan-var-force SupplierProposal $element';
1641 $date = $element->date_validation; // There is no other date for this
1642 } elseif ($tablename == 'fichinter') {
1643 '@phan-var-force Fichinter $element';
1644 $date = $element->datev; // There is no other date for this
1645 } elseif ($tablename == 'projet_task') {
1646 '@phan-var-force Task $element';
1647 $date = ''; // We show no date. Showing date of beginning of task make user think it is date of time consumed
1648 } else {
1649 $date = $element->date; // invoice, ...
1650 if (empty($date)) {
1651 $date = $element->date_contrat;
1652 }
1653 if (empty($date)) {
1654 $date = $element->datev;
1655 }
1656 if (empty($date) && !empty($datefieldname)) {
1657 // @phan-suppress-next-line PhanUndeclaredProperty
1658 $date = $element->$datefieldname;
1659 }
1660 }
1661 } elseif ($key == 'loan') {
1662 '@phan-var-force Loan $element';
1663 $date = $element->datestart;
1664 }
1665
1666 if ($key != 'stocktransfer') {
1667 print '<td class="center">';
1668 if ($tablename == 'actioncomm') {
1669 '@phan-var-force ActionComm $element';
1670 print dol_print_date($element->datep, 'dayhour');
1671 if ($element->datef && $element->datef > $element->datep) {
1672 print " - ".dol_print_date($element->datef, 'dayhour');
1673 }
1674 } elseif (in_array($tablename, array('projet_task'))) {
1675 '@phan-var-force Task $element';
1676 $tmpprojtime = $element->getSumOfAmount($idofelementuser ? $elementuser : '', (string) $dates, (string) $datee); // $element is a task. $elementuser may be empty
1677 print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$idofelement.'&withproject=1">';
1678 print convertSecondToTime($tmpprojtime['nbseconds'], 'allhourmin');
1679 print '</a>';
1680 $total_time_by_line = $tmpprojtime['nbseconds'];
1681 } else {
1682 print dol_print_date($date, 'day');
1683 }
1684 print '</td>';
1685 }
1686
1687 if ($key == 'stocktransfer') {
1688 $warehouseSource = new Entrepot($db);
1689 $warehouseDestination = new Entrepot($db);
1690 print '<td class="tdoverflowmax150">';
1691 if (!empty($element->fk_warehouse_source) && $warehouseSource->fetch($element->fk_warehouse_source) > 0) {
1692 print $warehouseSource->getNomUrl(1);
1693 }
1694 print '</td>';
1695 print '<td class="tdoverflowmax150">';
1696 if (!empty($element->fk_warehouse_destination) && $warehouseDestination->fetch($element->fk_warehouse_destination) > 0) {
1697 print $warehouseDestination->getNomUrl(1);
1698 }
1699 print '</td>';
1700 print '<td class="center">'.dol_print_date($element->date_prevue_depart, 'day').'</td>';
1701 print '<td class="center">'.dol_print_date($element->date_reelle_depart, 'day').'</td>';
1702 print '<td class="center">'.dol_print_date($element->date_prevue_arrivee, 'day').'</td>';
1703 print '<td class="center">'.dol_print_date($element->date_reelle_arrivee, 'day').'</td>';
1704 }
1705
1706 // Third party or user
1707 print '<td class="tdoverflowmax150">';
1708 if (is_object($element->thirdparty)) {
1709 print $element->thirdparty->getNomUrl(1, '', 48);
1710 } elseif ($tablename == 'expensereport_det') {
1711 $tmpuser = new User($db);
1712 $tmpuser->fetch($expensereport->fk_user_author);
1713 print $tmpuser->getNomUrl(1, '', 48);
1714 } elseif ($tablename == 'salary') {
1715 $tmpuser = new User($db);
1716 $tmpuser->fetch($element->fk_user);
1717 print $tmpuser->getNomUrl(1, '', 48);
1718 } elseif ($tablename == 'don' || $tablename == 'stock_mouvement') {
1719 '@phan-var-force Don|MouvementStock $element';
1720 if ($element->fk_user_author > 0) {
1721 $tmpuser2 = new User($db);
1722 $tmpuser2->fetch($element->fk_user_author);
1723 print $tmpuser2->getNomUrl(1, '', 48);
1724 }
1725 } elseif ($tablename == 'projet_task' && $key == 'element_time') { // if $key == 'project_task', we don't want details per user
1726 print $elementuser->getNomUrl(1);
1727 } elseif ($tablename == 'payment_various') { // payment label
1728 '@phan-var-force PaymentVarious $element';
1729 print $element->label;
1730 }
1731 print '</td>';
1732
1733 // Add duration and store it in counter for fichinter
1734 if ($tablename == 'fichinter') {
1735 '@phan-var-force FichInter $element';
1736 print '<td>';
1737 print convertSecondToTime($element->duration, 'all', $conf->global->MAIN_DURATION_OF_WORKDAY);
1738 $total_duration += $element->duration;
1739 print '</td>';
1740 }
1741
1742 // Type from Expense Report
1743 if ($tablename == 'expensereport_det') {
1744 print '<td class="left linecoltype">';
1745 $labeltype = ($langs->trans(($element->type_fees_code)) == $element->type_fees_code ? $element->type_fees_libelle : $langs->trans($element->type_fees_code));
1746 print (string) $labeltype;
1747 print '</td>';
1748 }
1749 // Description from Expense Report
1750 if ($tablename == 'expensereport_det') {
1751 print '<td class="left linecolcomment">';
1752 print (string) $element->comments;
1753 print '</td>';
1754 }
1755
1756
1757 // Amount without tax
1758 $warning = '';
1759 if (empty($value['disableamount'])) {
1760 $total_ht_by_line = null;
1761 $othermessage = '';
1762 if ($tablename == 'don' || $tablename == 'chargesociales' || $tablename == 'payment_various' || $tablename == 'salary') {
1763 '@phan-var-force Don|ChargeSociales|PaymentVarious|Salary $element';
1764 $total_ht_by_line = $element->amount;
1765 } elseif ($tablename == 'fichinter') {
1766 '@phan-var-force FichInter $element';
1767 $total_ht_by_line = $element->getAmount();
1768 } elseif ($tablename == 'stock_mouvement') {
1769 '@phan-var-force MouvementStock $element';
1770 $total_ht_by_line = $element->price * abs($element->qty);
1771 } elseif (in_array($tablename, array('projet_task'))) {
1772 if (isModEnabled('salaries')) {
1773 // TODO Permission to read daily rate to show value
1774 $total_ht_by_line = price2num($tmpprojtime['amount'], 'MT');
1775 if (isset($tmpprojtime['nblinesnull']) && ($tmpprojtime['nblinesnull'] > 0)) {
1776 $langs->load("errors");
1777 $warning = $langs->trans("WarningSomeLinesWithNullHourlyRate", $conf->currency);
1778 }
1779 } else {
1780 $othermessage = $form->textwithpicto($langs->trans("NotAvailable"), $langs->trans("ModuleSalaryToDefineHourlyRateMustBeEnabled"));
1781 }
1782 } elseif ($key == 'loan') {
1783 '@phan-var-force Loan $element';
1784 $total_ht_by_line = $element->capital;
1785 } else {
1786 $total_ht_by_line = $element->total_ht;
1787 }
1788
1789 // Change sign of $total_ht_by_line and $total_ttc_by_line for some cases
1790 if ($tablename == 'payment_various') {
1791 if ($element->sens == 0) {
1792 $total_ht_by_line = -$total_ht_by_line;
1793 }
1794 }
1795
1796 print '<td class="right">';
1797 if ($othermessage) {
1798 print '<span class="opacitymedium">'.$othermessage.'</span>';
1799 }
1800 if (isset($total_ht_by_line)) {
1801 if (!$qualifiedfortotal) {
1802 print '<strike>';
1803 }
1804 print '<span class="amount">'.price($total_ht_by_line).'</span>';
1805 if (!$qualifiedfortotal) {
1806 print '</strike>';
1807 }
1808 }
1809 if ($warning) {
1810 print ' '.img_warning($warning);
1811 }
1812 if (isset($tmpprojtime['nblinesnull']) && ($tmpprojtime['nblinesnull'] > 0)) {
1813 if ($tmpprojtime['nbuserthmnull'] > 0) {
1814 $title = $langs->trans("EnterUsersHourlyRateFirst");
1815 print ' '.img_picto($title, "sync", '', 0, 0, 0, '', 'opacitymedium');
1816 } else {
1817 $title = $langs->trans("UpdateUndefinedWithLastHourlyRate");
1818 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>';
1819 }
1820 }
1821 if (getDolGlobalString('PROJECT_CAN_OVERWRITE_TIMESTPENT_HOURLY_RATE_WITH_LASTONE')) {
1822 $title = $langs->trans("UpdateWithLastHourlyRate");
1823 print ' <a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$id.'&action=updateallwithlasthourlyrate&taskid='.$idofelement.'&token='.currentToken().'">'.img_picto($title, "sync", '', 0, 0, 0, '', '').'</a>';
1824 }
1825 print '</td>';
1826 } else {
1827 print '<td></td>';
1828 }
1829
1830 // Amount inc tax
1831 if (empty($value['disableamount'])) {
1832 $total_ttc_by_line = null;
1833 if ($tablename == 'don' || $tablename == 'chargesociales' || $tablename == 'payment_various' || $tablename == 'salary') {
1834 '@phan-var-force Don|ChargeSociales|PaymentVarious $element';
1835 $total_ttc_by_line = $element->amount;
1836 } elseif ($tablename == 'fichinter') {
1837 '@phan-var-force Fichinter $element';
1838 $total_ttc_by_line = $element->getAmount();
1839 } elseif ($tablename == 'stock_mouvement') {
1840 '@phan-var-force MouvementStock $element';
1841 $total_ttc_by_line = $element->price * abs($element->qty);
1842 } elseif ($tablename == 'projet_task') {
1843 if (isModEnabled('salaries')) {
1844 // TODO Permission to read daily rate
1845 $defaultvat = get_default_tva($mysoc, $mysoc);
1846 $total_ttc_by_line = price2num($total_ht_by_line * (1 + ($defaultvat / 100)), 'MT');
1847 } else {
1848 $othermessage = $form->textwithpicto($langs->trans("NotAvailable"), $langs->trans("ModuleSalaryToDefineHourlyRateMustBeEnabled"));
1849 }
1850 } elseif ($key == 'loan') {
1851 '@phan-var-force Loan $element';
1852 $total_ttc_by_line = $element->capital - $element->getSumPayment();
1853 } else {
1854 $total_ttc_by_line = $element->total_ttc;
1855 }
1856
1857 // Change sign of $total_ht_by_line and $total_ttc_by_line for some cases
1858 if ($tablename == 'payment_various') {
1859 if ($element->sens == 0) {
1860 $total_ttc_by_line = -$total_ttc_by_line;
1861 }
1862 }
1863
1864 print '<td class="right">';
1865 if ($othermessage) {
1866 print $othermessage;
1867 }
1868 if (isset($total_ttc_by_line)) {
1869 if (!$qualifiedfortotal) {
1870 print '<strike>';
1871 }
1872 print '<span class="amount">'.price($total_ttc_by_line).'</span>';
1873 if (!$qualifiedfortotal) {
1874 print '</strike>';
1875 }
1876 }
1877 if ($warning) {
1878 print ' '.img_warning($warning);
1879 }
1880 if (isset($tmpprojtime['nblinesnull']) && ($tmpprojtime['nblinesnull'] > 0)) {
1881 if ($tmpprojtime['nbuserthmnull'] > 0) {
1882 $title = $langs->trans("EnterUsersHourlyRateFirst");
1883 print ' '.img_picto($title, "sync", '', 0, 0, 0, '', 'opacitymedium');
1884 } else {
1885 $title = $langs->trans("UpdateUndefinedWithLastHourlyRate");
1886 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>';
1887 }
1888 }
1889 if (getDolGlobalString('PROJECT_CAN_OVERWRITE_TIMESTPENT_HOURLY_RATE_WITH_LASTONE')) {
1890 $title = $langs->trans("UpdateWithLastHourlyRate");
1891 print ' <a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$id.'&action=updateallwithlasthourlyrate&taskid='.$idofelement.'&token='.currentToken().'">'.img_picto($title, "sync").'</a>';
1892 }
1893 print '</td>';
1894 } else {
1895 print '<td></td>';
1896 }
1897
1898 // Status
1899 print '<td class="right">';
1900 if ($tablename == 'expensereport_det') {
1901 print $expensereport->getLibStatut(5);
1902 } elseif ($element instanceof CommonInvoice) {
1903 //This applies for Facture and FactureFournisseur
1904 print $element->getLibStatut(5, $element->getSommePaiement());
1905 } elseif ($element instanceof Task) {
1906 if ($element->progress != '') {
1907 print $element->progress.' %';
1908 }
1909 } elseif ($tablename == 'stock_mouvement') {
1910 '@phan-var-force MouvementStock $element';
1911 print $element->getLibStatut(3);
1912 } else {
1913 print $element->getLibStatut(5);
1914 }
1915 print '</td>';
1916
1917 print '</tr>';
1918
1919 if ($qualifiedfortotal) {
1920 $total_ht += $total_ht_by_line;
1921 $total_ttc += $total_ttc_by_line;
1922
1923 $total_ht_by_third += $total_ht_by_line;
1924 $total_ttc_by_third += $total_ttc_by_line;
1925
1926 if (!isset($total_time)) {
1927 $total_time = $total_time_by_line;
1928 } else {
1929 $total_time += $total_time_by_line;
1930 }
1931 }
1932
1933 if (canApplySubtotalOn($tablename)) {
1934 $breakline = '<tr class="liste_total liste_sub_total">';
1935 $breakline .= '<td colspan="2">';
1936 $breakline .= '</td>';
1937 $breakline .= '<td>';
1938 $breakline .= '</td>';
1939 $breakline .= '<td class="right">';
1940 $breakline .= $langs->trans('SubTotal').' : ';
1941 if (is_object($element->thirdparty)) {
1942 $breakline .= $element->thirdparty->getNomUrl(0, '', 48);
1943 }
1944 $breakline .= '</td>';
1945 $breakline .= '<td class="right">'.price($total_ht_by_third).'</td>';
1946 $breakline .= '<td class="right">'.price($total_ttc_by_third).'</td>';
1947 $breakline .= '<td></td>';
1948 $breakline .= '</tr>';
1949 }
1950
1951 //var_dump($element->thirdparty->name.' - '.$saved_third_id.' - '.$element->thirdparty->id);
1952 }
1953
1954 if ($breakline) {
1955 print $breakline;
1956 }
1957
1958 // Total
1959 if (empty($nototal)) {
1960 $colspan = 4;
1961 if (in_array($tablename, array('projet_task'))) {
1962 $colspan = 2;
1963 }
1964 if ($key == 'stocktransfer') {
1965 $colspan = 9;
1966 }
1967
1968 print '<tr class="liste_total"><td colspan="'.$colspan.'">'.$langs->trans("Number").': '.$i.'</td>';
1969 if (in_array($tablename, array('projet_task'))) {
1970 print '<td class="center">';
1971 print convertSecondToTime((int) $total_time, 'allhourmin');
1972 print '</td>';
1973 print '<td>';
1974 print '</td>';
1975 }
1976 //if (empty($value['disableamount']) && ! in_array($tablename, array('projet_task'))) print '<td class="right" width="100">'.$langs->trans("TotalHT").' : '.price($total_ht).'</td>';
1977 //elseif (empty($value['disableamount']) && in_array($tablename, array('projet_task'))) print '<td class="right" width="100">'.$langs->trans("Total").' : '.price($total_ht).'</td>';
1978 // If fichinter add the total_duration
1979 if ($tablename == 'fichinter') {
1980 print '<td class="left">'.convertSecondToTime($total_duration, 'all', $conf->global->MAIN_DURATION_OF_WORKDAY).'</td>';
1981 }
1982 print '<td class="right">';
1983 if (empty($value['disableamount'])) {
1984 if ($key == 'loan') {
1985 print $langs->trans("Total").' '.$langs->trans("LoanCapital").' : '.price($total_ttc);
1986 } elseif ($tablename != 'projet_task' || isModEnabled('salaries')) {
1987 print ''.$langs->trans("TotalHT").' : '.price($total_ht);
1988 }
1989 }
1990 print '</td>';
1991 //if (empty($value['disableamount']) && ! in_array($tablename, array('projet_task'))) print '<td class="right" width="100">'.$langs->trans("TotalTTC").' : '.price($total_ttc).'</td>';
1992 //elseif (empty($value['disableamount']) && in_array($tablename, array('projet_task'))) print '<td class="right" width="100"></td>';
1993 print '<td class="right">';
1994 if (empty($value['disableamount'])) {
1995 if ($key == 'loan') {
1996 print $langs->trans("Total").' '.$langs->trans("RemainderToPay").' : '.price($total_ttc);
1997 } elseif ($tablename != 'projet_task' || isModEnabled('salaries')) {
1998 print $langs->trans("TotalTTC").' : '.price($total_ttc);
1999 }
2000 }
2001 print '</td>';
2002 print '<td>&nbsp;</td>';
2003 // Because of the added Type and Description columns to Expense Reports
2004 if ($tablename == 'expensereport_det') {
2005 print '<td>&nbsp;</td>';
2006 print '<td>&nbsp;</td>';
2007 }
2008 print '</tr>';
2009 }
2010 } else {
2011 if (!is_array($elementarray)) { // error
2012 print '<tr><td>'.$elementarray.'</td></tr>';
2013 } else {
2014 $colspan = 7;
2015 if ($tablename == 'fichinter') {
2016 $colspan++;
2017 }
2018 if ($key == 'stocktransfer') {
2019 $colspan = 12;
2020 }
2021 print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("None").'</td></tr>';
2022 }
2023 }
2024 print "</table>";
2025 print '</div>';
2026 print "<br>\n";
2027 }
2028}
2029
2030// Enhance with select2
2031if ($conf->use_javascript_ajax) {
2032 include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
2033 $comboenhancement = ajax_combobox('.elementselect');
2034
2035 print $comboenhancement;
2036}
2037
2038// End of page
2039llxFooter();
2040$db->close();
2041
2042
2043
2050function canApplySubtotalOn($tablename)
2051{
2052 global $conf;
2053
2054 if (!getDolGlobalString('PROJECT_ADD_SUBTOTAL_LINES')) {
2055 return false;
2056 }
2057 return in_array($tablename, array('facture_fourn', 'commande_fournisseur'));
2058}
2059
2066function sortElementsByClientName($elementarray)
2067{
2068 global $db, $classname;
2069 '@phan-var-force string $classname';
2070
2071 $element = new $classname($db);
2072 '@phan-var-force CommonObject $element';
2073
2074 $clientname = array();
2075 foreach ($elementarray as $key => $id) { // id = id of object
2076 if (empty($clientname[$id])) {
2077 $element->fetch($id);
2078 $element->fetch_thirdparty();
2079
2080 $clientname[$id] = $element->thirdparty->name;
2081 }
2082 }
2083
2084 //var_dump($clientname);
2085 asort($clientname); // sort on name
2086
2087 $elementarray = array();
2088 foreach ($clientname as $id => $name) {
2089 $elementarray[] = $id;
2090 }
2091
2092 return $elementarray;
2093}
$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:476
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 warehouses.
Class to manage Trips and Expenses.
const TYPE_DEPOSIT
Deposit invoice.
const STATUS_CLOSED
Classified paid.
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:620
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:263
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:451
sortElementsByClientName($elementarray)
sortElementsByClientName
Definition element.php:2066
canApplySubtotalOn($tablename)
Return if we should do a group by customer with sub-total.
Definition element.php:2050
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_now($mode='gmt')
Return date for now.
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.
dolPrintHTML($s, $allowiframe=0, $moreallowedtags=array())
Return a string (that can be on several lines) ready to be output on a HTML page.
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.
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, $nodefault=0)
Return value of a param into GET or POST supervariable.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_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.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
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...
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
buildzip.php
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, $nodie=0, $mode='')
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.