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