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