dolibarr 25.0.0-alpha
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 $referentTables = array_values(array_map(
849 function ($definition) {
850 return $definition['table'];
851 }, $listofreferent));
852 if (!in_array($tablename, $referentTables)) {
853 accessforbidden('', 0, 0);
854 }
855 $projectField = GETPOSTISSET('projectfield') ? GETPOST('projectfield', 'aZ09') : 'fk_projet';
856 $elementselectid = GETPOSTINT("elementselect");
857
858 $result = $object->remove_element($tablename, $elementselectid, $projectField);
859 if ($result < 0) {
860 setEventMessages($object->error, $object->errors, 'errors');
861 }
862}
863
864$elementuser = new User($db);
865
866
867
868$showdatefilter = 0;
869// Show the filter on date on top of element list
870if (!$showdatefilter) {
871 print '<div class="center centpercent">';
872 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">';
873 print '<input type="hidden" name="token" value="'.newToken().'">';
874 print '<input type="hidden" name="tablename" value="'.(empty($tablename) ? '' : $tablename).'">';
875 print '<input type="hidden" name="action" value="view">';
876 print '<div class="inline-block">';
877 print $form->selectDate($dates, 'dates', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From"));
878 print '</div>';
879 print '<div class="inline-block">';
880 print $form->selectDate($datee, 'datee', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"));
881 print '</div>';
882 print '<div class="inline-block">';
883 print '<input type="submit" name="refresh" value="'.$langs->trans("Refresh").'" class="button small">';
884 print '</div>';
885 print '</form>';
886 print '</div>';
887
888 $showdatefilter++;
889}
890
891
892
893// Show balance for whole project
894
895$langs->loadLangs(array("suppliers", "bills", "orders", "proposals", "margins"));
896
897if (isModEnabled('stock') || isModEnabled('stocktransfer')) {
898 $langs->load('stocks');
899}
900
901print '<!-- Begin PROFIT table -->';
902print load_fiche_titre($langs->trans("Profit"), '', 'title_accountancy');
903
904print '<div class="div-table-responsive">';
905print '<table class="noborder centpercent">';
906print '<tr class="liste_titre">';
907print '<td class="left" width="200">';
908$tooltiponprofit = $langs->trans("ProfitIsCalculatedWith")."<br>\n";
909$tooltiponprofitplus = $tooltiponprofitminus = '';
910foreach ($listofreferent as $key => $value) {
911 if (!empty($value['lang'])) {
912 $langs->load($value['lang']);
913 }
914 $name = $langs->trans($value['name']);
915 $qualified = $value['test'];
916 $margin = empty($value['margin']) ? '' : $value['margin'];
917 if ($qualified && $margin) { // If this element must be included into profit calculation ($margin is 'minus' or 'add')
918 if ($margin === 'add') {
919 $tooltiponprofitplus .= ' &gt; '.$name." (+)<br>\n";
920 } elseif ($margin === 'minus') {
921 $tooltiponprofitminus .= ' &gt; '.$name." (-)<br>\n";
922 }
923 }
924}
925$tooltiponprofit .= $tooltiponprofitplus;
926$tooltiponprofit .= $tooltiponprofitminus;
927print $form->textwithpicto($langs->trans("Element"), $tooltiponprofit);
928print '</td>';
929print '<td class="right" width="100">'.$langs->trans("Number").'</td>';
930print '<td class="right" width="100">'.$langs->trans("AmountHT").'</td>';
931print '<td class="right" width="100">'.$langs->trans("AmountTTC").'</td>';
932print '</tr>';
933
934$total_revenue_ht = 0;
935$balance_ht = 0;
936$balance_ttc = 0;
937
938// Loop on each element type (proposal, sale order, invoices, ...)
939foreach ($listofreferent as $key => $value) {
940 $parameters = array(
941 'total_revenue_ht' => & $total_revenue_ht,
942 'balance_ht' => & $balance_ht,
943 'balance_ttc' => & $balance_ttc,
944 'key' => $key,
945 'value' => & $value,
946 'dates' => $dates,
947 'datee' => $datee
948 );
949 $reshook = $hookmanager->executeHooks('printOverviewProfit', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
950 if ($reshook < 0) {
951 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
952 } elseif ($reshook > 0) {
953 print $hookmanager->resPrint;
954 continue;
955 }
956
957 $name = $langs->trans($value['name']);
958 $title = $value['title'];
959 $classname = $value['class'];
960 $tablename = $value['table'];
961 $datefieldname = $value['datefieldname'];
962 $qualified = $value['test'];
963 // Hide project_task amounts in profit section for users without financial access
964 if ($key === 'project_task' && !$canSeeFinancials) {
965 $qualified = false;
966 }
967 $margin = empty($value['margin']) ? 0 : $value['margin'];
968 $project_field = empty($value['project_field']) ? '' : $value['project_field'];
969 if ($qualified) { // If this element must be included into profit summary table ($margin is '', 'minus' or 'add')
970 $element = new $classname($db);
971
972 $elementarray = $object->get_element_list($key, $tablename, $datefieldname, $dates, $datee, !empty($project_field) ? $project_field : 'fk_projet');
973
974 if (is_array($elementarray) && count($elementarray) > 0) {
975 $total_ht = 0;
976 $total_ttc = 0;
977 $i = 0;
978
979 // Loop on each object for the current element type
980 $num = count($elementarray);
981 for ($i = 0; $i < $num; $i++) {
982 $tmp = explode('_', $elementarray[$i]);
983 $idofelement = (int) $tmp[0];
984 $idofelementuser = !empty($tmp[1]) ? (int) $tmp[1] : 0;
985
986 $element->fetch($idofelement);
987 if ($idofelementuser) {
988 $elementuser->fetch($idofelementuser);
989 }
990
991 // Define if record must be used for total or not
992 $qualifiedfortotal = true;
993 if ($key == 'invoice') {
994 if (!empty($element->close_code) && $element->close_code == 'replaced') {
995 $qualifiedfortotal = false; // Replacement invoice, do not include into total
996 }
997 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS') && $element->type == Facture::TYPE_DEPOSIT) {
998 $qualifiedfortotal = false; // If hidden option to use deposits as payment (deprecated, not recommended to use this), deposits are not included
999 }
1000 if (getDolGlobalString('PROJECT_ONLY_PAYED_INVOICE_ON_PROFIT') && $element->status != Facture::STATUS_CLOSED) {
1001 $qualifiedfortotal = false; // Only paid invoices qualify
1002 }
1003 }
1004 if ($key == 'propal') {
1005 if ($element->status != Propal::STATUS_SIGNED && $element->status != Propal::STATUS_BILLED) {
1006 $qualifiedfortotal = false; // Only signed proposal must not be included in total
1007 }
1008 }
1009
1010 if ($tablename != 'expensereport_det' && method_exists($element, 'fetch_thirdparty')) {
1011 $element->fetch_thirdparty();
1012 }
1013
1014 // Define $total_ht_by_line
1015 if ($tablename == 'don' || $tablename == 'chargesociales' || $tablename == 'payment_various' || $tablename == 'salary') {
1016 '@phan-var-force ChargeSociales|PaymentVarious|Salary $element';
1017 $total_ht_by_line = $element->amount;
1018 } elseif ($tablename == 'fichinter') {
1019 '@phan-var-force Fichinter $element';
1020 $total_ht_by_line = $element->getAmount();
1021 } elseif ($tablename == 'stock_mouvement') {
1022 '@phan-var-force MouvementStock $element';
1023 $total_ht_by_line = $element->price * abs($element->qty);
1024 } elseif ($tablename == 'projet_task') {
1025 '@phan-var-force Task $element';
1026 $tmp = $element->getSumOfAmount($idofelementuser ? $elementuser : '', (string) $dates, (string) $datee);
1027 $total_ht_by_line = price2num($tmp['amount'], 'MT');
1028 } elseif ($key == 'loan') {
1029 '@phan-var-force Loan $element';
1030 if ((empty($dates) && empty($datee)) || (intval($dates) <= $element->datestart && intval($datee) >= $element->dateend)) {
1031 // Get total loan
1032 $total_ht_by_line = -$element->capital;
1033 } else {
1034 // Get loan schedule according to date filter
1035 $total_ht_by_line = 0;
1036 $loanScheduleStatic = new LoanSchedule($element->db);
1037 $loanScheduleStatic->fetchAll($element->id);
1038 if (!empty($loanScheduleStatic->lines)) {
1039 foreach ($loanScheduleStatic->lines as $loanSchedule) {
1043 if (($loanSchedule->datep >= $dates && $loanSchedule->datep <= $datee) // dates filter is defined
1044 || !empty($dates) && empty($datee) && $loanSchedule->datep >= $dates && $loanSchedule->datep <= dol_now()
1045 || empty($dates) && !empty($datee) && $loanSchedule->datep <= $datee
1046 ) {
1047 $total_ht_by_line -= $loanSchedule->amount_capital;
1048 }
1049 }
1050 }
1051 }
1052 } else {
1053 $total_ht_by_line = $element->total_ht;
1054 }
1055
1056 // Define $total_ttc_by_line
1057 if ($tablename == 'don' || $tablename == 'chargesociales' || $tablename == 'payment_various' || $tablename == 'salary') {
1058 '@phan-var-force ChargeSociales|PaymentVarious|Salary $element';
1059 $total_ttc_by_line = $element->amount;
1060 } elseif ($tablename == 'fichinter') {
1061 '@phan-var-force Fichinter $element';
1062 $total_ttc_by_line = $element->getAmount();
1063 } elseif ($tablename == 'stock_mouvement') {
1064 '@phan-var-force MouvementStock $element';
1065 $total_ttc_by_line = $element->price * abs($element->qty);
1066 } elseif ($tablename == 'projet_task') {
1067 '@phan-var-force Task $element';
1068 $defaultvat = get_default_tva($mysoc, $mysoc);
1069 $reg = array();
1070 if (preg_replace('/^(\d+\.)\s\‍(.*\‍)/', $defaultvat, $reg)) {
1071 // @phan-suppress-next-line PhanTypeInvalidDimOffset
1072 $defaultvat = $reg[1];
1073 }
1074 $total_ttc_by_line = price2num($total_ht_by_line * (1 + ((float) $defaultvat / 100)), 'MT');
1075 } elseif ($key == 'loan') {
1076 $total_ttc_by_line = $total_ht_by_line; // For loan there is actually no taxe managed in Dolibarr
1077 } else {
1078 $total_ttc_by_line = $element->total_ttc;
1079 }
1080
1081 // Change sign of $total_ht_by_line and $total_ttc_by_line for various payments
1082 if ($tablename == 'payment_various') {
1083 if ($element->sens == 1) {
1084 $total_ht_by_line = -$total_ht_by_line;
1085 $total_ttc_by_line = -$total_ttc_by_line;
1086 }
1087 }
1088
1089 // Change sign of $total_ht_by_line and $total_ttc_by_line for supplier proposal and supplier order.
1090 // Skip when the element already participates to the margin computation via margin='minus'
1091 // (line 1095 below will revert sign too, and double-negation would silently flip the value
1092 // back to positive - see PROJECT_ELEMENTS_FOR_MINUS_MARGIN=order_supplier in #34684).
1093 if (($tablename == 'commande_fournisseur' || $tablename == 'supplier_proposal') && $margin !== 'minus') {
1094 $total_ht_by_line = -$total_ht_by_line;
1095 $total_ttc_by_line = -$total_ttc_by_line;
1096 }
1097
1098 // Add total if we have to
1099 if ($qualifiedfortotal) {
1100 $total_ht += $total_ht_by_line;
1101 $total_ttc += $total_ttc_by_line;
1102 }
1103 }
1104
1105 // Each element with at least one line is output
1106
1107 // Calculate margin
1108 if ($margin) {
1109 if ($margin === 'add') {
1110 $total_revenue_ht += $total_ht;
1111 }
1112
1113 if ($margin === "minus") { // Revert sign
1114 $total_ht = -$total_ht;
1115 $total_ttc = -$total_ttc;
1116 }
1117
1118 $balance_ht += $total_ht;
1119 $balance_ttc += $total_ttc;
1120 }
1121
1122 print '<tr class="oddeven">';
1123 // Module
1124 print '<!-- // Module '.$name.' with tablename '.$tablename.' -->';
1125 print '<td class="left"><a href="#table_'.$tablename.'">'.$name.'</a></td>';
1126 // Nb
1127 print '<td class="right">'.$i.'</td>';
1128 // Amount HT
1129 print '<td class="right">';
1130 if ($key == 'intervention' && !$margin) {
1131 print '<span class="opacitymedium">'.$form->textwithpicto($langs->trans("NA"), $langs->trans("AmountOfInteventionNotIncludedByDefault")).'</span>';
1132 } elseif ($key == 'stocktransfer') {
1133 print '<span class="opacitymedium">'.$form->textwithpicto($langs->trans("NA"), $langs->trans("NoAmountforStockTransfer")).'</span>';
1134 } else {
1135 if ($key == 'propal') {
1136 print '<span class="opacitymedium">'.$form->textwithpicto('', $langs->trans("SignedOnly")).'</span>';
1137 }
1138 print price($total_ht);
1139 }
1140 print '</td>';
1141 // Amount TTC
1142 print '<td class="right">';
1143 if ($key == 'intervention' && !$margin) {
1144 print '<span class="opacitymedium">'.$form->textwithpicto($langs->trans("NA"), $langs->trans("AmountOfInteventionNotIncludedByDefault")).'</span>';
1145 } elseif ($key == 'stocktransfer') {
1146 print '<span class="opacitymedium">'.$form->textwithpicto($langs->trans("NA"), $langs->trans("NoAmountforStockTransfer")).'</span>';
1147 } else {
1148 if ($key == 'propal') {
1149 print '<span class="opacitymedium">'.$form->textwithpicto('', $langs->trans("SignedOnly")).'</span>';
1150 }
1151 print price($total_ttc);
1152 }
1153 print '</td>';
1154 print '</tr>';
1155 }
1156 }
1157}
1158// and the final balance
1159print '<tr class="liste_total">';
1160print '<td class="right" colspan="2">'.$langs->trans("Profit").'</td>';
1161print '<td class="right">'.price(price2num($balance_ht, 'MT')).'</td>';
1162print '<td class="right">'.price(price2num($balance_ttc, 'MT')).'</td>';
1163print '</tr>';
1164
1165// and the cost per attendee
1166if ($object->usage_organize_event) {
1167 require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorboothattendee.class.php';
1168 $conforboothattendee = new ConferenceOrBoothAttendee($db);
1169 $result = $conforboothattendee->fetchAll('', '', 0, 0, '(t.fk_project:=:'.((int) $object->id).') AND (t.status:=:'.ConferenceOrBoothAttendee::STATUS_VALIDATED.')');
1170
1171 if (!is_array($result) && $result < 0) {
1172 setEventMessages($conforboothattendee->error, $conforboothattendee->errors, 'errors');
1173 } else {
1174 $nbAttendees = count($result);
1175 }
1176
1177 if ($nbAttendees >= 2) {
1178 $costperattendee_ht = $balance_ht / $nbAttendees;
1179 $costperattendee_ttc = $balance_ttc / $nbAttendees;
1180 print '<tr class="liste_total">';
1181 print '<td class="right" colspan="2">'.$langs->trans("ProfitPerValidatedAttendee").'</td>';
1182 print '<td class="right">'.price(price2num($costperattendee_ht, 'MT')).'</td>';
1183 print '<td class="right">'.price(price2num($costperattendee_ttc, 'MT')).'</td>';
1184 print '</tr>';
1185 }
1186}
1187
1188// and the margin (profit / revenues)
1189if ($total_revenue_ht) {
1190 print '<tr class="liste_total">';
1191 print '<td class="right" colspan="2">'.$langs->trans("Margin").'</td>';
1192 print '<td class="right">'.round(100 * $balance_ht / $total_revenue_ht, 1).'%</td>';
1193 print '<td class="right"></td>';
1194 print '</tr>';
1195}
1196
1197print "</table>";
1198print '</div>';
1199print '<!-- End PROFIT table -->';
1200
1201
1202print '<br><br>';
1203print '<br>';
1204
1205
1206$total_time = 0;
1207
1208// Detail
1209foreach ($listofreferent as $key => $value) {
1210 $parameters = array(
1211 'key' => $key,
1212 'value' => & $value,
1213 'dates' => $dates,
1214 'datee' => $datee
1215 );
1216 $reshook = $hookmanager->executeHooks('printOverviewDetail', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1217 if ($reshook < 0) {
1218 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1219 } elseif ($reshook > 0) {
1220 print $hookmanager->resPrint;
1221 continue;
1222 }
1223
1224 $title = $value['title'];
1225 $classname = $value['class'];
1226 $tablename = $value['table'];
1227 $datefieldname = $value['datefieldname'];
1228 $qualified = $value['test'];
1229 $urlnew = empty($value['urlnew']) ? '' : $value['urlnew'];
1230 $buttonnew = empty($value['buttonnew']) ? '' : $value['buttonnew'];
1231 $testnew = empty($value['testnew']) ? '' : $value['testnew'];
1232 $project_field = empty($value['project_field']) ? '' : $value['project_field'];
1233 $nototal = empty($value['nototal']) ? 0 : 1;
1234
1235 $exclude_select_element = array('payment_various');
1236 if (!empty($value['exclude_select_element'])) {
1237 $exclude_select_element[] = $value['exclude_select_element'];
1238 }
1239
1240 if ($qualified && $tablename !== null) {
1241 // If we want the project task array to have details of users
1242 //if ($key == 'project_task') $key = 'project_task_time';
1243
1244 $element = new $classname($db);
1245
1246 $addform = '';
1247
1248 $idtofilterthirdparty = 0;
1249 $array_of_element_linkable_with_different_thirdparty = array('facture_fourn', 'commande_fournisseur');
1250 if (!in_array($tablename, $array_of_element_linkable_with_different_thirdparty)) {
1251 $idtofilterthirdparty = empty($object->thirdparty->id) ? 0 : $object->thirdparty->id;
1252 if (getDolGlobalString('PROJECT_OTHER_THIRDPARTY_ID_TO_ADD_ELEMENTS')) {
1253 $idtofilterthirdparty .= ',' . getDolGlobalString('PROJECT_OTHER_THIRDPARTY_ID_TO_ADD_ELEMENTS');
1254 }
1255 }
1256
1257 $elementarray = $object->get_element_list($key, $tablename, $datefieldname, $dates, $datee, !empty($project_field) ? $project_field : 'fk_projet');
1258
1259
1260 if (!getDolGlobalString('PROJECT_LINK_ON_OVERWIEW_DISABLED') && $idtofilterthirdparty && !in_array($tablename, $exclude_select_element)) {
1261 $selectList = $formproject->select_element($tablename, $idtofilterthirdparty, 'minwidth300 minwidth75imp', -2, empty($project_field) ? 'fk_projet' : $project_field, $langs->trans("SelectElement"));
1262 if ((int) $selectList < 0) { // cast to int because ''<0 is true.
1263 setEventMessages($formproject->error, $formproject->errors, 'errors');
1264 } elseif ($selectList) {
1265 // Define form with the combo list of elements to link
1266 $addform .= '<div class="inline-block valignmiddle">';
1267 $addform .= '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
1268 $addform .= '<input type="hidden" name="token" value="'.newToken().'">';
1269 $addform .= '<input type="hidden" name="tablename" value="'.$tablename.'">';
1270 $addform .= '<input type="hidden" name="action" value="addelement">';
1271 $addform .= '<input type="hidden" name="datesrfc" value="'.dol_print_date($dates, 'dayhourrfc').'">';
1272 $addform .= '<input type="hidden" name="dateerfc" value="'.dol_print_date($datee, 'dayhourrfc').'">';
1273 $addform .= '<table><tr>';
1274 //$addform .= '<td><span class="hideonsmartphone opacitymedium">'.$langs->trans("SelectElement").'</span></td>';
1275 $addform .= '<td>'.$selectList.'</td>';
1276 $addform .= '<td><input type="submit" class="button button-linkto smallpaddingimp" value="'.dol_escape_htmltag($langs->trans("LinkToElementShort")).'"></td>';
1277 $addform .= '</tr></table>';
1278 $addform .= '</form>';
1279 $addform .= '</div>';
1280 }
1281 }
1282 if (!getDolGlobalString('PROJECT_CREATE_ON_OVERVIEW_DISABLED') && $urlnew) {
1283 $addform .= '<div class="inline-block valignmiddle">';
1284 if ($testnew) {
1285 $addform .= '<a class="buttonxxx marginleftonly" href="'.$urlnew.'" title="'.dol_escape_htmltag($langs->trans($buttonnew)).'"><span class="fa fa-plus-circle valignmiddle paddingleft"></span></a>';
1286 } elseif (!getDolGlobalString('MAIN_BUTTON_HIDE_UNAUTHORIZED')) {
1287 $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>';
1288 }
1289 $addform .= '<div>';
1290 }
1291
1292 if (is_array($elementarray) && count($elementarray) > 0 && $key == "order_supplier") {
1293 $addform .= '<div class="inline-block valignmiddle"><a id="btnShow" class="buttonxxx marginleftonly" href="#" onClick="return false;">
1294 <span id="textBtnShow" class="valignmiddle text-plus-circle hideonsmartphone">'.$langs->trans("CanceledShown").'</span><span id="minus-circle" class="fa fa-eye valignmiddle paddingleft"></span>
1295 </a>
1296 <script>
1297 $("#btnShow").on("click", function () {
1298 console.log("We click to show or hide the canceled lines");
1299 var attr = $(this).attr("data-canceledarehidden");
1300 if (typeof attr !== "undefined" && attr !== false) {
1301 console.log("Show canceled");
1302 $(".tr_canceled").show();
1303 $("#textBtnShow").text("'.dol_escape_js($langs->transnoentitiesnoconv("CanceledShown")).'");
1304 $("#btnShow").removeAttr("data-canceledarehidden");
1305 $("#minus-circle").removeClass("fa-eye-slash").addClass("fa-eye");
1306 } else {
1307 console.log("Hide canceled");
1308 $(".tr_canceled").hide();
1309 $("#textBtnShow").text("'.dol_escape_js($langs->transnoentitiesnoconv("CanceledHidden")).'");
1310 $("#btnShow").attr("data-canceledarehidden", 1);
1311 $("#minus-circle").removeClass("fa-eye").addClass("fa-eye-slash");
1312 }
1313 });
1314 </script></div>';
1315
1316 $addform .= '<div class="inline-block valignmiddle"><a id="btnShowPaid" class="buttonxxx marginleftonly" href="#" onClick="return false;">
1317 <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>
1318 </a>
1319 <script>
1320 $("#btnShowPaid").on("click", function () {
1321 console.log("We click to show or hide the paid lines");
1322 var attr = $(this).attr("data-paidarehidden");
1323 if (typeof attr !== "undefined" && attr !== false) {
1324 console.log("Show paid");
1325 $(".tr_paid").show();
1326 $("#textBtnShowPaid").text("'.dol_escape_js($langs->transnoentitiesnoconv("PaidShown")).'");
1327 $("#btnShowPaid").removeAttr("data-paidarehidden");
1328 $("#minus-circle-paid").removeClass("fa-eye-slash").addClass("fa-eye");
1329 } else {
1330 console.log("Hide paid");
1331 $(".tr_paid").hide();
1332 $("#textBtnShowPaid").text("'.dol_escape_js($langs->transnoentitiesnoconv("PaidHidden")).'");
1333 $("#btnShowPaid").attr("data-paidarehidden", 1);
1334 $("#minus-circle-paid").removeClass("fa-eye").addClass("fa-eye-slash");
1335 }
1336 });
1337 </script></div>';
1338 }
1339
1340 print '<a id="table_'.$tablename.'"></a>';
1341 print load_fiche_titre($langs->trans($title), $addform, '');
1342
1343 print "\n".'<!-- Table for tablename = '.$tablename.' -->'."\n";
1344 print '<div class="div-table-responsive">';
1345 print '<table class="noborder centpercent">';
1346
1347 print '<tr class="liste_titre">';
1348 $stocktransfercolstyle = ($key == 'stocktransfer' ? ' style="width: 9%"' : '');
1349 // Remove link column
1350 print '<td style="width: 24px"></td>';
1351 // Ref
1352 if ($key == 'stocktransfer') {
1353 print '<td'.$stocktransfercolstyle.'>'.$langs->trans("Ref").'</td>';
1354 } else {
1355 print '<td'.(($tablename != 'actioncomm' && $tablename != 'projet_task') ? ' style="width: 200px"' : '').'>'.$langs->trans("Ref").'</td>';
1356 }
1357 // Product and qty on stock_movement
1358 if ('MouvementStock' == $classname) {
1359 print '<td style="width: 200px">'.$langs->trans("Product").'</td>';
1360 print '<td style="width: 50px">'.$langs->trans("Qty").'</td>';
1361 }
1362 // Date
1363 if ($key != 'stocktransfer') {
1364 print '<td'.(($tablename != 'actioncomm' && $tablename != 'projet_task') ? ' style="width: 200px"' : '').' class="center">';
1365 if (in_array($tablename, array('projet_task'))) {
1366 print $langs->trans("TimeSpent");
1367 }
1368 if (!in_array($tablename, array('projet_task'))) {
1369 print $langs->trans("Date");
1370 }
1371 print '</td>';
1372 }
1373 if ($key == 'stocktransfer') {
1374 print '<td'.$stocktransfercolstyle.'>'.$langs->trans("WarehouseSource").'</td>';
1375 print '<td'.$stocktransfercolstyle.'>'.$langs->trans("WarehouseDestination").'</td>';
1376 print '<td class="center"'.$stocktransfercolstyle.'>'.$langs->trans("DatePrevueDepart").'</td>';
1377 print '<td class="center"'.$stocktransfercolstyle.'>'.$langs->trans("DateReelleDepart").'</td>';
1378 print '<td class="center"'.$stocktransfercolstyle.'>'.$langs->trans("DatePrevueArrivee").'</td>';
1379 print '<td class="center"'.$stocktransfercolstyle.'>'.$langs->trans("DateReelleArrivee").'</td>';
1380 }
1381 // Thirdparty or user
1382 print '<td'.($key == 'stocktransfer' ? $stocktransfercolstyle : '').'>';
1383 if (in_array($tablename, array('projet_task')) && $key == 'project_task') {
1384 print ''; // if $key == 'project_task', we don't want details per user
1385 } elseif (in_array($tablename, array('payment_various'))) {
1386 print $langs->trans("Label"); // complementary info about the payment
1387 } elseif (in_array($tablename, array('expensereport_det', 'don', 'projet_task', 'stock_mouvement', 'salary'))) {
1388 print $langs->trans("User");
1389 } else {
1390 print $langs->trans("ThirdParty");
1391 }
1392 print '</td>';
1393 // Duration of intervention
1394 if ($tablename == 'fichinter') {
1395 print '<td>';
1396 print $langs->trans("TotalDuration");
1397 $total_duration = 0;
1398 print '</td>';
1399 }
1400 // Type from Expense Report
1401 if ($tablename == 'expensereport_det') {
1402 print '<td id="expensereport_type">';
1403 print $langs->trans("Type");
1404 print '</td>';
1405 }
1406 // Description from Expense Report
1407 if ($tablename == 'expensereport_det') {
1408 print '<td id="expensereport_description">';
1409 print $langs->trans("Description");
1410 print '</td>';
1411 }
1412
1413
1414 // Amount HT
1415 //if (empty($value['disableamount']) && ! in_array($tablename, array('projet_task'))) print '<td class="right" width="120">'.$langs->trans("AmountHT").'</td>';
1416 //elseif (empty($value['disableamount']) && in_array($tablename, array('projet_task'))) print '<td class="right" width="120">'.$langs->trans("Amount").'</td>';
1417 if ($key == 'loan') {
1418 print '<td class="right" width="120">'.$langs->trans("LoanCapital").'</td>';
1419 } elseif (empty($value['disableamount'])) {
1420 if ($key == 'stocktransfer') {
1421 print '<td class="right"'.$stocktransfercolstyle.'>'.$langs->trans("AmountHT").'</td>';
1422 } else {
1423 print '<td class="right" width="120">'.$langs->trans("AmountHT").'</td>';
1424 }
1425 } else {
1426 if ($key == 'stocktransfer') {
1427 print '<td'.$stocktransfercolstyle.'></td>';
1428 } else {
1429 print '<td width="120"></td>';
1430 }
1431 }
1432 // Amount TTC
1433 //if (empty($value['disableamount']) && ! in_array($tablename, array('projet_task'))) print '<td class="right" width="120">'.$langs->trans("AmountTTC").'</td>';
1434 if ($key == 'loan') {
1435 print '<td class="right" width="120">'.$langs->trans("RemainderToPay").'</td>';
1436 } elseif (empty($value['disableamount'])) {
1437 if ($key == 'stocktransfer') {
1438 print '<td class="right"'.$stocktransfercolstyle.'>'.$langs->trans("AmountTTC").'</td>';
1439 } else {
1440 print '<td class="right" width="120">'.$langs->trans("AmountTTC").'</td>';
1441 }
1442 } else {
1443 if ($key == 'stocktransfer') {
1444 print '<td'.$stocktransfercolstyle.'></td>';
1445 } else {
1446 print '<td width="120"></td>';
1447 }
1448 }
1449 // Status
1450 if (in_array($tablename, array('projet_task'))) {
1451 print '<td class="right" width="200">'.$langs->trans("ProgressDeclared").'</td>';
1452 } else {
1453 if ($key == 'stocktransfer') {
1454 print '<td class="right"'.$stocktransfercolstyle.'>'.$langs->trans("Status").'</td>';
1455 } else {
1456 print '<td class="right" width="200">'.$langs->trans("Status").'</td>';
1457 }
1458 }
1459 print '</tr>';
1460
1461 if (is_array($elementarray) && count($elementarray) > 0) {
1462 $total_ht = 0;
1463 $total_ttc = 0;
1464 $i = 0;
1465
1466 $total_ht_by_third = 0;
1467 $total_ttc_by_third = 0;
1468
1469 $saved_third_id = 0;
1470 $breakline = '';
1471
1472 if (canApplySubtotalOn($tablename)) {
1473 // Sort
1474 $elementarray = sortElementsByClientName($elementarray);
1475 }
1476
1477 $num = count($elementarray);
1478 $total_time = 0;
1479 for ($i = 0; $i < $num; $i++) {
1480 $tmp = explode('_', $elementarray[$i]);
1481 $idofelement = (int) $tmp[0];
1482 $idofelementuser = isset($tmp[1]) ? (int) $tmp[1] : 0;
1483
1484 $element->fetch($idofelement);
1485 if ($idofelementuser) {
1486 $elementuser->fetch($idofelementuser);
1487 }
1488
1489 // Special cases
1490 if ($tablename != 'expensereport_det') {
1491 if (method_exists($element, 'fetch_thirdparty')) {
1492 $element->fetch_thirdparty();
1493 }
1494 } else {
1495 $expensereport = new ExpenseReport($db);
1496 $expensereport->fetch($element->fk_expensereport);
1497 }
1498
1499 //print 'xxx'.$tablename.'yyy'.$classname;
1500
1501 if ($breakline && $saved_third_id != $element->thirdparty->id) {
1502 print $breakline;
1503
1504 $saved_third_id = $element->thirdparty->id;
1505 $breakline = '';
1506
1507 $total_ht_by_third = 0;
1508 $total_ttc_by_third = 0;
1509 }
1510
1511 $saved_third_id = empty($element->thirdparty->id) ? 0 : $element->thirdparty->id;
1512
1513 $qualifiedfortotal = true;
1514 if ($key == 'invoice') {
1515 if (!empty($element->close_code) && $element->close_code == 'replaced') {
1516 $qualifiedfortotal = false; // Replacement invoice, do not include into total
1517 }
1518 } elseif ($key == 'order_supplier' && ($element->status == 6 || $element->status == 7)) {
1519 $qualifiedfortotal = false; // It makes no sense to include canceled orders in the total
1520 }
1521
1522 if ($key == "order_supplier" && ($element->status == 6 || $element->status == 7)) {
1523 print '<tr class="oddeven tr_canceled">';
1524 } elseif ($key == "order_supplier" && ($element->billed)) {
1525 print '<tr class="oddeven tr_paid">';
1526 } else {
1527 print '<tr class="oddeven" >';
1528 }
1529
1530
1531 // Remove link
1532 print '<td style="width: 24px">';
1533 if ($tablename != 'projet_task' && $tablename != 'stock_mouvement') {
1534 if (!getDolGlobalString('PROJECT_DISABLE_UNLINK_FROM_OVERVIEW') || $user->admin) { // PROJECT_DISABLE_UNLINK_FROM_OVERVIEW is empty by default, so this test true
1535 print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=unlink&tablename='.$tablename.'&elementselect='.$element->id.($project_field ? '&projectfield='.$project_field : '').'" class="reposition">';
1536 print img_picto($langs->trans('Unlink'), 'unlink');
1537 print '</a>';
1538 }
1539 }
1540 print "</td>\n";
1541
1542 // Ref
1543 print '<td class="left nowraponall">';
1544 if ($tablename == 'expensereport_det') {
1545 print $expensereport->getNomUrl(1);
1546 } else {
1547 print '<table><tr><td style="border-bottom: none;">';
1548 // Show ref with link
1549 if ($element instanceof Task) {
1550 print $element->getNomUrl(1, 'withproject', 'time');
1551 print ' - '.dol_trunc($element->label, 48);
1552 } elseif ($key == 'loan') {
1553 print $element->getNomUrl(1);
1554 print ' - '.dol_trunc($element->label, 48);
1555 } else {
1556 print $element->getNomUrl(1);
1557 }
1558
1559 $element_doc = $element->element;
1560 $filename = dol_sanitizeFileName($element->ref);
1561 if (!empty($conf->$element_doc)) {
1562 $confelementdoc = $conf->$element_doc;
1563 $filedir = $confelementdoc->multidir_output[$element->entity ?? $conf->entity].'/'.dol_sanitizeFileName($element->ref);
1564 } else {
1565 $filedir = '';
1566 }
1567
1568 if ($element_doc === 'order_supplier') {
1569 $element_doc = 'commande_fournisseur';
1570 $filedir = $conf->fournisseur->commande->multidir_output[$element->entity ?? $conf->entity].'/'.dol_sanitizeFileName($element->ref);
1571 } elseif ($element_doc === 'invoice_supplier') {
1572 $element_doc = 'facture_fournisseur';
1573 $filename = get_exdir($element->id, 2, 0, 0, $element, 'invoice_supplier').dol_sanitizeFileName($element->ref);
1574 $filedir = $conf->fournisseur->facture->multidir_output[$element->entity ?? $conf->entity].'/'.$filename;
1575 }
1576
1577 print '<div class="inline-block valignmiddle">';
1578 if ($filedir) {
1579 print $formfile->getDocumentsLink($element_doc, $filename, $filedir);
1580 }
1581 print '</div>';
1582
1583 print '</td>';
1584
1585 print '<td class="tdoverflowmax250" style="border-bottom: none;">';
1586
1587 // Show supplier ref
1588 if (!empty($element->ref_supplier)) {
1589 print ' - '.$element->ref_supplier;
1590 }
1591 // Show customer ref
1592 if (!empty($element->ref_customer)) {
1593 print ' - '.$element->ref_customer;
1594 }
1595 // Compatibility propale
1596 if (empty($element->ref_customer) && !empty($element->ref_client)) {
1597 print ' - '.$element->ref_client;
1598 }
1599
1600 print '</td></tr></table>';
1601 }
1602 print "</td>\n";
1603 // Product and qty on stock movement
1604 if ('MouvementStock' == $classname) {
1605 '@phan-var-force MouvementStock $element';
1606 $mvsProd = new Product($element->db);
1607 $mvsProd->fetch($element->product_id);
1608 print '<td>'.$mvsProd->getNomUrl(1).'</td>';
1609 print '<td>'.$element->qty.'</td>';
1610 }
1611 // Date or TimeSpent
1612 $date = '';
1613 $total_time_by_line = 0;
1614 if ($tablename == 'expensereport_det') {
1615 '@phan-var-force ExpenseReportLine $element';
1616 $date = $element->date; // No draft status on lines
1617 } elseif ($tablename == 'stock_mouvement') {
1618 '@phan-var-force MouvementStock $element';
1619 $date = $element->datem;
1620 } elseif ($tablename == 'salary') {
1621 '@phan-var-force Salary $element';
1622 $date = $element->datesp;
1623 } elseif ($tablename == 'payment_various') {
1624 '@phan-var-force PaymentVarious $element';
1625 $date = $element->datev;
1626 } elseif ($tablename == 'chargesociales') {
1627 '@phan-var-force ChargeSociales $element';
1628 $date = $element->date_ech;
1629 } elseif (!empty($element->status) || !empty($element->statut) || !empty($element->fk_status)) {
1630 if ($tablename == 'don') {
1631 '@phan-var-force Don $element';
1632 $date = $element->date;
1633 }
1634 if ($tablename == 'commande_fournisseur' || $tablename == 'supplier_order') {
1635 '@phan-var-force CommandeFournisseur $element';
1636 $date = ($element->date_commande ? $element->date_commande : $element->date_valid);
1637 } elseif ($tablename == 'supplier_proposal') {
1638 '@phan-var-force SupplierProposal $element';
1639 $date = $element->date_validation; // There is no other date for this
1640 } elseif ($tablename == 'fichinter') {
1641 '@phan-var-force Fichinter $element';
1642 $date = $element->datev; // There is no other date for this
1643 } elseif ($tablename == 'projet_task') {
1644 '@phan-var-force Task $element';
1645 $date = ''; // We show no date. Showing date of beginning of task make user think it is date of time consumed
1646 } else {
1647 $date = $element->date; // invoice, ...
1648 if (empty($date)) {
1649 $date = $element->date_contrat;
1650 }
1651 if (empty($date)) {
1652 $date = $element->datev;
1653 }
1654 if (empty($date) && !empty($datefieldname)) {
1655 // @phan-suppress-next-line PhanUndeclaredProperty
1656 $date = $element->$datefieldname;
1657 }
1658 }
1659 } elseif ($key == 'loan') {
1660 '@phan-var-force Loan $element';
1661 $date = $element->datestart;
1662 }
1663
1664 if ($key != 'stocktransfer') {
1665 print '<td class="center">';
1666 if ($tablename == 'actioncomm') {
1667 '@phan-var-force ActionComm $element';
1668 print dol_print_date($element->datep, 'dayhour');
1669 if ($element->datef && $element->datef > $element->datep) {
1670 print " - ".dol_print_date($element->datef, 'dayhour');
1671 }
1672 } elseif (in_array($tablename, array('projet_task'))) {
1673 '@phan-var-force Task $element';
1674 $tmpprojtime = $element->getSumOfAmount($idofelementuser ? $elementuser : '', (string) $dates, (string) $datee); // $element is a task. $elementuser may be empty
1675 print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$idofelement.'&withproject=1">';
1676 print convertSecondToTime($tmpprojtime['nbseconds'], 'allhourmin');
1677 print '</a>';
1678 $total_time_by_line = $tmpprojtime['nbseconds'];
1679 } else {
1680 print dol_print_date($date, 'day');
1681 }
1682 print '</td>';
1683 }
1684
1685 if ($key == 'stocktransfer') {
1686 $warehouseSource = new Entrepot($db);
1687 $warehouseDestination = new Entrepot($db);
1688 print '<td class="tdoverflowmax150">';
1689 if (!empty($element->fk_warehouse_source) && $warehouseSource->fetch($element->fk_warehouse_source) > 0) {
1690 print $warehouseSource->getNomUrl(1);
1691 }
1692 print '</td>';
1693 print '<td class="tdoverflowmax150">';
1694 if (!empty($element->fk_warehouse_destination) && $warehouseDestination->fetch($element->fk_warehouse_destination) > 0) {
1695 print $warehouseDestination->getNomUrl(1);
1696 }
1697 print '</td>';
1698 print '<td class="center">'.dol_print_date($element->date_prevue_depart, 'day').'</td>';
1699 print '<td class="center">'.dol_print_date($element->date_reelle_depart, 'day').'</td>';
1700 print '<td class="center">'.dol_print_date($element->date_prevue_arrivee, 'day').'</td>';
1701 print '<td class="center">'.dol_print_date($element->date_reelle_arrivee, 'day').'</td>';
1702 }
1703
1704 // Third party or user
1705 print '<td class="tdoverflowmax150">';
1706 if (is_object($element->thirdparty)) {
1707 print $element->thirdparty->getNomUrl(1, '', 48);
1708 } elseif ($tablename == 'expensereport_det') {
1709 $tmpuser = new User($db);
1710 $tmpuser->fetch($expensereport->fk_user_author);
1711 print $tmpuser->getNomUrl(1, '', 48);
1712 } elseif ($tablename == 'salary') {
1713 $tmpuser = new User($db);
1714 $tmpuser->fetch($element->fk_user);
1715 print $tmpuser->getNomUrl(1, '', 48);
1716 } elseif ($tablename == 'don' || $tablename == 'stock_mouvement') {
1717 '@phan-var-force Don|MouvementStock $element';
1718 if ($element->fk_user_author > 0) {
1719 $tmpuser2 = new User($db);
1720 $tmpuser2->fetch($element->fk_user_author);
1721 print $tmpuser2->getNomUrl(1, '', 48);
1722 }
1723 } elseif ($tablename == 'projet_task' && $key == 'element_time') { // if $key == 'project_task', we don't want details per user
1724 print $elementuser->getNomUrl(1);
1725 } elseif ($tablename == 'payment_various') { // payment label
1726 '@phan-var-force PaymentVarious $element';
1727 print $element->label;
1728 }
1729 print '</td>';
1730
1731 // Add duration and store it in counter for fichinter
1732 if ($tablename == 'fichinter') {
1733 '@phan-var-force FichInter $element';
1734 print '<td>';
1735 print convertSecondToTime($element->duration, 'all', $conf->global->MAIN_DURATION_OF_WORKDAY);
1736 $total_duration += $element->duration;
1737 print '</td>';
1738 }
1739
1740 // Type from Expense Report
1741 if ($tablename == 'expensereport_det') {
1742 print '<td class="left linecoltype">';
1743 $labeltype = ($langs->trans(($element->type_fees_code)) == $element->type_fees_code ? $element->type_fees_libelle : $langs->trans($element->type_fees_code));
1744 print (string) $labeltype;
1745 print '</td>';
1746 }
1747 // Description from Expense Report
1748 if ($tablename == 'expensereport_det') {
1749 print '<td class="left linecolcomment">';
1750 print (string) $element->comments;
1751 print '</td>';
1752 }
1753
1754
1755 // Amount without tax
1756 $warning = '';
1757 if (empty($value['disableamount'])) {
1758 $total_ht_by_line = null;
1759 $othermessage = '';
1760 if ($tablename == 'don' || $tablename == 'chargesociales' || $tablename == 'payment_various' || $tablename == 'salary') {
1761 '@phan-var-force Don|ChargeSociales|PaymentVarious|Salary $element';
1762 $total_ht_by_line = $element->amount;
1763 } elseif ($tablename == 'fichinter') {
1764 '@phan-var-force FichInter $element';
1765 $total_ht_by_line = $element->getAmount();
1766 } elseif ($tablename == 'stock_mouvement') {
1767 '@phan-var-force MouvementStock $element';
1768 $total_ht_by_line = $element->price * abs($element->qty);
1769 } elseif (in_array($tablename, array('projet_task'))) {
1770 if (isModEnabled('salaries')) {
1771 // TODO Permission to read daily rate to show value
1772 $total_ht_by_line = price2num($tmpprojtime['amount'], 'MT');
1773 if (isset($tmpprojtime['nblinesnull']) && ($tmpprojtime['nblinesnull'] > 0)) {
1774 $langs->load("errors");
1775 $warning = $langs->trans("WarningSomeLinesWithNullHourlyRate", $conf->currency);
1776 }
1777 } else {
1778 $othermessage = $form->textwithpicto($langs->trans("NotAvailable"), $langs->trans("ModuleSalaryToDefineHourlyRateMustBeEnabled"));
1779 }
1780 } elseif ($key == 'loan') {
1781 '@phan-var-force Loan $element';
1782 $total_ht_by_line = $element->capital;
1783 } else {
1784 $total_ht_by_line = $element->total_ht;
1785 }
1786
1787 // Change sign of $total_ht_by_line and $total_ttc_by_line for some cases
1788 if ($tablename == 'payment_various') {
1789 if ($element->sens == 0) {
1790 $total_ht_by_line = -$total_ht_by_line;
1791 }
1792 }
1793
1794 print '<td class="right">';
1795 if ($othermessage) {
1796 print '<span class="opacitymedium">'.$othermessage.'</span>';
1797 }
1798 if (isset($total_ht_by_line)) {
1799 if (!$qualifiedfortotal) {
1800 print '<strike>';
1801 }
1802 print '<span class="amount">'.price($total_ht_by_line).'</span>';
1803 if (!$qualifiedfortotal) {
1804 print '</strike>';
1805 }
1806 }
1807 if ($warning) {
1808 print ' '.img_warning($warning);
1809 }
1810 if (isset($tmpprojtime['nblinesnull']) && ($tmpprojtime['nblinesnull'] > 0)) {
1811 if ($tmpprojtime['nbuserthmnull'] > 0) {
1812 $title = $langs->trans("EnterUsersHourlyRateFirst");
1813 print ' '.img_picto($title, "sync", '', 0, 0, 0, '', 'opacitymedium');
1814 } else {
1815 $title = $langs->trans("UpdateUndefinedWithLastHourlyRate");
1816 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>';
1817 }
1818 }
1819 if (getDolGlobalString('PROJECT_CAN_OVERWRITE_TIMESTPENT_HOURLY_RATE_WITH_LASTONE')) {
1820 $title = $langs->trans("UpdateWithLastHourlyRate");
1821 print ' <a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$id.'&action=updateallwithlasthourlyrate&taskid='.$idofelement.'&token='.currentToken().'">'.img_picto($title, "sync", '', 0, 0, 0, '', '').'</a>';
1822 }
1823 print '</td>';
1824 } else {
1825 print '<td></td>';
1826 }
1827
1828 // Amount inc tax
1829 if (empty($value['disableamount'])) {
1830 $total_ttc_by_line = null;
1831 if ($tablename == 'don' || $tablename == 'chargesociales' || $tablename == 'payment_various' || $tablename == 'salary') {
1832 '@phan-var-force Don|ChargeSociales|PaymentVarious $element';
1833 $total_ttc_by_line = $element->amount;
1834 } elseif ($tablename == 'fichinter') {
1835 '@phan-var-force Fichinter $element';
1836 $total_ttc_by_line = $element->getAmount();
1837 } elseif ($tablename == 'stock_mouvement') {
1838 '@phan-var-force MouvementStock $element';
1839 $total_ttc_by_line = $element->price * abs($element->qty);
1840 } elseif ($tablename == 'projet_task') {
1841 if (isModEnabled('salaries')) {
1842 // TODO Permission to read daily rate
1843 $defaultvat = get_default_tva($mysoc, $mysoc);
1844 $total_ttc_by_line = price2num($total_ht_by_line * (1 + ($defaultvat / 100)), 'MT');
1845 } else {
1846 $othermessage = $form->textwithpicto($langs->trans("NotAvailable"), $langs->trans("ModuleSalaryToDefineHourlyRateMustBeEnabled"));
1847 }
1848 } elseif ($key == 'loan') {
1849 '@phan-var-force Loan $element';
1850 $total_ttc_by_line = $element->capital - $element->getSumPayment();
1851 } else {
1852 $total_ttc_by_line = $element->total_ttc;
1853 }
1854
1855 // Change sign of $total_ht_by_line and $total_ttc_by_line for some cases
1856 if ($tablename == 'payment_various') {
1857 if ($element->sens == 0) {
1858 $total_ttc_by_line = -$total_ttc_by_line;
1859 }
1860 }
1861
1862 print '<td class="right">';
1863 if ($othermessage) {
1864 print $othermessage;
1865 }
1866 if (isset($total_ttc_by_line)) {
1867 if (!$qualifiedfortotal) {
1868 print '<strike>';
1869 }
1870 print '<span class="amount">'.price($total_ttc_by_line).'</span>';
1871 if (!$qualifiedfortotal) {
1872 print '</strike>';
1873 }
1874 }
1875 if ($warning) {
1876 print ' '.img_warning($warning);
1877 }
1878 if (isset($tmpprojtime['nblinesnull']) && ($tmpprojtime['nblinesnull'] > 0)) {
1879 if ($tmpprojtime['nbuserthmnull'] > 0) {
1880 $title = $langs->trans("EnterUsersHourlyRateFirst");
1881 print ' '.img_picto($title, "sync", '', 0, 0, 0, '', 'opacitymedium');
1882 } else {
1883 $title = $langs->trans("UpdateUndefinedWithLastHourlyRate");
1884 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>';
1885 }
1886 }
1887 if (getDolGlobalString('PROJECT_CAN_OVERWRITE_TIMESTPENT_HOURLY_RATE_WITH_LASTONE')) {
1888 $title = $langs->trans("UpdateWithLastHourlyRate");
1889 print ' <a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$id.'&action=updateallwithlasthourlyrate&taskid='.$idofelement.'&token='.currentToken().'">'.img_picto($title, "sync").'</a>';
1890 }
1891 print '</td>';
1892 } else {
1893 print '<td></td>';
1894 }
1895
1896 // Status
1897 print '<td class="right">';
1898 if ($tablename == 'expensereport_det') {
1899 print $expensereport->getLibStatut(5);
1900 } elseif ($element instanceof CommonInvoice) {
1901 //This applies for Facture and FactureFournisseur
1902 print $element->getLibStatut(5, $element->getSommePaiement());
1903 } elseif ($element instanceof Task) {
1904 if ($element->progress != '') {
1905 print $element->progress.' %';
1906 }
1907 } elseif ($tablename == 'stock_mouvement') {
1908 '@phan-var-force MouvementStock $element';
1909 print $element->getLibStatut(3);
1910 } else {
1911 print $element->getLibStatut(5);
1912 }
1913 print '</td>';
1914
1915 print '</tr>';
1916
1917 if ($qualifiedfortotal) {
1918 $total_ht += $total_ht_by_line;
1919 $total_ttc += $total_ttc_by_line;
1920
1921 $total_ht_by_third += $total_ht_by_line;
1922 $total_ttc_by_third += $total_ttc_by_line;
1923
1924 if (!isset($total_time)) {
1925 $total_time = $total_time_by_line;
1926 } else {
1927 $total_time += $total_time_by_line;
1928 }
1929 }
1930
1931 if (canApplySubtotalOn($tablename)) {
1932 $breakline = '<tr class="liste_total liste_sub_total">';
1933 $breakline .= '<td colspan="2">';
1934 $breakline .= '</td>';
1935 $breakline .= '<td>';
1936 $breakline .= '</td>';
1937 $breakline .= '<td class="right">';
1938 $breakline .= $langs->trans('SubTotal').' : ';
1939 if (is_object($element->thirdparty)) {
1940 $breakline .= $element->thirdparty->getNomUrl(0, '', 48);
1941 }
1942 $breakline .= '</td>';
1943 $breakline .= '<td class="right">'.price($total_ht_by_third).'</td>';
1944 $breakline .= '<td class="right">'.price($total_ttc_by_third).'</td>';
1945 $breakline .= '<td></td>';
1946 $breakline .= '</tr>';
1947 }
1948
1949 //var_dump($element->thirdparty->name.' - '.$saved_third_id.' - '.$element->thirdparty->id);
1950 }
1951
1952 if ($breakline) {
1953 print $breakline;
1954 }
1955
1956 // Total
1957 if (empty($nototal)) {
1958 $colspan = 4;
1959 if (in_array($tablename, array('projet_task'))) {
1960 $colspan = 2;
1961 }
1962 if ($key == 'stocktransfer') {
1963 $colspan = 9;
1964 }
1965
1966 print '<tr class="liste_total"><td colspan="'.$colspan.'">'.$langs->trans("Number").': '.$i.'</td>';
1967 if (in_array($tablename, array('projet_task'))) {
1968 print '<td class="center">';
1969 print convertSecondToTime((int) $total_time, 'allhourmin');
1970 print '</td>';
1971 print '<td>';
1972 print '</td>';
1973 }
1974 //if (empty($value['disableamount']) && ! in_array($tablename, array('projet_task'))) print '<td class="right" width="100">'.$langs->trans("TotalHT").' : '.price($total_ht).'</td>';
1975 //elseif (empty($value['disableamount']) && in_array($tablename, array('projet_task'))) print '<td class="right" width="100">'.$langs->trans("Total").' : '.price($total_ht).'</td>';
1976 // If fichinter add the total_duration
1977 if ($tablename == 'fichinter') {
1978 print '<td class="left">'.convertSecondToTime($total_duration, 'all', $conf->global->MAIN_DURATION_OF_WORKDAY).'</td>';
1979 }
1980 print '<td class="right">';
1981 if (empty($value['disableamount'])) {
1982 if ($key == 'loan') {
1983 print $langs->trans("Total").' '.$langs->trans("LoanCapital").' : '.price($total_ttc);
1984 } elseif ($tablename != 'projet_task' || isModEnabled('salaries')) {
1985 print ''.$langs->trans("TotalHT").' : '.price($total_ht);
1986 }
1987 }
1988 print '</td>';
1989 //if (empty($value['disableamount']) && ! in_array($tablename, array('projet_task'))) print '<td class="right" width="100">'.$langs->trans("TotalTTC").' : '.price($total_ttc).'</td>';
1990 //elseif (empty($value['disableamount']) && in_array($tablename, array('projet_task'))) print '<td class="right" width="100"></td>';
1991 print '<td class="right">';
1992 if (empty($value['disableamount'])) {
1993 if ($key == 'loan') {
1994 print $langs->trans("Total").' '.$langs->trans("RemainderToPay").' : '.price($total_ttc);
1995 } elseif ($tablename != 'projet_task' || isModEnabled('salaries')) {
1996 print $langs->trans("TotalTTC").' : '.price($total_ttc);
1997 }
1998 }
1999 print '</td>';
2000 print '<td>&nbsp;</td>';
2001 // Because of the added Type and Description columns to Expense Reports
2002 if ($tablename == 'expensereport_det') {
2003 print '<td>&nbsp;</td>';
2004 print '<td>&nbsp;</td>';
2005 }
2006 print '</tr>';
2007 }
2008 } else {
2009 if (!is_array($elementarray)) { // error
2010 print '<tr><td>'.$elementarray.'</td></tr>';
2011 } else {
2012 $colspan = 7;
2013 if ($tablename == 'fichinter') {
2014 $colspan++;
2015 }
2016 if ($key == 'stocktransfer') {
2017 $colspan = 12;
2018 }
2019 print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("None").'</td></tr>';
2020 }
2021 }
2022 print "</table>";
2023 print '</div>';
2024 print "<br>\n";
2025 }
2026}
2027
2028// Enhance with select2
2029if ($conf->use_javascript_ajax) {
2030 include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
2031 $comboenhancement = ajax_combobox('.elementselect');
2032
2033 print $comboenhancement;
2034}
2035
2036// End of page
2037llxFooter();
2038$db->close();
2039
2040
2041
2048function canApplySubtotalOn($tablename)
2049{
2050 global $conf;
2051
2052 if (!getDolGlobalString('PROJECT_ADD_SUBTOTAL_LINES')) {
2053 return false;
2054 }
2055 return in_array($tablename, array('facture_fourn', 'commande_fournisseur'));
2056}
2057
2064function sortElementsByClientName($elementarray)
2065{
2066 global $db, $classname;
2067 '@phan-var-force string $classname';
2068
2069 $element = new $classname($db);
2070 '@phan-var-force CommonObject $element';
2071
2072 $clientname = array();
2073 foreach ($elementarray as $key => $id) { // id = id of object
2074 if (empty($clientname[$id])) {
2075 $element->fetch($id);
2076 $element->fetch_thirdparty();
2077
2078 $clientname[$id] = $element->thirdparty->name;
2079 }
2080 }
2081
2082 //var_dump($clientname);
2083 asort($clientname); // sort on name
2084
2085 $elementarray = array();
2086 foreach ($clientname as $id => $name) {
2087 $elementarray[] = $id;
2088 }
2089
2090 return $elementarray;
2091}
$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:605
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:436
sortElementsByClientName($elementarray)
sortElementsByClientName
Definition element.php:2064
canApplySubtotalOn($tablename)
Return if we should do a group by customer with sub-total.
Definition element.php:2048
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_now($mode='gmt')
Return date for now.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='', $useCache=true)
Return an id or code from a code or id.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
dolPrintHTML($s, $allowiframe=0, $moreallowedtags=array())
Return a string (that can be on several lines) ready to be output on a HTML page.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
currentToken()
Return the value of token currently saved into session with name 'token'.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
dol_eval($s, $returnvalue=1, $hideerrors=1, $onlysimplestring='1')
Replace eval function to add more security.
setEventMessage($mesgs, $style='mesgs', $noduplicate=0, $attop=0)
Set event message in dol_events session object.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into JavaScript code.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_clone($srcobject, $native=2)
Create a clone of instance of object (new instance with same value for each properties) With native =...
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that return vat rate of a product line (according to seller, buyer and product vat rate) VAT...
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart='')
Return a path to have a the directory according to object where files are stored.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
buildzip.php
project_prepare_head(Project $project, $moreparam='')
Prepare array with list of tabs.
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.