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