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