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