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