dolibarr 20.0.2
time.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2006-2023 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2010-2012 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2011 Juanjo Menent <jmenent@2byte.es>
6 * Copyright (C) 2018 Ferran Marcet <fmarcet@2byte.es>
7 * Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr>
8 * Copyright (C) 2019-2021 Christophe Battarel <christophe@altairis.fr>
9 * Copyright (C) 2023 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
10 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
11 * Copyright (C) 2024 Vincent de Grandpré <vincent@de-grandpre.quebec>
12 * Copyright (C) 2024 Solution Libre SAS <contact@solution-libre.fr>
13 *
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 . '/compta/facture/class/facture.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.formother.class.php';
42require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
43require_once DOL_DOCUMENT_ROOT . '/core/class/html.formintervention.class.php';
44
45// Load translation files required by the page
46$langsLoad = array('projects', 'bills', 'orders', 'companies');
47if (isModEnabled('eventorganization')) {
48 $langsLoad[] = 'eventorganization';
49}
50
51$langs->loadLangs($langsLoad);
52
53$action = GETPOST('action', 'alpha');
54$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists)
55$confirm = GETPOST('confirm', 'alpha');
56$cancel = GETPOST('cancel', 'alpha');
57$toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list
58$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'timespentlist'; // To manage different context of search
59$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page
60$optioncss = GETPOST('optioncss', 'alpha');
61$mode = GETPOST('mode', 'alpha');
62
63$id = GETPOSTINT('id');
64$projectid = GETPOSTINT('projectid');
65$ref = GETPOST('ref', 'alpha');
66$withproject = GETPOSTINT('withproject');
67$project_ref = GETPOST('project_ref', 'alpha');
68$tab = GETPOST('tab', 'aZ09');
69
70$search_day = GETPOSTINT('search_day');
71$search_month = GETPOSTINT('search_month');
72$search_year = GETPOSTINT('search_year');
73$search_date_startday = GETPOSTINT('search_date_startday');
74$search_date_startmonth = GETPOSTINT('search_date_startmonth');
75$search_date_startyear = GETPOSTINT('search_date_startyear');
76$search_date_endday = GETPOSTINT('search_date_endday');
77$search_date_endmonth = GETPOSTINT('search_date_endmonth');
78$search_date_endyear = GETPOSTINT('search_date_endyear');
79$search_date_start = dol_mktime(0, 0, 0, $search_date_startmonth, $search_date_startday, $search_date_startyear); // Use tzserver
80$search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_endday, $search_date_endyear);
81$search_note = GETPOST('search_note', 'alpha');
82$search_duration = GETPOST('search_duration', 'alpha');
83$search_task_ref = GETPOST('search_task_ref', 'alpha');
84$search_task_label = GETPOST('search_task_label', 'alpha');
85$search_user = GETPOST('search_user', 'intcomma');
86$search_valuebilled = GETPOST('search_valuebilled', 'intcomma');
87$search_product_ref = GETPOST('search_product_ref', 'alpha');
88$search_company = GETPOST('$search_company', 'alpha');
89$search_company_alias = GETPOST('$search_company_alias', 'alpha');
90$search_project_ref = GETPOST('$search_project_ref', 'alpha');
91$search_project_label = GETPOST('$search_project_label', 'alpha');
92$search_timespent_starthour = GETPOSTINT("search_timespent_duration_starthour");
93$search_timespent_startmin = GETPOSTINT("search_timespent_duration_startmin");
94$search_timespent_endhour = GETPOSTINT("search_timespent_duration_endhour");
95$search_timespent_endmin = GETPOSTINT("search_timespent_duration_endmin");
96
97$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
98$sortfield = GETPOST('sortfield', 'aZ09comma');
99$sortorder = GETPOST('sortorder', 'aZ09comma');
100$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
101if (empty($page) || $page == -1) {
102 $page = 0;
103} // If $page is not defined, or '' or -1
104$offset = $limit * $page;
105$pageprev = $page - 1;
106$pagenext = $page + 1;
107if (!$sortfield) {
108 $sortfield = 't.element_date,t.element_datehour,t.rowid';
109}
110if (!$sortorder) {
111 $sortorder = 'DESC,DESC,DESC';
112}
113
114$childids = $user->getAllChildIds(1);
115
116// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
117//$object = new TaskTime($db);
118$hookmanager->initHooks(array('projecttasktime', 'globalcard'));
119
120$object = new Task($db);
121$extrafields = new ExtraFields($db);
122$projectstatic = new Project($db);
123
124// fetch optionals attributes and labels
125$extrafields->fetch_name_optionals_label($projectstatic->table_element);
126$extrafields->fetch_name_optionals_label($object->table_element);
127
128// Load task
129if ($id > 0 || $ref) {
130 $object->fetch($id, $ref);
131}
132
133
134// Security check
135$socid = 0;
136//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.
137if (!$user->hasRight('projet', 'lire')) {
139}
140
141if ($object->fk_project > 0) {
142 restrictedArea($user, 'projet', $object->fk_project, 'projet&project');
143} else {
144 restrictedArea($user, 'projet', null, 'projet&project');
145 // We check user has permission to see all tasks of all users
146 if (empty($projectid) && !$user->hasRight('projet', 'all', 'lire')) {
147 $search_user = $user->id;
148 }
149}
150
151
152/*
153 * Actions
154 */
155
156if (GETPOST('cancel', 'alpha')) {
157 $action = '';
158}
159if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend' && $massaction != 'confirm_generateinvoice' && $massaction != 'confirm_generateinter') {
160 $massaction = '';
161}
162
163$parameters = array('socid' => $socid, 'projectid' => $projectid);
164$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
165if ($reshook < 0) {
166 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
167}
168
169include DOL_DOCUMENT_ROOT . '/core/actions_changeselectedfields.inc.php';
170
171// Purge search criteria
172if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
173 $search_day = '';
174 $search_month = '';
175 $search_year = '';
176 $search_note = '';
177 $search_duration = '';
178 $search_value = '';
179 $search_date_startday = '';
180 $search_date_startmonth = '';
181 $search_date_startyear = '';
182 $search_date_endday = '';
183 $search_date_endmonth = '';
184 $search_date_endyear = '';
185 $search_date_start = '';
186 $search_date_end = '';
187 $search_task_ref = '';
188 $search_company = '';
189 $search_company_alias = '';
190 $search_project_ref = '';
191 $search_project_label = '';
192 $search_task_label = '';
193 $search_user = -1;
194 $search_valuebilled = '';
195 $search_product_ref = '';
196 $toselect = array();
197 $search_array_options = array();
198 $search_timespent_starthour = '';
199 $search_timespent_startmin = '';
200 $search_timespent_endhour = '';
201 $search_timespent_endmin = '';
202 $action = '';
203}
204
205if ($action == 'addtimespent' && $user->hasRight('projet', 'time')) {
206 $error = 0;
207
208 $timespent_durationhour = GETPOSTINT('timespent_durationhour');
209 $timespent_durationmin = GETPOSTINT('timespent_durationmin');
210 if (empty($timespent_durationhour) && empty($timespent_durationmin)) {
211 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Duration")), null, 'errors');
212 $error++;
213 }
214 if (!GETPOSTINT("userid")) {
215 $langs->load("errors");
216 setEventMessages($langs->trans('ErrorUserNotAssignedToTask'), null, 'errors');
217 $error++;
218 }
219
220 if (!$error) {
221 if ($id || $ref) {
222 $object->fetch($id, $ref);
223 } else {
224 if (!GETPOSTINT('taskid') || GETPOSTINT('taskid') < 0) {
225 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Task")), null, 'errors');
226 $action = 'createtime';
227 $error++;
228 } else {
229 $object->fetch(GETPOSTINT('taskid'));
230 }
231 }
232
233 if (!$error) {
234 $object->fetch_projet();
235
236 if (empty($object->project->status)) {
237 setEventMessages($langs->trans("ProjectMustBeValidatedFirst"), null, 'errors');
238 $action = 'createtime';
239 $error++;
240 } else {
241 $object->timespent_note = GETPOST("timespent_note", 'alpha');
242 if (GETPOSTINT('progress') > 0) {
243 $object->progress = GETPOSTINT('progress'); // If progress is -1 (not defined), we do not change value
244 }
245 $object->timespent_duration = GETPOSTINT("timespent_durationhour") * 60 * 60; // We store duration in seconds
246 $object->timespent_duration += (GETPOSTINT('timespent_durationmin') ? GETPOSTINT('timespent_durationmin') : 0) * 60; // We store duration in seconds
247 if (GETPOST("timehour") != '' && GETPOST("timehour") >= 0) { // If hour was entered
248 $object->timespent_date = dol_mktime(GETPOSTINT("timehour"), GETPOSTINT("timemin"), 0, GETPOSTINT("timemonth"), GETPOSTINT("timeday"), GETPOSTINT("timeyear"));
249 $object->timespent_withhour = 1;
250 } else {
251 $object->timespent_date = dol_mktime(12, 0, 0, GETPOSTINT("timemonth"), GETPOSTINT("timeday"), GETPOSTINT("timeyear"));
252 }
253 $object->timespent_fk_user = GETPOSTINT("userid");
254 $object->timespent_fk_product = GETPOSTINT("fk_product");
255
256 $result = $object->addTimeSpent($user);
257
258 if ($result >= 0) {
259 setEventMessages($langs->trans("RecordSaved"), null, 'mesgs');
260 } else {
261 setEventMessages($langs->trans($object->error), null, 'errors');
262 $error++;
263 }
264 }
265 }
266 } else {
267 $action = 'createtime';
268 }
269}
270
271if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $user->hasRight('projet', 'lire')) {
272 $error = 0;
273
274 if (!GETPOST("new_durationhour") && !GETPOST("new_durationmin")) {
275 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Duration")), null, 'errors');
276 $error++;
277 }
278
279 if (!$error) {
280 if (GETPOSTINT('taskid') != $id) { // GETPOST('taskid') is id of new task
281 $id_temp = GETPOSTINT('taskid'); // should not overwrite $id
282
283
284 $object->fetchTimeSpent(GETPOSTINT('lineid'));
285
286 $result = 0;
287 if (in_array($object->timespent_fk_user, $childids) || $user->hasRight('projet', 'all', 'creer')) {
288 $result = $object->delTimeSpent($user);
289 }
290
291 $object->fetch($id_temp, $ref);
292
293 $object->timespent_note = GETPOST("timespent_note_line", "alphanohtml");
294 $object->timespent_old_duration = GETPOSTINT("old_duration");
295 $object->timespent_duration = GETPOSTINT("new_durationhour") * 60 * 60; // We store duration in seconds
296 $object->timespent_duration += (GETPOSTINT("new_durationmin") ? GETPOSTINT('new_durationmin') : 0) * 60; // We store duration in seconds
297 if (GETPOST("timelinehour") != '' && GETPOST("timelinehour") >= 0) { // If hour was entered
298 $object->timespent_date = dol_mktime(GETPOST("timelinehour"), GETPOST("timelinemin"), 0, GETPOST("timelinemonth"), GETPOST("timelineday"), GETPOST("timelineyear"));
299 $object->timespent_withhour = 1;
300 } else {
301 $object->timespent_date = dol_mktime(12, 0, 0, GETPOST("timelinemonth"), GETPOST("timelineday"), GETPOST("timelineyear"));
302 }
303 $object->timespent_fk_user = GETPOSTINT("userid_line");
304 $object->timespent_fk_product = GETPOSTINT("fk_product");
305 $object->timespent_invoiceid = GETPOSTINT("invoiceid");
306 $object->timespent_invoicelineid = GETPOSTINT("invoicelineid");
307
308 $result = 0;
309 if (in_array($object->timespent_fk_user, $childids) || $user->hasRight('projet', 'all', 'creer')) {
310 $result = $object->addTimeSpent($user);
311 if ($result >= 0) {
312 setEventMessages($langs->trans("RecordSaved"), null, 'mesgs');
313 } else {
314 setEventMessages($langs->trans($object->error), null, 'errors');
315 $error++;
316 }
317 }
318 } else {
319 $object->fetch($id, $ref);
320
321 $object->timespent_id = GETPOSTINT("lineid");
322 $object->timespent_note = GETPOST("timespent_note_line", "alphanohtml");
323 $object->timespent_old_duration = GETPOSTINT("old_duration");
324 $object->timespent_duration = GETPOSTINT("new_durationhour") * 60 * 60; // We store duration in seconds
325 $object->timespent_duration += (GETPOSTINT("new_durationmin") ? GETPOSTINT('new_durationmin') : 0) * 60; // We store duration in seconds
326 if (GETPOST("timelinehour") != '' && GETPOST("timelinehour") >= 0) { // If hour was entered
327 $object->timespent_date = dol_mktime(GETPOSTINT("timelinehour"), GETPOSTINT("timelinemin"), 0, GETPOSTINT("timelinemonth"), GETPOSTINT("timelineday"), GETPOSTINT("timelineyear"));
328 $object->timespent_withhour = 1;
329 } else {
330 $object->timespent_date = dol_mktime(12, 0, 0, GETPOSTINT("timelinemonth"), GETPOSTINT("timelineday"), GETPOSTINT("timelineyear"));
331 }
332 $object->timespent_fk_user = GETPOSTINT("userid_line");
333 $object->timespent_fk_product = GETPOSTINT("fk_product");
334 $object->timespent_invoiceid = GETPOSTINT("invoiceid");
335 $object->timespent_invoicelineid = GETPOSTINT("invoicelineid");
336 $result = 0;
337
338 if (in_array($object->timespent_fk_user, $childids) || $user->hasRight('projet', 'all', 'creer')) {
339 $result = $object->updateTimeSpent($user);
340
341 if ($result >= 0) {
342 setEventMessages($langs->trans("RecordSaved"), null, 'mesgs');
343 } else {
344 setEventMessages($langs->trans($object->error), null, 'errors');
345 $error++;
346 }
347 }
348 }
349 } else {
350 $action = '';
351 }
352}
353
354if ($action == 'confirm_deleteline' && $confirm == "yes" && ($user->hasRight('projet', 'time') || $user->hasRight('projet', 'all', 'creer'))) {
355 $object->fetchTimeSpent(GETPOSTINT('lineid')); // load properties like $object->timespent_xxx
356
357 if (in_array($object->timespent_fk_user, $childids) || $user->hasRight('projet', 'all', 'creer')) {
358 $result = $object->delTimeSpent($user); // delete line with $object->timespent_id
359
360 if ($result < 0) {
361 $langs->load("errors");
362 setEventMessages($langs->trans($object->error), null, 'errors');
363 $error++;
364 $action = '';
365 } else {
366 setEventMessages($langs->trans("RecordDeleted"), null, 'mesgs');
367 }
368 }
369}
370
371// Retrieve First Task ID of Project if withprojet is on to allow project prev next to work
372if (!empty($project_ref) && !empty($withproject)) {
373 if ($projectstatic->fetch(0, $project_ref) > 0) {
374 $tasksarray = $object->getTasksArray(0, 0, $projectstatic->id, $socid, 0);
375 if (count($tasksarray) > 0) {
376 $id = $tasksarray[0]->id;
377 } else {
378 header("Location: " . DOL_URL_ROOT . '/projet/tasks.php?id=' . $projectstatic->id . ($withproject ? '&withproject=1' : '') . (empty($mode) ? '' : '&mode=' . $mode));
379 exit;
380 }
381 }
382}
383
384// To show all time lines for project
385$projectidforalltimes = 0;
386if (GETPOSTINT('projectid') > 0) {
387 $projectidforalltimes = GETPOSTINT('projectid');
388
389 $result = $projectstatic->fetch($projectidforalltimes);
390 if (!empty($projectstatic->socid)) {
391 $projectstatic->fetch_thirdparty();
392 }
393 $res = $projectstatic->fetch_optionals();
394} elseif (GETPOST('project_ref', 'alpha')) {
395 $projectstatic->fetch(0, GETPOST('project_ref', 'alpha'));
396 $projectidforalltimes = $projectstatic->id;
397 $withproject = 1;
398} elseif ($id > 0) {
399 $object->fetch($id);
400 $result = $projectstatic->fetch($object->fk_project);
401}
402// If not task selected and no project selected
403if ($id <= 0 && $projectidforalltimes == 0) {
404 $allprojectforuser = $user->id;
405}
406
407if ($action == 'confirm_generateinvoice') {
408 if (!empty($projectstatic->socid)) {
409 $projectstatic->fetch_thirdparty();
410 }
411
412 if (!($projectstatic->thirdparty->id > 0)) {
413 setEventMessages($langs->trans("ThirdPartyRequiredToGenerateInvoice"), null, 'errors');
414 } else {
415 include_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
416 include_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
417 include_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
418
419 $tmpinvoice = new Facture($db);
420 $tmptimespent = new Task($db);
421 $tmpproduct = new Product($db);
422 $fuser = new User($db);
423 $remiseproject = price2num(GETPOST('remiseprojet', 'alphanohtml'));
424 $condidproject = GETPOSTINT('condidproject');
425 $db->begin();
426 $idprod = GETPOSTINT('productid');
427 $generateinvoicemode = GETPOST('generateinvoicemode', 'alphanohtml');
428 $invoiceToUse = GETPOSTINT('invoiceid');
429
430 $prodDurationHoursBase = 1.0;
431 $product_data_cache = array();
432 if ($idprod > 0) {
433 $tmpproduct->fetch($idprod);
434 if ($result < 0) {
435 $error++;
436 setEventMessages($tmpproduct->error, $tmpproduct->errors, 'errors');
437 }
438
439 $prodDurationHoursBase = $tmpproduct->getProductDurationHours();
440 if ($prodDurationHoursBase < 0) {
441 $error++;
442 $langs->load("errors");
443 setEventMessages(null, $tmpproduct->errors, 'errors');
444 }
445
446 $dataforprice = $tmpproduct->getSellPrice($mysoc, $projectstatic->thirdparty, 0);
447
448 $pu_ht = empty($dataforprice['pu_ht']) ? 0 : $dataforprice['pu_ht'];
449 $txtva = $dataforprice['tva_tx'];
450 $localtax1 = $dataforprice['localtax1'];
451 $localtax2 = $dataforprice['localtax2'];
452 } else {
453 $prodDurationHoursBase = 1;
454
455 $pu_ht = 0;
456 $txtva = get_default_tva($mysoc, $projectstatic->thirdparty);
457 $localtax1 = get_default_localtax($mysoc, $projectstatic->thirdparty, 1);
458 $localtax2 = get_default_localtax($mysoc, $projectstatic->thirdparty, 2);
459 }
460
461 $tmpinvoice->socid = $projectstatic->thirdparty->id;
462 $tmpinvoice->date = dol_mktime(GETPOSTINT('rehour'), GETPOSTINT('remin'), GETPOSTINT('resec'), GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'));
463 $tmpinvoice->fk_project = $projectstatic->id;
464 $tmpinvoice->cond_reglement_id = $condidproject;
465 $tmpinvoice->mode_reglement_id = $projectstatic->thirdparty->mode_reglement_id;
466 $tmpinvoice->fk_account = $projectstatic->thirdparty->fk_account;
467
468 if ($invoiceToUse) {
469 $tmpinvoice->fetch($invoiceToUse);
470 } else {
471 $result = $tmpinvoice->create($user);
472 if ($result <= 0) {
473 $error++;
474 setEventMessages($tmpinvoice->error, $tmpinvoice->errors, 'errors');
475 }
476 }
477
478 if (!$error) {
479 if ($generateinvoicemode == 'onelineperuser') { // 1 line per user (and per product)
480 $arrayoftasks = array();
481 foreach ($toselect as $key => $value) {
482 // Get userid, timepent
483 $object->fetchTimeSpent($value); // $value is ID of 1 line in timespent table
484 $arrayoftasks[$object->timespent_fk_user][(int) $object->timespent_fk_product]['timespent'] += $object->timespent_duration;
485 $arrayoftasks[$object->timespent_fk_user][(int) $object->timespent_fk_product]['totalvaluetodivideby3600'] += ($object->timespent_duration * $object->timespent_thm);
486 }
487
488 foreach ($arrayoftasks as $userid => $data) {
489 $fuser->fetch($userid);
490 $username = $fuser->getFullName($langs);
491
492 foreach ($data as $fk_product => $timespent_data) {
493 // Define qty per hour
494 $qtyhour = $timespent_data['timespent'] / 3600;
495 $qtyhourtext = convertSecondToTime($timespent_data['timespent'], 'all', $conf->global->MAIN_DURATION_OF_WORKDAY);
496
497 // Set the unit price we want to sell the time, for this user
498 if (getDolGlobalInt('PROJECT_USE_REAL_COST_FOR_TIME_INVOICING')) {
499 // We set unit price to 0 to force the use of the rate saved during recording
500 $pu_ht = 0;
501 } elseif ($idprod <= 0) {
502 // We want to sell all the time spent with the last hourly rate of user
503 // -> but what about choice user selected ? add idprod test
504 $pu_ht = $fuser->thm;
505 }
506
507 // If no unit price known for user, we use the price recorded when recording timespent.
508 if (empty($pu_ht)) {
509 if ($timespent_data['timespent']) {
510 $pu_ht = price2num(($timespent_data['totalvaluetodivideby3600'] / $timespent_data['timespent']), 'MU');
511 }
512 }
513
514 // Add lines
515 $prodDurationHours = $prodDurationHoursBase;
516 $idprodline = $idprod;
517 $pu_htline = $pu_ht;
518 $txtvaline = $txtva;
519 $localtax1line = $localtax1;
520 $localtax2line = $localtax2;
521
522 // If a particular product/service was defined for the task
523 if (!empty($fk_product) && ($fk_product > 0) && ($fk_product !== $idprod)) {
524 if (!array_key_exists($fk_product, $product_data_cache)) {
525 $result = $tmpproduct->fetch($fk_product);
526 if ($result < 0) {
527 $error++;
528 setEventMessages($tmpproduct->error, $tmpproduct->errors, 'errors');
529 }
530 $prodDurationHours = $tmpproduct->getProductDurationHours();
531 if ($prodDurationHours < 0) {
532 $error++;
533 $langs->load("errors");
534 setEventMessages(null, $tmpproduct->errors, 'errors');
535 }
536
537 $dataforprice = $tmpproduct->getSellPrice($mysoc, $projectstatic->thirdparty, 0);
538
539 $pu_htline = empty($dataforprice['pu_ht']) ? 0 : $dataforprice['pu_ht'];
540 $txtvaline = $dataforprice['tva_tx'];
541 $localtax1line = $dataforprice['localtax1'];
542 $localtax2line = $dataforprice['localtax2'];
543
544 $product_data_cache[$fk_product] = array('duration' => $prodDurationHours, 'dataforprice' => $dataforprice);
545 } else {
546 $prodDurationHours = $product_data_cache[$fk_product]['duration'];
547 $pu_htline = empty($product_data_cache[$fk_product]['dataforprice']['pu_ht']) ? 0 : $product_data_cache[$fk_product]['dataforprice']['pu_ht'];
548 $txtvaline = $product_data_cache[$fk_product]['dataforprice']['tva_tx'];
549 $localtax1line = $product_data_cache[$fk_product]['dataforprice']['localtax1'];
550 $localtax2line = $product_data_cache[$fk_product]['dataforprice']['localtax2'];
551 }
552 $idprodline = $fk_product;
553 }
554
555 // Add lines
556 $lineid = $tmpinvoice->addline($langs->trans("TimeSpentForInvoice", $username) . ' : ' . $qtyhourtext, $pu_htline, round($qtyhour / $prodDurationHours, 2), $txtvaline, $localtax1line, $localtax2line, ($idprodline > 0 ? $idprodline : 0), $remiseproject);
557 if ($lineid < 0) {
558 $error++;
559 setEventMessages(null, $tmpinvoice->errors, 'errors');
560 }
561
562 // Update lineid into line of timespent
563 $sql = 'UPDATE '.MAIN_DB_PREFIX.'element_time SET invoice_line_id = '.((int) $lineid).', invoice_id = '.((int) $tmpinvoice->id);
564 $sql .= ' WHERE rowid IN ('.$db->sanitize(implode(',', $toselect)).') AND fk_user = '.((int) $userid);
565 $result = $db->query($sql);
566 if (!$result) {
567 $error++;
568 setEventMessages($db->lasterror(), null, 'errors');
569 break;
570 }
571 }
572 }
573 } elseif ($generateinvoicemode == 'onelineperperiod') { // One line for each time spent line
574 $arrayoftasks = array();
575
576 $withdetail = GETPOST('detail_time_duration', 'alpha');
577 foreach ($toselect as $key => $value) {
578 // Get userid, timepent
579 $object->fetchTimeSpent($value);
580 // $object->id is the task id
581 $ftask = new Task($db);
582 $ftask->fetch($object->id);
583
584 $fuser->fetch($object->timespent_fk_user);
585 $username = $fuser->getFullName($langs);
586
587 $arrayoftasks[$object->timespent_id]['timespent'] = $object->timespent_duration;
588 $arrayoftasks[$object->timespent_id]['totalvaluetodivideby3600'] = $object->timespent_duration * $object->timespent_thm;
589 $arrayoftasks[$object->timespent_id]['note'] = $ftask->ref . ' - ' . $ftask->label . ' - ' . $username;
590 $arrayoftasks[$object->timespent_id]['note'] = dol_concatdesc($arrayoftasks[$object->timespent_id]['note'], $object->timespent_note);
591
592 if (!empty($withdetail)) {
593 if (!empty($object->timespent_withhour)) {
594 $arrayoftasks[$object->timespent_id]['note'] = dol_concatdesc($arrayoftasks[$object->timespent_id]['note'], $langs->trans("Date") . ': ' . dol_print_date($object->timespent_datehour));
595 } else {
596 $arrayoftasks[$object->timespent_id]['note'] = dol_concatdesc($arrayoftasks[$object->timespent_id]['note'], $langs->trans("Date") . ': ' . dol_print_date($object->timespent_date));
597 }
598 $arrayoftasks[$object->timespent_id]['note'] = dol_concatdesc($arrayoftasks[$object->timespent_id]['note'], $langs->trans("Duration") . ': ' . convertSecondToTime($object->timespent_duration, 'all', $conf->global->MAIN_DURATION_OF_WORKDAY));
599 }
600 $arrayoftasks[$object->timespent_id]['user'] = $object->timespent_fk_user;
601 $arrayoftasks[$object->timespent_id]['fk_product'] = $object->timespent_fk_product;
602 }
603
604 foreach ($arrayoftasks as $timespent_id => $value) {
605 $userid = $value['user'];
606 //$pu_ht = $value['timespent'] * $fuser->thm;
607
608 // Define qty per hour
609 $qtyhour = $value['timespent'] / 3600;
610
611 // If no unit price known
612 if (empty($pu_ht)) {
613 $pu_ht = price2num($value['totalvaluetodivideby3600'] / 3600, 'MU');
614 }
615
616 // Add lines
617 $prodDurationHours = $prodDurationHoursBase;
618 $idprodline = $idprod;
619 $pu_htline = $pu_ht;
620 $txtvaline = $txtva;
621 $localtax1line = $localtax1;
622 $localtax2line = $localtax2;
623
624 if (!empty($value['fk_product']) && $value['fk_product'] !== $idprod) {
625 if (!array_key_exists($value['fk_product'], $product_data_cache)) {
626 $result = $tmpproduct->fetch($value['fk_product']);
627 if ($result < 0) {
628 $error++;
629 setEventMessages($tmpproduct->error, $tmpproduct->errors, 'errors');
630 }
631 $prodDurationHours = $tmpproduct->getProductDurationHours();
632 if ($prodDurationHours < 0) {
633 $error++;
634 $langs->load("errors");
635 setEventMessages(null, $tmpproduct->errors, 'errors');
636 }
637
638 $dataforprice = $tmpproduct->getSellPrice($mysoc, $projectstatic->thirdparty, 0);
639
640 $pu_htline = empty($dataforprice['pu_ht']) ? 0 : $dataforprice['pu_ht'];
641 $txtvaline = $dataforprice['tva_tx'];
642 $localtax1line = $dataforprice['localtax1'];
643 $localtax2line = $dataforprice['localtax2'];
644
645 $product_data_cache[$value['fk_product']] = array('duration' => $prodDurationHours, 'dataforprice' => $dataforprice);
646 } else {
647 $prodDurationHours = $product_data_cache[$value['fk_product']]['duration'];
648 $pu_htline = empty($product_data_cache[$value['fk_product']]['dataforprice']['pu_ht']) ? 0 : $product_data_cache[$value['fk_product']]['dataforprice']['pu_ht'];
649 $txtvaline = $product_data_cache[$value['fk_product']]['dataforprice']['tva_tx'];
650 $localtax1line = $product_data_cache[$value['fk_product']]['dataforprice']['localtax1'];
651 $localtax2line = $product_data_cache[$value['fk_product']]['dataforprice']['localtax2'];
652 }
653 $idprodline = $value['fk_product'];
654 }
655 $lineid = $tmpinvoice->addline($value['note'], $pu_htline, round($qtyhour / $prodDurationHours, 2), $txtvaline, $localtax1line, $localtax2line, ($idprodline > 0 ? $idprodline : 0), $remiseproject);
656 if ($lineid < 0) {
657 $error++;
658 setEventMessages(null, $tmpinvoice->errors, 'errors');
659 }
660 //var_dump($lineid);exit;
661
662 // Update lineid into line of timespent
663 $sql = 'UPDATE '.MAIN_DB_PREFIX.'element_time SET invoice_line_id = '.((int) $lineid).', invoice_id = '.((int) $tmpinvoice->id);
664 $sql .= ' WHERE rowid = '.((int) $timespent_id).' AND fk_user = '.((int) $userid);
665 $result = $db->query($sql);
666 if (!$result) {
667 $error++;
668 setEventMessages($db->lasterror(), null, 'errors');
669 break;
670 }
671 }
672 } elseif ($generateinvoicemode == 'onelinepertask') { // One line for each different task
673 $arrayoftasks = array();
674 foreach ($toselect as $key => $value) {
675 // Get userid, timepent
676 $object->fetchTimeSpent($value); // Call method to get list of timespent for a timespent line id (We use the utiliy method found into Task object)
677 // $object->id is now the task id
678 $arrayoftasks[$object->id][(int) $object->timespent_fk_product]['timespent'] += $object->timespent_duration;
679 $arrayoftasks[$object->id][(int) $object->timespent_fk_product]['totalvaluetodivideby3600'] += ($object->timespent_duration * $object->timespent_thm);
680 }
681
682 foreach ($arrayoftasks as $task_id => $data) {
683 $ftask = new Task($db);
684 $ftask->fetch($task_id);
685
686 foreach ($data as $fk_product => $timespent_data) {
687 $qtyhour = $timespent_data['timespent'] / 3600;
688 $qtyhourtext = convertSecondToTime($timespent_data['timespent'], 'all', $conf->global->MAIN_DURATION_OF_WORKDAY);
689
690 // Add lines
691 $prodDurationHours = $prodDurationHoursBase;
692 $idprodline = $idprod;
693 $pu_htline = $pu_ht;
694 $txtvaline = $txtva;
695 $localtax1line = $localtax1;
696 $localtax2line = $localtax2;
697
698 if (!empty($fk_product) && $fk_product !== $idprod) {
699 if (!array_key_exists($fk_product, $product_data_cache)) {
700 $result = $tmpproduct->fetch($fk_product);
701 if ($result < 0) {
702 $error++;
703 setEventMessages($tmpproduct->error, $tmpproduct->errors, 'errors');
704 }
705 $prodDurationHours = $tmpproduct->getProductDurationHours();
706 if ($prodDurationHours < 0) {
707 $error++;
708 $langs->load("errors");
709 setEventMessages(null, $tmpproduct->errors, 'errors');
710 }
711
712 $dataforprice = $tmpproduct->getSellPrice($mysoc, $projectstatic->thirdparty, 0);
713
714 $pu_htline = empty($dataforprice['pu_ht']) ? 0 : $dataforprice['pu_ht'];
715 $txtvaline = $dataforprice['tva_tx'];
716 $localtax1line = $dataforprice['localtax1'];
717 $localtax2line = $dataforprice['localtax2'];
718
719 $product_data_cache[$fk_product] = array('duration' => $prodDurationHours, 'dataforprice' => $dataforprice);
720 } else {
721 $prodDurationHours = $product_data_cache[$fk_product]['duration'];
722 $pu_htline = empty($product_data_cache[$fk_product]['dataforprice']['pu_ht']) ? 0 : $product_data_cache[$fk_product]['dataforprice']['pu_ht'];
723 $txtvaline = $product_data_cache[$fk_product]['dataforprice']['tva_tx'];
724 $localtax1line = $product_data_cache[$fk_product]['dataforprice']['localtax1'];
725 $localtax2line = $product_data_cache[$fk_product]['dataforprice']['localtax2'];
726 }
727 $idprodline = $fk_product;
728 }
729
730
731 if ($idprodline > 0) {
732 // If a product is defined, we msut use the $prodDurationHours and $pu_ht of product (already set previously).
733 $pu_ht_for_task = $pu_htline;
734 // If we want to reuse the value of timespent (so use same price than cost price)
735 if (getDolGlobalString('PROJECT_TIME_SPENT_INTO_INVOICE_USE_VALUE')) {
736 $pu_ht_for_task = price2num($timespent_data['totalvaluetodivideby3600'] / $timespent_data['timespent'], 'MU') * $prodDurationHours;
737 }
738 $pa_ht = price2num($timespent_data['totalvaluetodivideby3600'] / $timespent_data['timespent'], 'MU') * $prodDurationHours;
739 } else {
740 // If not product used, we use the hour unit for duration and unit price.
741 $pu_ht_for_task = 0;
742 // If we want to reuse the value of timespent (so use same price than cost price)
743 if (getDolGlobalString('PROJECT_TIME_SPENT_INTO_INVOICE_USE_VALUE')) {
744 $pu_ht_for_task = price2num($timespent_data['totalvaluetodivideby3600'] / $timespent_data['timespent'], 'MU');
745 }
746 $pa_ht = price2num($timespent_data['totalvaluetodivideby3600'] / $timespent_data['timespent'], 'MU');
747 }
748
749 // Add lines
750 $date_start = '';
751 $date_end = '';
752 $lineName = $ftask->ref . ' - ' . $ftask->label;
753 $lineid = $tmpinvoice->addline($lineName, $pu_ht_for_task, price2num($qtyhour / $prodDurationHours, 'MS'), $txtvaline, $localtax1line, $localtax2line, ($idprodline > 0 ? $idprodline : 0), $remiseproject, $date_start, $date_end, 0, 0, '', 'HT', 0, 1, -1, 0, '', 0, 0, null, $pa_ht);
754 if ($lineid < 0) {
755 $error++;
756 setEventMessages($tmpinvoice->error, $tmpinvoice->errors, 'errors');
757 break;
758 }
759
760 if (!$error) {
761 // Update lineid into line of timespent
762 $sql = 'UPDATE ' . MAIN_DB_PREFIX . 'element_time SET invoice_line_id = ' . ((int) $lineid) . ', invoice_id = ' . ((int) $tmpinvoice->id);
763 $sql .= ' WHERE rowid IN (' . $db->sanitize(implode(',', $toselect)) . ')';
764 $result = $db->query($sql);
765 if (!$result) {
766 $error++;
767 setEventMessages($db->lasterror(), null, 'errors');
768 break;
769 }
770 }
771 }
772 }
773 }
774 }
775
776 if (!$error) {
777 $urltoinvoice = $tmpinvoice->getNomUrl(0);
778 $mesg = $langs->trans("InvoiceGeneratedFromTimeSpent", '{s1}');
779 $mesg = str_replace('{s1}', $urltoinvoice, $mesg);
780 setEventMessages($mesg, null, 'mesgs');
781
782 //var_dump($tmpinvoice);
783
784 $db->commit();
785 } else {
786 $db->rollback();
787 }
788 }
789}
790
791if ($action == 'confirm_generateinter') {
792 $langs->load('interventions');
793
794 if (!empty($projectstatic->socid)) {
795 $projectstatic->fetch_thirdparty();
796 }
797
798 if (!($projectstatic->thirdparty->id > 0)) {
799 setEventMessages($langs->trans("ThirdPartyRequiredToGenerateIntervention"), null, 'errors');
800 } else {
801 include_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
802 include_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
803 include_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
804
805
806 require_once DOL_DOCUMENT_ROOT . '/fichinter/class/fichinter.class.php';
807 $tmpinter = new Fichinter($db);
808 $tmptimespent = new Task($db);
809 $fuser = new User($db);
810
811 $db->begin();
812 $interToUse = GETPOSTINT('interid');
813
814
815 $tmpinter->socid = $projectstatic->thirdparty->id;
816 $tmpinter->date = dol_mktime(GETPOSTINT('rehour'), GETPOSTINT('remin'), GETPOSTINT('resec'), GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'));
817 $tmpinter->fk_project = $projectstatic->id;
818 $tmpinter->description = $projectstatic->title . (!empty($projectstatic->description) ? '-' . $projectstatic->label : '');
819
820 if ($interToUse) {
821 $tmpinter->fetch($interToUse);
822 } else {
823 $result = $tmpinter->create($user);
824 if ($result <= 0) {
825 $error++;
826 setEventMessages($tmpinter->error, $tmpinter->errors, 'errors');
827 }
828 }
829
830 if (!$error) {
831 $arrayoftasks = array();
832 foreach ($toselect as $key => $value) {
833 // Get userid, timespent
834 $object->fetchTimeSpent($value);
835 // $object->id is the task id
836 $arrayoftasks[$object->timespent_id]['id'] = $object->id;
837 $arrayoftasks[$object->timespent_id]['timespent'] = $object->timespent_duration;
838 $arrayoftasks[$object->timespent_id]['totalvaluetodivideby3600'] = $object->timespent_duration * $object->timespent_thm;
839 $arrayoftasks[$object->timespent_id]['note'] = $object->timespent_note;
840 $arrayoftasks[$object->timespent_id]['date'] = date('Y-m-d H:i:s', $object->timespent_datehour);
841 }
842
843 foreach ($arrayoftasks as $timespent_id => $value) {
844 $ftask = new Task($db);
845 $ftask->fetch($value['id']);
846 // Define qty per hour
847 $qtyhour = $value['timespent'] / 3600;
848 $qtyhourtext = convertSecondToTime($value['timespent'], 'all', $conf->global->MAIN_DURATION_OF_WORKDAY);
849
850 // Add lines
851 $lineid = $tmpinter->addline($user, $tmpinter->id, $ftask->label . (!empty($value['note']) ? ' - ' . $value['note'] : ''), $value['date'], $value['timespent']);
852 }
853 }
854
855 if (!$error) {
856 $urltointer = $tmpinter->getNomUrl(0);
857 $mesg = $langs->trans("InterventionGeneratedFromTimeSpent", '{s1}');
858 $mesg = str_replace('{s1}', $urltointer, $mesg);
859 setEventMessages($mesg, null, 'mesgs');
860
861 //var_dump($tmpinvoice);
862
863 $db->commit();
864 } else {
865 $db->rollback();
866 }
867 }
868}
869
870
871/*
872 * View
873 */
874
875$form = new Form($db);
876$formother = new FormOther($db);
877$formproject = new FormProjets($db);
878$userstatic = new User($db);
879//$result = $projectstatic->fetch($object->fk_project);
880$arrayofselected = is_array($toselect) ? $toselect : array();
881
882$title = $object->ref . ' - ' . $langs->trans("TimeSpent");
883if (!empty($withproject)) {
884 $title .= ' | ' . $langs->trans("Project") . (!empty($projectstatic->ref) ? ': ' . $projectstatic->ref : '');
885}
886$help_url = '';
887
888llxHeader('', $title, $help_url);
889
890if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser > 0) {
891 /*
892 * Fiche projet en mode visu
893 */
894 if ($projectidforalltimes > 0) {
895 $result = $projectstatic->fetch($projectidforalltimes);
896 if (!empty($projectstatic->socid)) {
897 $projectstatic->fetch_thirdparty();
898 }
899 $res = $projectstatic->fetch_optionals();
900 } elseif ($object->fetch($id, $ref) >= 0) {
901 if (getDolGlobalString('PROJECT_ALLOW_COMMENT_ON_TASK') && method_exists($object, 'fetchComments') && empty($object->comments)) {
902 $object->fetchComments();
903 }
904 $result = $projectstatic->fetch($object->fk_project);
905 if (getDolGlobalString('PROJECT_ALLOW_COMMENT_ON_PROJECT') && method_exists($projectstatic, 'fetchComments') && empty($projectstatic->comments)) {
906 $projectstatic->fetchComments();
907 }
908 if (!empty($projectstatic->socid)) {
909 $projectstatic->fetch_thirdparty();
910 }
911 $res = $projectstatic->fetch_optionals();
912
913 $object->project = clone $projectstatic;
914 }
915
916 $userRead = $projectstatic->restrictedProjectArea($user, 'read');
917 $linktocreatetime = '';
918
919 if ($projectstatic->id > 0) {
920 if ($withproject) {
921 // Tabs for project
922 if (empty($id) || $tab == 'timespent') {
923 $tab = 'timespent';
924 } else {
925 $tab = 'tasks';
926 }
927
928 $head = project_prepare_head($projectstatic);
929 print dol_get_fiche_head($head, $tab, $langs->trans("Project"), -1, ($projectstatic->public ? 'projectpub' : 'project'));
930
931 $param = ((!empty($mode) && $mode == 'mine') ? '&mode=mine' : '');
932 if ($search_user) {
933 $param .= '&search_user=' . ((int) $search_user);
934 }
935 if ($search_month) {
936 $param .= '&search_month=' . ((int) $search_month);
937 }
938 if ($search_year) {
939 $param .= '&search_year=' . ((int) $search_year);
940 }
941
942 // Project card
943
944 $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
945
946 $morehtmlref = '<div class="refidno">';
947 // Title
948 $morehtmlref .= $projectstatic->title;
949 // Thirdparty
950 if (!empty($projectstatic->thirdparty->id) && $projectstatic->thirdparty->id > 0) {
951 $morehtmlref .= '<br>' . $projectstatic->thirdparty->getNomUrl(1, 'project');
952 }
953 $morehtmlref .= '</div>';
954
955 // Define a complementary filter for search of next/prev ref.
956 if (!$user->hasRight('projet', 'all', 'lire')) {
957 $objectsListId = $projectstatic->getProjectsAuthorizedForUser($user, 0, 0);
958 $projectstatic->next_prev_filter = "rowid IN (" . $db->sanitize(count($objectsListId) ? implode(',', array_keys($objectsListId)) : '0') . ")";
959 }
960
961 dol_banner_tab($projectstatic, 'project_ref', $linkback, 1, 'ref', 'ref', $morehtmlref, $param);
962
963 print '<div class="fichecenter">';
964 print '<div class="fichehalfleft">';
965 print '<div class="underbanner clearboth"></div>';
966
967 print '<table class="border tableforfield centpercent">';
968
969 // Usage
970 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES') || !getDolGlobalString('PROJECT_HIDE_TASKS') || isModEnabled('eventorganization')) {
971 print '<tr><td class="tdtop">';
972 print $langs->trans("Usage");
973 print '</td>';
974 print '<td>';
975 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
976 print '<input type="checkbox" disabled name="usage_opportunity"' . (GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ($projectstatic->usage_opportunity ? ' checked="checked"' : '')) . '"> ';
977 $htmltext = $langs->trans("ProjectFollowOpportunity");
978 print $form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext);
979 print '<br>';
980 }
981 if (!getDolGlobalString('PROJECT_HIDE_TASKS')) {
982 print '<input type="checkbox" disabled name="usage_task"' . (GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($projectstatic->usage_task ? ' checked="checked"' : '')) . '"> ';
983 $htmltext = $langs->trans("ProjectFollowTasks");
984 print $form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext);
985 print '<br>';
986 }
987 if (!getDolGlobalString('PROJECT_HIDE_TASKS') && getDolGlobalString('PROJECT_BILL_TIME_SPENT')) {
988 print '<input type="checkbox" disabled name="usage_bill_time"' . (GETPOSTISSET('usage_bill_time') ? (GETPOST('usage_bill_time', 'alpha') != '' ? ' checked="checked"' : '') : ($projectstatic->usage_bill_time ? ' checked="checked"' : '')) . '"> ';
989 $htmltext = $langs->trans("ProjectBillTimeDescription");
990 print $form->textwithpicto($langs->trans("BillTime"), $htmltext);
991 print '<br>';
992 }
993 if (isModEnabled('eventorganization')) {
994 print '<input type="checkbox" disabled name="usage_organize_event"' . (GETPOSTISSET('usage_organize_event') ? (GETPOST('usage_organize_event', 'alpha') != '' ? ' checked="checked"' : '') : ($projectstatic->usage_organize_event ? ' checked="checked"' : '')) . '"> ';
995 $htmltext = $langs->trans("EventOrganizationDescriptionLong");
996 print $form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext);
997 }
998 print '</td></tr>';
999 }
1000
1001 // Visibility
1002 print '<tr><td class="titlefield">' . $langs->trans("Visibility") . '</td><td>';
1003 if ($projectstatic->public) {
1004 print img_picto($langs->trans('SharedProject'), 'world', 'class="paddingrightonly"');
1005 print $langs->trans('SharedProject');
1006 } else {
1007 print img_picto($langs->trans('PrivateProject'), 'private', 'class="paddingrightonly"');
1008 print $langs->trans('PrivateProject');
1009 }
1010 print '</td></tr>';
1011
1012 // Budget
1013 print '<tr><td>' . $langs->trans("Budget") . '</td><td>';
1014 if (!is_null($projectstatic->budget_amount) && strcmp($projectstatic->budget_amount, '')) {
1015 print '<span class="amount">' . price($projectstatic->budget_amount, 0, $langs, 1, 0, 0, $conf->currency) . '</span>';
1016 }
1017 print '</td></tr>';
1018
1019 // Date start - end project
1020 print '<tr><td>' . $langs->trans("Dates") . '</td><td>';
1021 $start = dol_print_date($projectstatic->date_start, 'day');
1022 print($start ? $start : '?');
1023 $end = dol_print_date($projectstatic->date_end, 'day');
1024 print ' - ';
1025 print($end ? $end : '?');
1026 if ($projectstatic->hasDelay()) {
1027 print img_warning("Late");
1028 }
1029 print '</td></tr>';
1030
1031 // Other attributes
1032 $cols = 2;
1033 $savobject = $object;
1034 $object = $projectstatic;
1035 include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
1036 $object = $savobject;
1037
1038 print '</table>';
1039
1040 print '</div>';
1041 print '<div class="fichehalfright">';
1042 print '<div class="underbanner clearboth"></div>';
1043
1044 print '<table class="border tableforfield centpercent">';
1045
1046 // Description
1047 print '<td class="titlefield tdtop">'.$langs->trans("Description").'</td><td>';
1048 print dol_htmlentitiesbr($projectstatic->description);
1049 print '</td></tr>';
1050
1051 // Categories
1052 if (isModEnabled('category')) {
1053 print '<tr><td class="valignmiddle">' . $langs->trans("Categories") . '</td><td>';
1054 print $form->showCategories($projectstatic->id, 'project', 1);
1055 print "</td></tr>";
1056 }
1057
1058 print '</table>';
1059
1060 print '</div>';
1061 print '</div>';
1062
1063 print '<div class="clearboth"></div>';
1064
1065 print dol_get_fiche_end();
1066
1067 print '<br>';
1068 }
1069
1070 $param = '';
1071
1072 // Link to create time
1073 $linktocreatetimeBtnStatus = 0;
1074 $linktocreatetimeUrl = '';
1075 $linktocreatetimeHelpText = '';
1076 if ($user->hasRight('projet', 'time')) {
1077 if ($projectstatic->public || $userRead > 0) {
1078 $linktocreatetimeBtnStatus = 1;
1079
1080 if (!empty($projectidforalltimes)) {
1081 // We are on tab 'Time Spent' of project
1082 $backtourl = $_SERVER['PHP_SELF'] . '?projectid=' . $projectstatic->id . ($withproject ? '&withproject=1' : '');
1083 $linktocreatetimeUrl = $_SERVER['PHP_SELF'] . '?' . ($withproject ? 'withproject=1' : '') . '&projectid=' . $projectstatic->id . '&action=createtime&token=' . newToken() . $param . '&backtopage=' . urlencode($backtourl);
1084 } else {
1085 // We are on tab 'Time Spent' of task
1086 $backtourl = $_SERVER['PHP_SELF'] . '?id=' . $object->id . ($withproject ? '&withproject=1' : '');
1087 $linktocreatetimeUrl = $_SERVER['PHP_SELF'] . '?' . ($withproject ? 'withproject=1' : '') . ($object->id > 0 ? '&id=' . $object->id : '&projectid=' . $projectstatic->id) . '&action=createtime&token=' . newToken() . $param . '&backtopage=' . urlencode($backtourl);
1088 }
1089 } else {
1090 $linktocreatetimeBtnStatus = -2;
1091 $linktocreatetimeHelpText = $langs->trans("NotOwnerOfProject");
1092 }
1093 } else {
1094 $linktocreatetimeBtnStatus = -2;
1095 $linktocreatetimeHelpText = $langs->trans("NotEnoughPermissions");
1096 }
1097
1098 $paramsbutton = array('morecss' => 'reposition');
1099 $linktocreatetime = dolGetButtonTitle($langs->trans('AddTimeSpent'), $linktocreatetimeHelpText, 'fa fa-plus-circle', $linktocreatetimeUrl, '', $linktocreatetimeBtnStatus, $paramsbutton);
1100 }
1101
1102 $massactionbutton = '';
1103 $arrayofmassactions = array();
1104
1105 if ($projectstatic->id > 0) {
1106 // If we are on a given project.
1107 if ($projectstatic->usage_bill_time) {
1108 $arrayofmassactions = array(
1109 'generateinvoice' => $langs->trans("GenerateBill"),
1110 //'builddoc'=>$langs->trans("PDFMerge"),
1111 );
1112 }
1113 if (isModEnabled('intervention') && $user->hasRight('ficheinter', 'creer')) {
1114 $langs->load("interventions");
1115 $arrayofmassactions['generateinter'] = $langs->trans("GenerateInter");
1116 }
1117 }
1118 //if ($user->rights->projet->creer) $arrayofmassactions['predelete']='<span class="fa fa-trash paddingrightonly"></span>'.$langs->trans("Delete");
1119 if (in_array($massaction, array('presend', 'predelete', 'generateinvoice', 'generateinter'))) {
1120 $arrayofmassactions = array();
1121 }
1122 $massactionbutton = $form->selectMassAction('', $arrayofmassactions);
1123
1124 // Task
1125
1126 // Show section with information of task. If id of task is not defined and project id defined, then $projectidforalltimes is not empty.
1127 if (empty($projectidforalltimes) && empty($allprojectforuser)) {
1128 $head = task_prepare_head($object);
1129 print dol_get_fiche_head($head, 'task_time', $langs->trans("Task"), -1, 'projecttask', 0, '', 'reposition');
1130
1131 if ($action == 'deleteline') {
1132 $urlafterconfirm = $_SERVER["PHP_SELF"] . "?" . ($object->id > 0 ? "id=" . $object->id : 'projectid=' . $projectstatic->id) . '&lineid=' . GETPOSTINT("lineid") . ($withproject ? '&withproject=1' : '');
1133 print $form->formconfirm($urlafterconfirm, $langs->trans("DeleteATimeSpent"), $langs->trans("ConfirmDeleteATimeSpent"), "confirm_deleteline", '', '', 1);
1134 }
1135
1136 $param = ($withproject ? '&withproject=1' : '');
1137 $param .= ($param ? '&' : '') . 'id=' . $object->id; // ID of task
1138 $linkback = $withproject ? '<a href="' . DOL_URL_ROOT . '/projet/tasks.php?id=' . $projectstatic->id . '">' . $langs->trans("BackToList") . '</a>' : '';
1139
1140 if (!GETPOST('withproject') || empty($projectstatic->id)) {
1141 $projectsListId = $projectstatic->getProjectsAuthorizedForUser($user, 0, 1);
1142 $object->next_prev_filter = "fk_projet IN (" . $db->sanitize($projectsListId) . ")";
1143 } else {
1144 $object->next_prev_filter = "fk_projet = " . ((int) $projectstatic->id);
1145 }
1146
1147 $morehtmlref = '';
1148
1149 // Project
1150 if (empty($withproject)) {
1151 $morehtmlref .= '<div class="refidno">';
1152 $morehtmlref .= $langs->trans("Project") . ': ';
1153 $morehtmlref .= $projectstatic->getNomUrl(1);
1154 $morehtmlref .= '<br>';
1155
1156 // Third party
1157 $morehtmlref .= $langs->trans("ThirdParty") . ': ';
1158 if (!empty($projectstatic->thirdparty) && is_object($projectstatic->thirdparty)) {
1159 $morehtmlref .= $projectstatic->thirdparty->getNomUrl(1);
1160 }
1161 $morehtmlref .= '</div>';
1162 }
1163
1164 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref, $param);
1165
1166 print '<div class="fichecenter">';
1167 print '<div class="fichehalfleft">';
1168
1169 print '<div class="underbanner clearboth"></div>';
1170 print '<table class="border centpercent tableforfield">';
1171
1172 // Task parent
1173 print '<tr><td>' . $langs->trans("ChildOfTask") . '</td><td>';
1174 if ($object->fk_task_parent > 0) {
1175 $tasktmp = new Task($db);
1176 $tasktmp->fetch($object->fk_task_parent);
1177 print $tasktmp->getNomUrl(1);
1178 }
1179 print '</td></tr>';
1180
1181 // Date start - Date end task
1182 print '<tr><td class="titlefield">' . $langs->trans("DateStart") . ' - ' . $langs->trans("Deadline") . '</td><td>';
1183 $start = dol_print_date($object->date_start, 'dayhour');
1184 print($start ? $start : '?');
1185 $end = dol_print_date($object->date_end, 'dayhour');
1186 print ' - ';
1187 print($end ? $end : '?');
1188 if ($object->hasDelay()) {
1189 print img_warning("Late");
1190 }
1191 print '</td></tr>';
1192
1193 // Planned workload
1194 print '<tr><td>' . $langs->trans("PlannedWorkload") . '</td><td>';
1195 if ($object->planned_workload) {
1196 print convertSecondToTime($object->planned_workload, 'allhourmin');
1197 }
1198 print '</td></tr>';
1199
1200 print '</table>';
1201 print '</div>';
1202
1203 print '<div class="fichehalfright">';
1204
1205 print '<div class="underbanner clearboth"></div>';
1206 print '<table class="border tableforfield centpercent">';
1207
1208 // Progress declared
1209 print '<tr><td class="titlefield">' . $langs->trans("ProgressDeclared") . '</td><td>';
1210 print $object->progress != '' ? $object->progress . ' %' : '';
1211 print '</td></tr>';
1212
1213 // Progress calculated
1214 print '<tr><td>' . $langs->trans("ProgressCalculated") . '</td><td>';
1215 if ($object->planned_workload) {
1216 $tmparray = $object->getSummaryOfTimeSpent();
1217 if ($tmparray['total_duration'] > 0) {
1218 print round($tmparray['total_duration'] / $object->planned_workload * 100, 2) . ' %';
1219 } else {
1220 print '0 %';
1221 }
1222 } else {
1223 print '<span class="opacitymedium">' . $langs->trans("WorkloadNotDefined") . '</span>';
1224 }
1225 print '</td>';
1226
1227 print '</tr>';
1228
1229 print '</table>';
1230
1231 print '</div>';
1232
1233 print '</div>';
1234 print '<div class="clearboth"></div>';
1235
1236 print dol_get_fiche_end();
1237 } else {
1238 if ($action == 'deleteline') {
1239 $urlafterconfirm = $_SERVER["PHP_SELF"] . "?" . ($object->id > 0 ? "id=" . $object->id : 'projectid=' . $projectstatic->id) . '&lineid=' . GETPOSTINT("lineid") . ($withproject ? '&withproject=1' : '');
1240 print $form->formconfirm($urlafterconfirm, $langs->trans("DeleteATimeSpent"), $langs->trans("ConfirmDeleteATimeSpent"), "confirm_deleteline", '', '', 1);
1241 }
1242 }
1243
1244
1245 if ($projectstatic->id > 0 || $allprojectforuser > 0) {
1246 // Initialize technical object to manage hooks. Note that conf->hooks_modules contains array
1247 $hookmanager->initHooks(array('tasktimelist'));
1248
1249 $formconfirm = '';
1250
1251 if ($action == 'deleteline' && !empty($projectidforalltimes)) {
1252 // We must use projectidprojectid if on list of timespent of project and id=taskid if on list of timespent of a task
1253 $urlafterconfirm = $_SERVER["PHP_SELF"] . "?" . ($projectstatic->id > 0 ? 'projectid=' . $projectstatic->id : ($object->id > 0 ? "id=" . $object->id : '')) . '&lineid=' . GETPOSTINT('lineid') . ($withproject ? '&withproject=1' : '') . "&contextpage=" . urlencode($contextpage);
1254 $formconfirm = $form->formconfirm($urlafterconfirm, $langs->trans("DeleteATimeSpent"), $langs->trans("ConfirmDeleteATimeSpent"), "confirm_deleteline", '', '', 1);
1255 }
1256
1257 // Call Hook formConfirm
1258 $parameters = array('formConfirm' => $formconfirm, "projectstatic" => $projectstatic, "withproject" => $withproject);
1259 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1260 if (empty($reshook)) {
1261 $formconfirm .= $hookmanager->resPrint;
1262 } elseif ($reshook > 0) {
1263 $formconfirm = $hookmanager->resPrint;
1264 }
1265
1266 // Print form confirm
1267 print $formconfirm;
1268
1269 // Definition of fields for list
1270 $arrayfields = array();
1271 $arrayfields['t.element_date'] = array('label' => $langs->trans("Date"), 'checked' => 1);
1272 $arrayfields['p.fk_soc'] = array('label' => $langs->trans("ThirdParty"), 'type' => 'integer:Societe:/societe/class/societe.class.php:1','checked' => 1);
1273 $arrayfields['s.name_alias'] = array('label' => $langs->trans("AliasNameShort"), 'type' => 'integer:Societe:/societe/class/societe.class.php:1');
1274 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
1275 if (! empty($allprojectforuser)) {
1276 $arrayfields['p.project_ref'] = ['label' => $langs->trans('RefProject'), 'checked' => 1];
1277 $arrayfields['p.project_label'] = ['label' => $langs->trans('ProjectLabel'), 'checked' => 1];
1278 }
1279 $arrayfields['t.element_ref'] = array('label' => $langs->trans("RefTask"), 'checked' => 1);
1280 $arrayfields['t.element_label'] = array('label' => $langs->trans("LabelTask"), 'checked' => 1);
1281 }
1282 $arrayfields['author'] = array('label' => $langs->trans("By"), 'checked' => 1);
1283 $arrayfields['t.note'] = array('label' => $langs->trans("Note"), 'checked' => 1);
1284 if (isModEnabled('service') && !empty($projectstatic->thirdparty) && $projectstatic->thirdparty->id > 0 && $projectstatic->usage_bill_time) {
1285 $arrayfields['t.fk_product'] = array('label' => $langs->trans("Product"), 'checked' => 1);
1286 }
1287 $arrayfields['t.element_duration'] = array('label' => $langs->trans("Duration"), 'checked' => 1);
1288 $arrayfields['value'] = array('label' => $langs->trans("Value"), 'checked' => 1, 'enabled' => isModEnabled("salaries"));
1289 $arrayfields['valuebilled'] = array('label' => $langs->trans("Billed"), 'checked' => 1, 'enabled' => (((getDolGlobalInt('PROJECT_HIDE_TASKS') || !getDolGlobalInt('PROJECT_BILL_TIME_SPENT')) ? 0 : 1) && $projectstatic->usage_bill_time));
1290 // Extra fields
1291 include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_list_array_fields.tpl.php';
1292
1293 $arrayfields = dol_sort_array($arrayfields, 'position');
1294 '@phan-var-force array<string,array{label:string,checked?:int<0,1>,position?:int,help?:string}> $arrayfields'; // dol_sort_array looses type for Phan
1295
1296 $param = '';
1297 if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
1298 $param .= '&contextpage=' . urlencode($contextpage);
1299 }
1300 if ($limit > 0 && $limit != $conf->liste_limit) {
1301 $param .= '&limit='.((int) $limit);
1302 }
1303 if ($search_month > 0) {
1304 $param .= '&search_month=' . urlencode((string) ($search_month));
1305 }
1306 if ($search_year > 0) {
1307 $param .= '&search_year=' . urlencode((string) ($search_year));
1308 }
1309 if (!empty($search_user)) { // We keep param if -1 because default value is forced to user id if not set
1310 $param .= '&search_user='.urlencode($search_user);
1311 }
1312 if ($search_task_ref != '') {
1313 $param .= '&search_task_ref=' . urlencode($search_task_ref);
1314 }
1315 if ($search_company != '') {
1316 $param .= '&amp;$search_company=' . urlencode($search_company);
1317 }
1318 if ($search_company_alias != '') {
1319 $param .= '&amp;$search_company_alias=' . urlencode($search_company_alias);
1320 }
1321 if ($search_project_ref != '') {
1322 $param .= '&amp;$search_project_ref=' . urlencode($search_project_ref);
1323 }
1324 if ($search_project_label != '') {
1325 $param .= '&amp;$search_project_label=' . urlencode($search_project_label);
1326 }
1327 if ($search_task_label != '') {
1328 $param .= '&search_task_label=' . urlencode($search_task_label);
1329 }
1330 if ($search_note != '') {
1331 $param .= '&search_note=' . urlencode($search_note);
1332 }
1333 if ($search_duration != '') {
1334 $param .= '&amp;search_field2=' . urlencode((string) ($search_duration));
1335 }
1336 if ($optioncss != '') {
1337 $param .= '&optioncss=' . urlencode($optioncss);
1338 }
1339 if ($search_date_startday) {
1340 $param .= '&search_date_startday=' . urlencode((string) ($search_date_startday));
1341 }
1342 if ($search_date_startmonth) {
1343 $param .= '&search_date_startmonth=' . urlencode((string) ($search_date_startmonth));
1344 }
1345 if ($search_date_startyear) {
1346 $param .= '&search_date_startyear=' . urlencode((string) ($search_date_startyear));
1347 }
1348 if ($search_date_endday) {
1349 $param .= '&search_date_endday=' . urlencode((string) ($search_date_endday));
1350 }
1351 if ($search_date_endmonth) {
1352 $param .= '&search_date_endmonth=' . urlencode((string) ($search_date_endmonth));
1353 }
1354 if ($search_date_endyear) {
1355 $param .= '&search_date_endyear=' . urlencode((string) ($search_date_endyear));
1356 }
1357 if ($search_timespent_starthour) {
1358 $param .= '&search_timespent_duration_starthour=' . urlencode((string) ($search_timespent_starthour));
1359 }
1360 if ($search_timespent_startmin) {
1361 $param .= '&search_timespent_duration_startmin=' . urlencode((string) ($search_timespent_startmin));
1362 }
1363 if ($search_timespent_endhour) {
1364 $param .= '&search_timespent_duration_endhour=' . urlencode((string) ($search_timespent_endhour));
1365 }
1366 if ($search_timespent_endmin) {
1367 $param .= '&search_timespent_duration_endmin=' . urlencode((string) ($search_timespent_endmin));
1368 }
1369
1370 /*
1371 // Add $param from extra fields
1372 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
1373 */
1374 if ($id) {
1375 $param .= '&id=' . urlencode((string) ($id));
1376 }
1377 if ($projectid) {
1378 $param .= '&projectid=' . urlencode((string) ($projectid));
1379 }
1380 if ($withproject) {
1381 $param .= '&withproject=' . urlencode((string) ($withproject));
1382 }
1383 // Add $param from hooks
1384 $parameters = array('param' => &$param);
1385 $reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1386 $param .= $hookmanager->resPrint;
1387
1388 print '<form method="POST" action="' . $_SERVER["PHP_SELF"] . '">';
1389 if ($optioncss != '') {
1390 print '<input type="hidden" name="optioncss" value="' . $optioncss . '">';
1391 }
1392 print '<input type="hidden" name="token" value="' . newToken() . '">';
1393 print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
1394 if ($action == 'editline') {
1395 print '<input type="hidden" name="action" value="updateline">';
1396 } elseif ($action == 'splitline') {
1397 print '<input type="hidden" name="action" value="updatesplitline">';
1398 } elseif ($action == 'createtime' && $user->hasRight('projet', 'time')) {
1399 print '<input type="hidden" name="action" value="addtimespent">';
1400 } elseif ($massaction == 'generateinvoice' && $user->hasRight('facture', 'creer')) {
1401 print '<input type="hidden" name="action" value="confirm_generateinvoice">';
1402 } elseif ($massaction == 'generateinter' && $user->hasRight('ficheinter', 'creer')) {
1403 print '<input type="hidden" name="action" value="confirm_generateinter">';
1404 } else {
1405 print '<input type="hidden" name="action" value="list">';
1406 }
1407 print '<input type="hidden" name="sortfield" value="' . $sortfield . '">';
1408 print '<input type="hidden" name="sortorder" value="' . $sortorder . '">';
1409
1410 print '<input type="hidden" name="id" value="' . $id . '">';
1411 print '<input type="hidden" name="projectid" value="' . $projectidforalltimes . '">';
1412 print '<input type="hidden" name="withproject" value="' . $withproject . '">';
1413 print '<input type="hidden" name="tab" value="' . $tab . '">';
1414 print '<input type="hidden" name="page_y" value="">';
1415
1416 // Form to convert time spent into invoice
1417 if ($massaction == 'generateinvoice') {
1418 if (!empty($projectstatic->thirdparty) && $projectstatic->thirdparty->id > 0) {
1419 print '<table class="noborder centerpercent">';
1420 print '<tr>';
1421 print '<td class="titlefield">';
1422 print $langs->trans('DateInvoice');
1423 print '</td>';
1424 print '<td>';
1425 print $form->selectDate('', '', 0, 0, 0, '', 1, 1);
1426 print '</td>';
1427 print '</tr>';
1428
1429 print '<tr>';
1430 print '<td>';
1431 print $langs->trans('Mode');
1432 print '</td>';
1433 print '<td>';
1434 $tmparray = array(
1435 'onelineperuser' => 'OneLinePerUser',
1436 'onelinepertask' => 'OneLinePerTask',
1437 'onelineperperiod' => 'OneLinePerTimeSpentLine',
1438 );
1439 print $form->selectarray('generateinvoicemode', $tmparray, 'onelineperuser', 0, 0, 0, '', 1);
1440 print "\n" . '<script type="text/javascript">';
1441 print '
1442 $(document).ready(function () {
1443 setDetailVisibility();
1444 $("#generateinvoicemode").change(function() {
1445 setDetailVisibility();
1446 });
1447 function setDetailVisibility() {
1448 generateinvoicemode = $("#generateinvoicemode option:selected").val();
1449 if (generateinvoicemode=="onelineperperiod") {
1450 $("#detail_time_duration").show();
1451 } else {
1452 $("#detail_time_duration").hide();
1453 }
1454 }
1455 });
1456 ';
1457 print '</script>' . "\n";
1458 print '<span style="display:none" id="detail_time_duration"><input type="checkbox" value="detail" name="detail_time_duration"/>' . $langs->trans('AddDetailDateAndDuration') . '</span>';
1459 print '</td>';
1460 print '</tr>';
1461
1462 if (isModEnabled("service")) {
1463 print '<tr>';
1464 print '<td>';
1465 print $langs->trans('ServiceToUseOnLines');
1466 print '</td>';
1467 print '<td>';
1468 $form->select_produits('', 'productid', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 0, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth500');
1469 print '</td>';
1470 print '</tr>';
1471 }
1472 print '<tr>';
1473 print '<td class="titlefield">';
1474 print $langs->trans('InvoiceToUse');
1475 print '</td>';
1476 print '<td>';
1477 print $form->selectInvoice($projectstatic->thirdparty->id, '', 'invoiceid', 24, 0, $langs->trans('NewInvoice'), 1, 0, 0, 'maxwidth500', '', 'all');
1478 print '</td>';
1479 print '</tr>';
1480 print '<tr>';
1481 print '<td class="titlefield">';
1482 print $langs->trans("CustomerRelativeDiscount");
1483 print '</td>';
1484 print '<td>';
1485 print '<input type="text" size="5" name="remiseproject" value="'.$projectstatic->thirdparty->remise_percent.'">%';
1486 print '</td>';
1487 print '</tr>';
1488 print '<tr class="newinvoicedetail">';
1489 print '<td class="titlefield">';
1490 print $langs->trans("PaymentConditions");
1491 print '</td>';
1492 print '<td>';
1493 print $form->getSelectConditionsPaiements($projectstatic->thirdparty->cond_reglement_id, 'condidproject');
1494 print '</td>';
1495 print '</tr>';
1496 /*print '<tr>';
1497 print '<td>';
1498 print $langs->trans('ValidateInvoices');
1499 print '</td>';
1500 print '<td>';
1501 print $form->selectyesno('validate_invoices', 0, 1);
1502 print '</td>';
1503 print '</tr>';*/
1504 print '</table>';
1505
1506 print '<br>';
1507 print '<div class="center">';
1508 print '<input type="submit" class="button" id="createbills" name="createbills" value="' . $langs->trans('GenerateBill') . '"> ';
1509 print '<input type="submit" class="button button-cancel" id="cancel" name="cancel" value="' . $langs->trans("Cancel") . '">';
1510 print '</div>';
1511 print '<br>';
1512 } else {
1513 print '<div class="warning">' . $langs->trans("ThirdPartyRequiredToGenerateInvoice") . '</div>';
1514 print '<div class="center">';
1515 print '<input type="submit" class="button button-cancel" id="cancel" name="cancel" value="' . $langs->trans("Cancel") . '">';
1516 print '</div>';
1517 $massaction = '';
1518 }
1519 } elseif ($massaction == 'generateinter') {
1520 // Form to convert time spent into invoice
1521 print '<input type="hidden" name="massaction" value="confirm_createinter">';
1522
1523 if (!empty($projectstatic->thirdparty) && $projectstatic->thirdparty->id > 0) {
1524 print '<br>';
1525 print '<table class="noborder centpercent">';
1526 print '<tr>';
1527 print '<td class="titlefield">';
1528 print img_picto('', 'intervention', 'class="pictofixedwidth"') . $langs->trans('InterToUse');
1529 print '</td>';
1530 print '<td>';
1531 $forminter = new FormIntervention($db);
1532 print $forminter->select_interventions($projectstatic->thirdparty->id, '', 'interid', 24, $langs->trans('NewInter'), true);
1533 print '</td>';
1534 print '</tr>';
1535 print '</table>';
1536
1537 print '<div class="center">';
1538 print '<input type="submit" class="button" id="createinter" name="createinter" value="' . $langs->trans('GenerateInter') . '"> ';
1539 print '<input type="submit" class="button" id="cancel" name="cancel" value="' . $langs->trans('Cancel') . '">';
1540 print '</div>';
1541 print '<br>';
1542 } else {
1543 print '<div class="warning">' . $langs->trans("ThirdPartyRequiredToGenerateIntervention") . '</div>';
1544 print '<div class="center">';
1545 print '<input type="submit" class="button" id="cancel" name="cancel" value="' . $langs->trans('Cancel') . '">';
1546 print '</div>';
1547 $massaction = '';
1548 }
1549 }
1550
1551 // Allow Pre-Mass-Action hook (eg for confirmation dialog)
1552 $parameters = array(
1553 'toselect' => $toselect,
1554 'uploaddir' => isset($uploaddir) ? $uploaddir : null
1555 );
1556
1557 $reshook = $hookmanager->executeHooks('doPreMassActions', $parameters, $object, $action);
1558 if ($reshook < 0) {
1559 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1560 } else {
1561 print $hookmanager->resPrint;
1562 }
1563
1564 /*
1565 * List of time spent
1566 */
1567 $tasks = array();
1568
1569 $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
1570 $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')); // This also change content of $arrayfields
1571
1572 $sql = "SELECT t.rowid, t.fk_element, t.element_date, t.element_datehour, t.element_date_withhour, t.element_duration, t.fk_user, t.note, t.thm,";
1573 $sql .= " t.fk_product,";
1574 $sql .= " pt.ref, pt.label, pt.fk_projet,";
1575 $sql .= " u.lastname, u.firstname, u.login, u.photo, u.gender, u.statut as user_status,";
1576 $sql .= " il.fk_facture as invoice_id, inv.fk_statut,";
1577 $sql .= " p.fk_soc,s.name_alias,";
1578 $sql .= " t.invoice_line_id";
1579 // Add fields from hooks
1580 $parameters = array();
1581 $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1582 $sql .= $hookmanager->resPrint;
1583 $sql = preg_replace('/,\s*$/', '', $sql);
1584
1585 $sqlfields = $sql; // $sql fields to remove for count total
1586
1587 $sql .= " FROM ".MAIN_DB_PREFIX."element_time as t";
1588 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facturedet as il ON il.rowid = t.invoice_line_id";
1589 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture as inv ON inv.rowid = il.fk_facture";
1590 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as prod ON prod.rowid = t.fk_product";
1591 $sql .= " INNER JOIN ".MAIN_DB_PREFIX."projet_task as pt ON pt.rowid = t.fk_element";
1592 $sql .= " INNER JOIN ".MAIN_DB_PREFIX."projet as p ON p.rowid = pt.fk_projet";
1593 $sql .= " INNER JOIN ".MAIN_DB_PREFIX."user as u ON t.fk_user = u.rowid";
1594 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = p.fk_soc";
1595
1596 // Add table from hooks
1597 $parameters = array();
1598 $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1599 $sql .= $hookmanager->resPrint;
1600 $sql .= " WHERE elementtype = 'task'";
1601 $sql .= " AND p.entity IN (".getEntity('project').")";
1602 if (!$user->hasRight('projet', 'all', 'lire')) {
1603 // Get list of project id allowed to user (in a string list separated by comma)
1604 // TODO This may generate performance trouble when list of project is very large. Solution can be to complete $filterproj with filters on project.
1605 $filterproj = '';
1606 $projectsListId = $projectstatic->getProjectsAuthorizedForUser($user, 0, 1, $user->socid > 0 ? $user->socid : 0, $filterproj);
1607 $sql .= " AND p.rowid IN (".$db->sanitize($projectsListId).")"; // public and assigned to, or restricted to company for external users
1608 }
1609 if (empty($projectidforalltimes) && empty($allprojectforuser)) {
1610 // Limit on one task
1611 $sql .= " AND t.fk_element =".((int) $object->id);
1612 } elseif (!empty($projectidforalltimes)) {
1613 // Limit on one project
1614 $sql .= " AND pt.fk_projet IN (" . $db->sanitize($projectidforalltimes) . ")";
1615 } elseif (!empty($allprojectforuser)) {
1616 // Limit on on user
1617 if (empty($search_user)) {
1618 $search_user = $user->id;
1619 }
1620 if ($search_user > 0) {
1621 $sql .= " AND t.fk_user = " . ((int) $search_user);
1622 }
1623 }
1624
1625 if ($search_note) {
1626 $sql .= natural_search('t.note', $search_note);
1627 }
1628 if ($search_task_ref) {
1629 $sql .= natural_search('pt.ref', $search_task_ref);
1630 }
1631 if (empty($arrayfields['s.name_alias']['checked']) && $search_company) {
1632 $sql .= natural_search(array("s.nom", "s.name_alias"), $search_company);
1633 } else {
1634 if ($search_company) {
1635 $sql .= natural_search('s.nom', $search_company);
1636 }
1637 if ($search_company_alias) {
1638 $sql .= natural_search('s.name_alias', $search_company_alias);
1639 }
1640 }
1641 if ($search_project_ref) {
1642 $sql .= natural_search('p.ref', $search_project_ref);
1643 }
1644 if ($search_project_label) {
1645 $sql .= natural_search('p.title', $search_project_label);
1646 }
1647 if ($search_task_label) {
1648 $sql .= natural_search('pt.label', $search_task_label);
1649 }
1650 if ($search_user > 0) {
1651 $sql .= natural_search('t.fk_user', $search_user, 2);
1652 }
1653 if (!empty($search_product_ref)) {
1654 $sql .= natural_search('prod.ref', $search_product_ref);
1655 }
1656 if ($search_valuebilled == '1') {
1657 $sql .= ' AND t.invoice_id > 0';
1658 }
1659 if ($search_valuebilled == '0') {
1660 $sql .= ' AND (t.invoice_id = 0 OR t.invoice_id IS NULL)';
1661 }
1662
1663 if ($search_date_start) {
1664 $sql .= " AND t.element_date >= '".$db->idate($search_date_start)."'";
1665 }
1666 if ($search_date_end) {
1667 $sql .= " AND t.element_date <= '".$db->idate($search_date_end)."'";
1668 }
1669
1670 if (!empty($arrayfields['t.element_duration']['checked'])) {
1671 if ($search_timespent_starthour || $search_timespent_startmin) {
1672 $timespent_duration_start = $search_timespent_starthour * 60 * 60; // We store duration in seconds
1673 $timespent_duration_start += ($search_timespent_startmin ? $search_timespent_startmin : 0) * 60; // We store duration in seconds
1674 $sql .= " AND t.element_duration >= " . $timespent_duration_start;
1675 }
1676
1677 if ($search_timespent_endhour || $search_timespent_endmin) {
1678 $timespent_duration_end = $search_timespent_endhour * 60 * 60; // We store duration in seconds
1679 $timespent_duration_end += ($search_timespent_endmin ? $search_timespent_endmin : 0) * 60; // We store duration in seconds
1680 $sql .= " AND t.element_duration <= " . $timespent_duration_end;
1681 }
1682 }
1683
1684 $sql .= dolSqlDateFilter('t.element_datehour', $search_day, $search_month, $search_year);
1685
1686 // Add where from hooks
1687 $parameters = array();
1688 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1689 $sql .= $hookmanager->resPrint;
1690
1691 // Count total nb of records
1692 $nbtotalofrecords = '';
1693 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
1694 /* The fast and low memory method to get and count full list converts the sql into a sql count */
1695 $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql);
1696 $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount);
1697 $resql = $db->query($sqlforcount);
1698 if ($resql) {
1699 $objforcount = $db->fetch_object($resql);
1700 $nbtotalofrecords = $objforcount->nbtotalofrecords;
1701 } else {
1702 dol_print_error($db);
1703 }
1704
1705 if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 0
1706 $page = 0;
1707 $offset = 0;
1708 }
1709 $db->free($resql);
1710 }
1711
1712 // Complete request and execute it with limit
1713 $sql .= $db->order($sortfield, $sortorder);
1714 if ($limit) {
1715 $sql .= $db->plimit($limit + 1, $offset);
1716 }
1717
1718 $resql = $db->query($sql);
1719 if (!$resql) {
1720 dol_print_error($db);
1721 exit;
1722 }
1723
1724 $num = $db->num_rows($resql);
1725
1726 if ($num >= 0) {
1727 if (!empty($projectidforalltimes)) {
1728 print '<!-- List of time spent for project -->' . "\n";
1729
1730 $title = $langs->trans("ListTaskTimeUserProject");
1731
1732 print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'clock', 0, $linktocreatetime, '', $limit, 0, 0, 1);
1733 } else {
1734 print '<!-- List of time spent -->' . "\n";
1735
1736 $title = $langs->trans("ListTaskTimeForTask");
1737
1738 print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'clock', 0, $linktocreatetime, '', $limit, 0, 0, 1);
1739 }
1740
1741 $i = 0;
1742 while ($i < $num) {
1743 $row = $db->fetch_object($resql);
1744 $tasks[$i] = $row;
1745 $i++;
1746 }
1747 $db->free($resql);
1748 } else {
1749 dol_print_error($db);
1750 }
1751
1752 /*
1753 * Form to add a new line of time spent
1754 */
1755 if ($action == 'createtime' && $user->hasRight('projet', 'time')) {
1756 print '<!-- table to add time spent -->' . "\n";
1757 if (!empty($id)) {
1758 print '<input type="hidden" name="taskid" value="' . $id . '">';
1759 }
1760
1761 print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
1762 print '<table class="noborder nohover centpercent">';
1763
1764 print '<tr class="liste_titre">';
1765 print '<td>' . $langs->trans("Date") . '</td>';
1766 if (!empty($allprojectforuser)) {
1767 print '<td>' . $langs->trans("Project") . '</td>';
1768 }
1769 if (empty($id)) {
1770 print '<td>' . $langs->trans("Task") . '</td>';
1771 }
1772 print '<td>' . $langs->trans("By") . '</td>';
1773 print '<td>' . $langs->trans("Note") . '</td>';
1774 print '<td>' . $langs->trans("NewTimeSpent") . '</td>';
1775 print '<td>' . $langs->trans("ProgressDeclared") . '</td>';
1776 if (!getDolGlobalString('PROJECT_HIDE_TASKS') && getDolGlobalString('PROJECT_BILL_TIME_SPENT')) {
1777 print '<td></td>';
1778
1779 if (isModEnabled("service") && !empty($projectstatic->thirdparty) && $projectstatic->thirdparty->id > 0 && $projectstatic->usage_bill_time) {
1780 print '<td>'.$langs->trans("Product").'</td>';
1781 }
1782 }
1783 // Hook fields
1784 $parameters = array('mode' => 'create');
1785 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1786 print $hookmanager->resPrint;
1787 print '<td></td>';
1788 print "</tr>\n";
1789
1790 print '<tr class="oddeven nohover">';
1791
1792 // Date
1793 print '<td class="maxwidthonsmartphone">';
1794 $newdate = '';
1795 print $form->selectDate($newdate, 'time', ($conf->browser->layout == 'phone' ? 2 : 1), 1, 2, "timespent_date", 1, 0);
1796 print '</td>';
1797
1798 if (!empty($allprojectforuser)) {
1799 print '<td>';
1800 // Add project selector
1801 print '</td>';
1802 }
1803
1804 // Task
1805 $nboftasks = 0;
1806 if (empty($id)) {
1807 print '<td class="maxwidthonsmartphone">';
1808 $nboftasks = $formproject->selectTasks(-1, GETPOSTINT('taskid'), 'taskid', 0, 0, 1, 1, 0, 0, 'maxwidth300', $projectstatic->id, 'progress');
1809 print '</td>';
1810 }
1811
1812 // Contributor
1813 print '<td class="maxwidthonsmartphone nowraponall">';
1814 $contactsofproject = $projectstatic->getListContactId('internal');
1815 if (count($contactsofproject) > 0) {
1816 print img_object('', 'user', 'class="hideonsmartphone"');
1817 if (in_array($user->id, $contactsofproject)) {
1818 $userid = $user->id;
1819 } else {
1820 $userid = $contactsofproject[0];
1821 }
1822
1823 if ($projectstatic->public) {
1824 $contactsofproject = array();
1825 }
1826 print $form->select_dolusers((GETPOSTINT('userid') ? GETPOSTINT('userid') : $userid), 'userid', 0, '', 0, '', $contactsofproject, 0, 0, 0, '', 0, $langs->trans("ResourceNotAssignedToProject"), 'minwidth150imp maxwidth200');
1827 } else {
1828 if ($nboftasks) {
1829 print img_error($langs->trans('FirstAddRessourceToAllocateTime')) . ' ' . $langs->trans('FirstAddRessourceToAllocateTime');
1830 }
1831 }
1832 print '</td>';
1833
1834 // Note
1835 print '<td>';
1836 print '<textarea name="timespent_note" class="maxwidth100onsmartphone" rows="' . ROWS_2 . '">' . (GETPOST('timespent_note') ? GETPOST('timespent_note') : '') . '</textarea>';
1837 print '</td>';
1838
1839 // Duration - Time spent
1840 print '<td class="nowraponall">';
1841 $durationtouse = (GETPOST('timespent_duration') ? GETPOST('timespent_duration') : '');
1842 if (GETPOSTISSET('timespent_durationhour') || GETPOSTISSET('timespent_durationmin')) {
1843 $durationtouse = ((int) GETPOST('timespent_durationhour') * 3600 + (int) GETPOST('timespent_durationmin') * 60);
1844 }
1845 print $form->select_duration('timespent_duration', $durationtouse, 0, 'text');
1846 print '</td>';
1847
1848 // Progress declared
1849 print '<td class="nowrap">';
1850 print $formother->select_percent(GETPOST('progress') ? GETPOST('progress') : $object->progress, 'progress', 0, 5, 0, 100, 1);
1851 print '</td>';
1852
1853 // Invoiced
1854 if (!getDolGlobalString('PROJECT_HIDE_TASKS') && getDolGlobalString('PROJECT_BILL_TIME_SPENT')) {
1855 print '<td>';
1856 print '</td>';
1857
1858 if (isModEnabled("service") && !empty($projectstatic->thirdparty) && $projectstatic->thirdparty->id > 0 && $projectstatic->usage_bill_time) {
1859 print '<td class="nowraponall">';
1860 print img_picto('', 'service');
1861 print $form->select_produits((GETPOSTISSET('fk_product') ? GETPOSTINT("fk_product") : ''), 'fk_product', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 1, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth150', 0, '', null, 1);
1862 print '</td>';
1863 }
1864 }
1865
1866 // Fields from hook
1867 $parameters = array('mode' => 'create');
1868 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1869 print $hookmanager->resPrint;
1870
1871 print '<td class="center">';
1872 $form->buttonsSaveCancel();
1873 print '<input type="submit" name="save" class="button buttongen smallpaddingimp marginleftonly margintoponlyshort marginbottomonlyshort button-add reposition" value="'.$langs->trans("Add").'">';
1874 print '<input type="submit" name="cancel" class="button buttongen smallpaddingimp marginleftonly margintoponlyshort marginbottomonlyshort button-cancel" value="'.$langs->trans("Cancel").'">';
1875 print '</td></tr>';
1876
1877 print '</table>';
1878 print '</div>';
1879
1880 print '<br>';
1881 }
1882
1883 $moreforfilter = '';
1884
1885 $parameters = array();
1886 $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1887 if (empty($reshook)) {
1888 $moreforfilter .= $hookmanager->resPrint;
1889 } else {
1890 $moreforfilter = $hookmanager->resPrint;
1891 }
1892
1893 if (!empty($moreforfilter)) {
1894 print '<div class="liste_titre liste_titre_bydiv centpercent">';
1895 print $moreforfilter;
1896 print '</div>';
1897 }
1898
1899 $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
1900 $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')); // This also change content of $arrayfields
1901 $selectedfields .= (is_array($arrayofmassactions) && count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
1902
1903 print '<div class="div-table-responsive">';
1904 print '<table class="tagtable nobottomiftotal liste' . ($moreforfilter ? " listwithfilterbefore" : "") . '">' . "\n";
1905
1906 // Fields title search
1907 // --------------------------------------------------------------------
1908 print '<tr class="liste_titre_filter">';
1909 // Action column
1910 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1911 print '<td class="liste_titre center">';
1912 $searchpicto = $form->showFilterButtons('left');
1913 print $searchpicto;
1914 print '</td>';
1915 }
1916 // Date
1917 if (!empty($arrayfields['t.element_date']['checked'])) {
1918 print '<td class="liste_titre left">';
1919 print '<div class="nowrapfordate">';
1920 print $form->selectDate($search_date_start ? $search_date_start : -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
1921 print '</div>';
1922 print '<div class="nowrapfordate">';
1923 print $form->selectDate($search_date_end ? $search_date_end : -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
1924 print '</div>';
1925 print '</td>';
1926 }
1927 // Thirdparty
1928 if (!empty($arrayfields['p.fk_soc']['checked'])) {
1929 print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="$search_company" value="' . dol_escape_htmltag($search_company) . '"></td>';
1930 }
1931
1932 // Thirdparty alias
1933 if (!empty($arrayfields['s.name_alias']['checked'])) {
1934 print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="$search_company_alias" value="' . dol_escape_htmltag($search_company_alias) . '"></td>';
1935 }
1936
1937 if (!empty($allprojectforuser)) {
1938 if (!empty($arrayfields['p.project_ref']['checked'])) {
1939 print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="$search_project_ref" value="' . dol_escape_htmltag($search_project_ref) . '"></td>';
1940 }
1941 if (!empty($arrayfields['p.project_label']['checked'])) {
1942 print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="$search_project_label" value="' . dol_escape_htmltag($search_project_label) . '"></td>';
1943 }
1944 }
1945 // Task
1946 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
1947 if (!empty($arrayfields['t.element_ref']['checked'])) {
1948 print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="search_task_ref" value="'.dol_escape_htmltag($search_task_ref).'"></td>';
1949 }
1950 if (!empty($arrayfields['t.element_label']['checked'])) {
1951 print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="search_task_label" value="'.dol_escape_htmltag($search_task_label).'"></td>';
1952 }
1953 }
1954 // Author
1955 if (!empty($arrayfields['author']['checked'])) {
1956 print '<td class="liste_titre">'.$form->select_dolusers(($search_user > 0 ? $search_user : -1), 'search_user', 1, null, 0, '', '', 0, 0, 0, '', 0, '', 'maxwidth125').'</td>';
1957 }
1958 // Note
1959 if (!empty($arrayfields['t.note']['checked'])) {
1960 print '<td class="liste_titre"><input type="text" class="flat maxwidth75" name="search_note" value="' . dol_escape_htmltag($search_note) . '"></td>';
1961 }
1962 // Duration
1963 if (!empty($arrayfields['t.element_duration']['checked'])) {
1964 // Duration - Time spent
1965 print '<td class="liste_titre right">';
1966
1967 $durationtouse_start = '';
1968 if ($search_timespent_starthour || $search_timespent_startmin) {
1969 $durationtouse_start = ($search_timespent_starthour * 3600 + $search_timespent_startmin * 60);
1970 }
1971 print '<div class="nowraponall">' . $langs->trans('from') . ' ';
1972 print $form->select_duration('search_timespent_duration_start', $durationtouse_start, 0, 'text', 0, 1);
1973 print '</div>';
1974
1975 $durationtouse_end = '';
1976 if ($search_timespent_endhour || $search_timespent_endmin) {
1977 $durationtouse_end = ($search_timespent_endhour * 3600 + $search_timespent_endmin * 60);
1978 }
1979 print '<div class="nowraponall">' . $langs->trans('to') . ' ';
1980 print $form->select_duration('search_timespent_duration_end', $durationtouse_end, 0, 'text', 0, 1);
1981 print '</div>';
1982
1983 print '</td>';
1984 }
1985 // Product
1986 if (!empty($arrayfields['t.fk_product']['checked'])) {
1987 print '<td class="liste_titre right"></td>';
1988 }
1989 // Value in main currency
1990 if (!empty($arrayfields['value']['checked'])) {
1991 print '<td class="liste_titre"></td>';
1992 }
1993 // Value billed
1994 if (!empty($arrayfields['valuebilled']['checked'])) {
1995 print '<td class="liste_titre center">' . $form->selectyesno('search_valuebilled', $search_valuebilled, 1, false, 1) . '</td>';
1996 }
1997
1998 /*
1999 // Extra fields
2000 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
2001 */
2002 // Fields from hook
2003 $parameters = array('arrayfields' => $arrayfields);
2004 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2005 print $hookmanager->resPrint;
2006 // Action column
2007 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2008 print '<td class="liste_titre center">';
2009 $searchpicto = $form->showFilterButtons();
2010 print $searchpicto;
2011 print '</td>';
2012 }
2013 print '</tr>' . "\n";
2014
2015
2016 $totalarray = array();
2017 $totalarray['nbfield'] = 0;
2018
2019 // Fields title label
2020 // --------------------------------------------------------------------
2021 print '<tr class="liste_titre">';
2022 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2023 print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
2024 $totalarray['nbfield']++;
2025 }
2026 if (!empty($arrayfields['t.element_date']['checked'])) {
2027 print_liste_field_titre($arrayfields['t.element_date']['label'], $_SERVER['PHP_SELF'], 't.element_date,t.element_datehour,t.rowid', '', $param, '', $sortfield, $sortorder);
2028 $totalarray['nbfield']++;
2029 }
2030 if (!empty($arrayfields['p.fk_soc']['checked'])) {
2031 print_liste_field_titre($arrayfields['p.fk_soc']['label'], $_SERVER['PHP_SELF'], 't.element_date,t.element_datehour,t.rowid', '', $param, '', $sortfield, $sortorder);
2032 $totalarray['nbfield']++;
2033 }
2034 if (!empty($arrayfields['s.name_alias']['checked'])) {
2035 print_liste_field_titre($arrayfields['s.name_alias']['label'], $_SERVER['PHP_SELF'], 's.name_alias', '', $param, '', $sortfield, $sortorder);
2036 $totalarray['nbfield']++;
2037 }
2038 if (!empty($allprojectforuser)) {
2039 if (!empty($arrayfields['p.project_ref']['checked'])) {
2040 print_liste_field_titre("Project", $_SERVER['PHP_SELF'], 'p.ref', '', $param, '', $sortfield, $sortorder);
2041 $totalarray['nbfield']++;
2042 }
2043 if (!empty($arrayfields['p.project_label']['checked'])) {
2044 print_liste_field_titre("ProjectLabel", $_SERVER['PHP_SELF'], 'p.title', '', $param, '', $sortfield, $sortorder);
2045 $totalarray['nbfield']++;
2046 }
2047 }
2048 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2049 if (!empty($arrayfields['t.element_ref']['checked'])) {
2050 print_liste_field_titre($arrayfields['t.element_ref']['label'], $_SERVER['PHP_SELF'], 'pt.ref', '', $param, '', $sortfield, $sortorder);
2051 $totalarray['nbfield']++;
2052 }
2053 if (!empty($arrayfields['t.element_label']['checked'])) {
2054 print_liste_field_titre($arrayfields['t.element_label']['label'], $_SERVER['PHP_SELF'], 'pt.label', '', $param, '', $sortfield, $sortorder);
2055 $totalarray['nbfield']++;
2056 }
2057 }
2058 if (!empty($arrayfields['author']['checked'])) {
2059 print_liste_field_titre($arrayfields['author']['label'], $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder);
2060 $totalarray['nbfield']++;
2061 }
2062 if (!empty($arrayfields['t.note']['checked'])) {
2063 print_liste_field_titre($arrayfields['t.note']['label'], $_SERVER['PHP_SELF'], 't.note', '', $param, '', $sortfield, $sortorder);
2064 $totalarray['nbfield']++;
2065 }
2066 if (!empty($arrayfields['t.element_duration']['checked'])) {
2067 print_liste_field_titre($arrayfields['t.element_duration']['label'], $_SERVER['PHP_SELF'], 't.element_duration', '', $param, '', $sortfield, $sortorder, 'right ');
2068 $totalarray['nbfield']++;
2069 }
2070 if (!empty($arrayfields['t.fk_product']['checked'])) {
2071 print_liste_field_titre($arrayfields['t.fk_product']['label'], $_SERVER['PHP_SELF'], 't.fk_product', '', $param, '', $sortfield, $sortorder);
2072 $totalarray['nbfield']++;
2073 }
2074
2075 if (!empty($arrayfields['value']['checked'])) {
2076 print_liste_field_titre($arrayfields['value']['label'], $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder, 'right ');
2077 $totalarray['nbfield']++;
2078 }
2079 if (!empty($arrayfields['valuebilled']['checked'])) {
2080 print_liste_field_titre($arrayfields['valuebilled']['label'], $_SERVER['PHP_SELF'], 'il.total_ht', '', $param, '', $sortfield, $sortorder, 'center ', $langs->trans("SelectLinesOfTimeSpentToInvoice"));
2081 $totalarray['nbfield']++;
2082 }
2083 /*
2084 // Extra fields
2085 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
2086 */
2087 // Hook fields
2088 $parameters = array('arrayfields' => $arrayfields, 'param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder);
2089 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2090 print $hookmanager->resPrint;
2091 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2092 print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', 'width="80"', $sortfield, $sortorder, 'center maxwidthsearch ');
2093 $totalarray['nbfield']++;
2094 }
2095 print "</tr>\n";
2096
2097 $tasktmp = new Task($db);
2098 $tmpinvoice = new Facture($db);
2099
2100 if ($page) {
2101 $param .= '&page='.((int) $page);
2102 }
2103 $param .= '&sortfield='.urlencode($sortfield).'&sortorder='.urlencode($sortorder);
2104
2105 $i = 0;
2106
2107 $savnbfield = $totalarray['nbfield'];
2108 $totalarray = array();
2109 $totalarray['nbfield'] = 0;
2110 //$imaxinloop = ($limit ? min($num, $limit) : $num);
2111 foreach ($tasks as $task_time) {
2112 if ($i >= $limit) {
2113 break;
2114 }
2115
2116 $date1 = $db->jdate($task_time->element_date);
2117 $date2 = $db->jdate($task_time->element_datehour);
2118
2119 // Show here line of result
2120 $j = 0;
2121 print '<tr data-rowid="'.$task_time->rowid.'" class="oddeven">';
2122
2123 // Action column
2124 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2125 print '<td class="center nowraponall">';
2126 if (($action == 'editline' || $action == 'splitline') && GETPOSTINT('lineid') == $task_time->rowid) {
2127 print '<input type="hidden" name="lineid" value="' . GETPOSTINT('lineid') . '">';
2128 print '<input type="submit" class="button buttongen smallpaddingimp margintoponlyshort marginbottomonlyshort button-save" name="save" value="'.$langs->trans("Save").'">';
2129 print '<br>';
2130 print '<input type="submit" class="button buttongen smallpaddingimp margintoponlyshort marginbottomonlyshort button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
2131 } elseif ($user->hasRight('projet', 'time') || $user->hasRight('projet', 'all', 'creer')) { // Read project and enter time consumed on assigned tasks
2132 if (in_array($task_time->fk_user, $childids) || $user->hasRight('projet', 'all', 'creer')) {
2133 print '<a class="reposition editfielda" href="'.$_SERVER["PHP_SELF"].'?'.($withproject ? 'id='.$task_time->fk_element : '').'&action=editline&token='.newToken().'&lineid='.$task_time->rowid.$param.((empty($id) || $tab == 'timespent') ? '&tab=timespent' : '').'">';
2134 print img_edit('default', 0, 'class="pictofixedwidth paddingleft"');
2135 print '</a>';
2136
2137 if (getDolGlobalString('PROJECT_ALLOW_SPLIT_TIMESPENT')) {
2138 print '<a class="reposition editfielda paddingleft" href="' . $_SERVER["PHP_SELF"] . '?action=splitline&token=' . newToken() . '&lineid=' . $task_time->rowid . $param . ((empty($id) || $tab == 'timespent') ? '&tab=timespent' : '') . '">';
2139 print img_split('', 'class="pictofixedwidth paddingleft"');
2140 print '</a>';
2141 }
2142
2143 print '<a class="reposition paddingleft" href="'.$_SERVER["PHP_SELF"].'?'.($withproject ? 'id='.$task_time->fk_element : '').'&action=deleteline&token='.newToken().'&lineid='.$task_time->rowid.$param.((empty($id) || $tab == 'timespent') ? '&tab=timespent' : '').'">';
2144 print img_delete('default', 'class="pictodelete paddingleft"');
2145 print '</a>';
2146
2147 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
2148 $selected = 0;
2149 if (in_array($task_time->rowid, $arrayofselected)) {
2150 $selected = 1;
2151 }
2152 print '&nbsp;';
2153 print '<input id="cb' . $task_time->rowid . '" class="flat checkforselect marginleftonly" type="checkbox" name="toselect[]" value="' . $task_time->rowid . '"' . ($selected ? ' checked="checked"' : '') . '>';
2154 }
2155 }
2156 }
2157 print '</td>';
2158 if (!$i) {
2159 $totalarray['nbfield']++;
2160 }
2161 }
2162
2163 // Date
2164 if (!empty($arrayfields['t.element_date']['checked'])) {
2165 print '<td class="nowrap">';
2166 if ($action == 'editline' && GETPOSTINT('lineid') == $task_time->rowid) {
2167 if (empty($task_time->element_date_withhour)) {
2168 print $form->selectDate(($date2 ? $date2 : $date1), 'timeline', 4, 3, 2, "timespent_date", 1, 0);
2169 } else {
2170 print $form->selectDate(($date2 ? $date2 : $date1), 'timeline', 2, 1, 2, "timespent_date", 1, 0);
2171 }
2172 } else {
2173 print dol_print_date(($date2 ? $date2 : $date1), ($task_time->element_date_withhour ? 'dayhour' : 'day'));
2174 }
2175 print '</td>';
2176 if (!$i) {
2177 $totalarray['nbfield']++;
2178 }
2179 }
2180
2181 // Thirdparty
2182 if (!empty($arrayfields['p.fk_soc']['checked'])) {
2183 print '<td class="tdoverflowmax125">';
2184 if ($task_time->fk_soc > 0) {
2185 if (empty($conf->cache['thridparty'][$task_time->fk_soc])) {
2186 $tmpsociete = new Societe($db);
2187 $tmpsociete->fetch($task_time->fk_soc);
2188 $conf->cache['thridparty'][$task_time->fk_soc] = $tmpsociete;
2189 } else {
2190 $tmpsociete = $conf->cache['thridparty'][$task_time->fk_soc];
2191 }
2192 print $tmpsociete->getNomUrl(1, '', 100, 0, 1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1);
2193 }
2194 print '</td>';
2195 if (!$i) {
2196 $totalarray['nbfield']++;
2197 }
2198 }
2199
2200 // Thirdparty alias
2201 if (!empty($arrayfields['s.name_alias']['checked'])) {
2202 if ($task_time->fk_soc > 0) {
2203 if (empty($conf->cache['thridparty'][$task_time->fk_soc])) {
2204 $tmpsociete = new Societe($db);
2205 $tmpsociete->fetch($task_time->fk_soc);
2206 $conf->cache['thridparty'][$task_time->fk_soc] = $tmpsociete;
2207 } else {
2208 $tmpsociete = $conf->cache['thridparty'][$task_time->fk_soc];
2209 }
2210 $valtoshow = $tmpsociete->name_alias;
2211 }
2212 print '<td class="nowrap tdoverflowmax150" title="'.dol_escape_htmltag($valtoshow).'">';
2213 print $valtoshow;
2214 print '</td>';
2215 if (!$i) {
2216 $totalarray['nbfield']++;
2217 }
2218 }
2219
2220 // Project ref & label
2221 if (!empty($allprojectforuser)) {
2222 if (!empty($arrayfields['p.project_ref']['checked'])) {
2223 print '<td class="nowraponall">';
2224 if (empty($conf->cache['project'][$task_time->fk_projet])) {
2225 $tmpproject = new Project($db);
2226 $tmpproject->fetch($task_time->fk_projet);
2227 $conf->cache['project'][$task_time->fk_projet] = $tmpproject;
2228 } else {
2229 $tmpproject = $conf->cache['project'][$task_time->fk_projet];
2230 }
2231 print $tmpproject->getNomUrl(1);
2232 print '</td>';
2233 if (!$i) {
2234 $totalarray['nbfield']++;
2235 }
2236 }
2237 if (!empty($arrayfields['p.project_label']['checked'])) {
2238 if (empty($conf->cache['project'][$task_time->fk_projet])) {
2239 $tmpproject = new Project($db);
2240 $tmpproject->fetch($task_time->fk_projet);
2241 $conf->cache['project'][$task_time->fk_projet] = $tmpproject;
2242 } else {
2243 $tmpproject = $conf->cache['project'][$task_time->fk_projet];
2244 }
2245 print '<td class="tdoverflowmax250" title="'.dol_escape_htmltag($tmpproject->title).'">';
2246 print dol_escape_htmltag($tmpproject->title);
2247 print '</td>';
2248 if (!$i) {
2249 $totalarray['nbfield']++;
2250 }
2251 }
2252 }
2253
2254 // Task ref
2255 if (!empty($arrayfields['t.element_ref']['checked'])) {
2256 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2257 print '<td class="nowrap">';
2258 if ($action == 'editline' && GETPOSTINT('lineid') == $task_time->rowid) {
2259 $formproject->selectTasks(-1, GETPOSTINT('taskid') ? GETPOSTINT('taskid') : $task_time->fk_element, 'taskid', 0, 0, 1, 1, 0, 0, 'maxwidth250', $projectstatic->id, '');
2260 } else {
2261 $tasktmp->id = $task_time->fk_element;
2262 $tasktmp->ref = $task_time->ref;
2263 $tasktmp->label = $task_time->label;
2264 print $tasktmp->getNomUrl(1, 'withproject', 'time');
2265 }
2266 print '</td>';
2267 if (!$i) {
2268 $totalarray['nbfield']++;
2269 }
2270 }
2271 } elseif ($action !== 'createtime') {
2272 print '<input type="hidden" name="taskid" value="' . $id . '">';
2273 }
2274
2275 // Task label
2276 if (!empty($arrayfields['t.element_label']['checked'])) {
2277 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2278 print '<td class="tdoverflowmax250" title="'.dol_escape_htmltag($task_time->label).'">';
2279 print dol_escape_htmltag($task_time->label);
2280 print '</td>';
2281 if (!$i) {
2282 $totalarray['nbfield']++;
2283 }
2284 }
2285 }
2286
2287 // By User
2288 if (!empty($arrayfields['author']['checked'])) {
2289 print '<td class="minwidth100 tdoverflowmax125">';
2290 if ($action == 'editline' && GETPOSTINT('lineid') == $task_time->rowid) {
2291 // Here $object is task. TODO Add a cache
2292 if (empty($object->id)) {
2293 $object->fetch($task_time->fk_element);
2294 }
2295 $contactsoftask = $object->getListContactId('internal');
2296 if (!in_array($task_time->fk_user, $contactsoftask)) {
2297 $contactsoftask[] = $task_time->fk_user;
2298 }
2299 if (count($contactsoftask) > 0) {
2300 print img_object('', 'user', 'class="pictofixedwidth hideonsmartphone"');
2301 print $form->select_dolusers($task_time->fk_user, 'userid_line', 0, null, 0, '', $contactsoftask, '0', 0, 0, '', 0, '', 'minwidth100 maxwidth100'); // maxwidth must be lowed than minwidth of the td
2302 } else {
2303 print img_error($langs->trans('FirstAddRessourceToAllocateTime')) . $langs->trans('FirstAddRessourceToAllocateTime');
2304 }
2305 } else {
2306 $userstatic->id = $task_time->fk_user;
2307 $userstatic->lastname = $task_time->lastname;
2308 $userstatic->firstname = $task_time->firstname;
2309 $userstatic->photo = $task_time->photo;
2310 $userstatic->gender = $task_time->gender;
2311 $userstatic->status = $task_time->user_status;
2312
2313 print $userstatic->getNomUrl(-1);
2314 }
2315 print '</td>';
2316 if (!$i) {
2317 $totalarray['nbfield']++;
2318 }
2319 }
2320
2321 // Note
2322 if (!empty($arrayfields['t.note']['checked'])) {
2323 if ($action == 'editline' && GETPOSTINT('lineid') == $task_time->rowid) {
2324 print '<td class="small">';
2325 print '<textarea name="timespent_note_line" width="95%" rows="' . ROWS_1 . '">' . dol_escape_htmltag($task_time->note, 0, 1) . '</textarea>';
2326 print '</td>';
2327 } else {
2328 print '<td class="small tdoverflowmax150 classfortooltip" title="'.dol_string_onlythesehtmltags(dol_htmlentitiesbr($task_time->note)).'">';
2329 print dolGetFirstLineOfText($task_time->note);
2330 print '</td>';
2331 }
2332 if (!$i) {
2333 $totalarray['nbfield']++;
2334 }
2335 } elseif ($action == 'editline' && GETPOSTINT('lineid') == $task_time->rowid) {
2336 print '<input type="hidden" name="timespent_note_line" value="' . dol_escape_htmltag($task_time->note, 0, 1) . '">';
2337 }
2338
2339 // Time spent
2340 if (!empty($arrayfields['t.element_duration']['checked'])) {
2341 print '<td class="right nowraponall">';
2342 if ($action == 'editline' && GETPOSTINT('lineid') == $task_time->rowid) {
2343 print '<input type="hidden" name="old_duration" value="'.$task_time->element_duration.'">';
2344 print $form->select_duration('new_duration', $task_time->element_duration, 0, 'text');
2345 } else {
2346 print convertSecondToTime($task_time->element_duration, 'allhourmin');
2347 }
2348 print '</td>';
2349 if (!$i) {
2350 $totalarray['nbfield']++;
2351 }
2352 if (!$i) {
2353 $totalarray['pos'][$totalarray['nbfield']] = 't.element_duration';
2354 }
2355 if (empty($totalarray['val']['t.element_duration'])) {
2356 $totalarray['val']['t.element_duration'] = $task_time->element_duration;
2357 } else {
2358 $totalarray['val']['t.element_duration'] += $task_time->element_duration;
2359 }
2360 if (!$i) {
2361 $totalarray['totaldurationfield'] = $totalarray['nbfield'];
2362 }
2363 if (empty($totalarray['totalduration'])) {
2364 $totalarray['totalduration'] = $task_time->element_duration;
2365 } else {
2366 $totalarray['totalduration'] += $task_time->element_duration;
2367 }
2368 }
2369
2370 // Product
2371 if (!empty($arrayfields['t.fk_product']['checked'])) {
2372 print '<td class="nowraponall">';
2373 if ($action == 'editline' && GETPOSTINT('lineid') == $task_time->rowid) {
2374 print img_picto('', 'service');
2375 print $form->select_produits($task_time->fk_product, 'fk_product', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 1, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth500', 0, '', null, 1);
2376 } elseif (!empty($task_time->fk_product)) {
2377 $product = new Product($db);
2378 $resultFetch = $product->fetch($task_time->fk_product);
2379 if ($resultFetch < 0) {
2380 setEventMessages($product->error, $product->errors, 'errors');
2381 } else {
2382 print $product->getNomUrl(1);
2383 }
2384 }
2385 print '</td>';
2386 if (!$i) {
2387 $totalarray['nbfield']++;
2388 }
2389 }
2390
2391 // Value spent
2392 if (!empty($arrayfields['value']['checked'])) {
2393 $langs->load("salaries");
2394 $value = price2num($task_time->thm * $task_time->element_duration / 3600, 'MT', 1);
2395
2396 print '<td class="nowraponall right">';
2397 print '<span class="amount" title="' . $langs->trans("THM") . ': ' . price($task_time->thm) . '">';
2398 print price($value, 1, $langs, 1, -1, -1, $conf->currency);
2399 print '</span>';
2400 print '</td>';
2401 if (!$i) {
2402 $totalarray['nbfield']++;
2403 }
2404 if (!$i) {
2405 $totalarray['pos'][$totalarray['nbfield']] = 'value';
2406 }
2407 if (empty($totalarray['val']['value'])) {
2408 $totalarray['val']['value'] = $value;
2409 } else {
2410 $totalarray['val']['value'] += $value;
2411 }
2412 if (!$i) {
2413 $totalarray['totalvaluefield'] = $totalarray['nbfield'];
2414 }
2415 if (empty($totalarray['totalvalue'])) {
2416 $totalarray['totalvalue'] = $value;
2417 } else {
2418 $totalarray['totalvalue'] += $value;
2419 }
2420 }
2421
2422 // Invoiced
2423 if (!empty($arrayfields['valuebilled']['checked'])) {
2424 print '<td class="center">'; // invoice_id and invoice_line_id
2425 if (!getDolGlobalString('PROJECT_HIDE_TASKS') && getDolGlobalString('PROJECT_BILL_TIME_SPENT')) {
2426 if ($projectstatic->usage_bill_time) {
2427 if ($task_time->invoice_id) {
2428 $result = $tmpinvoice->fetch($task_time->invoice_id);
2429 if ($result > 0) {
2430 if ($action == 'editline' && GETPOSTINT('lineid') == $task_time->rowid) {
2431 print $formproject->selectInvoiceAndLine($task_time->invoice_id, $task_time->invoice_line_id, 'invoiceid', 'invoicelineid', 'maxwidth500', array('p.rowid' => $projectstatic->id));
2432 } else {
2433 print $tmpinvoice->getNomUrl(1);
2434 if (!empty($task_time->invoice_line_id)) {
2435 $invoiceLine = new FactureLigne($db);
2436 $invoiceLine->fetch($task_time->invoice_line_id);
2437 if (!empty($invoiceLine->id)) {
2438 print '<br>'.$langs->trans('Qty').':'.$invoiceLine->qty;
2439 print ' '.$langs->trans('TotalHT').':'.price($invoiceLine->total_ht);
2440 }
2441 }
2442 }
2443 }
2444 } else {
2445 print $langs->trans("No");
2446 }
2447 } else {
2448 print '<span class="opacitymedium">' . $langs->trans("NA") . '</span>';
2449 }
2450 }
2451 print '</td>';
2452 if (!$i) {
2453 $totalarray['nbfield']++;
2454 }
2455 }
2456
2457 /*
2458 // Extra fields
2459 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
2460 */
2461
2462 // Fields from hook
2463 $parameters = array('arrayfields' => $arrayfields, 'obj' => $task_time, 'i' => $i, 'totalarray' => &$totalarray);
2464 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2465 print $hookmanager->resPrint;
2466
2467 // Action column
2468 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2469 print '<td class="center nowraponall">';
2470 if (($action == 'editline' || $action == 'splitline') && GETPOSTINT('lineid') == $task_time->rowid) {
2471 print '<input type="hidden" name="lineid" value="'.GETPOSTINT('lineid').'">';
2472 print '<input type="submit" class="button buttongen smallpaddingimp margintoponlyshort marginbottomonlyshort button-save" name="save" value="'.$langs->trans("Save").'">';
2473 print '<br>';
2474 print '<input type="submit" class="button buttongen smallpaddingimp margintoponlyshort marginbottomonlyshort button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
2475 } elseif ($user->hasRight('projet', 'time') || $user->hasRight('projet', 'all', 'creer')) { // Read project and enter time consumed on assigned tasks
2476 if (in_array($task_time->fk_user, $childids) || $user->hasRight('projet', 'all', 'creer')) {
2477 print '<a class="reposition editfielda" href="'.$_SERVER["PHP_SELF"].'?'.($withproject ? 'id='.$task_time->fk_element : '').'&action=editline&token='.newToken().'&lineid='.$task_time->rowid.$param.((empty($id) || $tab == 'timespent') ? '&tab=timespent' : '').'">';
2478 print img_edit('default', 0, 'class="pictofixedwidth paddingleft"');
2479 print '</a>';
2480
2481 if (getDolGlobalString('PROJECT_ALLOW_SPLIT_TIMESPENT')) {
2482 print '<a class="reposition editfielda paddingleft" href="' . $_SERVER["PHP_SELF"] . '?action=splitline&token=' . newToken() . '&lineid=' . $task_time->rowid . $param . ((empty($id) || $tab == 'timespent') ? '&tab=timespent' : '') . '">';
2483 print img_split('', 'class="pictofixedwidth paddingleft"');
2484 print '</a>';
2485 }
2486
2487 print '<a class="reposition paddingleft" href="'.$_SERVER["PHP_SELF"].'?'.($withproject ? 'id='.$task_time->fk_element : '').'&action=deleteline&token='.newToken().'&lineid='.$task_time->rowid.$param.((empty($id) || $tab == 'timespent') ? '&tab=timespent' : '').'">';
2488 print img_delete('default', 'class="pictodelete paddingleft"');
2489 print '</a>';
2490
2491 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
2492 $selected = 0;
2493 if (in_array($task_time->rowid, $arrayofselected)) {
2494 $selected = 1;
2495 }
2496 print '&nbsp;';
2497 print '<input id="cb' . $task_time->rowid . '" class="flat checkforselect marginleftonly" type="checkbox" name="toselect[]" value="' . $task_time->rowid . '"' . ($selected ? ' checked="checked"' : '') . '>';
2498 }
2499 }
2500 }
2501 print '</td>';
2502 if (!$i) {
2503 $totalarray['nbfield']++;
2504 }
2505 }
2506
2507 print "</tr>\n";
2508
2509
2510 // Add the lines for the split feature
2511
2512 if ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2513 print '<!-- first line -->';
2514 print '<tr class="oddeven">';
2515
2516 // Action column
2517 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2518 print '<td></td>';
2519 }
2520
2521 // Date
2522 if (!empty($arrayfields['t.element_date']['checked'])) {
2523 print '<td class="nowrap">';
2524 if ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2525 if (empty($task_time->element_date_withhour)) {
2526 print $form->selectDate(($date2 ? $date2 : $date1), 'timeline', 3, 3, 2, "timespent_date", 1, 0);
2527 } else {
2528 print $form->selectDate(($date2 ? $date2 : $date1), 'timeline', 1, 1, 2, "timespent_date", 1, 0);
2529 }
2530 } else {
2531 print dol_print_date(($date2 ? $date2 : $date1), ($task_time->element_date_withhour ? 'dayhour' : 'day'));
2532 }
2533 print '</td>';
2534 }
2535
2536 // Thirdparty
2537 if (!empty($arrayfields['p.fk_soc']['checked'])) {
2538 print '<td class="nowrap">';
2539 print '</td>';
2540 }
2541
2542 // Thirdparty alias
2543 if (!empty($arrayfields['s.name_alias']['checked'])) {
2544 print '<td class="nowrap">';
2545 print '</td>';
2546 }
2547
2548 // Project ref
2549 if (!empty($allprojectforuser)) {
2550 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2551 print '<td class="nowrap">';
2552 print '</td>';
2553 }
2554 }
2555
2556 // Task ref
2557 if (!empty($arrayfields['t.element_ref']['checked'])) {
2558 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2559 print '<td class="nowrap">';
2560 $tasktmp->id = $task_time->fk_element;
2561 $tasktmp->ref = $task_time->ref;
2562 $tasktmp->label = $task_time->label;
2563 print $tasktmp->getNomUrl(1, 'withproject', 'time');
2564 print '</td>';
2565 }
2566 }
2567
2568 // Task label
2569 if (!empty($arrayfields['t.element_label']['checked'])) {
2570 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2571 print '<td class="tdoverflowmax300" title="'.dol_escape_htmltag($task_time->label).'">';
2572 print dol_escape_htmltag($task_time->label);
2573 print '</td>';
2574 }
2575 }
2576
2577 // User
2578 if (!empty($arrayfields['author']['checked'])) {
2579 print '<td class="nowraponall">';
2580 if ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2581 if (empty($object->id)) {
2582 $object->fetch($id);
2583 }
2584 $contactsoftask = $object->getListContactId('internal');
2585 if (!in_array($task_time->fk_user, $contactsoftask)) {
2586 $contactsoftask[] = $task_time->fk_user;
2587 }
2588 if (count($contactsoftask) > 0) {
2589 print img_object('', 'user', 'class="hideonsmartphone"');
2590 print $form->select_dolusers($task_time->fk_user, 'userid_line', 0, '', 0, '', $contactsoftask);
2591 } else {
2592 print img_error($langs->trans('FirstAddRessourceToAllocateTime')) . $langs->trans('FirstAddRessourceToAllocateTime');
2593 }
2594 } else {
2595 $userstatic->id = $task_time->fk_user;
2596 $userstatic->lastname = $task_time->lastname;
2597 $userstatic->firstname = $task_time->firstname;
2598 $userstatic->photo = $task_time->photo;
2599 $userstatic->status = $task_time->user_status;
2600 print $userstatic->getNomUrl(-1);
2601 }
2602 print '</td>';
2603 }
2604
2605 // Note
2606 if (!empty($arrayfields['t.note']['checked'])) {
2607 print '<td class="tdoverflowmax300">';
2608 if ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2609 print '<textarea name="timespent_note_line" width="95%" rows="' . ROWS_1 . '">' . dol_escape_htmltag($task_time->note, 0, 1) . '</textarea>';
2610 } else {
2611 print dol_nl2br($task_time->note);
2612 }
2613 print '</td>';
2614 } elseif ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2615 print '<input type="hidden" name="timespent_note_line" rows="' . ROWS_1 . '" value="' . dol_escape_htmltag($task_time->note, 0, 1) . '">';
2616 }
2617
2618 // Time spent
2619 if (!empty($arrayfields['t.element_duration']['checked'])) {
2620 print '<td class="right">';
2621 if ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2622 print '<input type="hidden" name="old_duration" value="'.$task_time->element_duration.'">';
2623 print $form->select_duration('new_duration', $task_time->element_duration, 0, 'text');
2624 } else {
2625 print convertSecondToTime($task_time->element_duration, 'allhourmin');
2626 }
2627 print '</td>';
2628 }
2629
2630 // Product
2631 if (!empty($arrayfields['t.fk_product']['checked'])) {
2632 print '<td class="nowraponall tdoverflowmax125">';
2633 print '</td>';
2634 }
2635
2636 // Value spent
2637 if (!empty($arrayfields['value']['checked'])) {
2638 print '<td class="right">';
2639 print '<span class="amount">';
2640 $value = price2num($task_time->thm * $task_time->element_duration / 3600, 'MT', 1);
2641 print price($value, 1, $langs, 1, -1, -1, $conf->currency);
2642 print '</span>';
2643 print '</td>';
2644 }
2645
2646 // Value billed
2647 if (!empty($arrayfields['valuebilled']['checked'])) {
2648 print '<td class="right">';
2649 $valuebilled = price2num($task_time->total_ht, '', 1);
2650 if (isset($task_time->total_ht)) {
2651 print price($valuebilled, 1, $langs, 1, -1, -1, $conf->currency);
2652 }
2653 print '</td>';
2654 }
2655
2656 /*
2657 // Extra fields
2658 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
2659 */
2660
2661 // Fields from hook
2662 $parameters = array('arrayfields' => $arrayfields, 'obj' => $task_time, 'mode' => 'split1');
2663 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2664 print $hookmanager->resPrint;
2665
2666 // Action column
2667 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2668 print '<td class="center nowraponall">';
2669 print '</td>';
2670 }
2671
2672 print "</tr>\n";
2673
2674
2675 // Line for second dispatching
2676
2677 print '<!-- second line --><tr class="oddeven">';
2678
2679 // Action column
2680 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2681 print '<td class="center nowraponall">';
2682 print '</td>';
2683 }
2684
2685 // Date
2686 if (!empty($arrayfields['t.element_date']['checked'])) {
2687 print '<td class="nowrap">';
2688 if ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2689 if (empty($task_time->element_date_withhour)) {
2690 print $form->selectDate(($date2 ? $date2 : $date1), 'timeline_2', 3, 3, 2, "timespent_date", 1, 0);
2691 } else {
2692 print $form->selectDate(($date2 ? $date2 : $date1), 'timeline_2', 1, 1, 2, "timespent_date", 1, 0);
2693 }
2694 } else {
2695 print dol_print_date(($date2 ? $date2 : $date1), ($task_time->element_date_withhour ? 'dayhour' : 'day'));
2696 }
2697 print '</td>';
2698 }
2699
2700 // Thirdparty
2701 if (!empty($arrayfields['p.fk_soc']['checked'])) {
2702 print '<td class="nowrap">';
2703 print '</td>';
2704 }
2705
2706 // Thirdparty alias
2707 if (!empty($arrayfields['s.name_alias']['checked'])) {
2708 print '<td class="nowrap">';
2709 print '</td>';
2710 }
2711
2712 // Project ref
2713 if (!empty($allprojectforuser)) {
2714 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2715 print '<td class="nowrap">';
2716 print '</td>';
2717 }
2718 }
2719
2720 // Task ref
2721 if (!empty($arrayfields['t.element_ref']['checked'])) {
2722 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2723 print '<td class="nowrap">';
2724 $tasktmp->id = $task_time->fk_element;
2725 $tasktmp->ref = $task_time->ref;
2726 $tasktmp->label = $task_time->label;
2727 print $tasktmp->getNomUrl(1, 'withproject', 'time');
2728 print '</td>';
2729 }
2730 }
2731
2732 // Task label
2733 if (!empty($arrayfields['t.element_label']['checked'])) {
2734 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2735 print '<td class="nowrap">';
2736 print dol_escape_htmltag($task_time->label);
2737 print '</td>';
2738 }
2739 }
2740
2741 // User
2742 if (!empty($arrayfields['author']['checked'])) {
2743 print '<td class="nowraponall tdoverflowmax100">';
2744 if ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2745 if (empty($object->id)) {
2746 $object->fetch($id);
2747 }
2748 $contactsoftask = $object->getListContactId('internal');
2749 if (!in_array($task_time->fk_user, $contactsoftask)) {
2750 $contactsoftask[] = $task_time->fk_user;
2751 }
2752 if (count($contactsoftask) > 0) {
2753 print img_object('', 'user', 'class="hideonsmartphone"');
2754 print $form->select_dolusers($task_time->fk_user, 'userid_line_2', 0, '', 0, '', $contactsoftask);
2755 } else {
2756 print img_error($langs->trans('FirstAddRessourceToAllocateTime')) . $langs->trans('FirstAddRessourceToAllocateTime');
2757 }
2758 } else {
2759 $userstatic->id = $task_time->fk_user;
2760 $userstatic->lastname = $task_time->lastname;
2761 $userstatic->firstname = $task_time->firstname;
2762 $userstatic->photo = $task_time->photo;
2763 $userstatic->status = $task_time->user_status;
2764 print $userstatic->getNomUrl(-1);
2765 }
2766 print '</td>';
2767 }
2768
2769 // Note
2770 if (!empty($arrayfields['t.note']['checked'])) {
2771 print '<td class="small tdoverflowmax300"">';
2772 if ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2773 print '<textarea name="timespent_note_line_2" width="95%" rows="' . ROWS_1 . '">' . dol_escape_htmltag($task_time->note, 0, 1) . '</textarea>';
2774 } else {
2775 print dol_nl2br($task_time->note);
2776 }
2777 print '</td>';
2778 } elseif ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2779 print '<input type="hidden" name="timespent_note_line_2" value="' . dol_escape_htmltag($task_time->note, 0, 1) . '">';
2780 }
2781
2782 // Time spent
2783 if (!empty($arrayfields['t.element_duration']['checked'])) {
2784 print '<td class="right">';
2785 if ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2786 print '<input type="hidden" name="old_duration_2" value="0">';
2787 print $form->select_duration('new_duration_2', 0, 0, 'text');
2788 } else {
2789 print convertSecondToTime($task_time->element_duration, 'allhourmin');
2790 }
2791 print '</td>';
2792 }
2793
2794 // Product
2795 if (!empty($arrayfields['t.fk_product']['checked'])) {
2796 print '<td class="nowraponall tdoverflowmax125">';
2797 print '</td>';
2798 }
2799
2800 // Value spent
2801 if (!empty($arrayfields['value']['checked'])) {
2802 print '<td class="right">';
2803 print '<span class="amount">';
2804 $value = 0;
2805 print price($value, 1, $langs, 1, -1, -1, $conf->currency);
2806 print '</span>';
2807 print '</td>';
2808 }
2809
2810 // Value billed
2811 if (!empty($arrayfields['valuebilled']['checked'])) {
2812 print '<td class="right">';
2813 $valuebilled = price2num($task_time->total_ht, '', 1);
2814 if (isset($task_time->total_ht)) {
2815 print '<span class="amount">';
2816 print price($valuebilled, 1, $langs, 1, -1, -1, $conf->currency);
2817 print '</span>';
2818 }
2819 print '</td>';
2820 }
2821
2822 /*
2823 // Extra fields
2824 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
2825 */
2826
2827 // Fields from hook
2828 $parameters = array('arrayfields' => $arrayfields, 'obj' => $task_time, 'mode' => 'split2');
2829 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2830 print $hookmanager->resPrint;
2831
2832 // Action column
2833 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2834 print '<td class="center nowraponall">';
2835 print '</td>';
2836 }
2837
2838 print "</tr>\n";
2839 }
2840
2841 $i++;
2842 }
2843
2844 // Show total line
2845 //include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
2846 if (isset($totalarray['totaldurationfield']) || isset($totalarray['totalvaluefield'])) {
2847 print '<tr class="liste_total">';
2848 $i = 0;
2849 while ($i < $totalarray['nbfield']) {
2850 $i++;
2851 if ($i == 1) {
2852 if ($num < $limit && empty($offset)) {
2853 print '<td class="left">' . $langs->trans("Total") . '</td>';
2854 } else {
2855 print '<td class="left">'.$form->textwithpicto($langs->trans("Total"), $langs->trans("Totalforthispage")).'</td>';
2856 }
2857 } elseif (isset($totalarray['totaldurationfield']) && $totalarray['totaldurationfield'] == $i) {
2858 print '<td class="right">' . convertSecondToTime($totalarray['totalduration'], 'allhourmin') . '</td>';
2859 } elseif (isset($totalarray['totalvaluefield']) && $totalarray['totalvaluefield'] == $i) {
2860 print '<td class="right">' . price($totalarray['totalvalue']) . '</td>';
2861 //} elseif ($totalarray['totalvaluebilledfield'] == $i) { print '<td class="center">'.price($totalarray['totalvaluebilled']).'</td>';
2862 } else {
2863 print '<td></td>';
2864 }
2865 }
2866 print '</tr>';
2867 }
2868
2869 if (!count($tasks)) {
2870 $totalnboffields = 1;
2871 foreach ($arrayfields as $value) {
2872 if (!empty($value['checked'])) {
2873 $totalnboffields++;
2874 }
2875 }
2876 print '<tr class="oddeven"><td colspan="' . $totalnboffields . '">';
2877 print '<span class="opacitymedium">' . $langs->trans("None") . '</span>';
2878 print '</td></tr>';
2879 }
2880
2881 $parameters = array('arrayfields' => $arrayfields, 'sql' => $sql);
2882 $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2883 print $hookmanager->resPrint;
2884
2885 print "</table>";
2886 print '</div>';
2887 print "</form>";
2888 }
2889}
2890
2891// End of page
2892llxFooter();
2893$db->close();
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:58
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader()
Empty header.
Definition wrapper.php:55
llxFooter()
Empty footer.
Definition wrapper.php:69
Class to manage standard extra fields.
Class to manage invoices.
Class to manage invoice lines.
Class to manage interventions.
Class to manage generation of HTML components Only common components must be here.
Class to manage generation of HTML components for contract module.
Class permettant la generation de composants html autre Only common components are here.
Class to manage building of HTML components.
Class to manage products or services.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage tasks.
Class to manage Dolibarr users.
dolSqlDateFilter($datefield, $day_date, $month_date, $year_date, $excludefirstand=0, $gm=false)
Generate a SQL string to make a filter into a range (for second of date until last second of date).
Definition date.lib.php:378
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:242
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...
get_default_localtax($thirdparty_seller, $thirdparty_buyer, $local, $idprod=0)
Function that return localtax of a product line (according to seller, buyer and product vat rate) If ...
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
img_delete($titlealt='default', $other='class="pictodelete"', $morecss='')
Show delete logo.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dolGetFirstLineOfText($text, $nboflines=1, $charset='UTF-8')
Return first line of text.
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.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dolGetButtonTitle($label, $helpText='', $iconClass='fa fa-file', $url='', $id='', $status=1, $params=array())
Function dolGetButtonTitle : this kind of buttons are used in title in list.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
dol_nl2br($stringtoencode, $nl2brmode=0, $forxml=false)
Replace CRLF in string with a HTML BR tag.
natural_search($fields, $value, $mode=0, $nofirstand=0)
Generate natural SQL search string for a criteria (this criteria can be tested on one or several fiel...
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.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
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).
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by the value of a given key, which produces ascending (default) or descending out...
newToken()
Return the value of token currently saved into session with name 'newtoken'.
print_liste_field_titre($name, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
img_split($titlealt='default', $other='class="pictosplit"')
Show split logo.
print_barre_liste($title, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $hideselectlimit=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
img_error($titlealt='default')
Show error logo.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
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...
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...
task_prepare_head($object)
Prepare array with list of tabs.
project_prepare_head(Project $project, $moreparam='')
Prepare array with list of tabs.
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.