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