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