dolibarr 21.0.0-alpha
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-2024 Frédéric France <frederic.france@free.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 a technical object to manage hooks of page. Note that conf->hooks_modules contains an 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', 0, '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 = (float) price2num($timespent_data['totalvaluetodivideby3600'] / $timespent_data['timespent'], 'MU') * $prodDurationHours;
737 }
738 $pa_ht = (float) 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, '', 0, 0, '', '', '', 'mod-project project-tasks page-task_time');
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 a 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 $sql .= " pt.billable";
1580 // Add fields from hooks
1581 $parameters = array();
1582 $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1583 $sql .= $hookmanager->resPrint;
1584 $sql = preg_replace('/,\s*$/', '', $sql);
1585
1586 $sqlfields = $sql; // $sql fields to remove for count total
1587
1588 $sql .= " FROM ".MAIN_DB_PREFIX."element_time as t";
1589 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facturedet as il ON il.rowid = t.invoice_line_id";
1590 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture as inv ON inv.rowid = il.fk_facture";
1591 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as prod ON prod.rowid = t.fk_product";
1592 $sql .= " INNER JOIN ".MAIN_DB_PREFIX."projet_task as pt ON pt.rowid = t.fk_element";
1593 $sql .= " INNER JOIN ".MAIN_DB_PREFIX."projet as p ON p.rowid = pt.fk_projet";
1594 $sql .= " INNER JOIN ".MAIN_DB_PREFIX."user as u ON t.fk_user = u.rowid";
1595 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = p.fk_soc";
1596
1597 // Add table from hooks
1598 $parameters = array();
1599 $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1600 $sql .= $hookmanager->resPrint;
1601 $sql .= " WHERE elementtype = 'task'";
1602 $sql .= " AND p.entity IN (".getEntity('project').")";
1603 if (!$user->hasRight('projet', 'all', 'lire')) {
1604 // Get list of project id allowed to user (in a string list separated by comma)
1605 // TODO This may generate performance trouble when list of project is very large. Solution can be to complete $filterproj with filters on project.
1606 $filterproj = '';
1607 $projectsListId = $projectstatic->getProjectsAuthorizedForUser($user, 0, 1, $user->socid > 0 ? $user->socid : 0, $filterproj);
1608 $sql .= " AND p.rowid IN (".$db->sanitize($projectsListId).")"; // public and assigned to, or restricted to company for external users
1609 }
1610 if (empty($projectidforalltimes) && empty($allprojectforuser)) {
1611 // Limit on one task
1612 $sql .= " AND t.fk_element =".((int) $object->id);
1613 } elseif (!empty($projectidforalltimes)) {
1614 // Limit on one project
1615 $sql .= " AND pt.fk_projet IN (" . $db->sanitize($projectidforalltimes) . ")";
1616 } elseif (!empty($allprojectforuser)) {
1617 // Limit on on user
1618 if (empty($search_user)) {
1619 $search_user = $user->id;
1620 }
1621 if ($search_user > 0) {
1622 $sql .= " AND t.fk_user = " . ((int) $search_user);
1623 }
1624 }
1625
1626 if ($search_note) {
1627 $sql .= natural_search('t.note', $search_note);
1628 }
1629 if ($search_task_ref) {
1630 $sql .= natural_search('pt.ref', $search_task_ref);
1631 }
1632 if (empty($arrayfields['s.name_alias']['checked']) && $search_company) {
1633 $sql .= natural_search(array("s.nom", "s.name_alias"), $search_company);
1634 } else {
1635 if ($search_company) {
1636 $sql .= natural_search('s.nom', $search_company);
1637 }
1638 if ($search_company_alias) {
1639 $sql .= natural_search('s.name_alias', $search_company_alias);
1640 }
1641 }
1642 if ($search_project_ref) {
1643 $sql .= natural_search('p.ref', $search_project_ref);
1644 }
1645 if ($search_project_label) {
1646 $sql .= natural_search('p.title', $search_project_label);
1647 }
1648 if ($search_task_label) {
1649 $sql .= natural_search('pt.label', $search_task_label);
1650 }
1651 if ($search_user > 0) {
1652 $sql .= natural_search('t.fk_user', $search_user, 2);
1653 }
1654 if (!empty($search_product_ref)) {
1655 $sql .= natural_search('prod.ref', $search_product_ref);
1656 }
1657 if ($search_valuebilled == '1') {
1658 $sql .= ' AND t.invoice_id > 0';
1659 }
1660 if ($search_valuebilled == '0') {
1661 $sql .= ' AND (t.invoice_id = 0 OR t.invoice_id IS NULL)';
1662 }
1663
1664 if ($search_date_start) {
1665 $sql .= " AND t.element_date >= '".$db->idate($search_date_start)."'";
1666 }
1667 if ($search_date_end) {
1668 $sql .= " AND t.element_date <= '".$db->idate($search_date_end)."'";
1669 }
1670
1671 if (!empty($arrayfields['t.element_duration']['checked'])) {
1672 if ($search_timespent_starthour || $search_timespent_startmin) {
1673 $timespent_duration_start = $search_timespent_starthour * 60 * 60; // We store duration in seconds
1674 $timespent_duration_start += ($search_timespent_startmin ? $search_timespent_startmin : 0) * 60; // We store duration in seconds
1675 $sql .= " AND t.element_duration >= " . $timespent_duration_start;
1676 }
1677
1678 if ($search_timespent_endhour || $search_timespent_endmin) {
1679 $timespent_duration_end = $search_timespent_endhour * 60 * 60; // We store duration in seconds
1680 $timespent_duration_end += ($search_timespent_endmin ? $search_timespent_endmin : 0) * 60; // We store duration in seconds
1681 $sql .= " AND t.element_duration <= " . $timespent_duration_end;
1682 }
1683 }
1684
1685 $sql .= dolSqlDateFilter('t.element_datehour', $search_day, $search_month, $search_year);
1686
1687 // Add where from hooks
1688 $parameters = array();
1689 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1690 $sql .= $hookmanager->resPrint;
1691
1692 // Count total nb of records
1693 $nbtotalofrecords = '';
1694 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
1695 /* The fast and low memory method to get and count full list converts the sql into a sql count */
1696 $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql);
1697 $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount);
1698 $resql = $db->query($sqlforcount);
1699 if ($resql) {
1700 $objforcount = $db->fetch_object($resql);
1701 $nbtotalofrecords = $objforcount->nbtotalofrecords;
1702 } else {
1703 dol_print_error($db);
1704 }
1705
1706 if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 0
1707 $page = 0;
1708 $offset = 0;
1709 }
1710 $db->free($resql);
1711 }
1712
1713 // Complete request and execute it with limit
1714 $sql .= $db->order($sortfield, $sortorder);
1715 if ($limit) {
1716 $sql .= $db->plimit($limit + 1, $offset);
1717 }
1718
1719 $resql = $db->query($sql);
1720 if (!$resql) {
1721 dol_print_error($db);
1722 exit;
1723 }
1724
1725 $num = $db->num_rows($resql);
1726
1727 if ($num >= 0) {
1728 if (!empty($projectidforalltimes)) {
1729 print '<!-- List of time spent for project -->' . "\n";
1730
1731 $title = $langs->trans("ListTaskTimeUserProject");
1732
1733 print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'clock', 0, $linktocreatetime, '', $limit, 0, 0, 1);
1734 } else {
1735 print '<!-- List of time spent -->' . "\n";
1736
1737 $title = $langs->trans("ListTaskTimeForTask");
1738
1739 print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'clock', 0, $linktocreatetime, '', $limit, 0, 0, 1);
1740 }
1741
1742 $i = 0;
1743 while ($i < $num) {
1744 $row = $db->fetch_object($resql);
1745 $tasks[$i] = $row;
1746 $i++;
1747 }
1748 $db->free($resql);
1749 } else {
1750 dol_print_error($db);
1751 }
1752
1753 /*
1754 * Form to add a new line of time spent
1755 */
1756 if ($action == 'createtime' && $user->hasRight('projet', 'time')) {
1757 print '<!-- table to add time spent -->' . "\n";
1758 if (!empty($id)) {
1759 print '<input type="hidden" name="taskid" value="' . $id . '">';
1760 }
1761
1762 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
1763 print '<table class="noborder nohover centpercent">';
1764
1765 print '<tr class="liste_titre">';
1766 print '<td>' . $langs->trans("Date") . '</td>';
1767 if (!empty($allprojectforuser)) {
1768 print '<td>' . $langs->trans("Project") . '</td>';
1769 }
1770 if (empty($id)) {
1771 print '<td>' . $langs->trans("Task") . '</td>';
1772 }
1773 print '<td>' . $langs->trans("By") . '</td>';
1774 print '<td>' . $langs->trans("Note") . '</td>';
1775 print '<td>' . $langs->trans("NewTimeSpent") . '</td>';
1776 print '<td>' . $langs->trans("ProgressDeclared") . '</td>';
1777 if (!getDolGlobalString('PROJECT_HIDE_TASKS') && getDolGlobalString('PROJECT_BILL_TIME_SPENT')) {
1778 print '<td></td>';
1779
1780 if (isModEnabled("service") && !empty($projectstatic->thirdparty) && $projectstatic->thirdparty->id > 0 && $projectstatic->usage_bill_time) {
1781 print '<td>'.$langs->trans("Product").'</td>';
1782 }
1783 }
1784 // Hook fields
1785 $parameters = array('mode' => 'create');
1786 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1787 print $hookmanager->resPrint;
1788 print '<td></td>';
1789 print "</tr>\n";
1790
1791 print '<tr class="oddeven nohover">';
1792
1793 // Date
1794 print '<td class="maxwidthonsmartphone">';
1795 $newdate = '';
1796 print $form->selectDate($newdate, 'time', ($conf->browser->layout == 'phone' ? 2 : 1), 1, 2, "timespent_date", 1, 0);
1797 print '</td>';
1798
1799 if (!empty($allprojectforuser)) {
1800 print '<td>';
1801 // Add project selector
1802 print '</td>';
1803 }
1804
1805 // Task
1806 $nboftasks = 0;
1807 if (empty($id)) {
1808 print '<td class="maxwidthonsmartphone">';
1809 $nboftasks = $formproject->selectTasks(-1, GETPOSTINT('taskid'), 'taskid', 0, 0, 1, 1, 0, 0, 'maxwidth300', $projectstatic->id, 'progress');
1810 print '</td>';
1811 }
1812
1813 // Contributor
1814 print '<td class="maxwidthonsmartphone nowraponall">';
1815 $contactsofproject = $projectstatic->getListContactId('internal');
1816 if (count($contactsofproject) > 0) {
1817 print img_object('', 'user', 'class="hideonsmartphone"');
1818 if (in_array($user->id, $contactsofproject)) {
1819 $userid = $user->id;
1820 } else {
1821 $userid = $contactsofproject[0];
1822 }
1823
1824 if ($projectstatic->public) {
1825 $contactsofproject = array();
1826 }
1827 print $form->select_dolusers((GETPOSTINT('userid') ? GETPOSTINT('userid') : $userid), 'userid', 0, '', 0, '', $contactsofproject, 0, 0, 0, '', 0, $langs->trans("ResourceNotAssignedToProject"), 'minwidth150imp maxwidth200');
1828 } else {
1829 if ($nboftasks) {
1830 print img_error($langs->trans('FirstAddRessourceToAllocateTime')) . ' ' . $langs->trans('FirstAddRessourceToAllocateTime');
1831 }
1832 }
1833 print '</td>';
1834
1835 // Note
1836 print '<td>';
1837 print '<textarea name="timespent_note" class="maxwidth100onsmartphone" rows="' . ROWS_2 . '">' . (GETPOST('timespent_note') ? GETPOST('timespent_note') : '') . '</textarea>';
1838 print '</td>';
1839
1840 // Duration - Time spent
1841 print '<td class="nowraponall">';
1842 $durationtouse = (GETPOST('timespent_duration') ? GETPOST('timespent_duration') : '');
1843 if (GETPOSTISSET('timespent_durationhour') || GETPOSTISSET('timespent_durationmin')) {
1844 $durationtouse = ((int) GETPOST('timespent_durationhour') * 3600 + (int) GETPOST('timespent_durationmin') * 60);
1845 }
1846 print $form->select_duration('timespent_duration', $durationtouse, 0, 'text');
1847 print '</td>';
1848
1849 // Progress declared
1850 print '<td class="nowrap">';
1851 print $formother->select_percent(GETPOST('progress') ? GETPOST('progress') : $object->progress, 'progress', 0, 5, 0, 100, 1);
1852 print '</td>';
1853
1854 // Invoiced
1855 if (!getDolGlobalString('PROJECT_HIDE_TASKS') && getDolGlobalString('PROJECT_BILL_TIME_SPENT')) {
1856 print '<td>';
1857 print '</td>';
1858
1859 if (isModEnabled("service") && !empty($projectstatic->thirdparty) && $projectstatic->thirdparty->id > 0 && $projectstatic->usage_bill_time) {
1860 print '<td class="nowraponall">';
1861 print img_picto('', 'service');
1862 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);
1863 print '</td>';
1864 }
1865 }
1866
1867 // Fields from hook
1868 $parameters = array('mode' => 'create');
1869 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1870 print $hookmanager->resPrint;
1871
1872 print '<td class="center">';
1873 $form->buttonsSaveCancel();
1874 print '<input type="submit" name="save" class="button buttongen smallpaddingimp marginleftonly margintoponlyshort marginbottomonlyshort button-add reposition" value="'.$langs->trans("Add").'">';
1875 print '<input type="submit" name="cancel" class="button buttongen smallpaddingimp marginleftonly margintoponlyshort marginbottomonlyshort button-cancel" value="'.$langs->trans("Cancel").'">';
1876 print '</td></tr>';
1877
1878 print '</table>';
1879 print '</div>';
1880
1881 print '<br>';
1882 }
1883
1884 $moreforfilter = '';
1885
1886 $parameters = array();
1887 $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1888 if (empty($reshook)) {
1889 $moreforfilter .= $hookmanager->resPrint;
1890 } else {
1891 $moreforfilter = $hookmanager->resPrint;
1892 }
1893
1894 if (!empty($moreforfilter)) {
1895 print '<div class="liste_titre liste_titre_bydiv centpercent">';
1896 print $moreforfilter;
1897 print '</div>';
1898 }
1899
1900 $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
1901 $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')); // This also change content of $arrayfields
1902 $selectedfields .= (is_array($arrayofmassactions) && count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
1903
1904 print '<div class="div-table-responsive">';
1905 print '<table class="tagtable nobottomiftotal liste' . ($moreforfilter ? " listwithfilterbefore" : "") . '">' . "\n";
1906
1907 // Fields title search
1908 // --------------------------------------------------------------------
1909 print '<tr class="liste_titre_filter">';
1910 // Action column
1911 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1912 print '<td class="liste_titre center">';
1913 $searchpicto = $form->showFilterButtons('left');
1914 print $searchpicto;
1915 print '</td>';
1916 }
1917 // Date
1918 if (!empty($arrayfields['t.element_date']['checked'])) {
1919 print '<td class="liste_titre left">';
1920 print '<div class="nowrapfordate">';
1921 print $form->selectDate($search_date_start ? $search_date_start : -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
1922 print '</div>';
1923 print '<div class="nowrapfordate">';
1924 print $form->selectDate($search_date_end ? $search_date_end : -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
1925 print '</div>';
1926 print '</td>';
1927 }
1928 // Thirdparty
1929 if (!empty($arrayfields['p.fk_soc']['checked'])) {
1930 print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="$search_company" value="' . dol_escape_htmltag($search_company) . '"></td>';
1931 }
1932
1933 // Thirdparty alias
1934 if (!empty($arrayfields['s.name_alias']['checked'])) {
1935 print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="$search_company_alias" value="' . dol_escape_htmltag($search_company_alias) . '"></td>';
1936 }
1937
1938 if (!empty($allprojectforuser)) {
1939 if (!empty($arrayfields['p.project_ref']['checked'])) {
1940 print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="$search_project_ref" value="' . dol_escape_htmltag($search_project_ref) . '"></td>';
1941 }
1942 if (!empty($arrayfields['p.project_label']['checked'])) {
1943 print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="$search_project_label" value="' . dol_escape_htmltag($search_project_label) . '"></td>';
1944 }
1945 }
1946 // Task
1947 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
1948 if (!empty($arrayfields['t.element_ref']['checked'])) {
1949 print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="search_task_ref" value="'.dol_escape_htmltag($search_task_ref).'"></td>';
1950 }
1951 if (!empty($arrayfields['t.element_label']['checked'])) {
1952 print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="search_task_label" value="'.dol_escape_htmltag($search_task_label).'"></td>';
1953 }
1954 }
1955 // Author
1956 if (!empty($arrayfields['author']['checked'])) {
1957 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>';
1958 }
1959 // Note
1960 if (!empty($arrayfields['t.note']['checked'])) {
1961 print '<td class="liste_titre"><input type="text" class="flat maxwidth75" name="search_note" value="' . dol_escape_htmltag($search_note) . '"></td>';
1962 }
1963 // Duration
1964 if (!empty($arrayfields['t.element_duration']['checked'])) {
1965 // Duration - Time spent
1966 print '<td class="liste_titre right">';
1967
1968 $durationtouse_start = '';
1969 if ($search_timespent_starthour || $search_timespent_startmin) {
1970 $durationtouse_start = ($search_timespent_starthour * 3600 + $search_timespent_startmin * 60);
1971 }
1972 print '<div class="nowraponall">' . $langs->trans('from') . ' ';
1973 print $form->select_duration('search_timespent_duration_start', $durationtouse_start, 0, 'text', 0, 1);
1974 print '</div>';
1975
1976 $durationtouse_end = '';
1977 if ($search_timespent_endhour || $search_timespent_endmin) {
1978 $durationtouse_end = ($search_timespent_endhour * 3600 + $search_timespent_endmin * 60);
1979 }
1980 print '<div class="nowraponall">' . $langs->trans('to') . ' ';
1981 print $form->select_duration('search_timespent_duration_end', $durationtouse_end, 0, 'text', 0, 1);
1982 print '</div>';
1983
1984 print '</td>';
1985 }
1986 // Product
1987 if (!empty($arrayfields['t.fk_product']['checked'])) {
1988 print '<td class="liste_titre right"></td>';
1989 }
1990 // Value in main currency
1991 if (!empty($arrayfields['value']['checked'])) {
1992 print '<td class="liste_titre"></td>';
1993 }
1994 // Value billed
1995 if (!empty($arrayfields['valuebilled']['checked'])) {
1996 print '<td class="liste_titre center">' . $form->selectyesno('search_valuebilled', $search_valuebilled, 1, false, 1) . '</td>';
1997 }
1998
1999 /*
2000 // Extra fields
2001 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
2002 */
2003 // Fields from hook
2004 $parameters = array('arrayfields' => $arrayfields);
2005 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2006 print $hookmanager->resPrint;
2007 // Action column
2008 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2009 print '<td class="liste_titre center">';
2010 $searchpicto = $form->showFilterButtons();
2011 print $searchpicto;
2012 print '</td>';
2013 }
2014 print '</tr>' . "\n";
2015
2016
2017 $totalarray = array();
2018 $totalarray['nbfield'] = 0;
2019
2020 // Fields title label
2021 // --------------------------------------------------------------------
2022 print '<tr class="liste_titre">';
2023 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2024 print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
2025 $totalarray['nbfield']++;
2026 }
2027 if (!empty($arrayfields['t.element_date']['checked'])) {
2028 print_liste_field_titre($arrayfields['t.element_date']['label'], $_SERVER['PHP_SELF'], 't.element_date,t.element_datehour,t.rowid', '', $param, '', $sortfield, $sortorder);
2029 $totalarray['nbfield']++;
2030 }
2031 if (!empty($arrayfields['p.fk_soc']['checked'])) {
2032 print_liste_field_titre($arrayfields['p.fk_soc']['label'], $_SERVER['PHP_SELF'], 't.element_date,t.element_datehour,t.rowid', '', $param, '', $sortfield, $sortorder);
2033 $totalarray['nbfield']++;
2034 }
2035 if (!empty($arrayfields['s.name_alias']['checked'])) {
2036 // @phan-suppress-next-line PhanTypeInvalidDimOffset
2037 print_liste_field_titre($arrayfields['s.name_alias']['label'], $_SERVER['PHP_SELF'], 's.name_alias', '', $param, '', $sortfield, $sortorder);
2038 $totalarray['nbfield']++;
2039 }
2040 if (!empty($allprojectforuser)) {
2041 if (!empty($arrayfields['p.project_ref']['checked'])) {
2042 print_liste_field_titre("Project", $_SERVER['PHP_SELF'], 'p.ref', '', $param, '', $sortfield, $sortorder);
2043 $totalarray['nbfield']++;
2044 }
2045 if (!empty($arrayfields['p.project_label']['checked'])) {
2046 print_liste_field_titre("ProjectLabel", $_SERVER['PHP_SELF'], 'p.title', '', $param, '', $sortfield, $sortorder);
2047 $totalarray['nbfield']++;
2048 }
2049 }
2050 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2051 if (!empty($arrayfields['t.element_ref']['checked'])) {
2052 print_liste_field_titre($arrayfields['t.element_ref']['label'], $_SERVER['PHP_SELF'], 'pt.ref', '', $param, '', $sortfield, $sortorder);
2053 $totalarray['nbfield']++;
2054 }
2055 if (!empty($arrayfields['t.element_label']['checked'])) {
2056 print_liste_field_titre($arrayfields['t.element_label']['label'], $_SERVER['PHP_SELF'], 'pt.label', '', $param, '', $sortfield, $sortorder);
2057 $totalarray['nbfield']++;
2058 }
2059 }
2060 if (!empty($arrayfields['author']['checked'])) {
2061 print_liste_field_titre($arrayfields['author']['label'], $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder);
2062 $totalarray['nbfield']++;
2063 }
2064 if (!empty($arrayfields['t.note']['checked'])) {
2065 print_liste_field_titre($arrayfields['t.note']['label'], $_SERVER['PHP_SELF'], 't.note', '', $param, '', $sortfield, $sortorder);
2066 $totalarray['nbfield']++;
2067 }
2068 if (!empty($arrayfields['t.element_duration']['checked'])) {
2069 print_liste_field_titre($arrayfields['t.element_duration']['label'], $_SERVER['PHP_SELF'], 't.element_duration', '', $param, '', $sortfield, $sortorder, 'right ');
2070 $totalarray['nbfield']++;
2071 }
2072 if (!empty($arrayfields['t.fk_product']['checked'])) {
2073 print_liste_field_titre($arrayfields['t.fk_product']['label'], $_SERVER['PHP_SELF'], 't.fk_product', '', $param, '', $sortfield, $sortorder);
2074 $totalarray['nbfield']++;
2075 }
2076
2077 if (!empty($arrayfields['value']['checked'])) {
2078 print_liste_field_titre($arrayfields['value']['label'], $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder, 'right ');
2079 $totalarray['nbfield']++;
2080 }
2081 if (!empty($arrayfields['valuebilled']['checked'])) {
2082 print_liste_field_titre($arrayfields['valuebilled']['label'], $_SERVER['PHP_SELF'], 'il.total_ht', '', $param, '', $sortfield, $sortorder, 'center ', $langs->trans("SelectLinesOfTimeSpentToInvoice"));
2083 $totalarray['nbfield']++;
2084 }
2085 /*
2086 // Extra fields
2087 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
2088 */
2089 // Hook fields
2090 $parameters = array('arrayfields' => $arrayfields, 'param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder);
2091 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2092 print $hookmanager->resPrint;
2093 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2094 print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', 'width="80"', $sortfield, $sortorder, 'center maxwidthsearch ');
2095 $totalarray['nbfield']++;
2096 }
2097 print "</tr>\n";
2098
2099 $tasktmp = new Task($db);
2100 $tmpinvoice = new Facture($db);
2101
2102 if ($page) {
2103 $param .= '&page='.((int) $page);
2104 }
2105 $param .= '&sortfield='.urlencode($sortfield).'&sortorder='.urlencode($sortorder);
2106
2107 $i = 0;
2108
2109 $savnbfield = $totalarray['nbfield'];
2110 $totalarray = array();
2111 $totalarray['nbfield'] = 0;
2112 //$imaxinloop = ($limit ? min($num, $limit) : $num);
2113 foreach ($tasks as $task_time) {
2114 if ($i >= $limit) {
2115 break;
2116 }
2117
2118 $date1 = $db->jdate($task_time->element_date);
2119 $date2 = $db->jdate($task_time->element_datehour);
2120
2121 // Show here line of result
2122 $j = 0;
2123 print '<tr data-rowid="'.$task_time->rowid.'" class="oddeven">';
2124
2125 // Action column
2126 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2127 print '<td class="center nowraponall">';
2128 if (($action == 'editline' || $action == 'splitline') && GETPOSTINT('lineid') == $task_time->rowid) {
2129 print '<input type="hidden" name="lineid" value="' . GETPOSTINT('lineid') . '">';
2130 print '<input type="submit" class="button buttongen smallpaddingimp margintoponlyshort marginbottomonlyshort button-save" name="save" value="'.$langs->trans("Save").'">';
2131 print '<br>';
2132 print '<input type="submit" class="button buttongen smallpaddingimp margintoponlyshort marginbottomonlyshort button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
2133 } elseif ($user->hasRight('projet', 'time') || $user->hasRight('projet', 'all', 'creer')) { // Read project and enter time consumed on assigned tasks
2134 if (in_array($task_time->fk_user, $childids) || $user->hasRight('projet', 'all', 'creer')) {
2135 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' : '').'">';
2136 print img_edit('default', 0, 'class="pictofixedwidth paddingleft"');
2137 print '</a>';
2138
2139 if (getDolGlobalString('PROJECT_ALLOW_SPLIT_TIMESPENT')) {
2140 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' : '') . '">';
2141 print img_split('', 'class="pictofixedwidth paddingleft"');
2142 print '</a>';
2143 }
2144
2145 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' : '').'">';
2146 print img_delete('default', 'class="pictodelete paddingleft"');
2147 print '</a>';
2148
2149 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
2150 $selected = 0;
2151 if (in_array($task_time->rowid, $arrayofselected)) {
2152 $selected = 1;
2153 }
2154 print '&nbsp;';
2155 print '<input id="cb' . $task_time->rowid . '" class="flat checkforselect marginleftonly" type="checkbox" name="toselect[]" value="' . $task_time->rowid . '"' . ($selected ? ' checked="checked"' : '') . '>';
2156 }
2157 }
2158 }
2159 print '</td>';
2160 if (!$i) {
2161 $totalarray['nbfield']++;
2162 }
2163 }
2164
2165 // Date
2166 if (!empty($arrayfields['t.element_date']['checked'])) {
2167 print '<td class="nowrap">';
2168 if ($action == 'editline' && GETPOSTINT('lineid') == $task_time->rowid) {
2169 if (empty($task_time->element_date_withhour)) {
2170 print $form->selectDate(($date2 ? $date2 : $date1), 'timeline', 4, 3, 2, "timespent_date", 1, 0);
2171 } else {
2172 print $form->selectDate(($date2 ? $date2 : $date1), 'timeline', 2, 1, 2, "timespent_date", 1, 0);
2173 }
2174 } else {
2175 print dol_print_date(($date2 ? $date2 : $date1), ($task_time->element_date_withhour ? 'dayhour' : 'day'));
2176 }
2177 print '</td>';
2178 if (!$i) {
2179 $totalarray['nbfield']++;
2180 }
2181 }
2182
2183 // Thirdparty
2184 if (!empty($arrayfields['p.fk_soc']['checked'])) {
2185 print '<td class="tdoverflowmax125">';
2186 if ($task_time->fk_soc > 0) {
2187 if (empty($conf->cache['thridparty'][$task_time->fk_soc])) {
2188 $tmpsociete = new Societe($db);
2189 $tmpsociete->fetch($task_time->fk_soc);
2190 $conf->cache['thridparty'][$task_time->fk_soc] = $tmpsociete;
2191 } else {
2192 $tmpsociete = $conf->cache['thridparty'][$task_time->fk_soc];
2193 }
2194 print $tmpsociete->getNomUrl(1, '', 100, 0, 1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1);
2195 }
2196 print '</td>';
2197 if (!$i) {
2198 $totalarray['nbfield']++;
2199 }
2200 }
2201
2202 // Thirdparty alias
2203 if (!empty($arrayfields['s.name_alias']['checked'])) {
2204 if ($task_time->fk_soc > 0) {
2205 if (empty($conf->cache['thridparty'][$task_time->fk_soc])) {
2206 $tmpsociete = new Societe($db);
2207 $tmpsociete->fetch($task_time->fk_soc);
2208 $conf->cache['thridparty'][$task_time->fk_soc] = $tmpsociete;
2209 } else {
2210 $tmpsociete = $conf->cache['thridparty'][$task_time->fk_soc];
2211 }
2212 $valtoshow = $tmpsociete->name_alias;
2213 }
2214 print '<td class="nowrap tdoverflowmax150" title="'.dol_escape_htmltag($valtoshow).'">';
2215 print $valtoshow;
2216 print '</td>';
2217 if (!$i) {
2218 $totalarray['nbfield']++;
2219 }
2220 }
2221
2222 // Project ref & label
2223 if (!empty($allprojectforuser)) {
2224 if (!empty($arrayfields['p.project_ref']['checked'])) {
2225 print '<td class="nowraponall">';
2226 if (empty($conf->cache['project'][$task_time->fk_projet])) {
2227 $tmpproject = new Project($db);
2228 $tmpproject->fetch($task_time->fk_projet);
2229 $conf->cache['project'][$task_time->fk_projet] = $tmpproject;
2230 } else {
2231 $tmpproject = $conf->cache['project'][$task_time->fk_projet];
2232 }
2233 print $tmpproject->getNomUrl(1);
2234 print '</td>';
2235 if (!$i) {
2236 $totalarray['nbfield']++;
2237 }
2238 }
2239 if (!empty($arrayfields['p.project_label']['checked'])) {
2240 if (empty($conf->cache['project'][$task_time->fk_projet])) {
2241 $tmpproject = new Project($db);
2242 $tmpproject->fetch($task_time->fk_projet);
2243 $conf->cache['project'][$task_time->fk_projet] = $tmpproject;
2244 } else {
2245 $tmpproject = $conf->cache['project'][$task_time->fk_projet];
2246 }
2247 print '<td class="tdoverflowmax250" title="'.dol_escape_htmltag($tmpproject->title).'">';
2248 print dol_escape_htmltag($tmpproject->title);
2249 print '</td>';
2250 if (!$i) {
2251 $totalarray['nbfield']++;
2252 }
2253 }
2254 }
2255
2256 // Task ref
2257 if (!empty($arrayfields['t.element_ref']['checked'])) {
2258 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2259 print '<td class="nowrap">';
2260 if ($action == 'editline' && GETPOSTINT('lineid') == $task_time->rowid) {
2261 $formproject->selectTasks(-1, GETPOSTINT('taskid') ? GETPOSTINT('taskid') : $task_time->fk_element, 'taskid', 0, 0, 1, 1, 0, 0, 'maxwidth250', $projectstatic->id, '');
2262 } else {
2263 $tasktmp->id = $task_time->fk_element;
2264 $tasktmp->ref = $task_time->ref;
2265 $tasktmp->label = $task_time->label;
2266 print $tasktmp->getNomUrl(1, 'withproject', 'time');
2267 }
2268 print '</td>';
2269 if (!$i) {
2270 $totalarray['nbfield']++;
2271 }
2272 }
2273 } elseif ($action !== 'createtime') {
2274 print '<input type="hidden" name="taskid" value="' . $id . '">';
2275 }
2276
2277 // Task label
2278 if (!empty($arrayfields['t.element_label']['checked'])) {
2279 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2280 print '<td class="tdoverflowmax250" title="'.dol_escape_htmltag($task_time->label).'">';
2281 print dol_escape_htmltag($task_time->label);
2282 print '</td>';
2283 if (!$i) {
2284 $totalarray['nbfield']++;
2285 }
2286 }
2287 }
2288
2289 // By User
2290 if (!empty($arrayfields['author']['checked'])) {
2291 print '<td class="minwidth100 tdoverflowmax125">';
2292 if ($action == 'editline' && GETPOSTINT('lineid') == $task_time->rowid) {
2293 // Here $object is task. TODO Add a cache
2294 if (empty($object->id)) {
2295 $object->fetch($task_time->fk_element);
2296 }
2297 $contactsoftask = $object->getListContactId('internal');
2298 if (!in_array($task_time->fk_user, $contactsoftask)) {
2299 $contactsoftask[] = $task_time->fk_user;
2300 }
2301 if (count($contactsoftask) > 0) {
2302 print img_object('', 'user', 'class="pictofixedwidth hideonsmartphone"');
2303 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
2304 } else {
2305 print img_error($langs->trans('FirstAddRessourceToAllocateTime')) . $langs->trans('FirstAddRessourceToAllocateTime');
2306 }
2307 } else {
2308 $userstatic->id = $task_time->fk_user;
2309 $userstatic->lastname = $task_time->lastname;
2310 $userstatic->firstname = $task_time->firstname;
2311 $userstatic->photo = $task_time->photo;
2312 $userstatic->gender = $task_time->gender;
2313 $userstatic->status = $task_time->user_status;
2314
2315 print $userstatic->getNomUrl(-1);
2316 }
2317 print '</td>';
2318 if (!$i) {
2319 $totalarray['nbfield']++;
2320 }
2321 }
2322
2323 // Note
2324 if (!empty($arrayfields['t.note']['checked'])) {
2325 if ($action == 'editline' && GETPOSTINT('lineid') == $task_time->rowid) {
2326 print '<td class="small">';
2327 print '<textarea name="timespent_note_line" width="95%" rows="' . ROWS_1 . '">' . dol_escape_htmltag($task_time->note, 0, 1) . '</textarea>';
2328 print '</td>';
2329 } else {
2330 print '<td class="small tdoverflowmax150 classfortooltip" title="'.dol_string_onlythesehtmltags(dol_htmlentitiesbr($task_time->note)).'">';
2331 print dolGetFirstLineOfText($task_time->note);
2332 print '</td>';
2333 }
2334 if (!$i) {
2335 $totalarray['nbfield']++;
2336 }
2337 } elseif ($action == 'editline' && GETPOSTINT('lineid') == $task_time->rowid) {
2338 print '<input type="hidden" name="timespent_note_line" value="' . dol_escape_htmltag($task_time->note, 0, 1) . '">';
2339 }
2340
2341 // Time spent
2342 if (!empty($arrayfields['t.element_duration']['checked'])) {
2343 print '<td class="right nowraponall">';
2344 if ($action == 'editline' && GETPOSTINT('lineid') == $task_time->rowid) {
2345 print '<input type="hidden" name="old_duration" value="'.$task_time->element_duration.'">';
2346 print $form->select_duration('new_duration', $task_time->element_duration, 0, 'text');
2347 } else {
2348 print convertSecondToTime($task_time->element_duration, 'allhourmin');
2349 }
2350 print '</td>';
2351 if (!$i) {
2352 $totalarray['nbfield']++;
2353 }
2354 if (!$i) {
2355 $totalarray['pos'][$totalarray['nbfield']] = 't.element_duration';
2356 }
2357 if (empty($totalarray['val']['t.element_duration'])) {
2358 $totalarray['val']['t.element_duration'] = $task_time->element_duration;
2359 } else {
2360 $totalarray['val']['t.element_duration'] += $task_time->element_duration;
2361 }
2362 if (!$i) {
2363 $totalarray['totaldurationfield'] = $totalarray['nbfield'];
2364 }
2365 if (empty($totalarray['totalduration'])) {
2366 $totalarray['totalduration'] = $task_time->element_duration;
2367 } else {
2368 $totalarray['totalduration'] += $task_time->element_duration;
2369 }
2370 }
2371
2372 // Product
2373 if (!empty($arrayfields['t.fk_product']['checked'])) {
2374 print '<td class="nowraponall">';
2375 if ($action == 'editline' && GETPOSTINT('lineid') == $task_time->rowid) {
2376 print img_picto('', 'service');
2377 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);
2378 } elseif (!empty($task_time->fk_product)) {
2379 $product = new Product($db);
2380 $resultFetch = $product->fetch($task_time->fk_product);
2381 if ($resultFetch < 0) {
2382 setEventMessages($product->error, $product->errors, 'errors');
2383 } else {
2384 print $product->getNomUrl(1);
2385 }
2386 }
2387 print '</td>';
2388 if (!$i) {
2389 $totalarray['nbfield']++;
2390 }
2391 }
2392
2393 // Value spent
2394 if (!empty($arrayfields['value']['checked'])) {
2395 $langs->load("salaries");
2396 $value = price2num($task_time->thm * $task_time->element_duration / 3600, 'MT', 1);
2397
2398 print '<td class="nowraponall right">';
2399 print '<span class="amount" title="' . $langs->trans("THM") . ': ' . price($task_time->thm) . '">';
2400 print price($value, 1, $langs, 1, -1, -1, $conf->currency);
2401 print '</span>';
2402 print '</td>';
2403 if (!$i) {
2404 $totalarray['nbfield']++;
2405 }
2406 if (!$i) {
2407 $totalarray['pos'][$totalarray['nbfield']] = 'value';
2408 }
2409 if (empty($totalarray['val']['value'])) {
2410 $totalarray['val']['value'] = $value;
2411 } else {
2412 $totalarray['val']['value'] += $value;
2413 }
2414 if (!$i) {
2415 $totalarray['totalvaluefield'] = $totalarray['nbfield'];
2416 }
2417 if (empty($totalarray['totalvalue'])) {
2418 $totalarray['totalvalue'] = $value;
2419 } else {
2420 $totalarray['totalvalue'] += $value;
2421 }
2422 }
2423
2424 // Invoiced
2425 $invoiced = false;
2426 if (!empty($arrayfields['valuebilled']['checked'])) {
2427 print '<td class="center">'; // invoice_id and invoice_line_id
2428 if (!getDolGlobalString('PROJECT_HIDE_TASKS') && getDolGlobalString('PROJECT_BILL_TIME_SPENT')) {
2429 if ($projectstatic->usage_bill_time) {
2430 if ($task_time->invoice_id) {
2431 $result = $tmpinvoice->fetch($task_time->invoice_id);
2432 if ($result > 0) {
2433 if ($action == 'editline' && GETPOSTINT('lineid') == $task_time->rowid) {
2434 print $formproject->selectInvoiceAndLine($task_time->invoice_id, $task_time->invoice_line_id, 'invoiceid', 'invoicelineid', 'maxwidth500', array('p.rowid' => $projectstatic->id));
2435 } else {
2436 print $tmpinvoice->getNomUrl(1);
2437 if (!empty($task_time->invoice_line_id)) {
2438 $invoiceLine = new FactureLigne($db);
2439 $invoiceLine->fetch($task_time->invoice_line_id);
2440 if (!empty($invoiceLine->id)) {
2441 print '<br>'.$langs->trans('Qty').':'.$invoiceLine->qty;
2442 print ' '.$langs->trans('TotalHT').':'.price($invoiceLine->total_ht);
2443 }
2444 }
2445 }
2446 }
2447 $invoiced = true;
2448 } else {
2449 if (intval($task_time->billable) == 1) {
2450 print $langs->trans("No");
2451 } else {
2452 print $langs->trans("Disabled");
2453 }
2454 }
2455 } else {
2456 print '<span class="opacitymedium">' . $langs->trans("NA") . '</span>';
2457 }
2458 }
2459 print '</td>';
2460 if (!$i) {
2461 $totalarray['nbfield']++;
2462 }
2463 }
2464
2465 /*
2466 // Extra fields
2467 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
2468 */
2469
2470 // Fields from hook
2471 $parameters = array('arrayfields' => $arrayfields, 'obj' => $task_time, 'i' => $i, 'totalarray' => &$totalarray);
2472 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2473 print $hookmanager->resPrint;
2474
2475 // Action column
2476 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2477 print '<td class="center nowraponall">';
2478 if (($action == 'editline' || $action == 'splitline') && GETPOSTINT('lineid') == $task_time->rowid) {
2479 print '<input type="hidden" name="lineid" value="'.GETPOSTINT('lineid').'">';
2480 print '<input type="submit" class="button buttongen smallpaddingimp margintoponlyshort marginbottomonlyshort button-save" name="save" value="'.$langs->trans("Save").'">';
2481 print '<br>';
2482 print '<input type="submit" class="button buttongen smallpaddingimp margintoponlyshort marginbottomonlyshort button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
2483 } elseif ($user->hasRight('projet', 'time') || $user->hasRight('projet', 'all', 'creer')) { // Read project and enter time consumed on assigned tasks
2484 if (in_array($task_time->fk_user, $childids) || $user->hasRight('projet', 'all', 'creer')) {
2485 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' : '').'">';
2486 print img_edit('default', 0, 'class="pictofixedwidth paddingleft"');
2487 print '</a>';
2488
2489 if (getDolGlobalString('PROJECT_ALLOW_SPLIT_TIMESPENT')) {
2490 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' : '') . '">';
2491 print img_split('', 'class="pictofixedwidth paddingleft"');
2492 print '</a>';
2493 }
2494
2495 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' : '').'">';
2496 print img_delete('default', 'class="pictodelete paddingleft"');
2497 print '</a>';
2498
2499 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
2500 $selected = 0;
2501 if (in_array($task_time->rowid, $arrayofselected)) {
2502 $selected = 1;
2503 }
2504 print '&nbsp;';
2505 // Disable select if task not billable or already invoiced
2506 $disabled = (intval($task_time->billable) != 1 || $invoiced);
2507 $ctrl = '<input '.($disabled ? 'disabled' : '').' id="cb' . $task_time->rowid . '" class="flat checkforselect marginleftonly" type="checkbox" name="toselect[]" value="' . $task_time->rowid . '"' . ($selected ? ' checked="checked"' : '') . '>';
2508 if ($disabled) {
2509 // If disabled, a dbl-click very close outside the control
2510 // will re-enable it, so that user is not blocked if needed.
2511 print '<span id="cbsp'. $task_time->rowid . '">'.$ctrl.'</span>';
2512 print '<script>$("#cbsp' . $task_time->rowid . '").dblclick(()=>{ $("#cb' . $task_time->rowid . '").removeAttr("disabled") })</script>';
2513 } else {
2514 print $ctrl;
2515 }
2516 }
2517 }
2518 }
2519 print '</td>';
2520 if (!$i) {
2521 $totalarray['nbfield']++;
2522 }
2523 }
2524
2525 print "</tr>\n";
2526
2527
2528 // Add the lines for the split feature
2529
2530 if ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2531 print '<!-- first line -->';
2532 print '<tr class="oddeven">';
2533
2534 // Action column
2535 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2536 print '<td></td>';
2537 }
2538
2539 // Date
2540 if (!empty($arrayfields['t.element_date']['checked'])) {
2541 print '<td class="nowrap">';
2542 if ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2543 if (empty($task_time->element_date_withhour)) {
2544 print $form->selectDate(($date2 ? $date2 : $date1), 'timeline', 3, 3, 2, "timespent_date", 1, 0);
2545 } else {
2546 print $form->selectDate(($date2 ? $date2 : $date1), 'timeline', 1, 1, 2, "timespent_date", 1, 0);
2547 }
2548 } else {
2549 print dol_print_date(($date2 ? $date2 : $date1), ($task_time->element_date_withhour ? 'dayhour' : 'day'));
2550 }
2551 print '</td>';
2552 }
2553
2554 // Thirdparty
2555 if (!empty($arrayfields['p.fk_soc']['checked'])) {
2556 print '<td class="nowrap">';
2557 print '</td>';
2558 }
2559
2560 // Thirdparty alias
2561 if (!empty($arrayfields['s.name_alias']['checked'])) {
2562 print '<td class="nowrap">';
2563 print '</td>';
2564 }
2565
2566 // Project ref
2567 if (!empty($allprojectforuser)) {
2568 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2569 print '<td class="nowrap">';
2570 print '</td>';
2571 }
2572 }
2573
2574 // Task ref
2575 if (!empty($arrayfields['t.element_ref']['checked'])) {
2576 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2577 print '<td class="nowrap">';
2578 $tasktmp->id = $task_time->fk_element;
2579 $tasktmp->ref = $task_time->ref;
2580 $tasktmp->label = $task_time->label;
2581 print $tasktmp->getNomUrl(1, 'withproject', 'time');
2582 print '</td>';
2583 }
2584 }
2585
2586 // Task label
2587 if (!empty($arrayfields['t.element_label']['checked'])) {
2588 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2589 print '<td class="tdoverflowmax300" title="'.dol_escape_htmltag($task_time->label).'">';
2590 print dol_escape_htmltag($task_time->label);
2591 print '</td>';
2592 }
2593 }
2594
2595 // User
2596 if (!empty($arrayfields['author']['checked'])) {
2597 print '<td class="nowraponall">';
2598 if ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2599 if (empty($object->id)) {
2600 $object->fetch($id);
2601 }
2602 $contactsoftask = $object->getListContactId('internal');
2603 if (!in_array($task_time->fk_user, $contactsoftask)) {
2604 $contactsoftask[] = $task_time->fk_user;
2605 }
2606 if (count($contactsoftask) > 0) {
2607 print img_object('', 'user', 'class="hideonsmartphone"');
2608 print $form->select_dolusers($task_time->fk_user, 'userid_line', 0, '', 0, '', $contactsoftask);
2609 } else {
2610 print img_error($langs->trans('FirstAddRessourceToAllocateTime')) . $langs->trans('FirstAddRessourceToAllocateTime');
2611 }
2612 } else {
2613 $userstatic->id = $task_time->fk_user;
2614 $userstatic->lastname = $task_time->lastname;
2615 $userstatic->firstname = $task_time->firstname;
2616 $userstatic->photo = $task_time->photo;
2617 $userstatic->status = $task_time->user_status;
2618 print $userstatic->getNomUrl(-1);
2619 }
2620 print '</td>';
2621 }
2622
2623 // Note
2624 if (!empty($arrayfields['t.note']['checked'])) {
2625 print '<td class="tdoverflowmax300">';
2626 if ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2627 print '<textarea name="timespent_note_line" width="95%" rows="' . ROWS_1 . '">' . dol_escape_htmltag($task_time->note, 0, 1) . '</textarea>';
2628 } else {
2629 print dol_nl2br($task_time->note);
2630 }
2631 print '</td>';
2632 } elseif ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2633 print '<input type="hidden" name="timespent_note_line" rows="' . ROWS_1 . '" value="' . dol_escape_htmltag($task_time->note, 0, 1) . '">';
2634 }
2635
2636 // Time spent
2637 if (!empty($arrayfields['t.element_duration']['checked'])) {
2638 print '<td class="right">';
2639 if ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2640 print '<input type="hidden" name="old_duration" value="'.$task_time->element_duration.'">';
2641 print $form->select_duration('new_duration', $task_time->element_duration, 0, 'text');
2642 } else {
2643 print convertSecondToTime($task_time->element_duration, 'allhourmin');
2644 }
2645 print '</td>';
2646 }
2647
2648 // Product
2649 if (!empty($arrayfields['t.fk_product']['checked'])) {
2650 print '<td class="nowraponall tdoverflowmax125">';
2651 print '</td>';
2652 }
2653
2654 // Value spent
2655 if (!empty($arrayfields['value']['checked'])) {
2656 print '<td class="right">';
2657 print '<span class="amount">';
2658 $value = price2num($task_time->thm * $task_time->element_duration / 3600, 'MT', 1);
2659 print price($value, 1, $langs, 1, -1, -1, $conf->currency);
2660 print '</span>';
2661 print '</td>';
2662 }
2663
2664 // Value billed
2665 if (!empty($arrayfields['valuebilled']['checked'])) {
2666 print '<td class="right">';
2667 $valuebilled = price2num($task_time->total_ht, '', 1);
2668 if (isset($task_time->total_ht)) {
2669 print price($valuebilled, 1, $langs, 1, -1, -1, $conf->currency);
2670 }
2671 print '</td>';
2672 }
2673
2674 /*
2675 // Extra fields
2676 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
2677 */
2678
2679 // Fields from hook
2680 $parameters = array('arrayfields' => $arrayfields, 'obj' => $task_time, 'mode' => 'split1');
2681 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2682 print $hookmanager->resPrint;
2683
2684 // Action column
2685 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2686 print '<td class="center nowraponall">';
2687 print '</td>';
2688 }
2689
2690 print "</tr>\n";
2691
2692
2693 // Line for second dispatching
2694
2695 print '<!-- second line --><tr class="oddeven">';
2696
2697 // Action column
2698 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2699 print '<td class="center nowraponall">';
2700 print '</td>';
2701 }
2702
2703 // Date
2704 if (!empty($arrayfields['t.element_date']['checked'])) {
2705 print '<td class="nowrap">';
2706 if ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2707 if (empty($task_time->element_date_withhour)) {
2708 print $form->selectDate(($date2 ? $date2 : $date1), 'timeline_2', 3, 3, 2, "timespent_date", 1, 0);
2709 } else {
2710 print $form->selectDate(($date2 ? $date2 : $date1), 'timeline_2', 1, 1, 2, "timespent_date", 1, 0);
2711 }
2712 } else {
2713 print dol_print_date(($date2 ? $date2 : $date1), ($task_time->element_date_withhour ? 'dayhour' : 'day'));
2714 }
2715 print '</td>';
2716 }
2717
2718 // Thirdparty
2719 if (!empty($arrayfields['p.fk_soc']['checked'])) {
2720 print '<td class="nowrap">';
2721 print '</td>';
2722 }
2723
2724 // Thirdparty alias
2725 if (!empty($arrayfields['s.name_alias']['checked'])) {
2726 print '<td class="nowrap">';
2727 print '</td>';
2728 }
2729
2730 // Project ref
2731 if (!empty($allprojectforuser)) {
2732 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2733 print '<td class="nowrap">';
2734 print '</td>';
2735 }
2736 }
2737
2738 // Task ref
2739 if (!empty($arrayfields['t.element_ref']['checked'])) {
2740 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2741 print '<td class="nowrap">';
2742 $tasktmp->id = $task_time->fk_element;
2743 $tasktmp->ref = $task_time->ref;
2744 $tasktmp->label = $task_time->label;
2745 print $tasktmp->getNomUrl(1, 'withproject', 'time');
2746 print '</td>';
2747 }
2748 }
2749
2750 // Task label
2751 if (!empty($arrayfields['t.element_label']['checked'])) {
2752 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2753 print '<td class="nowrap">';
2754 print dol_escape_htmltag($task_time->label);
2755 print '</td>';
2756 }
2757 }
2758
2759 // User
2760 if (!empty($arrayfields['author']['checked'])) {
2761 print '<td class="nowraponall tdoverflowmax100">';
2762 if ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2763 if (empty($object->id)) {
2764 $object->fetch($id);
2765 }
2766 $contactsoftask = $object->getListContactId('internal');
2767 if (!in_array($task_time->fk_user, $contactsoftask)) {
2768 $contactsoftask[] = $task_time->fk_user;
2769 }
2770 if (count($contactsoftask) > 0) {
2771 print img_object('', 'user', 'class="hideonsmartphone"');
2772 print $form->select_dolusers($task_time->fk_user, 'userid_line_2', 0, '', 0, '', $contactsoftask);
2773 } else {
2774 print img_error($langs->trans('FirstAddRessourceToAllocateTime')) . $langs->trans('FirstAddRessourceToAllocateTime');
2775 }
2776 } else {
2777 $userstatic->id = $task_time->fk_user;
2778 $userstatic->lastname = $task_time->lastname;
2779 $userstatic->firstname = $task_time->firstname;
2780 $userstatic->photo = $task_time->photo;
2781 $userstatic->status = $task_time->user_status;
2782 print $userstatic->getNomUrl(-1);
2783 }
2784 print '</td>';
2785 }
2786
2787 // Note
2788 if (!empty($arrayfields['t.note']['checked'])) {
2789 print '<td class="small tdoverflowmax300"">';
2790 if ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2791 print '<textarea name="timespent_note_line_2" width="95%" rows="' . ROWS_1 . '">' . dol_escape_htmltag($task_time->note, 0, 1) . '</textarea>';
2792 } else {
2793 print dol_nl2br($task_time->note);
2794 }
2795 print '</td>';
2796 } elseif ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2797 print '<input type="hidden" name="timespent_note_line_2" value="' . dol_escape_htmltag($task_time->note, 0, 1) . '">';
2798 }
2799
2800 // Time spent
2801 if (!empty($arrayfields['t.element_duration']['checked'])) {
2802 print '<td class="right">';
2803 if ($action == 'splitline' && GETPOSTINT('lineid') == $task_time->rowid) {
2804 print '<input type="hidden" name="old_duration_2" value="0">';
2805 print $form->select_duration('new_duration_2', 0, 0, 'text');
2806 } else {
2807 print convertSecondToTime($task_time->element_duration, 'allhourmin');
2808 }
2809 print '</td>';
2810 }
2811
2812 // Product
2813 if (!empty($arrayfields['t.fk_product']['checked'])) {
2814 print '<td class="nowraponall tdoverflowmax125">';
2815 print '</td>';
2816 }
2817
2818 // Value spent
2819 if (!empty($arrayfields['value']['checked'])) {
2820 print '<td class="right">';
2821 print '<span class="amount">';
2822 $value = 0;
2823 print price($value, 1, $langs, 1, -1, -1, $conf->currency);
2824 print '</span>';
2825 print '</td>';
2826 }
2827
2828 // Value billed
2829 if (!empty($arrayfields['valuebilled']['checked'])) {
2830 print '<td class="right">';
2831 $valuebilled = price2num($task_time->total_ht, '', 1);
2832 if (isset($task_time->total_ht)) {
2833 print '<span class="amount">';
2834 print price($valuebilled, 1, $langs, 1, -1, -1, $conf->currency);
2835 print '</span>';
2836 }
2837 print '</td>';
2838 }
2839
2840 /*
2841 // Extra fields
2842 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
2843 */
2844
2845 // Fields from hook
2846 $parameters = array('arrayfields' => $arrayfields, 'obj' => $task_time, 'mode' => 'split2');
2847 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2848 print $hookmanager->resPrint;
2849
2850 // Action column
2851 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2852 print '<td class="center nowraponall">';
2853 print '</td>';
2854 }
2855
2856 print "</tr>\n";
2857 }
2858
2859 $i++;
2860 }
2861
2862 // Show total line
2863 //include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
2864 if (isset($totalarray['totaldurationfield']) || isset($totalarray['totalvaluefield'])) {
2865 print '<tr class="liste_total">';
2866 $i = 0;
2867 while ($i < $totalarray['nbfield']) {
2868 $i++;
2869 if ($i == 1) {
2870 if ($num < $limit && empty($offset)) {
2871 print '<td class="left">' . $langs->trans("Total") . '</td>';
2872 } else {
2873 print '<td class="left">'.$form->textwithpicto($langs->trans("Total"), $langs->trans("Totalforthispage")).'</td>';
2874 }
2875 } elseif (isset($totalarray['totaldurationfield']) && $totalarray['totaldurationfield'] == $i) {
2876 print '<td class="right">' . convertSecondToTime($totalarray['totalduration'], 'allhourmin') . '</td>';
2877 } elseif (isset($totalarray['totalvaluefield']) && $totalarray['totalvaluefield'] == $i) {
2878 print '<td class="right">' . price($totalarray['totalvalue']) . '</td>';
2879 //} elseif ($totalarray['totalvaluebilledfield'] == $i) { print '<td class="center">'.price($totalarray['totalvaluebilled']).'</td>';
2880 } else {
2881 print '<td></td>';
2882 }
2883 }
2884 print '</tr>';
2885 }
2886
2887 if (!count($tasks)) {
2888 $totalnboffields = 1;
2889 foreach ($arrayfields as $value) {
2890 if (!empty($value['checked'])) {
2891 $totalnboffields++;
2892 }
2893 }
2894 print '<tr class="oddeven"><td colspan="' . $totalnboffields . '">';
2895 print '<span class="opacitymedium">' . $langs->trans("None") . '</span>';
2896 print '</td></tr>';
2897 }
2898
2899 $parameters = array('arrayfields' => $arrayfields, 'sql' => $sql);
2900 $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2901 print $hookmanager->resPrint;
2902
2903 print "</table>";
2904 print '</div>';
2905 print "</form>";
2906 }
2907}
2908
2909// End of page
2910llxFooter();
2911$db->close();
$id
Definition account.php:39
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($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:70
Class to manage standard extra fields.
Class to manage invoices.
Class to manage invoice lines.
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:377
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:241
llxFooter()
Footer empty.
Definition document.php:107
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)
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
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.
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 a 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.