dolibarr  16.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-2021 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  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <https://www.gnu.org/licenses/>.
22  */
23 
30 require '../../main.inc.php';
31 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
32 require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
33 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
34 require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
35 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
36 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
37 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
38 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formintervention.class.php';
39 
40 // Load translation files required by the page
41 $langsLoad=array('projects', 'bills', 'orders');
42 if (!empty($conf->eventorganization->enabled)) {
43  $langsLoad[]='eventorganization';
44 }
45 
46 $langs->loadLangs($langsLoad);
47 
48 $action = GETPOST('action', 'alpha');
49 $massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists)
50 $confirm = GETPOST('confirm', 'alpha');
51 $cancel = GETPOST('cancel', 'alpha');
52 $toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list
53 $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'timespentlist'; // To manage different context of search
54 $backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page
55 $optioncss = GETPOST('optioncss', 'alpha');
56 $mode = GETPOST('mode', 'alpha');
57 
58 $id = GETPOST('id', 'int');
59 $projectid = GETPOST('projectid', 'int');
60 $ref = GETPOST('ref', 'alpha');
61 $withproject = GETPOST('withproject', 'int');
62 $project_ref = GETPOST('project_ref', 'alpha');
63 $tab = GETPOST('tab', 'aZ09');
64 
65 $search_day = GETPOST('search_day', 'int');
66 $search_month = GETPOST('search_month', 'int');
67 $search_year = GETPOST('search_year', 'int');
68 $search_datehour = '';
69 $search_datewithhour = '';
70 $search_note = GETPOST('search_note', 'alpha');
71 $search_duration = GETPOST('search_duration', 'int');
72 $search_value = GETPOST('search_value', 'int');
73 $search_task_ref = GETPOST('search_task_ref', 'alpha');
74 $search_task_label = GETPOST('search_task_label', 'alpha');
75 $search_user = GETPOST('search_user', 'int');
76 $search_valuebilled = GETPOST('search_valuebilled', 'int');
77 
78 $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit;
79 $sortfield = GETPOST('sortfield', 'aZ09comma');
80 $sortorder = GETPOST('sortorder', 'aZ09comma');
81 $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
82 if (empty($page) || $page == -1) {
83  $page = 0;
84 } // If $page is not defined, or '' or -1
85 $offset = $limit * $page;
86 $pageprev = $page - 1;
87 $pagenext = $page + 1;
88 if (!$sortfield) {
89  $sortfield = 't.task_date,t.task_datehour,t.rowid';
90 }
91 if (!$sortorder) {
92  $sortorder = 'DESC,DESC,DESC';
93 }
94 
95 $childids = $user->getAllChildIds(1);
96 
97 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
98 //$object = new TaskTime($db);
99 $hookmanager->initHooks(array('projecttasktime', 'globalcard'));
100 
101 $object = new Task($db);
102 $extrafields = new ExtraFields($db);
103 $projectstatic = new Project($db);
104 
105 // fetch optionals attributes and labels
106 $extrafields->fetch_name_optionals_label($projectstatic->table_element);
107 $extrafields->fetch_name_optionals_label($object->table_element);
108 
109 // Load task
110 if ($id > 0 || $ref) {
111  $object->fetch($id, $ref);
112 }
113 
114 
115 // Security check
116 $socid = 0;
117 //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 assignement.
118 if (!$user->rights->projet->lire) {
119  accessforbidden();
120 }
121 
122 if ($object->fk_project > 0) {
123  restrictedArea($user, 'projet', $object->fk_project, 'projet&project');
124 } else {
125  restrictedArea($user, 'projet', null, 'projet&project');
126  // We check user has permission to see all tasks of all users
127  if (empty($projectid) && !$user->hasRight('projet', 'all', 'lire')) {
128  $search_user = $user->id;
129  }
130 }
131 
132 
133 
134 /*
135  * Actions
136  */
137 
138 if (GETPOST('cancel', 'alpha')) {
139  $action = '';
140 }
141 if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend' && $massaction != 'confirm_generateinvoice' && $massaction != 'confirm_generateinter') {
142  $massaction = '';
143 }
144 
145 $parameters = array('socid'=>$socid, 'projectid'=>$projectid);
146 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
147 if ($reshook < 0) {
148  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
149 }
150 
151 include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
152 
153 // Purge search criteria
154 if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
155  $search_day = '';
156  $search_month = '';
157  $search_year = '';
158  $search_date = '';
159  $search_datehour = '';
160  $search_datewithhour = '';
161  $search_note = '';
162  $search_duration = '';
163  $search_value = '';
164  $search_date_creation = '';
165  $search_date_update = '';
166  $search_task_ref = '';
167  $search_task_label = '';
168  $search_user = -1;
169  $search_valuebilled = '';
170  $toselect = array();
171  $search_array_options = array();
172  $action = '';
173 }
174 
175 if ($action == 'addtimespent' && $user->rights->projet->time) {
176  $error = 0;
177 
178  $timespent_durationhour = GETPOST('timespent_durationhour', 'int');
179  $timespent_durationmin = GETPOST('timespent_durationmin', 'int');
180  if (empty($timespent_durationhour) && empty($timespent_durationmin)) {
181  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Duration")), null, 'errors');
182  $error++;
183  }
184  if (!GETPOST("userid", 'int')) {
185  $langs->load("errors");
186  setEventMessages($langs->trans('ErrorUserNotAssignedToTask'), null, 'errors');
187  $error++;
188  }
189 
190  if (!$error) {
191  if ($id || $ref) {
192  $object->fetch($id, $ref);
193  } else {
194  if (!GETPOST('taskid', 'int') || GETPOST('taskid', 'int') < 0) {
195  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Task")), null, 'errors');
196  $action = 'createtime';
197  $error++;
198  } else {
199  $object->fetch(GETPOST('taskid', 'int'));
200  }
201  }
202 
203  if (!$error) {
204  $object->fetch_projet();
205 
206  if (empty($object->project->statut)) {
207  setEventMessages($langs->trans("ProjectMustBeValidatedFirst"), null, 'errors');
208  $action = 'createtime';
209  $error++;
210  } else {
211  $object->timespent_note = GETPOST("timespent_note", 'alpha');
212  if (GETPOST('progress', 'int') > 0) {
213  $object->progress = GETPOST('progress', 'int'); // If progress is -1 (not defined), we do not change value
214  }
215  $object->timespent_duration = GETPOSTINT("timespent_durationhour") * 60 * 60; // We store duration in seconds
216  $object->timespent_duration += (GETPOSTINT('timespent_durationmin') ? GETPOSTINT('timespent_durationmin') : 0) * 60; // We store duration in seconds
217  if (GETPOST("timehour") != '' && GETPOST("timehour") >= 0) { // If hour was entered
218  $object->timespent_date = dol_mktime(GETPOST("timehour", 'int'), GETPOST("timemin", 'int'), 0, GETPOST("timemonth", 'int'), GETPOST("timeday", 'int'), GETPOST("timeyear", 'int'));
219  $object->timespent_withhour = 1;
220  } else {
221  $object->timespent_date = dol_mktime(12, 0, 0, GETPOST("timemonth", 'int'), GETPOST("timeday", 'int'), GETPOST("timeyear", 'int'));
222  }
223  $object->timespent_fk_user = GETPOST("userid", 'int');
224  $result = $object->addTimeSpent($user);
225  if ($result >= 0) {
226  setEventMessages($langs->trans("RecordSaved"), null, 'mesgs');
227  } else {
228  setEventMessages($langs->trans($object->error), null, 'errors');
229  $error++;
230  }
231  }
232  }
233  } else {
234  if (empty($id)) {
235  $action = 'createtime';
236  } else {
237  $action = 'createtime';
238  }
239  }
240 }
241 
242 if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $user->rights->projet->lire) {
243  $error = 0;
244 
245  if (!GETPOST("new_durationhour") && !GETPOST("new_durationmin")) {
246  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Duration")), null, 'errors');
247  $error++;
248  }
249 
250  if (!$error) {
251  if (GETPOST('taskid', 'int') != $id) { // GETPOST('taskid') is id of new task
252  $id_temp = GETPOST('taskid', 'int'); // should not overwrite $id
253 
254 
255  $object->fetchTimeSpent(GETPOST('lineid', 'int'));
256 
257  $result = 0;
258  if (in_array($object->timespent_fk_user, $childids) || $user->rights->projet->all->creer) {
259  $result = $object->delTimeSpent($user);
260  }
261 
262  $object->fetch($id_temp, $ref);
263 
264  $object->timespent_note = GETPOST("timespent_note_line", "alphanohtml");
265  $object->timespent_old_duration = GETPOST("old_duration", "int");
266  $object->timespent_duration = GETPOSTINT("new_durationhour") * 60 * 60; // We store duration in seconds
267  $object->timespent_duration += (GETPOSTINT("new_durationmin") ? GETPOSTINT('new_durationmin') : 0) * 60; // We store duration in seconds
268  if (GETPOST("timelinehour") != '' && GETPOST("timelinehour") >= 0) { // If hour was entered
269  $object->timespent_date = dol_mktime(GETPOST("timelinehour"), GETPOST("timelinemin"), 0, GETPOST("timelinemonth"), GETPOST("timelineday"), GETPOST("timelineyear"));
270  $object->timespent_withhour = 1;
271  } else {
272  $object->timespent_date = dol_mktime(12, 0, 0, GETPOST("timelinemonth"), GETPOST("timelineday"), GETPOST("timelineyear"));
273  }
274  $object->timespent_fk_user = GETPOST("userid_line", 'int');
275 
276  $result = 0;
277  if (in_array($object->timespent_fk_user, $childids) || $user->rights->projet->all->creer) {
278  $result = $object->addTimeSpent($user);
279  }
280 
281  if ($result >= 0) {
282  setEventMessages($langs->trans("RecordSaved"), null, 'mesgs');
283  } else {
284  setEventMessages($langs->trans($object->error), null, 'errors');
285  $error++;
286  }
287  } else {
288  $object->fetch($id, $ref);
289 
290  $object->timespent_id = GETPOST("lineid", 'int');
291  $object->timespent_note = GETPOST("timespent_note_line", "alphanohtml");
292  $object->timespent_old_duration = GETPOST("old_duration", "int");
293  $object->timespent_duration = GETPOSTINT("new_durationhour") * 60 * 60; // We store duration in seconds
294  $object->timespent_duration += (GETPOSTINT("new_durationmin") ? GETPOSTINT('new_durationmin') : 0) * 60; // We store duration in seconds
295  if (GETPOST("timelinehour") != '' && GETPOST("timelinehour") >= 0) { // If hour was entered
296  $object->timespent_date = dol_mktime(GETPOST("timelinehour", 'int'), GETPOST("timelinemin", 'int'), 0, GETPOST("timelinemonth", 'int'), GETPOST("timelineday", 'int'), GETPOST("timelineyear", 'int'));
297  $object->timespent_withhour = 1;
298  } else {
299  $object->timespent_date = dol_mktime(12, 0, 0, GETPOST("timelinemonth", 'int'), GETPOST("timelineday", 'int'), GETPOST("timelineyear", 'int'));
300  }
301  $object->timespent_fk_user = GETPOST("userid_line", 'int');
302 
303  $result = 0;
304  if (in_array($object->timespent_fk_user, $childids) || $user->rights->projet->all->creer) {
305  $result = $object->updateTimeSpent($user);
306 
307  if ($result >= 0) {
308  setEventMessages($langs->trans("RecordSaved"), null, 'mesgs');
309  } else {
310  setEventMessages($langs->trans($object->error), null, 'errors');
311  $error++;
312  }
313  }
314  }
315  } else {
316  $action = '';
317  }
318 }
319 
320 if ($action == 'confirm_deleteline' && $confirm == "yes" && ($user->hasRight('projet', 'time') || $user->hasRight('projet', 'all', 'creer'))) {
321  $object->fetchTimeSpent(GETPOST('lineid', 'int')); // load properties like $object->timespent_id
322 
323  if (in_array($object->timespent_fk_user, $childids) || $user->hasRight('projet', 'all', 'creer')) {
324  $result = $object->delTimeSpent($user); // delete line with $object->timespent_id
325 
326  if ($result < 0) {
327  $langs->load("errors");
328  setEventMessages($langs->trans($object->error), null, 'errors');
329  $error++;
330  $action = '';
331  } else {
332  setEventMessages($langs->trans("RecordDeleted"), null, 'mesgs');
333  }
334  }
335 }
336 
337 // Retrieve First Task ID of Project if withprojet is on to allow project prev next to work
338 if (!empty($project_ref) && !empty($withproject)) {
339  if ($projectstatic->fetch(0, $project_ref) > 0) {
340  $tasksarray = $object->getTasksArray(0, 0, $projectstatic->id, $socid, 0);
341  if (count($tasksarray) > 0) {
342  $id = $tasksarray[0]->id;
343  } else {
344  header("Location: ".DOL_URL_ROOT.'/projet/tasks.php?id='.$projectstatic->id.($withproject ? '&withproject=1' : '').(empty($mode) ? '' : '&mode='.$mode));
345  exit;
346  }
347  }
348 }
349 
350 // To show all time lines for project
351 $projectidforalltimes = 0;
352 if (GETPOST('projectid', 'int') > 0) {
353  $projectidforalltimes = GETPOST('projectid', 'int');
354 
355  $result = $projectstatic->fetch($projectidforalltimes);
356  if (!empty($projectstatic->socid)) {
357  $projectstatic->fetch_thirdparty();
358  }
359  $res = $projectstatic->fetch_optionals();
360 } elseif (GETPOST('project_ref', 'alpha')) {
361  $projectstatic->fetch(0, GETPOST('project_ref', 'alpha'));
362  $projectidforalltimes = $projectstatic->id;
363  $withproject = 1;
364 } elseif ($id > 0) {
365  $object->fetch($id);
366  $result = $projectstatic->fetch($object->fk_project);
367 }
368 // If not task selected and no project selected
369 if ($id <= 0 && $projectidforalltimes == 0) {
370  $allprojectforuser = $user->id;
371 }
372 
373 if ($action == 'confirm_generateinvoice') {
374  if (!empty($projectstatic->socid)) {
375  $projectstatic->fetch_thirdparty();
376  }
377 
378  if (!($projectstatic->thirdparty->id > 0)) {
379  setEventMessages($langs->trans("ThirdPartyRequiredToGenerateInvoice"), null, 'errors');
380  } else {
381  include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
382  include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
383  include_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
384 
385  $tmpinvoice = new Facture($db);
386  $tmptimespent = new Task($db);
387  $tmpproduct = new Product($db);
388  $fuser = new User($db);
389 
390  $db->begin();
391  $idprod = GETPOST('productid', 'int');
392  $generateinvoicemode = GETPOST('generateinvoicemode', 'string');
393  $invoiceToUse = GETPOST('invoiceid', 'int');
394 
395  $prodDurationHours = 1.0;
396  if ($idprod > 0) {
397  $tmpproduct->fetch($idprod);
398 
399  if (empty($tmpproduct->duration_value)) {
400  $error++;
401  $langs->load("errors");
402  setEventMessages($langs->trans("ErrorDurationForServiceNotDefinedCantCalculateHourlyPrice"), null, 'errors');
403  }
404 
405  if ($tmpproduct->duration_unit == 'i') {
406  $prodDurationHours = 1. / 60;
407  }
408  if ($tmpproduct->duration_unit == 'h') {
409  $prodDurationHours = 1.;
410  }
411  if ($tmpproduct->duration_unit == 'd') {
412  $prodDurationHours = 24.;
413  }
414  if ($tmpproduct->duration_unit == 'w') {
415  $prodDurationHours = 24. * 7;
416  }
417  if ($tmpproduct->duration_unit == 'm') {
418  $prodDurationHours = 24. * 30;
419  }
420  if ($tmpproduct->duration_unit == 'y') {
421  $prodDurationHours = 24. * 365;
422  }
423  $prodDurationHours *= $tmpproduct->duration_value;
424 
425  $dataforprice = $tmpproduct->getSellPrice($mysoc, $projectstatic->thirdparty, 0);
426 
427  $pu_ht = empty($dataforprice['pu_ht']) ? 0 : $dataforprice['pu_ht'];
428  $txtva = $dataforprice['tva_tx'];
429  $localtax1 = $dataforprice['localtax1'];
430  $localtax2 = $dataforprice['localtax2'];
431  } else {
432  $prodDurationHours = 1;
433 
434  $pu_ht = 0;
435  $txtva = get_default_tva($mysoc, $projectstatic->thirdparty);
436  $localtax1 = get_default_localtax($mysoc, $projectstatic->thirdparty, 1);
437  $localtax2 = get_default_localtax($mysoc, $projectstatic->thirdparty, 2);
438  }
439 
440  $tmpinvoice->socid = $projectstatic->thirdparty->id;
441  $tmpinvoice->date = dol_mktime(GETPOST('rehour', 'int'), GETPOST('remin', 'int'), GETPOST('resec', 'int'), GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int'));
442  $tmpinvoice->fk_project = $projectstatic->id;
443 
444  if ($invoiceToUse) {
445  $tmpinvoice->fetch($invoiceToUse);
446  } else {
447  $result = $tmpinvoice->create($user);
448  if ($result <= 0) {
449  $error++;
450  setEventMessages($tmpinvoice->error, $tmpinvoice->errors, 'errors');
451  }
452  }
453 
454  if (!$error) {
455  if ($generateinvoicemode == 'onelineperuser') {
456  $arrayoftasks = array();
457  foreach ($toselect as $key => $value) {
458  // Get userid, timepent
459  $object->fetchTimeSpent($value);
460  $arrayoftasks[$object->timespent_fk_user]['timespent'] += $object->timespent_duration;
461  $arrayoftasks[$object->timespent_fk_user]['totalvaluetodivideby3600'] += ($object->timespent_duration * $object->timespent_thm);
462  }
463 
464  foreach ($arrayoftasks as $userid => $value) {
465  $fuser->fetch($userid);
466  $pu_ht = $fuser->thm;
467  $username = $fuser->getFullName($langs);
468 
469  // Define qty per hour
470  $qtyhour = $value['timespent'] / 3600;
471  $qtyhourtext = convertSecondToTime($value['timespent'], 'all', $conf->global->MAIN_DURATION_OF_WORKDAY);
472 
473  /*
474  // If no unit price known
475  if (empty($pu_ht)) {
476  $pu_ht = price2num($value['totalvaluetodivideby3600'] / 3600, 'MU');
477  }
478  */
479 
480  //Unit price
481  $pu_ht = price2num(($value['totalvaluetodivideby3600'] / $value['timespent']), 'MU');
482 
483  // Add lines
484  $lineid = $tmpinvoice->addline($langs->trans("TimeSpentForInvoice", $username).' : '.$qtyhourtext, $pu_ht, round($qtyhour / $prodDurationHours, 2), $txtva, $localtax1, $localtax2, ($idprod > 0 ? $idprod : 0));
485 
486  // Update lineid into line of timespent
487  $sql = 'UPDATE '.MAIN_DB_PREFIX.'projet_task_time SET invoice_line_id = '.((int) $lineid).', invoice_id = '.((int) $tmpinvoice->id);
488  $sql .= ' WHERE rowid IN ('.$db->sanitize(join(',', $toselect)).') AND fk_user = '.((int) $userid);
489  $result = $db->query($sql);
490  if (!$result) {
491  $error++;
492  setEventMessages($db->lasterror(), null, 'errors');
493  break;
494  }
495  }
496  } elseif ($generateinvoicemode == 'onelineperperiod') { // One line for each time spent line
497  $arrayoftasks = array();
498  $withdetail=GETPOST('detail_time_duration', 'alpha');
499  foreach ($toselect as $key => $value) {
500  // Get userid, timepent
501  $object->fetchTimeSpent($value);
502  // $object->id is the task id
503  $ftask = new Task($db);
504  $ftask->fetch($object->id);
505 
506  $fuser->fetch($object->timespent_fk_user);
507  $username = $fuser->getFullName($langs);
508 
509  $arrayoftasks[$object->timespent_id]['timespent'] = $object->timespent_duration;
510  $arrayoftasks[$object->timespent_id]['totalvaluetodivideby3600'] = $object->timespent_duration * $object->timespent_thm;
511  $arrayoftasks[$object->timespent_id]['note'] = $ftask->ref.' - '.$ftask->label.' - '.$username.($object->timespent_note ? ' - '.$object->timespent_note : ''); // TODO Add user name in note
512  if (!empty($withdetail)) {
513  if (!empty($conf->fckeditor->enabled) && !empty($conf->global->FCKEDITOR_ENABLE_DETAILS)) {
514  $arrayoftasks[$object->timespent_id]['note'] .= "<br/>";
515  } else {
516  $arrayoftasks[$object->timespent_id]['note'] .= "\n";
517  }
518 
519  if (!empty($object->timespent_withhour)) {
520  $arrayoftasks[$object->timespent_id]['note'] .= $langs->trans("Date") . ': ' . dol_print_date($object->timespent_datehour);
521  } else {
522  $arrayoftasks[$object->timespent_id]['note'] .= $langs->trans("Date") . ': ' . dol_print_date($object->timespent_date);
523  }
524  $arrayoftasks[$object->timespent_id]['note'] .= ' - '.$langs->trans("Duration").': '.convertSecondToTime($object->timespent_duration, 'all', $conf->global->MAIN_DURATION_OF_WORKDAY);
525  }
526  $arrayoftasks[$object->timespent_id]['user'] = $object->timespent_fk_user;
527  }
528 
529  foreach ($arrayoftasks as $timespent_id => $value) {
530  $userid = $value['user'];
531  //$pu_ht = $value['timespent'] * $fuser->thm;
532 
533  // Define qty per hour
534  $qtyhour = $value['timespent'] / 3600;
535 
536  // If no unit price known
537  if (empty($pu_ht)) {
538  $pu_ht = price2num($value['totalvaluetodivideby3600'] / 3600, 'MU');
539  }
540 
541  // Add lines
542  $lineid = $tmpinvoice->addline($value['note'], $pu_ht, round($qtyhour / $prodDurationHours, 2), $txtva, $localtax1, $localtax2, ($idprod > 0 ? $idprod : 0));
543  //var_dump($lineid);exit;
544 
545  // Update lineid into line of timespent
546  $sql = 'UPDATE '.MAIN_DB_PREFIX.'projet_task_time SET invoice_line_id = '.((int) $lineid).', invoice_id = '.((int) $tmpinvoice->id);
547  $sql .= ' WHERE rowid IN ('.$db->sanitize(join(',', $toselect)).') AND fk_user = '.((int) $userid);
548  $result = $db->query($sql);
549  if (!$result) {
550  $error++;
551  setEventMessages($db->lasterror(), null, 'errors');
552  break;
553  }
554  }
555  } elseif ($generateinvoicemode == 'onelinepertask') { // One line for each different task
556  $arrayoftasks = array();
557  foreach ($toselect as $key => $value) {
558  // Get userid, timepent
559  $object->fetchTimeSpent($value); // Call method to get list of timespent for a timespent line id (We use the utiliy method found into Task object)
560  // $object->id is now the task id
561  $arrayoftasks[$object->id]['timespent'] += $object->timespent_duration;
562  $arrayoftasks[$object->id]['totalvaluetodivideby3600'] += ($object->timespent_duration * $object->timespent_thm);
563  }
564 
565  foreach ($arrayoftasks as $task_id => $value) {
566  $ftask = new Task($db);
567  $ftask->fetch($task_id);
568  // Define qty per hour
569  $qtyhour = $value['timespent'] / 3600;
570  $qtyhourtext = convertSecondToTime($value['timespent'], 'all', $conf->global->MAIN_DURATION_OF_WORKDAY);
571 
572  if ($idprod > 0) {
573  // If a product is defined, we msut use the $prodDurationHours and $pu_ht of product (already set previously).
574  $pu_ht_for_task = $pu_ht;
575  // If we want to reuse the value of timespent (so use same price than cost price)
576  if (!empty($conf->global->PROJECT_TIME_SPENT_INTO_INVOICE_USE_VALUE)) {
577  $pu_ht_for_task = price2num($value['totalvaluetodivideby3600'] / $value['timespent'], 'MU') * $prodDurationHours;
578  }
579  $pa_ht = price2num($value['totalvaluetodivideby3600'] / $value['timespent'], 'MU') * $prodDurationHours;
580  } else {
581  // If not product used, we use the hour unit for duration and unit price.
582  $pu_ht_for_task = 0;
583  // If we want to reuse the value of timespent (so use same price than cost price)
584  if (!empty($conf->global->PROJECT_TIME_SPENT_INTO_INVOICE_USE_VALUE)) {
585  $pu_ht_for_task = price2num($value['totalvaluetodivideby3600'] / $value['timespent'], 'MU');
586  }
587  $pa_ht = price2num($value['totalvaluetodivideby3600'] / $value['timespent'], 'MU');
588  }
589 
590  // Add lines
591  $date_start = '';
592  $date_end = '';
593  $lineName = $ftask->ref.' - '.$ftask->label;
594  $lineid = $tmpinvoice->addline($lineName, $pu_ht_for_task, price2num($qtyhour / $prodDurationHours, 'MS'), $txtva, $localtax1, $localtax2, ($idprod > 0 ? $idprod : 0), 0, $date_start, $date_end, 0, 0, '', 'HT', 0, 1, -1, 0, '', 0, 0, null, $pa_ht);
595  if ($lineid < 0) {
596  $error++;
597  setEventMessages($tmpinvoice->error, $tmpinvoice->errors, 'errors');
598  break;
599  }
600 
601  if (!$error) {
602  // Update lineid into line of timespent
603  $sql = 'UPDATE '.MAIN_DB_PREFIX.'projet_task_time SET invoice_line_id = '.((int) $lineid).', invoice_id = '.((int) $tmpinvoice->id);
604  $sql .= ' WHERE rowid IN ('.$db->sanitize(join(',', $toselect)).')';
605  $result = $db->query($sql);
606  if (!$result) {
607  $error++;
608  setEventMessages($db->lasterror(), null, 'errors');
609  break;
610  }
611  }
612  }
613  }
614  }
615 
616  if (!$error) {
617  $urltoinvoice = $tmpinvoice->getNomUrl(0);
618  $mesg = $langs->trans("InvoiceGeneratedFromTimeSpent", '{s1}');
619  $mesg = str_replace('{s1}', $urltoinvoice, $mesg);
620  setEventMessages($mesg, null, 'mesgs');
621 
622  //var_dump($tmpinvoice);
623 
624  $db->commit();
625  } else {
626  $db->rollback();
627  }
628  }
629 }
630 
631 if ($action == 'confirm_generateinter') {
632  $langs->load('interventions');
633 
634  if (!empty($projectstatic->socid)) $projectstatic->fetch_thirdparty();
635 
636  if (!($projectstatic->thirdparty->id > 0)) {
637  setEventMessages($langs->trans("ThirdPartyRequiredToGenerateIntervention"), null, 'errors');
638  } else {
639  include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
640  include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
641  include_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
642 
643 
644  require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
645  $tmpinter = new Fichinter($db);
646  $tmptimespent = new Task($db);
647  $fuser = new User($db);
648 
649  $db->begin();
650  $interToUse = GETPOST('interid', 'int');
651 
652 
653  $tmpinter->socid = $projectstatic->thirdparty->id;
654  $tmpinter->date = dol_mktime(GETPOST('rehour', 'int'), GETPOST('remin', 'int'), GETPOST('resec', 'int'), GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int'));
655  $tmpinter->fk_project = $projectstatic->id;
656  $tmpinter->description = $projectstatic->title . ( ! empty($projectstatic->description) ? '-' . $projectstatic->label : '' );
657 
658  if ($interToUse) {
659  $tmpinter->fetch($interToUse);
660  } else {
661  $result = $tmpinter->create($user);
662  if ($result <= 0) {
663  $error++;
664  setEventMessages($tmpinter->error, $tmpinter->errors, 'errors');
665  }
666  }
667 
668  if (!$error) {
669  $arrayoftasks = array();
670  foreach ($toselect as $key => $value) {
671  // Get userid, timespent
672  $object->fetchTimeSpent($value);
673  // $object->id is the task id
674  $arrayoftasks[$object->timespent_id]['id'] = $object->id;
675  $arrayoftasks[$object->timespent_id]['timespent'] = $object->timespent_duration;
676  $arrayoftasks[$object->timespent_id]['totalvaluetodivideby3600'] = $object->timespent_duration * $object->timespent_thm;
677  $arrayoftasks[$object->timespent_id]['note'] = $object->timespent_note;
678  $arrayoftasks[$object->timespent_id]['date'] = date('Y-m-d H:i:s', $object->timespent_datehour);
679  }
680 
681  foreach ($arrayoftasks as $timespent_id => $value) {
682  $ftask = new Task($db);
683  $ftask->fetch($value['id']);
684  // Define qty per hour
685  $qtyhour = $value['timespent'] / 3600;
686  $qtyhourtext = convertSecondToTime($value['timespent'], 'all', $conf->global->MAIN_DURATION_OF_WORKDAY);
687 
688  // Add lines
689  $lineid = $tmpinter->addline($user, $tmpinter->id, $ftask->label . ( ! empty($value['note']) ? ' - ' . $value['note'] : '' ), $value['date'], $value['timespent']);
690  }
691  }
692 
693  if (!$error) {
694  $urltointer = $tmpinter->getNomUrl(0);
695  $mesg = $langs->trans("InterventionGeneratedFromTimeSpent", '{s1}');
696  $mesg = str_replace('{s1}', $urltointer, $mesg);
697  setEventMessages($mesg, null, 'mesgs');
698 
699  //var_dump($tmpinvoice);
700 
701  $db->commit();
702  } else {
703  $db->rollback();
704  }
705  }
706 }
707 
708 /*
709  * View
710  */
711 
712 $arrayofselected = is_array($toselect) ? $toselect : array();
713 
714 llxHeader("", $langs->trans("Task"));
715 
716 $form = new Form($db);
717 $formother = new FormOther($db);
718 $formproject = new FormProjets($db);
719 $userstatic = new User($db);
720 
721 if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser > 0) {
722  /*
723  * Fiche projet en mode visu
724  */
725  if ($projectidforalltimes > 0) {
726  $result = $projectstatic->fetch($projectidforalltimes);
727  if (!empty($projectstatic->socid)) {
728  $projectstatic->fetch_thirdparty();
729  }
730  $res = $projectstatic->fetch_optionals();
731  } elseif ($object->fetch($id, $ref) >= 0) {
732  if (!empty($conf->global->PROJECT_ALLOW_COMMENT_ON_TASK) && method_exists($object, 'fetchComments') && empty($object->comments)) {
733  $object->fetchComments();
734  }
735  $result = $projectstatic->fetch($object->fk_project);
736  if (!empty($conf->global->PROJECT_ALLOW_COMMENT_ON_PROJECT) && method_exists($projectstatic, 'fetchComments') && empty($projectstatic->comments)) {
737  $projectstatic->fetchComments();
738  }
739  if (!empty($projectstatic->socid)) {
740  $projectstatic->fetch_thirdparty();
741  }
742  $res = $projectstatic->fetch_optionals();
743 
744  $object->project = clone $projectstatic;
745  }
746 
747  $userRead = $projectstatic->restrictedProjectArea($user, 'read');
748  $linktocreatetime = '';
749 
750  if ($projectstatic->id > 0) {
751  if ($withproject) {
752  // Tabs for project
753  if (empty($id) || $tab == 'timespent') {
754  $tab = 'timespent';
755  } else {
756  $tab = 'tasks';
757  }
758 
759  $head = project_prepare_head($projectstatic);
760  print dol_get_fiche_head($head, $tab, $langs->trans("Project"), -1, ($projectstatic->public ? 'projectpub' : 'project'));
761 
762  $param = ((!empty($mode) && $mode == 'mine') ? '&mode=mine' : '');
763  if ($search_user) {
764  $param .= '&search_user='.((int) $search_user);
765  }
766  if ($search_month) {
767  $param .= '&search_month='.((int) $search_month);
768  }
769  if ($search_year) {
770  $param .= '&search_year='.((int) $search_year);
771  }
772 
773  // Project card
774 
775  $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
776 
777  $morehtmlref = '<div class="refidno">';
778  // Title
779  $morehtmlref .= $projectstatic->title;
780  // Thirdparty
781  if (!empty($projectstatic->thirdparty->id) && $projectstatic->thirdparty->id > 0) {
782  $morehtmlref .= '<br>'.$langs->trans('ThirdParty').' : '.$projectstatic->thirdparty->getNomUrl(1, 'project');
783  }
784  $morehtmlref .= '</div>';
785 
786  // Define a complementary filter for search of next/prev ref.
787  if (empty($user->rights->projet->all->lire)) {
788  $objectsListId = $projectstatic->getProjectsAuthorizedForUser($user, 0, 0);
789  $projectstatic->next_prev_filter = " rowid IN (".$db->sanitize(count($objectsListId) ?join(',', array_keys($objectsListId)) : '0').")";
790  }
791 
792  dol_banner_tab($projectstatic, 'project_ref', $linkback, 1, 'ref', 'ref', $morehtmlref, $param);
793 
794  print '<div class="fichecenter">';
795  print '<div class="fichehalfleft">';
796  print '<div class="underbanner clearboth"></div>';
797 
798  print '<table class="border tableforfield centpercent">';
799 
800  // Usage
801  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES) || empty($conf->global->PROJECT_HIDE_TASKS) || isModEnabled('eventorganization')) {
802  print '<tr><td class="tdtop">';
803  print $langs->trans("Usage");
804  print '</td>';
805  print '<td>';
806  if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) {
807  print '<input type="checkbox" disabled name="usage_opportunity"'.(GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ($projectstatic->usage_opportunity ? ' checked="checked"' : '')).'"> ';
808  $htmltext = $langs->trans("ProjectFollowOpportunity");
809  print $form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext);
810  print '<br>';
811  }
812  if (empty($conf->global->PROJECT_HIDE_TASKS)) {
813  print '<input type="checkbox" disabled name="usage_task"'.(GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($projectstatic->usage_task ? ' checked="checked"' : '')).'"> ';
814  $htmltext = $langs->trans("ProjectFollowTasks");
815  print $form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext);
816  print '<br>';
817  }
818  if (empty($conf->global->PROJECT_HIDE_TASKS) && !empty($conf->global->PROJECT_BILL_TIME_SPENT)) {
819  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"' : '')).'"> ';
820  $htmltext = $langs->trans("ProjectBillTimeDescription");
821  print $form->textwithpicto($langs->trans("BillTime"), $htmltext);
822  print '<br>';
823  }
824  if (isModEnabled('eventorganization')) {
825  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"' : '')).'"> ';
826  $htmltext = $langs->trans("EventOrganizationDescriptionLong");
827  print $form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext);
828  }
829  print '</td></tr>';
830  }
831 
832  // Visibility
833  print '<tr><td class="titlefield">'.$langs->trans("Visibility").'</td><td>';
834  if ($projectstatic->public) {
835  print img_picto($langs->trans('SharedProject'), 'world', 'class="paddingrightonly"');
836  print $langs->trans('SharedProject');
837  } else {
838  print img_picto($langs->trans('PrivateProject'), 'private', 'class="paddingrightonly"');
839  print $langs->trans('PrivateProject');
840  }
841  print '</td></tr>';
842 
843  // Date start - end
844  print '<tr><td>'.$langs->trans("DateStart").' - '.$langs->trans("DateEnd").'</td><td>';
845  $start = dol_print_date($projectstatic->date_start, 'day');
846  print ($start ? $start : '?');
847  $end = dol_print_date($projectstatic->date_end, 'day');
848  print ' - ';
849  print ($end ? $end : '?');
850  if ($projectstatic->hasDelay()) {
851  print img_warning("Late");
852  }
853  print '</td></tr>';
854 
855  // Budget
856  print '<tr><td>'.$langs->trans("Budget").'</td><td>';
857  if (strcmp($projectstatic->budget_amount, '')) {
858  print '<span class="amount">'.price($projectstatic->budget_amount, '', $langs, 1, 0, 0, $conf->currency).'</span>';
859  }
860  print '</td></tr>';
861 
862  // Other attributes
863  $cols = 2;
864  //include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
865 
866  print '</table>';
867 
868  print '</div>';
869  print '<div class="fichehalfright">';
870  print '<div class="underbanner clearboth"></div>';
871 
872  print '<table class="border tableforfield centpercent">';
873 
874  // Description
875  print '<td class="titlefield tdtop">'.$langs->trans("Description").'</td><td>';
876  print nl2br($projectstatic->description);
877  print '</td></tr>';
878 
879  // Categories
880  if (isModEnabled('categorie')) {
881  print '<tr><td class="valignmiddle">'.$langs->trans("Categories").'</td><td>';
882  print $form->showCategories($projectstatic->id, 'project', 1);
883  print "</td></tr>";
884  }
885 
886  print '</table>';
887 
888  print '</div>';
889  print '</div>';
890 
891  print '<div class="clearboth"></div>';
892 
893  print dol_get_fiche_end();
894 
895  print '<br>';
896  }
897 
898  // Link to create time
899  $linktocreatetimeBtnStatus = 0;
900  $linktocreatetimeUrl = '';
901  $linktocreatetimeHelpText = '';
902  if (!empty($user->rights->projet->time)) {
903  if ($projectstatic->public || $userRead > 0) {
904  $linktocreatetimeBtnStatus = 1;
905 
906  if (!empty($projectidforalltimes)) {
907  // We are on tab 'Time Spent' of project
908  $backtourl = $_SERVER['PHP_SELF'].'?projectid='.$projectstatic->id.($withproject ? '&withproject=1' : '');
909  $linktocreatetimeUrl = $_SERVER['PHP_SELF'].'?'.($withproject ? 'withproject=1' : '').'&projectid='.$projectstatic->id.'&action=createtime&token='.newToken().$param.'&backtopage='.urlencode($backtourl);
910  } else {
911  // We are on tab 'Time Spent' of task
912  $backtourl = $_SERVER['PHP_SELF'].'?id='.$object->id.($withproject ? '&withproject=1' : '');
913  $linktocreatetimeUrl = $_SERVER['PHP_SELF'].'?'.($withproject ? 'withproject=1' : '').($object->id > 0 ? '&id='.$object->id : '&projectid='.$projectstatic->id).'&action=createtime&token='.newToken().$param.'&backtopage='.urlencode($backtourl);
914  }
915  } else {
916  $linktocreatetimeBtnStatus = -2;
917  $linktocreatetimeHelpText = $langs->trans("NotOwnerOfProject");
918  }
919  } else {
920  $linktocreatetimeBtnStatus = -2;
921  $linktocreatetimeHelpText = $langs->trans("NotEnoughPermissions");
922  }
923 
924  $paramsbutton = array('morecss'=>'reposition');
925  $linktocreatetime = dolGetButtonTitle($langs->trans('AddTimeSpent'), $linktocreatetimeHelpText, 'fa fa-plus-circle', $linktocreatetimeUrl, '', $linktocreatetimeBtnStatus, $paramsbutton);
926  }
927 
928  $massactionbutton = '';
929  $arrayofmassactions = array();
930 
931  if ($projectstatic->id > 0) {
932  // If we are on a given project.
933  if ($projectstatic->usage_bill_time) {
934  $arrayofmassactions = array(
935  'generateinvoice'=>$langs->trans("GenerateBill"),
936  //'builddoc'=>$langs->trans("PDFMerge"),
937  );
938  }
939  if ( ! empty($conf->ficheinter->enabled) && $user->rights->ficheinter->creer) {
940  $langs->load("interventions");
941  $arrayofmassactions['generateinter'] = $langs->trans("GenerateInter");
942  }
943  }
944  //if ($user->rights->projet->creer) $arrayofmassactions['predelete']='<span class="fa fa-trash paddingrightonly"></span>'.$langs->trans("Delete");
945  if (in_array($massaction, array('presend', 'predelete', 'generateinvoice', 'generateinter'))) {
946  $arrayofmassactions = array();
947  }
948  $massactionbutton = $form->selectMassAction('', $arrayofmassactions);
949 
950  // Show section with information of task. If id of task is not defined and project id defined, then $projectidforalltimes is not empty.
951  if (empty($projectidforalltimes) && empty($allprojectforuser)) {
952  $head = task_prepare_head($object);
953  print dol_get_fiche_head($head, 'task_time', $langs->trans("Task"), -1, 'projecttask', 0, '', 'reposition');
954 
955  if ($action == 'deleteline') {
956  print $form->formconfirm($_SERVER["PHP_SELF"]."?".($object->id > 0 ? "id=".$object->id : 'projectid='.$projectstatic->id).'&lineid='.GETPOST("lineid", 'int').($withproject ? '&withproject=1' : ''), $langs->trans("DeleteATimeSpent"), $langs->trans("ConfirmDeleteATimeSpent"), "confirm_deleteline", '', '', 1);
957  }
958 
959  $param = ($withproject ? '&withproject=1' : '');
960  $linkback = $withproject ? '<a href="'.DOL_URL_ROOT.'/projet/tasks.php?id='.$projectstatic->id.'">'.$langs->trans("BackToList").'</a>' : '';
961 
962  if (!GETPOST('withproject') || empty($projectstatic->id)) {
963  $projectsListId = $projectstatic->getProjectsAuthorizedForUser($user, 0, 1);
964  $object->next_prev_filter = " fk_projet IN (".$db->sanitize($projectsListId).")";
965  } else {
966  $object->next_prev_filter = " fk_projet = ".$projectstatic->id;
967  }
968 
969  $morehtmlref = '';
970 
971  // Project
972  if (empty($withproject)) {
973  $morehtmlref .= '<div class="refidno">';
974  $morehtmlref .= $langs->trans("Project").': ';
975  $morehtmlref .= $projectstatic->getNomUrl(1);
976  $morehtmlref .= '<br>';
977 
978  // Third party
979  $morehtmlref .= $langs->trans("ThirdParty").': ';
980  if (!empty($projectstatic->thirdparty) && is_object($projectstatic->thirdparty)) {
981  $morehtmlref .= $projectstatic->thirdparty->getNomUrl(1);
982  }
983  $morehtmlref .= '</div>';
984  }
985 
986  dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref, $param);
987 
988  print '<div class="fichecenter">';
989  print '<div class="fichehalfleft">';
990 
991  print '<div class="underbanner clearboth"></div>';
992  print '<table class="border centpercent tableforfield">';
993 
994  // Task parent
995  print '<tr><td>'.$langs->trans("ChildOfTask").'</td><td>';
996  if ($object->fk_task_parent > 0) {
997  $tasktmp = new Task($db);
998  $tasktmp->fetch($object->fk_task_parent);
999  print $tasktmp->getNomUrl(1);
1000  }
1001  print '</td></tr>';
1002 
1003  // Date start - Date end
1004  print '<tr><td class="titlefield">'.$langs->trans("DateStart").' - '.$langs->trans("Deadline").'</td><td>';
1005  $start = dol_print_date($object->date_start, 'dayhour');
1006  print ($start ? $start : '?');
1007  $end = dol_print_date($object->date_end, 'dayhour');
1008  print ' - ';
1009  print ($end ? $end : '?');
1010  if ($object->hasDelay()) {
1011  print img_warning("Late");
1012  }
1013  print '</td></tr>';
1014 
1015  // Planned workload
1016  print '<tr><td>'.$langs->trans("PlannedWorkload").'</td><td>';
1017  if ($object->planned_workload) {
1018  print convertSecondToTime($object->planned_workload, 'allhourmin');
1019  }
1020  print '</td></tr>';
1021 
1022  print '</table>';
1023  print '</div>';
1024 
1025  print '<div class="fichehalfright">';
1026 
1027  print '<div class="underbanner clearboth"></div>';
1028  print '<table class="border tableforfield centpercent">';
1029 
1030  // Progress declared
1031  print '<tr><td class="titlefield">'.$langs->trans("ProgressDeclared").'</td><td>';
1032  print $object->progress != '' ? $object->progress.' %' : '';
1033  print '</td></tr>';
1034 
1035  // Progress calculated
1036  print '<tr><td>'.$langs->trans("ProgressCalculated").'</td><td>';
1037  if ($object->planned_workload) {
1038  $tmparray = $object->getSummaryOfTimeSpent();
1039  if ($tmparray['total_duration'] > 0) {
1040  print round($tmparray['total_duration'] / $object->planned_workload * 100, 2).' %';
1041  } else {
1042  print '0 %';
1043  }
1044  } else {
1045  print '<span class="opacitymedium">'.$langs->trans("WorkloadNotDefined").'</span>';
1046  }
1047  print '</td>';
1048 
1049  print '</tr>';
1050 
1051  print '</table>';
1052 
1053  print '</div>';
1054 
1055  print '</div>';
1056  print '<div class="clearboth"></div>';
1057 
1058  print dol_get_fiche_end();
1059  }
1060 
1061 
1062  if ($projectstatic->id > 0 || $allprojectforuser > 0) {
1063  if ($action == 'deleteline' && !empty($projectidforalltimes)) {
1064  print $form->formconfirm($_SERVER["PHP_SELF"]."?".($object->id > 0 ? "id=".$object->id : 'projectid='.$projectstatic->id).'&lineid='.GETPOST('lineid', 'int').($withproject ? '&withproject=1' : ''), $langs->trans("DeleteATimeSpent"), $langs->trans("ConfirmDeleteATimeSpent"), "confirm_deleteline", '', '', 1);
1065  }
1066 
1067  // Initialize technical object to manage hooks. Note that conf->hooks_modules contains array
1068  $hookmanager->initHooks(array('tasktimelist'));
1069 
1070  $formconfirm = '';
1071 
1072  if ($action == 'deleteline' && !empty($projectidforalltimes)) {
1073  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"]."?".($object->id > 0 ? "id=".$object->id : 'projectid='.$projectstatic->id).'&lineid='.GETPOST('lineid', 'int').($withproject ? '&withproject=1' : ''), $langs->trans("DeleteATimeSpent"), $langs->trans("ConfirmDeleteATimeSpent"), "confirm_deleteline", '', '', 1);
1074  }
1075 
1076  // Call Hook formConfirm
1077  $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid, "projectstatic" => $projectstatic, "withproject" => $withproject);
1078  $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1079  if (empty($reshook)) {
1080  $formconfirm .= $hookmanager->resPrint;
1081  } elseif ($reshook > 0) {
1082  $formconfirm = $hookmanager->resPrint;
1083  }
1084 
1085  // Print form confirm
1086  print $formconfirm;
1087 
1088  // Definition of fields for list
1089  $arrayfields = array();
1090  $arrayfields['t.task_date'] = array('label'=>$langs->trans("Date"), 'checked'=>1);
1091  if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
1092  $arrayfields['t.task_ref'] = array('label'=>$langs->trans("RefTask"), 'checked'=>1);
1093  $arrayfields['t.task_label'] = array('label'=>$langs->trans("LabelTask"), 'checked'=>1);
1094  }
1095  $arrayfields['author'] = array('label'=>$langs->trans("By"), 'checked'=>1);
1096  $arrayfields['t.note'] = array('label'=>$langs->trans("Note"), 'checked'=>1);
1097  $arrayfields['t.task_duration'] = array('label'=>$langs->trans("Duration"), 'checked'=>1);
1098  $arrayfields['value'] = array('label'=>$langs->trans("Value"), 'checked'=>1, 'enabled'=>(empty($conf->salaries->enabled) ? 0 : 1));
1099  $arrayfields['valuebilled'] = array('label'=>$langs->trans("Billed"), 'checked'=>1, 'enabled'=>(((!empty($conf->global->PROJECT_HIDE_TASKS) || empty($conf->global->PROJECT_BILL_TIME_SPENT)) ? 0 : 1) && $projectstatic->usage_bill_time));
1100  // Extra fields
1101  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php';
1102 
1103  $arrayfields = dol_sort_array($arrayfields, 'position');
1104 
1105  $param = '';
1106  if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
1107  $param .= '&contextpage='.urlencode($contextpage);
1108  }
1109  if ($limit > 0 && $limit != $conf->liste_limit) {
1110  $param .= '&limit='.urlencode($limit);
1111  }
1112  if ($search_month > 0) {
1113  $param .= '&search_month='.urlencode($search_month);
1114  }
1115  if ($search_year > 0) {
1116  $param .= '&search_year='.urlencode($search_year);
1117  }
1118  if ($search_user > 0) {
1119  $param .= '&search_user='.urlencode($search_user);
1120  }
1121  if ($search_task_ref != '') {
1122  $param .= '&search_task_ref='.urlencode($search_task_ref);
1123  }
1124  if ($search_task_label != '') {
1125  $param .= '&search_task_label='.urlencode($search_task_label);
1126  }
1127  if ($search_note != '') {
1128  $param .= '&search_note='.urlencode($search_note);
1129  }
1130  if ($search_duration != '') {
1131  $param .= '&amp;search_field2='.urlencode($search_duration);
1132  }
1133  if ($optioncss != '') {
1134  $param .= '&optioncss='.urlencode($optioncss);
1135  }
1136  /*
1137  // Add $param from extra fields
1138  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
1139  */
1140  if ($id) {
1141  $param .= '&id='.urlencode($id);
1142  }
1143  if ($projectid) {
1144  $param .= '&projectid='.urlencode($projectid);
1145  }
1146  if ($withproject) {
1147  $param .= '&withproject='.urlencode($withproject);
1148  }
1149  // Add $param from hooks
1150  $parameters = array();
1151  $reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object); // Note that $action and $object may have been modified by hook
1152  $param .= $hookmanager->resPrint;
1153 
1154  print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
1155  if ($optioncss != '') {
1156  print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
1157  }
1158  print '<input type="hidden" name="token" value="'.newToken().'">';
1159  print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
1160  if ($action == 'editline') {
1161  print '<input type="hidden" name="action" value="updateline">';
1162  } elseif ($action == 'splitline') {
1163  print '<input type="hidden" name="action" value="updatesplitline">';
1164  } elseif ($action == 'createtime' && $user->rights->projet->time) {
1165  print '<input type="hidden" name="action" value="addtimespent">';
1166  } elseif ($massaction == 'generateinvoice' && $user->rights->facture->lire) {
1167  print '<input type="hidden" name="action" value="confirm_generateinvoice">';
1168  } elseif ($massaction == 'generateinter' && $user->rights->ficheinter->lire) {
1169  print '<input type="hidden" name="action" value="confirm_generateinter">';
1170  } else {
1171  print '<input type="hidden" name="action" value="list">';
1172  }
1173  print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
1174  print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
1175 
1176  print '<input type="hidden" name="id" value="'.$id.'">';
1177  print '<input type="hidden" name="projectid" value="'.$projectidforalltimes.'">';
1178  print '<input type="hidden" name="withproject" value="'.$withproject.'">';
1179  print '<input type="hidden" name="tab" value="'.$tab.'">';
1180  print '<input type="hidden" name="page_y" value="">';
1181 
1182  // Form to convert time spent into invoice
1183  if ($massaction == 'generateinvoice') {
1184  if ($projectstatic->thirdparty->id > 0) {
1185  print '<table class="noborder centerpercent">';
1186  print '<tr>';
1187  print '<td class="titlefield">';
1188  print $langs->trans('DateInvoice');
1189  print '</td>';
1190  print '<td>';
1191  print $form->selectDate('', '', '', '', '', '', 1, 1);
1192  print '</td>';
1193  print '</tr>';
1194 
1195  print '<tr>';
1196  print '<td>';
1197  print $langs->trans('Mode');
1198  print '</td>';
1199  print '<td>';
1200  $tmparray = array(
1201  'onelineperuser'=>'OneLinePerUser',
1202  'onelinepertask'=>'OneLinePerTask',
1203  'onelineperperiod'=>'OneLinePerTimeSpentLine',
1204  );
1205  print $form->selectarray('generateinvoicemode', $tmparray, 'onelineperuser', 0, 0, 0, '', 1);
1206  print "\n".'<script type="text/javascript">';
1207  print '
1208  $(document).ready(function () {
1209  setDetailVisibility();
1210  $("#generateinvoicemode").change(function() {
1211  setDetailVisibility();
1212  });
1213  function setDetailVisibility() {
1214  generateinvoicemode = $("#generateinvoicemode option:selected").val();
1215  if (generateinvoicemode=="onelineperperiod") {
1216  $("#detail_time_duration").show();
1217  } else {
1218  $("#detail_time_duration").hide();
1219  }
1220  }
1221  });
1222  ';
1223  print '</script>'."\n";
1224  print '<span style="display:none" id="detail_time_duration"><input type="checkbox" value="detail" name="detail_time_duration"/>'.$langs->trans('AddDetailDateAndDuration').'</span>';
1225  print '</td>';
1226  print '</tr>';
1227 
1228  if ($conf->service->enabled) {
1229  print '<tr>';
1230  print '<td>';
1231  print $langs->trans('ServiceToUseOnLines');
1232  print '</td>';
1233  print '<td>';
1234  $form->select_produits('', 'productid', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 0, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth500');
1235  print '</td>';
1236  print '</tr>';
1237  }
1238 
1239  print '<tr>';
1240  print '<td class="titlefield">';
1241  print $langs->trans('InvoiceToUse');
1242  print '</td>';
1243  print '<td>';
1244  $form->selectInvoice($projectstatic->thirdparty->id, '', 'invoiceid', 24, 0, $langs->trans('NewInvoice'), 1, 0, 0, 'maxwidth500', '', 'all');
1245  print '</td>';
1246  print '</tr>';
1247  /*print '<tr>';
1248  print '<td>';
1249  print $langs->trans('ValidateInvoices');
1250  print '</td>';
1251  print '<td>';
1252  print $form->selectyesno('validate_invoices', 0, 1);
1253  print '</td>';
1254  print '</tr>';*/
1255  print '</table>';
1256 
1257  print '<br>';
1258  print '<div class="center">';
1259  print '<input type="submit" class="button" id="createbills" name="createbills" value="'.$langs->trans('GenerateBill').'"> ';
1260  print '<input type="submit" class="button button-cancel" id="cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
1261  print '</div>';
1262  print '<br>';
1263  } else {
1264  print '<div class="warning">'.$langs->trans("ThirdPartyRequiredToGenerateInvoice").'</div>';
1265  print '<div class="center">';
1266  print '<input type="submit" class="button button-cancel" id="cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
1267  print '</div>';
1268  $massaction = '';
1269  }
1270  } elseif ($massaction == 'generateinter') {
1271  // Form to convert time spent into invoice
1272  print '<input type="hidden" name="massaction" value="confirm_createinter">';
1273 
1274  if ($projectstatic->thirdparty->id > 0) {
1275  print '<br>';
1276  print '<table class="noborder centpercent">';
1277  print '<tr>';
1278  print '<td class="titlefield">';
1279  print img_picto('', 'intervention', 'class="pictofixedwidth"').$langs->trans('InterToUse');
1280  print '</td>';
1281  print '<td>';
1282  $forminter = new FormIntervention($db);
1283  print $forminter->select_interventions($projectstatic->thirdparty->id, '', 'interid', 24, $langs->trans('NewInter'), true);
1284  print '</td>';
1285  print '</tr>';
1286  print '</table>';
1287 
1288  print '<div class="center">';
1289  print '<input type="submit" class="button" id="createinter" name="createinter" value="'.$langs->trans('GenerateInter').'"> ';
1290  print '<input type="submit" class="button" id="cancel" name="cancel" value="'.$langs->trans('Cancel').'">';
1291  print '</div>';
1292  print '<br>';
1293  } else {
1294  print '<div class="warning">'.$langs->trans("ThirdPartyRequiredToGenerateIntervention").'</div>';
1295  print '<div class="center">';
1296  print '<input type="submit" class="button" id="cancel" name="cancel" value="'.$langs->trans('Cancel').'">';
1297  print '</div>';
1298  $massaction = '';
1299  }
1300  }
1301 
1302  // Allow Pre-Mass-Action hook (eg for confirmation dialog)
1303  $parameters = array(
1304  'toselect' => $toselect,
1305  'uploaddir' => isset($uploaddir) ? $uploaddir : null
1306  );
1307 
1308  $reshook = $hookmanager->executeHooks('doPreMassActions', $parameters, $object, $action);
1309  if ($reshook < 0) {
1310  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1311  } else {
1312  print $hookmanager->resPrint;
1313  }
1314 
1315  /*
1316  * List of time spent
1317  */
1318  $tasks = array();
1319 
1320  $sql = "SELECT t.rowid, t.fk_task, t.task_date, t.task_datehour, t.task_date_withhour, t.task_duration, t.fk_user, t.note, t.thm,";
1321  $sql .= " pt.ref, pt.label, pt.fk_projet,";
1322  $sql .= " u.lastname, u.firstname, u.login, u.photo, u.statut as user_status,";
1323  $sql .= " il.fk_facture as invoice_id, inv.fk_statut,";
1324  // Add fields from hooks
1325  $parameters = array();
1326  $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook
1327  $sql .= preg_replace('/^,/', '', $hookmanager->resPrint);
1328  $sql = preg_replace('/,\s*$/', '', $sql);
1329  $sql .= " FROM ".MAIN_DB_PREFIX."projet_task_time as t";
1330  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facturedet as il ON il.rowid = t.invoice_line_id";
1331  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture as inv ON inv.rowid = il.fk_facture";
1332  // Add table from hooks
1333  $parameters = array();
1334  $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook
1335  $sql .= $hookmanager->resPrint;
1336  $sql .= ", ".MAIN_DB_PREFIX."projet_task as pt, ".MAIN_DB_PREFIX."user as u";
1337  $sql .= " WHERE t.fk_user = u.rowid AND t.fk_task = pt.rowid";
1338 
1339  if (empty($projectidforalltimes) && empty($allprojectforuser)) {
1340  // Limit on one task
1341  $sql .= " AND t.fk_task =".((int) $object->id);
1342  } elseif (!empty($projectidforalltimes)) {
1343  // Limit on one project
1344  $sql .= " AND pt.fk_projet IN (".$db->sanitize($projectidforalltimes).")";
1345  } elseif (!empty($allprojectforuser)) {
1346  // Limit on on user
1347  if (empty($search_user)) {
1348  $search_user = $user->id;
1349  }
1350  if ($search_user > 0) $sql .= " AND t.fk_user = ".((int) $search_user);
1351  }
1352 
1353  if ($search_note) {
1354  $sql .= natural_search('t.note', $search_note);
1355  }
1356  if ($search_task_ref) {
1357  $sql .= natural_search('pt.ref', $search_task_ref);
1358  }
1359  if ($search_task_label) {
1360  $sql .= natural_search('pt.label', $search_task_label);
1361  }
1362  if ($search_user > 0) {
1363  $sql .= natural_search('t.fk_user', $search_user, 2);
1364  }
1365  if ($search_valuebilled == '1') {
1366  $sql .= ' AND t.invoice_id > 0';
1367  }
1368  if ($search_valuebilled == '0') {
1369  $sql .= ' AND (t.invoice_id = 0 OR t.invoice_id IS NULL)';
1370  }
1371 
1372  $sql .= dolSqlDateFilter('t.task_datehour', $search_day, $search_month, $search_year);
1373 
1374  // Add where from hooks
1375  $parameters = array();
1376  $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook
1377  $sql .= $hookmanager->resPrint;
1378  $sql .= $db->order($sortfield, $sortorder);
1379 
1380  // Count total nb of records
1381  $nbtotalofrecords = '';
1382  if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
1383  $resql = $db->query($sql);
1384 
1385  if (! $resql) {
1386  dol_print_error($db);
1387  exit;
1388  }
1389 
1390  $nbtotalofrecords = $db->num_rows($resql);
1391  if (($page * $limit) > $nbtotalofrecords) { // if total of record found is smaller than page * limit, goto and load page 0
1392  $page = 0;
1393  $offset = 0;
1394  }
1395  }
1396  // if total of record found is smaller than limit, no need to do paging and to restart another select with limits set.
1397  if (is_numeric($nbtotalofrecords) && $limit > $nbtotalofrecords) {
1398  $num = $nbtotalofrecords;
1399  } else {
1400  $sql .= $db->plimit($limit + 1, $offset);
1401 
1402  $resql = $db->query($sql);
1403  if (!$resql) {
1404  dol_print_error($db);
1405  exit;
1406  }
1407 
1408  $num = $db->num_rows($resql);
1409  }
1410 
1411  if ($num >= 0) {
1412  if (!empty($projectidforalltimes)) {
1413  print '<!-- List of time spent for project -->'."\n";
1414 
1415  $title = $langs->trans("ListTaskTimeUserProject");
1416 
1417  print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'clock', 0, $linktocreatetime, '', $limit, 0, 0, 1);
1418  } else {
1419  print '<!-- List of time spent -->'."\n";
1420 
1421  $title = $langs->trans("ListTaskTimeForTask");
1422 
1423  print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'clock', 0, $linktocreatetime, '', $limit, 0, 0, 1);
1424  }
1425 
1426  $i = 0;
1427  while ($i < $num) {
1428  $row = $db->fetch_object($resql);
1429  $tasks[$i] = $row;
1430  $i++;
1431  }
1432  $db->free($resql);
1433  } else {
1434  dol_print_error($db);
1435  }
1436 
1437  /*
1438  * Form to add a new line of time spent
1439  */
1440  if ($action == 'createtime' && $user->rights->projet->time) {
1441  print '<!-- table to add time spent -->'."\n";
1442  if (!empty($id)) {
1443  print '<input type="hidden" name="taskid" value="'.$id.'">';
1444  }
1445 
1446  print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
1447  print '<table class="noborder nohover centpercent">';
1448 
1449  print '<tr class="liste_titre">';
1450  print '<td>'.$langs->trans("Date").'</td>';
1451  if (!empty($allprojectforuser)) {
1452  print '<td>'.$langs->trans("Project").'</td>';
1453  }
1454  if (empty($id)) {
1455  print '<td>'.$langs->trans("Task").'</td>';
1456  }
1457  print '<td>'.$langs->trans("By").'</td>';
1458  print '<td>'.$langs->trans("Note").'</td>';
1459  print '<td>'.$langs->trans("NewTimeSpent").'</td>';
1460  print '<td>'.$langs->trans("ProgressDeclared").'</td>';
1461  if (empty($conf->global->PROJECT_HIDE_TASKS) && !empty($conf->global->PROJECT_BILL_TIME_SPENT)) {
1462  print '<td></td>';
1463  }
1464  // Hook fields
1465  $parameters = array('mode' => 'create');
1466  $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook
1467  print $hookmanager->resPrint;
1468  print '<td></td>';
1469  print "</tr>\n";
1470 
1471  print '<tr class="oddeven nohover">';
1472 
1473  // Date
1474  print '<td class="maxwidthonsmartphone">';
1475  $newdate = '';
1476  print $form->selectDate($newdate, 'time', ($conf->browser->layout == 'phone' ? 2 : 1), 1, 2, "timespent_date", 1, 0);
1477  print '</td>';
1478 
1479  if (!empty($allprojectforuser)) {
1480  print '<td>';
1481  // Add project selector
1482  print '</td>';
1483  }
1484 
1485  // Task
1486  $nboftasks = 0;
1487  if (empty($id)) {
1488  print '<td class="maxwidthonsmartphone">';
1489  $nboftasks = $formproject->selectTasks(-1, GETPOST('taskid', 'int'), 'taskid', 0, 0, 1, 1, 0, 0, 'maxwidth300', $projectstatic->id, 'progress');
1490  print '</td>';
1491  }
1492 
1493  // Contributor
1494  print '<td class="maxwidthonsmartphone nowraponall">';
1495  $contactsofproject = $projectstatic->getListContactId('internal');
1496  if (count($contactsofproject) > 0) {
1497  print img_object('', 'user', 'class="hideonsmartphone"');
1498  if (in_array($user->id, $contactsofproject)) {
1499  $userid = $user->id;
1500  } else {
1501  $userid = $contactsofproject[0];
1502  }
1503 
1504  if ($projectstatic->public) {
1505  $contactsofproject = array();
1506  }
1507  print $form->select_dolusers((GETPOST('userid', 'int') ? GETPOST('userid', 'int') : $userid), 'userid', 0, '', 0, '', $contactsofproject, 0, 0, 0, '', 0, $langs->trans("ResourceNotAssignedToProject"), 'maxwidth250');
1508  } else {
1509  if ($nboftasks) {
1510  print img_error($langs->trans('FirstAddRessourceToAllocateTime')).' '.$langs->trans('FirstAddRessourceToAllocateTime');
1511  }
1512  }
1513  print '</td>';
1514 
1515  // Note
1516  print '<td>';
1517  print '<textarea name="timespent_note" class="maxwidth100onsmartphone" rows="'.ROWS_2.'">'.(GETPOST('timespent_note') ? GETPOST('timespent_note') : '').'</textarea>';
1518  print '</td>';
1519 
1520  // Duration - Time spent
1521  print '<td class="nowraponall">';
1522  $durationtouse = (GETPOST('timespent_duration') ? GETPOST('timespent_duration') : '');
1523  if (GETPOSTISSET('timespent_durationhour') || GETPOSTISSET('timespent_durationmin')) {
1524  $durationtouse = (GETPOST('timespent_durationhour') * 3600 + GETPOST('timespent_durationmin') * 60);
1525  }
1526  print $form->select_duration('timespent_duration', $durationtouse, 0, 'text');
1527  print '</td>';
1528 
1529  // Progress declared
1530  print '<td class="nowrap">';
1531  print $formother->select_percent(GETPOST('progress') ?GETPOST('progress') : $object->progress, 'progress', 0, 5, 0, 100, 1);
1532  print '</td>';
1533 
1534  // Invoiced
1535  if (empty($conf->global->PROJECT_HIDE_TASKS) && !empty($conf->global->PROJECT_BILL_TIME_SPENT)) {
1536  print '<td>';
1537  print '</td>';
1538  }
1539 
1540  // Fields from hook
1541  $parameters = array('mode' => 'create');
1542  $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook
1543  print $hookmanager->resPrint;
1544 
1545  print '<td class="center">';
1546  $form->buttonsSaveCancel();
1547  print '<input type="submit" name="save" class="button buttongen marginleftonly margintoponlyshort marginbottomonlyshort button-add" value="'.$langs->trans("Add").'">';
1548  print '<input type="submit" name="cancel" class="button buttongen marginleftonly margintoponlyshort marginbottomonlyshort button-cancel" value="'.$langs->trans("Cancel").'">';
1549  print '</td></tr>';
1550 
1551  print '</table>';
1552  print '</div>';
1553 
1554  print '<br>';
1555  }
1556 
1557  $moreforfilter = '';
1558 
1559  $parameters = array();
1560  $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook
1561  if (empty($reshook)) {
1562  $moreforfilter .= $hookmanager->resPrint;
1563  } else {
1564  $moreforfilter = $hookmanager->resPrint;
1565  }
1566 
1567  if (!empty($moreforfilter)) {
1568  print '<div class="liste_titre liste_titre_bydiv centpercent">';
1569  print $moreforfilter;
1570  print '</div>';
1571  }
1572 
1573  $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
1574  $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields
1575  $selectedfields .= (is_array($arrayofmassactions) && count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
1576 
1577  print '<div class="div-table-responsive">';
1578  print '<table class="tagtable nobottomiftotal liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";
1579 
1580  // Fields title search
1581  print '<tr class="liste_titre_filter">';
1582  // Date
1583  if (!empty($arrayfields['t.task_date']['checked'])) {
1584  print '<td class="liste_titre">';
1585  if (!empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) {
1586  print '<input class="flat valignmiddle" type="text" size="1" maxlength="2" name="search_day" value="'.$search_day.'">';
1587  }
1588  print '<input class="flat valignmiddle" type="text" size="1" maxlength="2" name="search_month" value="'.$search_month.'">';
1589  print $formother->selectyear($search_year, 'search_year', 1, 20, 5);
1590  print '</td>';
1591  }
1592  if (!empty($allprojectforuser)) {
1593  print '<td class="liste_titre"></td>';
1594  }
1595  // Task
1596  if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
1597  if (!empty($arrayfields['t.task_ref']['checked'])) {
1598  print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="search_task_ref" value="'.dol_escape_htmltag($search_task_ref).'"></td>';
1599  }
1600  if (!empty($arrayfields['t.task_label']['checked'])) {
1601  print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="search_task_label" value="'.dol_escape_htmltag($search_task_label).'"></td>';
1602  }
1603  }
1604  // Author
1605  if (!empty($arrayfields['author']['checked'])) {
1606  print '<td class="liste_titre">'.$form->select_dolusers(($search_user > 0 ? $search_user : -1), 'search_user', 1, null, 0, '', '', 0, 0, 0, '', 0, '', 'maxwidth250').'</td>';
1607  }
1608  // Note
1609  if (!empty($arrayfields['t.note']['checked'])) {
1610  print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="search_note" value="'.dol_escape_htmltag($search_note).'"></td>';
1611  }
1612  // Duration
1613  if (!empty($arrayfields['t.task_duration']['checked'])) {
1614  print '<td class="liste_titre right"></td>';
1615  }
1616  // Value in main currency
1617  if (!empty($arrayfields['value']['checked'])) {
1618  print '<td class="liste_titre"></td>';
1619  }
1620  // Value billed
1621  if (!empty($arrayfields['valuebilled']['checked'])) {
1622  print '<td class="liste_titre center">'.$form->selectyesno('search_valuebilled', $search_valuebilled, 1, false, 1).'</td>';
1623  }
1624 
1625  /*
1626  // Extra fields
1627  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
1628  */
1629  // Fields from hook
1630  $parameters = array('arrayfields'=>$arrayfields);
1631  $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook
1632  print $hookmanager->resPrint;
1633  // Action column
1634  print '<td class="liste_titre center">';
1635  $searchpicto = $form->showFilterButtons();
1636  print $searchpicto;
1637  print '</td>';
1638  print '</tr>'."\n";
1639 
1640  print '<tr class="liste_titre">';
1641  if (!empty($arrayfields['t.task_date']['checked'])) {
1642  print_liste_field_titre($arrayfields['t.task_date']['label'], $_SERVER['PHP_SELF'], 't.task_date,t.task_datehour,t.rowid', '', $param, '', $sortfield, $sortorder);
1643  }
1644  if (!empty($allprojectforuser)) {
1645  print_liste_field_titre("Project", $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder);
1646  }
1647  if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
1648  if (!empty($arrayfields['t.task_ref']['checked'])) {
1649  print_liste_field_titre($arrayfields['t.task_ref']['label'], $_SERVER['PHP_SELF'], 'pt.ref', '', $param, '', $sortfield, $sortorder);
1650  }
1651  if (!empty($arrayfields['t.task_label']['checked'])) {
1652  print_liste_field_titre($arrayfields['t.task_label']['label'], $_SERVER['PHP_SELF'], 'pt.label', '', $param, '', $sortfield, $sortorder);
1653  }
1654  }
1655  if (!empty($arrayfields['author']['checked'])) {
1656  print_liste_field_titre($arrayfields['author']['label'], $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder);
1657  }
1658  if (!empty($arrayfields['t.note']['checked'])) {
1659  print_liste_field_titre($arrayfields['t.note']['label'], $_SERVER['PHP_SELF'], 't.note', '', $param, '', $sortfield, $sortorder);
1660  }
1661  if (!empty($arrayfields['t.task_duration']['checked'])) {
1662  print_liste_field_titre($arrayfields['t.task_duration']['label'], $_SERVER['PHP_SELF'], 't.task_duration', '', $param, '', $sortfield, $sortorder, 'right ');
1663  }
1664  if (!empty($arrayfields['value']['checked'])) {
1665  print_liste_field_titre($arrayfields['value']['label'], $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder, 'right ');
1666  }
1667  if (!empty($arrayfields['valuebilled']['checked'])) {
1668  print_liste_field_titre($arrayfields['valuebilled']['label'], $_SERVER['PHP_SELF'], 'il.total_ht', '', $param, '', $sortfield, $sortorder, 'center ', $langs->trans("SelectLinesOfTimeSpentToInvoice"));
1669  }
1670  /*
1671  // Extra fields
1672  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
1673  */
1674  // Hook fields
1675  $parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder);
1676  $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook
1677  print $hookmanager->resPrint;
1678  print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', 'width="80"', $sortfield, $sortorder, 'center maxwidthsearch ');
1679  print "</tr>\n";
1680 
1681  $tasktmp = new Task($db);
1682  $tmpinvoice = new Facture($db);
1683 
1684  $i = 0;
1685 
1686  $total = 0;
1687  $totalvalue = 0;
1688  $totalarray = array();
1689  foreach ($tasks as $task_time) {
1690  if ($i >= $limit) {
1691  break;
1692  }
1693 
1694  $date1 = $db->jdate($task_time->task_date);
1695  $date2 = $db->jdate($task_time->task_datehour);
1696 
1697  print '<tr class="oddeven">';
1698 
1699  // Date
1700  if (!empty($arrayfields['t.task_date']['checked'])) {
1701  print '<td class="nowrap">';
1702  if ($action == 'editline' && GETPOST('lineid', 'int') == $task_time->rowid) {
1703  if (empty($task_time->task_date_withhour)) {
1704  print $form->selectDate(($date2 ? $date2 : $date1), 'timeline', 3, 3, 2, "timespent_date", 1, 0);
1705  } else {
1706  print $form->selectDate(($date2 ? $date2 : $date1), 'timeline', 1, 1, 2, "timespent_date", 1, 0);
1707  }
1708  } else {
1709  print dol_print_date(($date2 ? $date2 : $date1), ($task_time->task_date_withhour ? 'dayhour' : 'day'));
1710  }
1711  print '</td>';
1712  if (!$i) {
1713  $totalarray['nbfield']++;
1714  }
1715  }
1716 
1717  // Project ref
1718  if (!empty($allprojectforuser)) {
1719  print '<td class="nowraponall">';
1720  if (empty($conf->cache['project'][$task_time->fk_projet])) {
1721  $tmpproject = new Project($db);
1722  $tmpproject->fetch($task_time->fk_projet);
1723  $conf->cache['project'][$task_time->fk_projet] = $tmpproject;
1724  } else {
1725  $tmpproject = $conf->cache['project'][$task_time->fk_projet];
1726  }
1727  print $tmpproject->getNomUrl(1);
1728  print '</td>';
1729  if (!$i) {
1730  $totalarray['nbfield']++;
1731  }
1732  }
1733 
1734  // Task ref
1735  if (!empty($arrayfields['t.task_ref']['checked'])) {
1736  if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
1737  print '<td class="nowrap">';
1738  if ($action == 'editline' && GETPOST('lineid', 'int') == $task_time->rowid) {
1739  $formproject->selectTasks(-1, GETPOST('taskid', 'int') ? GETPOST('taskid', 'int') : $task_time->fk_task, 'taskid', 0, 0, 1, 1, 0, 0, 'maxwidth300', $projectstatic->id, '');
1740  } else {
1741  $tasktmp->id = $task_time->fk_task;
1742  $tasktmp->ref = $task_time->ref;
1743  $tasktmp->label = $task_time->label;
1744  print $tasktmp->getNomUrl(1, 'withproject', 'time');
1745  }
1746  print '</td>';
1747  if (!$i) {
1748  $totalarray['nbfield']++;
1749  }
1750  }
1751  } elseif ($action !== 'createtime') {
1752  print '<input type="hidden" name="taskid" value="'.$id.'">';
1753  }
1754 
1755  // Task label
1756  if (!empty($arrayfields['t.task_label']['checked'])) {
1757  if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
1758  print '<td class="nowrap tdoverflowmax300" title="'.dol_escape_htmltag($task_time->label).'">';
1759  print dol_escape_htmltag($task_time->label);
1760  print '</td>';
1761  if (!$i) {
1762  $totalarray['nbfield']++;
1763  }
1764  }
1765  }
1766 
1767  // By User
1768  if (!empty($arrayfields['author']['checked'])) {
1769  print '<td class="tdoverflowmax100">';
1770  if ($action == 'editline' && GETPOST('lineid', 'int') == $task_time->rowid) {
1771  if (empty($object->id)) {
1772  $object->fetch($id);
1773  }
1774  $contactsoftask = $object->getListContactId('internal');
1775  if (!in_array($task_time->fk_user, $contactsoftask)) {
1776  $contactsoftask[] = $task_time->fk_user;
1777  }
1778  if (count($contactsoftask) > 0) {
1779  print img_object('', 'user', 'class="hideonsmartphone"');
1780  print $form->select_dolusers($task_time->fk_user, 'userid_line', 0, '', 0, '', $contactsoftask, '0', 0, 0, '', 0, '', 'maxwidth200');
1781  } else {
1782  print img_error($langs->trans('FirstAddRessourceToAllocateTime')).$langs->trans('FirstAddRessourceToAllocateTime');
1783  }
1784  } else {
1785  $userstatic->id = $task_time->fk_user;
1786  $userstatic->lastname = $task_time->lastname;
1787  $userstatic->firstname = $task_time->firstname;
1788  $userstatic->photo = $task_time->photo;
1789  $userstatic->statut = $task_time->user_status;
1790  print $userstatic->getNomUrl(-1);
1791  }
1792  print '</td>';
1793  if (!$i) {
1794  $totalarray['nbfield']++;
1795  }
1796  }
1797 
1798  // Note
1799  if (!empty($arrayfields['t.note']['checked'])) {
1800  print '<td class="small">';
1801  if ($action == 'editline' && GETPOST('lineid', 'int') == $task_time->rowid) {
1802  print '<textarea name="timespent_note_line" width="95%" rows="'.ROWS_1.'">'.dol_escape_htmltag($task_time->note, 0, 1).'</textarea>';
1803  } else {
1804  print dol_nl2br($task_time->note);
1805  }
1806  print '</td>';
1807  if (!$i) {
1808  $totalarray['nbfield']++;
1809  }
1810  } elseif ($action == 'editline' && GETPOST('lineid', 'int') == $task_time->rowid) {
1811  print '<input type="hidden" name="timespent_note_line" value="'.dol_escape_htmltag($task_time->note, 0, 1).'">';
1812  }
1813 
1814  // Time spent
1815  if (!empty($arrayfields['t.task_duration']['checked'])) {
1816  print '<td class="right nowraponall">';
1817  if ($action == 'editline' && GETPOST('lineid', 'int') == $task_time->rowid) {
1818  print '<input type="hidden" name="old_duration" value="'.$task_time->task_duration.'">';
1819  print $form->select_duration('new_duration', $task_time->task_duration, 0, 'text');
1820  } else {
1821  print convertSecondToTime($task_time->task_duration, 'allhourmin');
1822  }
1823  print '</td>';
1824  if (!$i) {
1825  $totalarray['nbfield']++;
1826  }
1827  if (!$i) {
1828  $totalarray['pos'][$totalarray['nbfield']] = 't.task_duration';
1829  }
1830  $totalarray['val']['t.task_duration'] += $task_time->task_duration;
1831  if (!$i) {
1832  $totalarray['totaldurationfield'] = $totalarray['nbfield'];
1833  }
1834  $totalarray['totalduration'] += $task_time->task_duration;
1835  }
1836 
1837  // Value spent
1838  if (!empty($arrayfields['value']['checked'])) {
1839  $langs->load("salaries");
1840  $value = price2num($task_time->thm * $task_time->task_duration / 3600, 'MT', 1);
1841 
1842  print '<td class="nowraponall right">';
1843  print '<span class="amount" title="'.$langs->trans("THM").': '.price($task_time->thm).'">';
1844  print price($value, 1, $langs, 1, -1, -1, $conf->currency);
1845  print '</span>';
1846  print '</td>';
1847  if (!$i) {
1848  $totalarray['nbfield']++;
1849  }
1850  if (!$i) {
1851  $totalarray['pos'][$totalarray['nbfield']] = 'value';
1852  }
1853  $totalarray['val']['value'] += $value;
1854  if (!$i) {
1855  $totalarray['totalvaluefield'] = $totalarray['nbfield'];
1856  }
1857  $totalarray['totalvalue'] += $value;
1858  }
1859 
1860  // Invoiced
1861  if (!empty($arrayfields['valuebilled']['checked'])) {
1862  print '<td class="center">'; // invoice_id and invoice_line_id
1863  if (empty($conf->global->PROJECT_HIDE_TASKS) && !empty($conf->global->PROJECT_BILL_TIME_SPENT)) {
1864  if ($projectstatic->usage_bill_time) {
1865  if ($task_time->invoice_id) {
1866  $result = $tmpinvoice->fetch($task_time->invoice_id);
1867  if ($result > 0) {
1868  print $tmpinvoice->getNomUrl(1);
1869  }
1870  } else {
1871  print $langs->trans("No");
1872  }
1873  } else {
1874  print '<span class="opacitymedium">'.$langs->trans("NA").'</span>';
1875  }
1876  }
1877  print '</td>';
1878  if (!$i) {
1879  $totalarray['nbfield']++;
1880  }
1881  }
1882 
1883  /*
1884  // Extra fields
1885  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
1886  */
1887 
1888  // Fields from hook
1889  $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$task_time, 'i'=>$i, 'totalarray'=>&$totalarray);
1890  $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook
1891  print $hookmanager->resPrint;
1892 
1893  // Action column
1894  print '<td class="center nowraponall">';
1895  if (($action == 'editline' || $action == 'splitline') && GETPOST('lineid', 'int') == $task_time->rowid) {
1896  print '<input type="hidden" name="lineid" value="'.GETPOST('lineid', 'int').'">';
1897  print '<input type="submit" class="button buttongen margintoponlyshort marginbottomonlyshort button-save" name="save" value="'.$langs->trans("Save").'">';
1898  print ' ';
1899  print '<input type="submit" class="button buttongen margintoponlyshort marginbottomonlyshort button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
1900  } elseif ($user->hasRight('projet', 'time') || $user->hasRight('projet', 'all', 'creer')) { // Read project and enter time consumed on assigned tasks
1901  if (in_array($task_time->fk_user, $childids) || $user->hasRight('projet', 'all', 'creer')) {
1902  if (getDolGlobalString('MAIN_FEATURES_LEVEL') >= 2) {
1903  print '&nbsp;';
1904  print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?action=splitline&token='.newToken().'&lineid='.$task_time->rowid.$param.((empty($id) || $tab == 'timespent') ? '&tab=timespent' : '').'">';
1905  print img_split('', 'class="pictofixedwidth"');
1906  print '</a>';
1907  }
1908 
1909  print '<a class="reposition editfielda" href="'.$_SERVER["PHP_SELF"].'?id='.$task_time->fk_task.'&action=editline&token='.newToken().'&lineid='.$task_time->rowid.$param.((empty($id) || $tab == 'timespent') ? '&tab=timespent' : '').'">';
1910  print img_edit('default', 0, 'class="pictofixedwidth paddingleft"');
1911  print '</a>';
1912 
1913  print '<a class="reposition paddingleft" href="'.$_SERVER["PHP_SELF"].'?id='.$task_time->fk_task.'&action=deleteline&token='.newToken().'&lineid='.$task_time->rowid.$param.((empty($id) || $tab == 'timespent') ? '&tab=timespent' : '').'">';
1914  print img_delete('default', 'class="pictodelete paddingleft"');
1915  print '</a>';
1916 
1917  if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1918  $selected = 0;
1919  if (in_array($task_time->rowid, $arrayofselected)) {
1920  $selected = 1;
1921  }
1922  print '&nbsp;';
1923  print '<input id="cb'.$task_time->rowid.'" class="flat checkforselect marginleftonly" type="checkbox" name="toselect[]" value="'.$task_time->rowid.'"'.($selected ? ' checked="checked"' : '').'>';
1924  }
1925  }
1926  }
1927  print '</td>';
1928  if (!$i) {
1929  $totalarray['nbfield']++;
1930  }
1931 
1932  print "</tr>\n";
1933 
1934 
1935  // Add line to split
1936 
1937  if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
1938  print '<tr class="oddeven">';
1939 
1940  // Date
1941  if (!empty($arrayfields['t.task_date']['checked'])) {
1942  print '<td class="nowrap">';
1943  if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
1944  if (empty($task_time->task_date_withhour)) {
1945  print $form->selectDate(($date2 ? $date2 : $date1), 'timeline', 3, 3, 2, "timespent_date", 1, 0);
1946  } else {
1947  print $form->selectDate(($date2 ? $date2 : $date1), 'timeline', 1, 1, 2, "timespent_date", 1, 0);
1948  }
1949  } else {
1950  print dol_print_date(($date2 ? $date2 : $date1), ($task_time->task_date_withhour ? 'dayhour' : 'day'));
1951  }
1952  print '</td>';
1953  }
1954 
1955  // Project ref
1956  if (!empty($allprojectforuser)) {
1957  if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
1958  print '<td class="nowrap">';
1959  print '</td>';
1960  }
1961  }
1962 
1963  // Task ref
1964  if (!empty($arrayfields['t.task_ref']['checked'])) {
1965  if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
1966  print '<td class="nowrap">';
1967  $tasktmp->id = $task_time->fk_task;
1968  $tasktmp->ref = $task_time->ref;
1969  $tasktmp->label = $task_time->label;
1970  print $tasktmp->getNomUrl(1, 'withproject', 'time');
1971  print '</td>';
1972  }
1973  }
1974 
1975  // Task label
1976  if (!empty($arrayfields['t.task_label']['checked'])) {
1977  if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
1978  print '<td class="tdoverflowmax300" title="'.dol_escape_htmltag($task_time->label).'">';
1979  print dol_escape_htmltag($task_time->label);
1980  print '</td>';
1981  }
1982  }
1983 
1984  // User
1985  if (!empty($arrayfields['author']['checked'])) {
1986  print '<td>';
1987  if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
1988  if (empty($object->id)) {
1989  $object->fetch($id);
1990  }
1991  $contactsoftask = $object->getListContactId('internal');
1992  if (!in_array($task_time->fk_user, $contactsoftask)) {
1993  $contactsoftask[] = $task_time->fk_user;
1994  }
1995  if (count($contactsoftask) > 0) {
1996  print img_object('', 'user', 'class="hideonsmartphone"');
1997  print $form->select_dolusers($task_time->fk_user, 'userid_line', 0, '', 0, '', $contactsoftask);
1998  } else {
1999  print img_error($langs->trans('FirstAddRessourceToAllocateTime')).$langs->trans('FirstAddRessourceToAllocateTime');
2000  }
2001  } else {
2002  $userstatic->id = $task_time->fk_user;
2003  $userstatic->lastname = $task_time->lastname;
2004  $userstatic->firstname = $task_time->firstname;
2005  $userstatic->photo = $task_time->photo;
2006  $userstatic->statut = $task_time->user_status;
2007  print $userstatic->getNomUrl(-1);
2008  }
2009  print '</td>';
2010  }
2011 
2012  // Note
2013  if (!empty($arrayfields['t.note']['checked'])) {
2014  print '<td class="tdoverflowmax300">';
2015  if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2016  print '<textarea name="timespent_note_line" width="95%" rows="'.ROWS_1.'">'.dol_escape_htmltag($task_time->note, 0, 1).'</textarea>';
2017  } else {
2018  print dol_nl2br($task_time->note);
2019  }
2020  print '</td>';
2021  } elseif ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2022  print '<input type="hidden" name="timespent_note_line" rows="'.ROWS_1.'" value="'.dol_escape_htmltag($task_time->note, 0, 1).'">';
2023  }
2024 
2025  // Time spent
2026  if (!empty($arrayfields['t.task_duration']['checked'])) {
2027  print '<td class="right">';
2028  if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2029  print '<input type="hidden" name="old_duration" value="'.$task_time->task_duration.'">';
2030  print $form->select_duration('new_duration', $task_time->task_duration, 0, 'text');
2031  } else {
2032  print convertSecondToTime($task_time->task_duration, 'allhourmin');
2033  }
2034  print '</td>';
2035  }
2036 
2037  // Value spent
2038  if (!empty($arrayfields['value']['checked'])) {
2039  print '<td class="right">';
2040  print '<span class="amount">';
2041  $value = price2num($task_time->thm * $task_time->task_duration / 3600, 'MT', 1);
2042  print price($value, 1, $langs, 1, -1, -1, $conf->currency);
2043  print '</span>';
2044  print '</td>';
2045  }
2046 
2047  // Value billed
2048  if (!empty($arrayfields['valuebilled']['checked'])) {
2049  print '<td class="right">';
2050  $valuebilled = price2num($task_time->total_ht, '', 1);
2051  if (isset($task_time->total_ht)) {
2052  print price($valuebilled, 1, $langs, 1, -1, -1, $conf->currency);
2053  }
2054  print '</td>';
2055  }
2056 
2057  /*
2058  // Extra fields
2059  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
2060  */
2061 
2062  // Fields from hook
2063  $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$task_time, 'mode' => 'split1');
2064  $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook
2065  print $hookmanager->resPrint;
2066 
2067  // Action column
2068  print '<td class="center nowraponall">';
2069  print '</td>';
2070 
2071  print "</tr>\n";
2072 
2073 
2074  // Line for second dispatching
2075 
2076  print '<tr class="oddeven">';
2077 
2078  // Date
2079  if (!empty($arrayfields['t.task_date']['checked'])) {
2080  print '<td class="nowrap">';
2081  if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2082  if (empty($task_time->task_date_withhour)) {
2083  print $form->selectDate(($date2 ? $date2 : $date1), 'timeline_2', 3, 3, 2, "timespent_date", 1, 0);
2084  } else {
2085  print $form->selectDate(($date2 ? $date2 : $date1), 'timeline_2', 1, 1, 2, "timespent_date", 1, 0);
2086  }
2087  } else {
2088  print dol_print_date(($date2 ? $date2 : $date1), ($task_time->task_date_withhour ? 'dayhour' : 'day'));
2089  }
2090  print '</td>';
2091  }
2092 
2093  // Project ref
2094  if (!empty($allprojectforuser)) {
2095  if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2096  print '<td class="nowrap">';
2097  print '</td>';
2098  }
2099  }
2100 
2101  // Task ref
2102  if (!empty($arrayfields['t.task_ref']['checked'])) {
2103  if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2104  print '<td class="nowrap">';
2105  $tasktmp->id = $task_time->fk_task;
2106  $tasktmp->ref = $task_time->ref;
2107  $tasktmp->label = $task_time->label;
2108  print $tasktmp->getNomUrl(1, 'withproject', 'time');
2109  print '</td>';
2110  }
2111  }
2112 
2113  // Task label
2114  if (!empty($arrayfields['t.task_label']['checked'])) {
2115  if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2116  print '<td class="nowrap">';
2117  print $task_time->label;
2118  print '</td>';
2119  }
2120  }
2121 
2122  // User
2123  if (!empty($arrayfields['author']['checked'])) {
2124  print '<td>';
2125  if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2126  if (empty($object->id)) {
2127  $object->fetch($id);
2128  }
2129  $contactsoftask = $object->getListContactId('internal');
2130  if (!in_array($task_time->fk_user, $contactsoftask)) {
2131  $contactsoftask[] = $task_time->fk_user;
2132  }
2133  if (count($contactsoftask) > 0) {
2134  print img_object('', 'user', 'class="hideonsmartphone"');
2135  print $form->select_dolusers($task_time->fk_user, 'userid_line_2', 0, '', 0, '', $contactsoftask);
2136  } else {
2137  print img_error($langs->trans('FirstAddRessourceToAllocateTime')).$langs->trans('FirstAddRessourceToAllocateTime');
2138  }
2139  } else {
2140  $userstatic->id = $task_time->fk_user;
2141  $userstatic->lastname = $task_time->lastname;
2142  $userstatic->firstname = $task_time->firstname;
2143  $userstatic->photo = $task_time->photo;
2144  $userstatic->statut = $task_time->user_status;
2145  print $userstatic->getNomUrl(-1);
2146  }
2147  print '</td>';
2148  }
2149 
2150  // Note
2151  if (!empty($arrayfields['t.note']['checked'])) {
2152  print '<td class="small tdoverflowmax300"">';
2153  if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2154  print '<textarea name="timespent_note_line_2" width="95%" rows="'.ROWS_1.'">'.dol_escape_htmltag($task_time->note, 0, 1).'</textarea>';
2155  } else {
2156  print dol_nl2br($task_time->note);
2157  }
2158  print '</td>';
2159  } elseif ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2160  print '<input type="hidden" name="timespent_note_line_2" value="'.dol_escape_htmltag($task_time->note, 0, 1).'">';
2161  }
2162 
2163  // Time spent
2164  if (!empty($arrayfields['t.task_duration']['checked'])) {
2165  print '<td class="right">';
2166  if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2167  print '<input type="hidden" name="old_duration_2" value="0">';
2168  print $form->select_duration('new_duration_2', 0, 0, 'text');
2169  } else {
2170  print convertSecondToTime($task_time->task_duration, 'allhourmin');
2171  }
2172  print '</td>';
2173  }
2174 
2175  // Value spent
2176  if (!empty($arrayfields['value']['checked'])) {
2177  print '<td class="right">';
2178  print '<span class="amount">';
2179  $value = 0;
2180  print price($value, 1, $langs, 1, -1, -1, $conf->currency);
2181  print '</span>';
2182  print '</td>';
2183  }
2184 
2185  // Value billed
2186  if (!empty($arrayfields['valuebilled']['checked'])) {
2187  print '<td class="right">';
2188  $valuebilled = price2num($task_time->total_ht, '', 1);
2189  if (isset($task_time->total_ht)) {
2190  print '<span class="amount">';
2191  print price($valuebilled, 1, $langs, 1, -1, -1, $conf->currency);
2192  print '</span>';
2193  }
2194  print '</td>';
2195  }
2196 
2197  /*
2198  // Extra fields
2199  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
2200  */
2201 
2202  // Fields from hook
2203  $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$task_time, 'mode' => 'split2');
2204  $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook
2205  print $hookmanager->resPrint;
2206 
2207  // Action column
2208  print '<td class="center nowraponall">';
2209  print '</td>';
2210 
2211  print "</tr>\n";
2212  }
2213 
2214  $i++;
2215  }
2216 
2217  // Show total line
2218  //include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
2219  if (isset($totalarray['totaldurationfield']) || isset($totalarray['totalvaluefield'])) {
2220  print '<tr class="liste_total">';
2221  $i = 0;
2222  while ($i < $totalarray['nbfield']) {
2223  $i++;
2224  if ($i == 1) {
2225  if ($num < $limit && empty($offset)) {
2226  print '<td class="left">'.$langs->trans("Total").'</td>';
2227  } else {
2228  print '<td class="left">'.$langs->trans("Totalforthispage").'</td>';
2229  }
2230  } elseif ($totalarray['totaldurationfield'] == $i) {
2231  print '<td class="right">'.convertSecondToTime($totalarray['totalduration'], 'allhourmin').'</td>';
2232  } elseif ($totalarray['totalvaluefield'] == $i) {
2233  print '<td class="right">'.price($totalarray['totalvalue']).'</td>';
2234  //} elseif ($totalarray['totalvaluebilledfield'] == $i) { print '<td class="center">'.price($totalarray['totalvaluebilled']).'</td>';
2235  } else {
2236  print '<td></td>';
2237  }
2238  }
2239  print '</tr>';
2240  }
2241 
2242  if (!count($tasks)) {
2243  $totalnboffields = 1;
2244  foreach ($arrayfields as $value) {
2245  if ($value['checked']) {
2246  $totalnboffields++;
2247  }
2248  }
2249  print '<tr class="oddeven"><td colspan="'.$totalnboffields.'">';
2250  print '<span class="opacitymedium">'.$langs->trans("None").'</span>';
2251  print '</td></tr>';
2252  }
2253 
2254  $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql);
2255  $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters); // Note that $action and $object may have been modified by hook
2256  print $hookmanager->resPrint;
2257 
2258  print "</table>";
2259  print '</div>';
2260  print "</form>";
2261  }
2262 }
2263 
2264 // End of page
2265 llxFooter();
2266 $db->close();
dol_escape_htmltag
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields.
Definition: functions.lib.php:1468
restrictedArea
restrictedArea($user, $features, $objectid=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.
Definition: security.lib.php:234
llxFooter
llxFooter()
Empty footer.
Definition: wrapper.php:73
Project
Class to manage projects.
Definition: project.class.php:35
img_error
img_error($titlealt='default')
Show error logo.
Definition: functions.lib.php:4539
GETPOST
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
Definition: functions.lib.php:484
dol_nl2br
dol_nl2br($stringtoencode, $nl2brmode=0, $forxml=false)
Replace CRLF in string with a HTML BR tag.
Definition: functions.lib.php:6963
dol_print_error
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
Definition: functions.lib.php:4844
dol_sort_array
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by second index function, which produces ascending (default) or descending output...
Definition: functions.lib.php:8385
img_warning
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
Definition: functions.lib.php:4521
Task
Class to manage tasks.
Definition: task.class.php:37
FormProjets
Class to manage building of HTML components.
Definition: html.formprojet.class.php:30
project_prepare_head
project_prepare_head(Project $project, $moreparam='')
Prepare array with list of tabs.
Definition: project.lib.php:38
img_split
img_split($titlealt='default', $other='class="pictosplit"')
Show split logo.
Definition: functions.lib.php:4463
$form
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:142
FormOther
Classe permettant la generation de composants html autre Only common components are here.
Definition: html.formother.class.php:39
FormIntervention
Class to manage generation of HTML components for contract module.
Definition: html.formintervention.class.php:28
Facture
Class to manage invoices.
Definition: facture.class.php:60
img_edit
img_edit($titlealt='default', $float=0, $other='')
Show logo editer/modifier fiche.
Definition: functions.lib.php:4389
dol_banner_tab
dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='rowid', $fieldref='ref', $morehtmlref='', $moreparam='', $nodbprefix=0, $morehtmlleft='', $morehtmlstatus='', $onlybanner=0, $morehtmlright='')
Show tab footer of a card.
Definition: functions.lib.php:2046
price2num
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
Definition: functions.lib.php:5661
convertSecondToTime
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:236
dol_print_date
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
Definition: functions.lib.php:2514
img_picto
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
Definition: functions.lib.php:3880
img_delete
img_delete($titlealt='default', $other='class="pictodelete"', $morecss='')
Show delete logo.
Definition: functions.lib.php:4429
$formconfirm
$formconfirm
if ($action == 'delbookkeepingyear') {
Definition: listbyaccount.php:576
get_default_localtax
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) Si ...
Definition: functions.lib.php:6441
dolGetButtonTitle
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.
Definition: functions.lib.php:10605
task_prepare_head
task_prepare_head($object)
Prepare array with list of tabs.
Definition: project.lib.php:335
GETPOSTINT
GETPOSTINT($paramname, $method=0)
Return value of a param into GET or POST supervariable.
Definition: functions.lib.php:795
print_barre_liste
print_barre_liste($titre, $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.
Definition: functions.lib.php:5257
dol_get_fiche_head
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='')
Show tabs of a record.
Definition: functions.lib.php:1822
getDolGlobalString
if(!function_exists('utf8_encode')) if(!function_exists('utf8_decode')) getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
Definition: functions.lib.php:80
get_default_tva
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...
Definition: functions.lib.php:6304
newToken
newToken()
Return the value of token currently saved into session with name 'newtoken'.
Definition: functions.lib.php:10878
Fichinter
Class to manage interventions.
Definition: fichinter.class.php:37
dol_get_fiche_end
dol_get_fiche_end($notab=0)
Return tab footer of a card.
Definition: functions.lib.php:2018
isModEnabled
isModEnabled($module)
Is Dolibarr module enabled.
Definition: functions.lib.php:105
User
Class to manage Dolibarr users.
Definition: user.class.php:44
GETPOSTISSET
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
Definition: functions.lib.php:386
print_liste_field_titre
print_liste_field_titre($name, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
Definition: functions.lib.php:5026
natural_search
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...
Definition: functions.lib.php:9420
ExtraFields
Class to manage standard extra fields.
Definition: extrafields.class.php:39
Product
Class to manage products or services.
Definition: product.class.php:46
Form
Class to manage generation of HTML components Only common components must be here.
Definition: html.form.class.php:52
img_object
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
Definition: functions.lib.php:4211
$resql
if(isModEnabled('facture') &&!empty($user->rights->facture->lire)) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->lire)||(isModEnabled('supplier_invoice') && $user->rights->supplier_invoice->lire)) if(isModEnabled('don') &&!empty($user->rights->don->lire)) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $resql
Social contributions to pay.
Definition: index.php:742
dolSqlDateFilter
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:334
price
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.
Definition: functions.lib.php:5541
setEventMessages
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='')
Set event messages in dol_events session object.
Definition: functions.lib.php:8137
accessforbidden
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program Calling this function terminate execution ...
Definition: security.lib.php:933
dol_mktime
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
Definition: functions.lib.php:2757
llxHeader
if(!defined('NOREQUIRESOC')) if(!defined('NOREQUIRETRAN')) if(!defined('NOCSRFCHECK')) if(!defined('NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) llxHeader()
Empty header.
Definition: wrapper.php:59