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