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