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