dolibarr 18.0.6
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->rights->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->rights->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->rights->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->rights->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->rights->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->rights->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 (!empty($conf->global->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 (!empty($conf->global->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)) $projectstatic->fetch_thirdparty();
796
797 if (!($projectstatic->thirdparty->id > 0)) {
798 setEventMessages($langs->trans("ThirdPartyRequiredToGenerateIntervention"), null, 'errors');
799 } else {
800 include_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
801 include_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
802 include_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
803
804
805 require_once DOL_DOCUMENT_ROOT . '/fichinter/class/fichinter.class.php';
806 $tmpinter = new Fichinter($db);
807 $tmptimespent = new Task($db);
808 $fuser = new User($db);
809
810 $db->begin();
811 $interToUse = GETPOST('interid', 'int');
812
813
814 $tmpinter->socid = $projectstatic->thirdparty->id;
815 $tmpinter->date = dol_mktime(GETPOST('rehour', 'int'), GETPOST('remin', 'int'), GETPOST('resec', 'int'), GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int'));
816 $tmpinter->fk_project = $projectstatic->id;
817 $tmpinter->description = $projectstatic->title . (!empty($projectstatic->description) ? '-' . $projectstatic->label : '');
818
819 if ($interToUse) {
820 $tmpinter->fetch($interToUse);
821 } else {
822 $result = $tmpinter->create($user);
823 if ($result <= 0) {
824 $error++;
825 setEventMessages($tmpinter->error, $tmpinter->errors, 'errors');
826 }
827 }
828
829 if (!$error) {
830 $arrayoftasks = array();
831 foreach ($toselect as $key => $value) {
832 // Get userid, timespent
833 $object->fetchTimeSpent($value);
834 // $object->id is the task id
835 $arrayoftasks[$object->timespent_id]['id'] = $object->id;
836 $arrayoftasks[$object->timespent_id]['timespent'] = $object->timespent_duration;
837 $arrayoftasks[$object->timespent_id]['totalvaluetodivideby3600'] = $object->timespent_duration * $object->timespent_thm;
838 $arrayoftasks[$object->timespent_id]['note'] = $object->timespent_note;
839 $arrayoftasks[$object->timespent_id]['date'] = date('Y-m-d H:i:s', $object->timespent_datehour);
840 }
841
842 foreach ($arrayoftasks as $timespent_id => $value) {
843 $ftask = new Task($db);
844 $ftask->fetch($value['id']);
845 // Define qty per hour
846 $qtyhour = $value['timespent'] / 3600;
847 $qtyhourtext = convertSecondToTime($value['timespent'], 'all', $conf->global->MAIN_DURATION_OF_WORKDAY);
848
849 // Add lines
850 $lineid = $tmpinter->addline($user, $tmpinter->id, $ftask->label . (!empty($value['note']) ? ' - ' . $value['note'] : ''), $value['date'], $value['timespent']);
851 }
852 }
853
854 if (!$error) {
855 $urltointer = $tmpinter->getNomUrl(0);
856 $mesg = $langs->trans("InterventionGeneratedFromTimeSpent", '{s1}');
857 $mesg = str_replace('{s1}', $urltointer, $mesg);
858 setEventMessages($mesg, null, 'mesgs');
859
860 //var_dump($tmpinvoice);
861
862 $db->commit();
863 } else {
864 $db->rollback();
865 }
866 }
867}
868
869
870/*
871 * View
872 */
873
874$form = new Form($db);
875$formother = new FormOther($db);
876$formproject = new FormProjets($db);
877$userstatic = new User($db);
878//$result = $projectstatic->fetch($object->fk_project);
879$arrayofselected = is_array($toselect) ? $toselect : array();
880
881$title = $object->ref . ' - ' . $langs->trans("TimeSpent");
882if (!empty($withproject)) {
883 $title .= ' | ' . $langs->trans("Project") . (!empty($projectstatic->ref) ? ': ' . $projectstatic->ref : '');
884}
885$help_url = '';
886
887llxHeader('', $title, $help_url);
888
889if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser > 0) {
890 /*
891 * Fiche projet en mode visu
892 */
893 if ($projectidforalltimes > 0) {
894 $result = $projectstatic->fetch($projectidforalltimes);
895 if (!empty($projectstatic->socid)) {
896 $projectstatic->fetch_thirdparty();
897 }
898 $res = $projectstatic->fetch_optionals();
899 } elseif ($object->fetch($id, $ref) >= 0) {
900 if (!empty($conf->global->PROJECT_ALLOW_COMMENT_ON_TASK) && method_exists($object, 'fetchComments') && empty($object->comments)) {
901 $object->fetchComments();
902 }
903 $result = $projectstatic->fetch($object->fk_project);
904 if (!empty($conf->global->PROJECT_ALLOW_COMMENT_ON_PROJECT) && method_exists($projectstatic, 'fetchComments') && empty($projectstatic->comments)) {
905 $projectstatic->fetchComments();
906 }
907 if (!empty($projectstatic->socid)) {
908 $projectstatic->fetch_thirdparty();
909 }
910 $res = $projectstatic->fetch_optionals();
911
912 $object->project = clone $projectstatic;
913 }
914
915 $userRead = $projectstatic->restrictedProjectArea($user, 'read');
916 $linktocreatetime = '';
917
918 if ($projectstatic->id > 0) {
919 if ($withproject) {
920 // Tabs for project
921 if (empty($id) || $tab == 'timespent') {
922 $tab = 'timespent';
923 } else {
924 $tab = 'tasks';
925 }
926
927 $head = project_prepare_head($projectstatic);
928 print dol_get_fiche_head($head, $tab, $langs->trans("Project"), -1, ($projectstatic->public ? 'projectpub' : 'project'));
929
930 $param = ((!empty($mode) && $mode == 'mine') ? '&mode=mine' : '');
931 if ($search_user) {
932 $param .= '&search_user=' . ((int) $search_user);
933 }
934 if ($search_month) {
935 $param .= '&search_month=' . ((int) $search_month);
936 }
937 if ($search_year) {
938 $param .= '&search_year=' . ((int) $search_year);
939 }
940
941 // Project card
942
943 if (!empty($_SESSION['pageforbacktolist']) && !empty($_SESSION['pageforbacktolist']['project'])) {
944 $tmpurl = $_SESSION['pageforbacktolist']['project'];
945 $tmpurl = preg_replace('/__SOCID__/', $projectstatic->socid, $tmpurl);
946 $linkback = '<a href="'.$tmpurl.(preg_match('/\?/', $tmpurl) ? '&' : '?'). 'restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
947 } else {
948 $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
949 }
950
951 $morehtmlref = '<div class="refidno">';
952 // Title
953 $morehtmlref .= $projectstatic->title;
954 // Thirdparty
955 if (!empty($projectstatic->thirdparty->id) && $projectstatic->thirdparty->id > 0) {
956 $morehtmlref .= '<br>' . $projectstatic->thirdparty->getNomUrl(1, 'project');
957 }
958 $morehtmlref .= '</div>';
959
960 // Define a complementary filter for search of next/prev ref.
961 if (empty($user->rights->projet->all->lire)) {
962 $objectsListId = $projectstatic->getProjectsAuthorizedForUser($user, 0, 0);
963 $projectstatic->next_prev_filter = "rowid IN (" . $db->sanitize(count($objectsListId) ? join(',', array_keys($objectsListId)) : '0') . ")";
964 }
965
966 dol_banner_tab($projectstatic, 'project_ref', $linkback, 1, 'ref', 'ref', $morehtmlref, $param);
967
968 print '<div class="fichecenter">';
969 print '<div class="fichehalfleft">';
970 print '<div class="underbanner clearboth"></div>';
971
972 print '<table class="border tableforfield centpercent">';
973
974 // Usage
975 if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES) || empty($conf->global->PROJECT_HIDE_TASKS) || isModEnabled('eventorganization')) {
976 print '<tr><td class="tdtop">';
977 print $langs->trans("Usage");
978 print '</td>';
979 print '<td>';
980 if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) {
981 print '<input type="checkbox" disabled name="usage_opportunity"' . (GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ($projectstatic->usage_opportunity ? ' checked="checked"' : '')) . '"> ';
982 $htmltext = $langs->trans("ProjectFollowOpportunity");
983 print $form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext);
984 print '<br>';
985 }
986 if (empty($conf->global->PROJECT_HIDE_TASKS)) {
987 print '<input type="checkbox" disabled name="usage_task"' . (GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($projectstatic->usage_task ? ' checked="checked"' : '')) . '"> ';
988 $htmltext = $langs->trans("ProjectFollowTasks");
989 print $form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext);
990 print '<br>';
991 }
992 if (empty($conf->global->PROJECT_HIDE_TASKS) && !empty($conf->global->PROJECT_BILL_TIME_SPENT)) {
993 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"' : '')) . '"> ';
994 $htmltext = $langs->trans("ProjectBillTimeDescription");
995 print $form->textwithpicto($langs->trans("BillTime"), $htmltext);
996 print '<br>';
997 }
998 if (isModEnabled('eventorganization')) {
999 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"' : '')) . '"> ';
1000 $htmltext = $langs->trans("EventOrganizationDescriptionLong");
1001 print $form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext);
1002 }
1003 print '</td></tr>';
1004 }
1005
1006 // Visibility
1007 print '<tr><td class="titlefield">' . $langs->trans("Visibility") . '</td><td>';
1008 if ($projectstatic->public) {
1009 print img_picto($langs->trans('SharedProject'), 'world', 'class="paddingrightonly"');
1010 print $langs->trans('SharedProject');
1011 } else {
1012 print img_picto($langs->trans('PrivateProject'), 'private', 'class="paddingrightonly"');
1013 print $langs->trans('PrivateProject');
1014 }
1015 print '</td></tr>';
1016
1017 // Budget
1018 print '<tr><td>' . $langs->trans("Budget") . '</td><td>';
1019 if (!is_null($projectstatic->budget_amount) && strcmp($projectstatic->budget_amount, '')) {
1020 print '<span class="amount">' . price($projectstatic->budget_amount, '', $langs, 1, 0, 0, $conf->currency) . '</span>';
1021 }
1022 print '</td></tr>';
1023
1024 // Date start - end project
1025 print '<tr><td>' . $langs->trans("Dates") . '</td><td>';
1026 $start = dol_print_date($projectstatic->date_start, 'day');
1027 print ($start ? $start : '?');
1028 $end = dol_print_date($projectstatic->date_end, 'day');
1029 print ' - ';
1030 print ($end ? $end : '?');
1031 if ($projectstatic->hasDelay()) {
1032 print img_warning("Late");
1033 }
1034 print '</td></tr>';
1035
1036 // Other attributes
1037 $cols = 2;
1038 $savobject = $object;
1039 $object = $projectstatic;
1040 include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
1041 $object = $savobject;
1042
1043 print '</table>';
1044
1045 print '</div>';
1046 print '<div class="fichehalfright">';
1047 print '<div class="underbanner clearboth"></div>';
1048
1049 print '<table class="border tableforfield centpercent">';
1050
1051 // Description
1052 print '<td class="titlefield tdtop">'.$langs->trans("Description").'</td><td>';
1053 print dol_htmlentitiesbr($projectstatic->description);
1054 print '</td></tr>';
1055
1056 // Categories
1057 if (isModEnabled('categorie')) {
1058 print '<tr><td class="valignmiddle">' . $langs->trans("Categories") . '</td><td>';
1059 print $form->showCategories($projectstatic->id, 'project', 1);
1060 print "</td></tr>";
1061 }
1062
1063 print '</table>';
1064
1065 print '</div>';
1066 print '</div>';
1067
1068 print '<div class="clearboth"></div>';
1069
1070 print dol_get_fiche_end();
1071
1072 print '<br>';
1073 }
1074
1075 $param = '';
1076
1077 // Link to create time
1078 $linktocreatetimeBtnStatus = 0;
1079 $linktocreatetimeUrl = '';
1080 $linktocreatetimeHelpText = '';
1081 if (!empty($user->rights->projet->time)) {
1082 if ($projectstatic->public || $userRead > 0) {
1083 $linktocreatetimeBtnStatus = 1;
1084
1085 if (!empty($projectidforalltimes)) {
1086 // We are on tab 'Time Spent' of project
1087 $backtourl = $_SERVER['PHP_SELF'] . '?projectid=' . $projectstatic->id . ($withproject ? '&withproject=1' : '');
1088 $linktocreatetimeUrl = $_SERVER['PHP_SELF'] . '?' . ($withproject ? 'withproject=1' : '') . '&projectid=' . $projectstatic->id . '&action=createtime&token=' . newToken() . $param . '&backtopage=' . urlencode($backtourl);
1089 } else {
1090 // We are on tab 'Time Spent' of task
1091 $backtourl = $_SERVER['PHP_SELF'] . '?id=' . $object->id . ($withproject ? '&withproject=1' : '');
1092 $linktocreatetimeUrl = $_SERVER['PHP_SELF'] . '?' . ($withproject ? 'withproject=1' : '') . ($object->id > 0 ? '&id=' . $object->id : '&projectid=' . $projectstatic->id) . '&action=createtime&token=' . newToken() . $param . '&backtopage=' . urlencode($backtourl);
1093 }
1094 } else {
1095 $linktocreatetimeBtnStatus = -2;
1096 $linktocreatetimeHelpText = $langs->trans("NotOwnerOfProject");
1097 }
1098 } else {
1099 $linktocreatetimeBtnStatus = -2;
1100 $linktocreatetimeHelpText = $langs->trans("NotEnoughPermissions");
1101 }
1102
1103 $paramsbutton = array('morecss' => 'reposition');
1104 $linktocreatetime = dolGetButtonTitle($langs->trans('AddTimeSpent'), $linktocreatetimeHelpText, 'fa fa-plus-circle', $linktocreatetimeUrl, '', $linktocreatetimeBtnStatus, $paramsbutton);
1105 }
1106
1107 $massactionbutton = '';
1108 $arrayofmassactions = array();
1109
1110 if ($projectstatic->id > 0) {
1111 // If we are on a given project.
1112 if ($projectstatic->usage_bill_time) {
1113 $arrayofmassactions = array(
1114 'generateinvoice' => $langs->trans("GenerateBill"),
1115 //'builddoc'=>$langs->trans("PDFMerge"),
1116 );
1117 }
1118 if (isModEnabled('ficheinter') && $user->hasRight('ficheinter', 'creer')) {
1119 $langs->load("interventions");
1120 $arrayofmassactions['generateinter'] = $langs->trans("GenerateInter");
1121 }
1122 }
1123 //if ($user->rights->projet->creer) $arrayofmassactions['predelete']='<span class="fa fa-trash paddingrightonly"></span>'.$langs->trans("Delete");
1124 if (in_array($massaction, array('presend', 'predelete', 'generateinvoice', 'generateinter'))) {
1125 $arrayofmassactions = array();
1126 }
1127 $massactionbutton = $form->selectMassAction('', $arrayofmassactions);
1128
1129 // Task
1130
1131 // Show section with information of task. If id of task is not defined and project id defined, then $projectidforalltimes is not empty.
1132 if (empty($projectidforalltimes) && empty($allprojectforuser)) {
1133 $head = task_prepare_head($object);
1134 print dol_get_fiche_head($head, 'task_time', $langs->trans("Task"), -1, 'projecttask', 0, '', 'reposition');
1135
1136 if ($action == 'deleteline') {
1137 $urlafterconfirm = $_SERVER["PHP_SELF"] . "?" . ($object->id > 0 ? "id=" . $object->id : 'projectid=' . $projectstatic->id) . '&lineid=' . GETPOST("lineid", 'int') . ($withproject ? '&withproject=1' : '');
1138 print $form->formconfirm($urlafterconfirm, $langs->trans("DeleteATimeSpent"), $langs->trans("ConfirmDeleteATimeSpent"), "confirm_deleteline", '', '', 1);
1139 }
1140
1141 $param = ($withproject ? '&withproject=1' : '');
1142 $param .= ($param ? '&' : '') . 'id=' . $object->id; // ID of task
1143 $linkback = $withproject ? '<a href="' . DOL_URL_ROOT . '/projet/tasks.php?id=' . $projectstatic->id . '">' . $langs->trans("BackToList") . '</a>' : '';
1144
1145 if (!GETPOST('withproject') || empty($projectstatic->id)) {
1146 $projectsListId = $projectstatic->getProjectsAuthorizedForUser($user, 0, 1);
1147 $object->next_prev_filter = "fk_projet IN (" . $db->sanitize($projectsListId) . ")";
1148 } else {
1149 $object->next_prev_filter = "fk_projet = " . ((int) $projectstatic->id);
1150 }
1151
1152 $morehtmlref = '';
1153
1154 // Project
1155 if (empty($withproject)) {
1156 $morehtmlref .= '<div class="refidno">';
1157 $morehtmlref .= $langs->trans("Project") . ': ';
1158 $morehtmlref .= $projectstatic->getNomUrl(1);
1159 $morehtmlref .= '<br>';
1160
1161 // Third party
1162 $morehtmlref .= $langs->trans("ThirdParty") . ': ';
1163 if (!empty($projectstatic->thirdparty) && is_object($projectstatic->thirdparty)) {
1164 $morehtmlref .= $projectstatic->thirdparty->getNomUrl(1);
1165 }
1166 $morehtmlref .= '</div>';
1167 }
1168
1169 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref, $param);
1170
1171 print '<div class="fichecenter">';
1172 print '<div class="fichehalfleft">';
1173
1174 print '<div class="underbanner clearboth"></div>';
1175 print '<table class="border centpercent tableforfield">';
1176
1177 // Task parent
1178 print '<tr><td>' . $langs->trans("ChildOfTask") . '</td><td>';
1179 if ($object->fk_task_parent > 0) {
1180 $tasktmp = new Task($db);
1181 $tasktmp->fetch($object->fk_task_parent);
1182 print $tasktmp->getNomUrl(1);
1183 }
1184 print '</td></tr>';
1185
1186 // Date start - Date end task
1187 print '<tr><td class="titlefield">' . $langs->trans("DateStart") . ' - ' . $langs->trans("Deadline") . '</td><td>';
1188 $start = dol_print_date($object->date_start, 'dayhour');
1189 print ($start ? $start : '?');
1190 $end = dol_print_date($object->date_end, 'dayhour');
1191 print ' - ';
1192 print ($end ? $end : '?');
1193 if ($object->hasDelay()) {
1194 print img_warning("Late");
1195 }
1196 print '</td></tr>';
1197
1198 // Planned workload
1199 print '<tr><td>' . $langs->trans("PlannedWorkload") . '</td><td>';
1200 if ($object->planned_workload) {
1201 print convertSecondToTime($object->planned_workload, 'allhourmin');
1202 }
1203 print '</td></tr>';
1204
1205 print '</table>';
1206 print '</div>';
1207
1208 print '<div class="fichehalfright">';
1209
1210 print '<div class="underbanner clearboth"></div>';
1211 print '<table class="border tableforfield centpercent">';
1212
1213 // Progress declared
1214 print '<tr><td class="titlefield">' . $langs->trans("ProgressDeclared") . '</td><td>';
1215 print $object->progress != '' ? $object->progress . ' %' : '';
1216 print '</td></tr>';
1217
1218 // Progress calculated
1219 print '<tr><td>' . $langs->trans("ProgressCalculated") . '</td><td>';
1220 if ($object->planned_workload) {
1221 $tmparray = $object->getSummaryOfTimeSpent();
1222 if ($tmparray['total_duration'] > 0) {
1223 print round($tmparray['total_duration'] / $object->planned_workload * 100, 2) . ' %';
1224 } else {
1225 print '0 %';
1226 }
1227 } else {
1228 print '<span class="opacitymedium">' . $langs->trans("WorkloadNotDefined") . '</span>';
1229 }
1230 print '</td>';
1231
1232 print '</tr>';
1233
1234 print '</table>';
1235
1236 print '</div>';
1237
1238 print '</div>';
1239 print '<div class="clearboth"></div>';
1240
1241 print dol_get_fiche_end();
1242 } else {
1243 if ($action == 'deleteline') {
1244 $urlafterconfirm = $_SERVER["PHP_SELF"] . "?" . ($object->id > 0 ? "id=" . $object->id : 'projectid=' . $projectstatic->id) . '&lineid=' . GETPOST("lineid", 'int') . ($withproject ? '&withproject=1' : '');
1245 print $form->formconfirm($urlafterconfirm, $langs->trans("DeleteATimeSpent"), $langs->trans("ConfirmDeleteATimeSpent"), "confirm_deleteline", '', '', 1);
1246 }
1247 }
1248
1249
1250 if ($projectstatic->id > 0 || $allprojectforuser > 0) {
1251 // Initialize technical object to manage hooks. Note that conf->hooks_modules contains array
1252 $hookmanager->initHooks(array('tasktimelist'));
1253
1254 $formconfirm = '';
1255
1256 if ($action == 'deleteline' && !empty($projectidforalltimes)) {
1257 // We must use projectidprojectid if on list of timespent of project and id=taskid if on list of timespent of a task
1258 $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);
1259 $formconfirm = $form->formconfirm($urlafterconfirm, $langs->trans("DeleteATimeSpent"), $langs->trans("ConfirmDeleteATimeSpent"), "confirm_deleteline", '', '', 1);
1260 }
1261
1262 // Call Hook formConfirm
1263 $parameters = array('formConfirm' => $formconfirm, "projectstatic" => $projectstatic, "withproject" => $withproject);
1264 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1265 if (empty($reshook)) {
1266 $formconfirm .= $hookmanager->resPrint;
1267 } elseif ($reshook > 0) {
1268 $formconfirm = $hookmanager->resPrint;
1269 }
1270
1271 // Print form confirm
1272 print $formconfirm;
1273
1274 // Definition of fields for list
1275 $arrayfields = array();
1276 $arrayfields['t.element_date'] = array('label'=>$langs->trans("Date"), 'checked'=>1);
1277 $arrayfields['p.fk_soc'] = array('label'=>$langs->trans("ThirdParty"), 'type'=>'integer:Societe:/societe/class/societe.class.php:1','checked'=>1);
1278 $arrayfields['s.name_alias'] = array('label'=>$langs->trans("AliasNameShort"), 'type'=>'integer:Societe:/societe/class/societe.class.php:1');
1279 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
1280 if (! empty($allprojectforuser)) {
1281 $arrayfields['p.project_ref'] = ['label' => $langs->trans('RefProject'), 'checked' => 1];
1282 $arrayfields['p.project_label'] = ['label' => $langs->trans('ProjectLabel'), 'checked' => 1];
1283 }
1284 $arrayfields['t.element_ref'] = array('label'=>$langs->trans("RefTask"), 'checked'=>1);
1285 $arrayfields['t.element_label'] = array('label'=>$langs->trans("LabelTask"), 'checked'=>1);
1286 }
1287 $arrayfields['author'] = array('label' => $langs->trans("By"), 'checked' => 1);
1288 $arrayfields['t.note'] = array('label' => $langs->trans("Note"), 'checked' => 1);
1289 if (isModEnabled('service') && !empty($projectstatic->thirdparty) && $projectstatic->thirdparty->id > 0 && $projectstatic->usage_bill_time) {
1290 $arrayfields['t.fk_product'] = array('label' => $langs->trans("Product"), 'checked' => 1);
1291 }
1292 $arrayfields['t.element_duration'] = array('label'=>$langs->trans("Duration"), 'checked'=>1);
1293 $arrayfields['value'] = array('label'=>$langs->trans("Value"), 'checked'=>1, 'enabled'=>isModEnabled("salaries"));
1294 $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));
1295 // Extra fields
1296 include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_list_array_fields.tpl.php';
1297
1298 $arrayfields = dol_sort_array($arrayfields, 'position');
1299
1300 $param = '';
1301 if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
1302 $param .= '&contextpage=' . urlencode($contextpage);
1303 }
1304 if ($limit > 0 && $limit != $conf->liste_limit) {
1305 $param .= '&limit='.((int) $limit);
1306 }
1307 if ($search_month > 0) {
1308 $param .= '&search_month=' . urlencode($search_month);
1309 }
1310 if ($search_year > 0) {
1311 $param .= '&search_year=' . urlencode($search_year);
1312 }
1313 if (!empty($search_user)) { // We keep param if -1 because default value is forced to user id if not set
1314 $param .= '&search_user='.urlencode($search_user);
1315 }
1316 if ($search_task_ref != '') {
1317 $param .= '&search_task_ref=' . urlencode($search_task_ref);
1318 }
1319 if ($search_company != '') {
1320 $param .= '&amp;$search_company=' . urlencode($search_company);
1321 }
1322 if ($search_company_alias != '') {
1323 $param .= '&amp;$search_company_alias=' . urlencode($search_company_alias);
1324 }
1325 if ($search_project_ref != '') {
1326 $param .= '&amp;$search_project_ref=' . urlencode($search_project_ref);
1327 }
1328 if ($search_project_label != '') {
1329 $param .= '&amp;$search_project_label=' . urlencode($search_project_label);
1330 }
1331 if ($search_task_label != '') {
1332 $param .= '&search_task_label=' . urlencode($search_task_label);
1333 }
1334 if ($search_note != '') {
1335 $param .= '&search_note=' . urlencode($search_note);
1336 }
1337 if ($search_duration != '') {
1338 $param .= '&amp;search_field2=' . urlencode($search_duration);
1339 }
1340 if ($optioncss != '') {
1341 $param .= '&optioncss=' . urlencode($optioncss);
1342 }
1343 if ($search_date_startday) {
1344 $param .= '&search_date_startday=' . urlencode($search_date_startday);
1345 }
1346 if ($search_date_startmonth) {
1347 $param .= '&search_date_startmonth=' . urlencode($search_date_startmonth);
1348 }
1349 if ($search_date_startyear) {
1350 $param .= '&search_date_startyear=' . urlencode($search_date_startyear);
1351 }
1352 if ($search_date_endday) {
1353 $param .= '&search_date_endday=' . urlencode($search_date_endday);
1354 }
1355 if ($search_date_endmonth) {
1356 $param .= '&search_date_endmonth=' . urlencode($search_date_endmonth);
1357 }
1358 if ($search_date_endyear) {
1359 $param .= '&search_date_endyear=' . urlencode($search_date_endyear);
1360 }
1361 if ($search_timespent_starthour) {
1362 $param .= '&search_timespent_duration_starthour=' . urlencode($search_timespent_starthour);
1363 }
1364 if ($search_timespent_startmin) {
1365 $param .= '&search_timespent_duration_startmin=' . urlencode($search_timespent_startmin);
1366 }
1367 if ($search_timespent_endhour) {
1368 $param .= '&search_timespent_duration_endhour=' . urlencode($search_timespent_endhour);
1369 }
1370 if ($search_timespent_endmin) {
1371 $param .= '&search_timespent_duration_endmin=' . urlencode($search_timespent_endmin);
1372 }
1373
1374 /*
1375 // Add $param from extra fields
1376 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
1377 */
1378 if ($id) {
1379 $param .= '&id=' . urlencode($id);
1380 }
1381 if ($projectid) {
1382 $param .= '&projectid=' . urlencode($projectid);
1383 }
1384 if ($withproject) {
1385 $param .= '&withproject=' . urlencode($withproject);
1386 }
1387 // Add $param from hooks
1388 $parameters = array();
1389 $reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object); // Note that $action and $object may have been modified by hook
1390 $param .= $hookmanager->resPrint;
1391
1392 print '<form method="POST" action="' . $_SERVER["PHP_SELF"] . '">';
1393 if ($optioncss != '') {
1394 print '<input type="hidden" name="optioncss" value="' . $optioncss . '">';
1395 }
1396 print '<input type="hidden" name="token" value="' . newToken() . '">';
1397 print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
1398 if ($action == 'editline') {
1399 print '<input type="hidden" name="action" value="updateline">';
1400 } elseif ($action == 'splitline') {
1401 print '<input type="hidden" name="action" value="updatesplitline">';
1402 } elseif ($action == 'createtime' && $user->rights->projet->time) {
1403 print '<input type="hidden" name="action" value="addtimespent">';
1404 } elseif ($massaction == 'generateinvoice' && $user->hasRight('facture', 'creer')) {
1405 print '<input type="hidden" name="action" value="confirm_generateinvoice">';
1406 } elseif ($massaction == 'generateinter' && $user->hasRight('ficheinter', 'creer')) {
1407 print '<input type="hidden" name="action" value="confirm_generateinter">';
1408 } else {
1409 print '<input type="hidden" name="action" value="list">';
1410 }
1411 print '<input type="hidden" name="sortfield" value="' . $sortfield . '">';
1412 print '<input type="hidden" name="sortorder" value="' . $sortorder . '">';
1413
1414 print '<input type="hidden" name="id" value="' . $id . '">';
1415 print '<input type="hidden" name="projectid" value="' . $projectidforalltimes . '">';
1416 print '<input type="hidden" name="withproject" value="' . $withproject . '">';
1417 print '<input type="hidden" name="tab" value="' . $tab . '">';
1418 print '<input type="hidden" name="page_y" value="">';
1419
1420 // Form to convert time spent into invoice
1421 if ($massaction == 'generateinvoice') {
1422 if (!empty($projectstatic->thirdparty) && $projectstatic->thirdparty->id > 0) {
1423 print '<table class="noborder centerpercent">';
1424 print '<tr>';
1425 print '<td class="titlefield">';
1426 print $langs->trans('DateInvoice');
1427 print '</td>';
1428 print '<td>';
1429 print $form->selectDate('', '', '', '', '', '', 1, 1);
1430 print '</td>';
1431 print '</tr>';
1432
1433 print '<tr>';
1434 print '<td>';
1435 print $langs->trans('Mode');
1436 print '</td>';
1437 print '<td>';
1438 $tmparray = array(
1439 'onelineperuser' => 'OneLinePerUser',
1440 'onelinepertask' => 'OneLinePerTask',
1441 'onelineperperiod' => 'OneLinePerTimeSpentLine',
1442 );
1443 print $form->selectarray('generateinvoicemode', $tmparray, 'onelineperuser', 0, 0, 0, '', 1);
1444 print "\n" . '<script type="text/javascript">';
1445 print '
1446 $(document).ready(function () {
1447 setDetailVisibility();
1448 $("#generateinvoicemode").change(function() {
1449 setDetailVisibility();
1450 });
1451 function setDetailVisibility() {
1452 generateinvoicemode = $("#generateinvoicemode option:selected").val();
1453 if (generateinvoicemode=="onelineperperiod") {
1454 $("#detail_time_duration").show();
1455 } else {
1456 $("#detail_time_duration").hide();
1457 }
1458 }
1459 });
1460 ';
1461 print '</script>' . "\n";
1462 print '<span style="display:none" id="detail_time_duration"><input type="checkbox" value="detail" name="detail_time_duration"/>' . $langs->trans('AddDetailDateAndDuration') . '</span>';
1463 print '</td>';
1464 print '</tr>';
1465
1466 if (isModEnabled("service")) {
1467 print '<tr>';
1468 print '<td>';
1469 print $langs->trans('ServiceToUseOnLines');
1470 print '</td>';
1471 print '<td>';
1472 $form->select_produits('', 'productid', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 0, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth500');
1473 print '</td>';
1474 print '</tr>';
1475 }
1476
1477 print '<tr>';
1478 print '<td class="titlefield">';
1479 print $langs->trans('InvoiceToUse');
1480 print '</td>';
1481 print '<td>';
1482 print $form->selectInvoice($projectstatic->thirdparty->id, '', 'invoiceid', 24, 0, $langs->trans('NewInvoice'), 1, 0, 0, 'maxwidth500', '', 'all');
1483 print '</td>';
1484 print '</tr>';
1485 /*print '<tr>';
1486 print '<td>';
1487 print $langs->trans('ValidateInvoices');
1488 print '</td>';
1489 print '<td>';
1490 print $form->selectyesno('validate_invoices', 0, 1);
1491 print '</td>';
1492 print '</tr>';*/
1493 print '</table>';
1494
1495 print '<br>';
1496 print '<div class="center">';
1497 print '<input type="submit" class="button" id="createbills" name="createbills" value="' . $langs->trans('GenerateBill') . '"> ';
1498 print '<input type="submit" class="button button-cancel" id="cancel" name="cancel" value="' . $langs->trans("Cancel") . '">';
1499 print '</div>';
1500 print '<br>';
1501 } else {
1502 print '<div class="warning">' . $langs->trans("ThirdPartyRequiredToGenerateInvoice") . '</div>';
1503 print '<div class="center">';
1504 print '<input type="submit" class="button button-cancel" id="cancel" name="cancel" value="' . $langs->trans("Cancel") . '">';
1505 print '</div>';
1506 $massaction = '';
1507 }
1508 } elseif ($massaction == 'generateinter') {
1509 // Form to convert time spent into invoice
1510 print '<input type="hidden" name="massaction" value="confirm_createinter">';
1511
1512 if (!empty($projectstatic->thirdparty) && $projectstatic->thirdparty->id > 0) {
1513 print '<br>';
1514 print '<table class="noborder centpercent">';
1515 print '<tr>';
1516 print '<td class="titlefield">';
1517 print img_picto('', 'intervention', 'class="pictofixedwidth"') . $langs->trans('InterToUse');
1518 print '</td>';
1519 print '<td>';
1520 $forminter = new FormIntervention($db);
1521 print $forminter->select_interventions($projectstatic->thirdparty->id, '', 'interid', 24, $langs->trans('NewInter'), true);
1522 print '</td>';
1523 print '</tr>';
1524 print '</table>';
1525
1526 print '<div class="center">';
1527 print '<input type="submit" class="button" id="createinter" name="createinter" value="' . $langs->trans('GenerateInter') . '"> ';
1528 print '<input type="submit" class="button" id="cancel" name="cancel" value="' . $langs->trans('Cancel') . '">';
1529 print '</div>';
1530 print '<br>';
1531 } else {
1532 print '<div class="warning">' . $langs->trans("ThirdPartyRequiredToGenerateIntervention") . '</div>';
1533 print '<div class="center">';
1534 print '<input type="submit" class="button" id="cancel" name="cancel" value="' . $langs->trans('Cancel') . '">';
1535 print '</div>';
1536 $massaction = '';
1537 }
1538 }
1539
1540 // Allow Pre-Mass-Action hook (eg for confirmation dialog)
1541 $parameters = array(
1542 'toselect' => $toselect,
1543 'uploaddir' => isset($uploaddir) ? $uploaddir : null
1544 );
1545
1546 $reshook = $hookmanager->executeHooks('doPreMassActions', $parameters, $object, $action);
1547 if ($reshook < 0) {
1548 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1549 } else {
1550 print $hookmanager->resPrint;
1551 }
1552
1553 /*
1554 * List of time spent
1555 */
1556 $tasks = array();
1557
1558 $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
1559 $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')); // This also change content of $arrayfields
1560
1561 $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,";
1562 $sql .= " t.fk_product,";
1563 $sql .= " pt.ref, pt.label, pt.fk_projet,";
1564 $sql .= " u.lastname, u.firstname, u.login, u.photo, u.statut as user_status,";
1565 $sql .= " il.fk_facture as invoice_id, inv.fk_statut,";
1566 $sql .= " p.fk_soc,s.name_alias,";
1567 $sql .= " t.invoice_line_id";
1568 // Add fields from hooks
1569 $parameters = array();
1570 $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook
1571 $sql .= $hookmanager->resPrint;
1572 $sql = preg_replace('/,\s*$/', '', $sql);
1573
1574 $sqlfields = $sql; // $sql fields to remove for count total
1575
1576 $sql .= " FROM ".MAIN_DB_PREFIX."element_time as t";
1577 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facturedet as il ON il.rowid = t.invoice_line_id";
1578 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture as inv ON inv.rowid = il.fk_facture";
1579 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as prod ON prod.rowid = t.fk_product";
1580 $sql .= " INNER JOIN ".MAIN_DB_PREFIX."projet_task as pt ON pt.rowid = t.fk_element";
1581 $sql .= " INNER JOIN ".MAIN_DB_PREFIX."projet as p ON p.rowid = pt.fk_projet";
1582 $sql .= " INNER JOIN ".MAIN_DB_PREFIX."user as u ON t.fk_user = u.rowid";
1583 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = p.fk_soc";
1584
1585 // Add table from hooks
1586 $parameters = array();
1587 $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook
1588 $sql .= $hookmanager->resPrint;
1589 $sql .= " WHERE elementtype = 'task'";
1590 $sql .= " AND p.entity IN (".getEntity('project').")";
1591 if (empty($projectidforalltimes) && empty($allprojectforuser)) {
1592 // Limit on one task
1593 $sql .= " AND t.fk_element =".((int) $object->id);
1594 } elseif (!empty($projectidforalltimes)) {
1595 // Limit on one project
1596 $sql .= " AND pt.fk_projet IN (" . $db->sanitize($projectidforalltimes) . ")";
1597 } elseif (!empty($allprojectforuser)) {
1598 // Limit on on user
1599 if (empty($search_user)) {
1600 $search_user = $user->id;
1601 }
1602 if ($search_user > 0) $sql .= " AND t.fk_user = " . ((int) $search_user);
1603 }
1604
1605 if ($search_note) {
1606 $sql .= natural_search('t.note', $search_note);
1607 }
1608 if ($search_task_ref) {
1609 $sql .= natural_search('pt.ref', $search_task_ref);
1610 }
1611 if (empty($arrayfields['s.name_alias']['checked']) && $search_company) {
1612 $sql .= natural_search(array("s.nom", "s.name_alias"), $search_company);
1613 } else {
1614 if ($search_company) {
1615 $sql .= natural_search('s.nom', $search_company);
1616 }
1617 if ($search_company_alias) {
1618 $sql .= natural_search('s.name_alias', $search_company_alias);
1619 }
1620 }
1621 if ($search_project_ref) {
1622 $sql .= natural_search('p.ref', $search_project_ref);
1623 }
1624 if ($search_project_label) {
1625 $sql .= natural_search('p.title', $search_project_label);
1626 }
1627 if ($search_task_label) {
1628 $sql .= natural_search('pt.label', $search_task_label);
1629 }
1630 if ($search_user > 0) {
1631 $sql .= natural_search('t.fk_user', $search_user, 2);
1632 }
1633 if (!empty($search_product_ref)) {
1634 $sql .= natural_search('prod.ref', $search_product_ref);
1635 }
1636 if ($search_valuebilled == '1') {
1637 $sql .= ' AND t.invoice_id > 0';
1638 }
1639 if ($search_valuebilled == '0') {
1640 $sql .= ' AND (t.invoice_id = 0 OR t.invoice_id IS NULL)';
1641 }
1642
1643 if ($search_date_start) {
1644 $sql .= " AND t.element_date >= '".$db->idate($search_date_start)."'";
1645 }
1646 if ($search_date_end) {
1647 $sql .= " AND t.element_date <= '".$db->idate($search_date_end)."'";
1648 }
1649
1650 if (!empty($arrayfields['t.element_duration']['checked'])) {
1651 if ($search_timespent_starthour || $search_timespent_startmin) {
1652 $timespent_duration_start = $search_timespent_starthour * 60 * 60; // We store duration in seconds
1653 $timespent_duration_start += ($search_timespent_startmin ? $search_timespent_startmin : 0) * 60; // We store duration in seconds
1654 $sql .= " AND t.element_duration >= " . $timespent_duration_start;
1655 }
1656
1657 if ($search_timespent_endhour || $search_timespent_endmin) {
1658 $timespent_duration_end = $search_timespent_endhour * 60 * 60; // We store duration in seconds
1659 $timespent_duration_end += ($search_timespent_endmin ? $search_timespent_endmin : 0) * 60; // We store duration in seconds
1660 $sql .= " AND t.element_duration <= " . $timespent_duration_end;
1661 }
1662 }
1663
1664 $sql .= dolSqlDateFilter('t.element_datehour', $search_day, $search_month, $search_year);
1665
1666 // Add where from hooks
1667 $parameters = array();
1668 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook
1669 $sql .= $hookmanager->resPrint;
1670
1671 // Count total nb of records
1672 $nbtotalofrecords = '';
1673 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
1674 /* The fast and low memory method to get and count full list converts the sql into a sql count */
1675 $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql);
1676 $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount);
1677 $resql = $db->query($sqlforcount);
1678 if ($resql) {
1679 $objforcount = $db->fetch_object($resql);
1680 $nbtotalofrecords = $objforcount->nbtotalofrecords;
1681 } else {
1682 dol_print_error($db);
1683 }
1684
1685 if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 0
1686 $page = 0;
1687 $offset = 0;
1688 }
1689 $db->free($resql);
1690 }
1691
1692 // Complete request and execute it with limit
1693 $sql .= $db->order($sortfield, $sortorder);
1694 if ($limit) {
1695 $sql .= $db->plimit($limit + 1, $offset);
1696 }
1697
1698 $resql = $db->query($sql);
1699 if (!$resql) {
1700 dol_print_error($db);
1701 exit;
1702 }
1703
1704 $num = $db->num_rows($resql);
1705
1706 if ($num >= 0) {
1707 if (!empty($projectidforalltimes)) {
1708 print '<!-- List of time spent for project -->' . "\n";
1709
1710 $title = $langs->trans("ListTaskTimeUserProject");
1711
1712 print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'clock', 0, $linktocreatetime, '', $limit, 0, 0, 1);
1713 } else {
1714 print '<!-- List of time spent -->' . "\n";
1715
1716 $title = $langs->trans("ListTaskTimeForTask");
1717
1718 print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'clock', 0, $linktocreatetime, '', $limit, 0, 0, 1);
1719 }
1720
1721 $i = 0;
1722 while ($i < $num) {
1723 $row = $db->fetch_object($resql);
1724 $tasks[$i] = $row;
1725 $i++;
1726 }
1727 $db->free($resql);
1728 } else {
1729 dol_print_error($db);
1730 }
1731
1732 /*
1733 * Form to add a new line of time spent
1734 */
1735 if ($action == 'createtime' && $user->hasRight('projet', 'time')) {
1736 print '<!-- table to add time spent -->' . "\n";
1737 if (!empty($id)) {
1738 print '<input type="hidden" name="taskid" value="' . $id . '">';
1739 }
1740
1741 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
1742 print '<table class="noborder nohover centpercent">';
1743
1744 print '<tr class="liste_titre">';
1745 print '<td>' . $langs->trans("Date") . '</td>';
1746 if (!empty($allprojectforuser)) {
1747 print '<td>' . $langs->trans("Project") . '</td>';
1748 }
1749 if (empty($id)) {
1750 print '<td>' . $langs->trans("Task") . '</td>';
1751 }
1752 print '<td>' . $langs->trans("By") . '</td>';
1753 print '<td>' . $langs->trans("Note") . '</td>';
1754 print '<td>' . $langs->trans("NewTimeSpent") . '</td>';
1755 print '<td>' . $langs->trans("ProgressDeclared") . '</td>';
1756 if (empty($conf->global->PROJECT_HIDE_TASKS) && !empty($conf->global->PROJECT_BILL_TIME_SPENT)) {
1757 print '<td></td>';
1758
1759 if (isModEnabled("service") && !empty($projectstatic->thirdparty) && $projectstatic->thirdparty->id > 0 && $projectstatic->usage_bill_time) {
1760 print '<td>'.$langs->trans("Product").'</td>';
1761 }
1762 }
1763 // Hook fields
1764 $parameters = array('mode' => 'create');
1765 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook
1766 print $hookmanager->resPrint;
1767 print '<td></td>';
1768 print "</tr>\n";
1769
1770 print '<tr class="oddeven nohover">';
1771
1772 // Date
1773 print '<td class="maxwidthonsmartphone">';
1774 $newdate = '';
1775 print $form->selectDate($newdate, 'time', ($conf->browser->layout == 'phone' ? 2 : 1), 1, 2, "timespent_date", 1, 0);
1776 print '</td>';
1777
1778 if (!empty($allprojectforuser)) {
1779 print '<td>';
1780 // Add project selector
1781 print '</td>';
1782 }
1783
1784 // Task
1785 $nboftasks = 0;
1786 if (empty($id)) {
1787 print '<td class="maxwidthonsmartphone">';
1788 $nboftasks = $formproject->selectTasks(-1, GETPOST('taskid', 'int'), 'taskid', 0, 0, 1, 1, 0, 0, 'maxwidth300', $projectstatic->id, 'progress');
1789 print '</td>';
1790 }
1791
1792 // Contributor
1793 print '<td class="maxwidthonsmartphone nowraponall">';
1794 $contactsofproject = $projectstatic->getListContactId('internal');
1795 if (count($contactsofproject) > 0) {
1796 print img_object('', 'user', 'class="hideonsmartphone"');
1797 if (in_array($user->id, $contactsofproject)) {
1798 $userid = $user->id;
1799 } else {
1800 $userid = $contactsofproject[0];
1801 }
1802
1803 if ($projectstatic->public) {
1804 $contactsofproject = array();
1805 }
1806 print $form->select_dolusers((GETPOST('userid', 'int') ? GETPOST('userid', 'int') : $userid), 'userid', 0, '', 0, '', $contactsofproject, 0, 0, 0, '', 0, $langs->trans("ResourceNotAssignedToProject"), 'minwidth150imp maxwidth200');
1807 } else {
1808 if ($nboftasks) {
1809 print img_error($langs->trans('FirstAddRessourceToAllocateTime')) . ' ' . $langs->trans('FirstAddRessourceToAllocateTime');
1810 }
1811 }
1812 print '</td>';
1813
1814 // Note
1815 print '<td>';
1816 print '<textarea name="timespent_note" class="maxwidth100onsmartphone" rows="' . ROWS_2 . '">' . (GETPOST('timespent_note') ? GETPOST('timespent_note') : '') . '</textarea>';
1817 print '</td>';
1818
1819 // Duration - Time spent
1820 print '<td class="nowraponall">';
1821 $durationtouse = (GETPOST('timespent_duration') ? GETPOST('timespent_duration') : '');
1822 if (GETPOSTISSET('timespent_durationhour') || GETPOSTISSET('timespent_durationmin')) {
1823 $durationtouse = ((int) GETPOST('timespent_durationhour') * 3600 + (int) GETPOST('timespent_durationmin') * 60);
1824 }
1825 print $form->select_duration('timespent_duration', $durationtouse, 0, 'text');
1826 print '</td>';
1827
1828 // Progress declared
1829 print '<td class="nowrap">';
1830 print $formother->select_percent(GETPOST('progress') ? GETPOST('progress') : $object->progress, 'progress', 0, 5, 0, 100, 1);
1831 print '</td>';
1832
1833 // Invoiced
1834 if (empty($conf->global->PROJECT_HIDE_TASKS) && !empty($conf->global->PROJECT_BILL_TIME_SPENT)) {
1835 print '<td>';
1836 print '</td>';
1837
1838 if (isModEnabled("service") && !empty($projectstatic->thirdparty) && $projectstatic->thirdparty->id > 0 && $projectstatic->usage_bill_time) {
1839 print '<td class="nowraponall">';
1840 print img_picto('', 'product');
1841 print $form->select_produits('', 'fk_product', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 1, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth150', 0, '', null, 1);
1842 print '</td>';
1843 }
1844 }
1845
1846 // Fields from hook
1847 $parameters = array('mode' => 'create');
1848 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook
1849 print $hookmanager->resPrint;
1850
1851 print '<td class="center">';
1852 $form->buttonsSaveCancel();
1853 print '<input type="submit" name="save" class="button buttongen smallpaddingimp marginleftonly margintoponlyshort marginbottomonlyshort button-add reposition" value="'.$langs->trans("Add").'">';
1854 print '<input type="submit" name="cancel" class="button buttongen smallpaddingimp marginleftonly margintoponlyshort marginbottomonlyshort button-cancel" value="'.$langs->trans("Cancel").'">';
1855 print '</td></tr>';
1856
1857 print '</table>';
1858 print '</div>';
1859
1860 print '<br>';
1861 }
1862
1863 $moreforfilter = '';
1864
1865 $parameters = array();
1866 $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook
1867 if (empty($reshook)) {
1868 $moreforfilter .= $hookmanager->resPrint;
1869 } else {
1870 $moreforfilter = $hookmanager->resPrint;
1871 }
1872
1873 if (!empty($moreforfilter)) {
1874 print '<div class="liste_titre liste_titre_bydiv centpercent">';
1875 print $moreforfilter;
1876 print '</div>';
1877 }
1878
1879 $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
1880 $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')); // This also change content of $arrayfields
1881 $selectedfields .= (is_array($arrayofmassactions) && count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
1882
1883 print '<div class="div-table-responsive">';
1884 print '<table class="tagtable nobottomiftotal liste' . ($moreforfilter ? " listwithfilterbefore" : "") . '">' . "\n";
1885
1886 // Fields title search
1887 // --------------------------------------------------------------------
1888 print '<tr class="liste_titre_filter">';
1889 // Action column
1890 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1891 print '<td class="liste_titre center">';
1892 $searchpicto = $form->showFilterButtons('left');
1893 print $searchpicto;
1894 print '</td>';
1895 }
1896 // Date
1897 if (!empty($arrayfields['t.element_date']['checked'])) {
1898 print '<td class="liste_titre left">';
1899 print '<div class="nowrap">';
1900 print $form->selectDate($search_date_start ? $search_date_start : -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
1901 print '</div>';
1902 print '<div class="nowrap">';
1903 print $form->selectDate($search_date_end ? $search_date_end : -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
1904 print '</div>';
1905 print '</td>';
1906 }
1907 // Thirdparty
1908 if (!empty($arrayfields['p.fk_soc']['checked'])) {
1909 print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="$search_company" value="' . dol_escape_htmltag($search_company) . '"></td>';
1910 }
1911
1912 // Thirdparty alias
1913 if (!empty($arrayfields['s.name_alias']['checked'])) {
1914 print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="$search_company_alias" value="' . dol_escape_htmltag($search_company_alias) . '"></td>';
1915 }
1916
1917 if (!empty($allprojectforuser)) {
1918 if (!empty($arrayfields['p.project_ref']['checked'])) {
1919 print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="$search_project_ref" value="' . dol_escape_htmltag($search_project_ref) . '"></td>';
1920 }
1921 if (!empty($arrayfields['p.project_label']['checked'])) {
1922 print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="$search_project_label" value="' . dol_escape_htmltag($search_project_label) . '"></td>';
1923 }
1924 }
1925 // Task
1926 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
1927 if (!empty($arrayfields['t.element_ref']['checked'])) {
1928 print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="search_task_ref" value="'.dol_escape_htmltag($search_task_ref).'"></td>';
1929 }
1930 if (!empty($arrayfields['t.element_label']['checked'])) {
1931 print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="search_task_label" value="'.dol_escape_htmltag($search_task_label).'"></td>';
1932 }
1933 }
1934 // Author
1935 if (!empty($arrayfields['author']['checked'])) {
1936 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>';
1937 }
1938 // Note
1939 if (!empty($arrayfields['t.note']['checked'])) {
1940 print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="search_note" value="' . dol_escape_htmltag($search_note) . '"></td>';
1941 }
1942 // Duration
1943 if (!empty($arrayfields['t.element_duration']['checked'])) {
1944 // Duration - Time spent
1945 print '<td class="liste_titre right">';
1946
1947 $durationtouse_start = '';
1948 if ($search_timespent_starthour || $search_timespent_startmin) {
1949 $durationtouse_start = ($search_timespent_starthour * 3600 + $search_timespent_startmin * 60);
1950 }
1951 print '<div class="nowraponall">' . $langs->trans('from') . ' ';
1952 print $form->select_duration('search_timespent_duration_start', $durationtouse_start, 0, 'text', 0, 1);
1953 print '</div>';
1954
1955 $durationtouse_end = '';
1956 if ($search_timespent_endhour || $search_timespent_endmin) {
1957 $durationtouse_end = ($search_timespent_endhour * 3600 + $search_timespent_endmin * 60);
1958 }
1959 print '<div class="nowraponall">' . $langs->trans('at') . ' ';
1960 print $form->select_duration('search_timespent_duration_end', $durationtouse_end, 0, 'text', 0, 1);
1961 print '</div>';
1962
1963 print '</td>';
1964 }
1965 // Product
1966 if (!empty($arrayfields['t.fk_product']['checked'])) {
1967 print '<td class="liste_titre right"></td>';
1968 }
1969 // Value in main currency
1970 if (!empty($arrayfields['value']['checked'])) {
1971 print '<td class="liste_titre"></td>';
1972 }
1973 // Value billed
1974 if (!empty($arrayfields['valuebilled']['checked'])) {
1975 print '<td class="liste_titre center">' . $form->selectyesno('search_valuebilled', $search_valuebilled, 1, false, 1) . '</td>';
1976 }
1977
1978 /*
1979 // Extra fields
1980 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
1981 */
1982 // Fields from hook
1983 $parameters = array('arrayfields' => $arrayfields);
1984 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook
1985 print $hookmanager->resPrint;
1986 // Action column
1987 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1988 print '<td class="liste_titre center">';
1989 $searchpicto = $form->showFilterButtons();
1990 print $searchpicto;
1991 print '</td>';
1992 }
1993 print '</tr>' . "\n";
1994
1995 $totalarray = array();
1996 $totalarray['nbfield'] = 0;
1997
1998 // Fields title label
1999 // --------------------------------------------------------------------
2000 print '<tr class="liste_titre">';
2001 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2002 print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
2003 $totalarray['nbfield']++;
2004 }
2005 if (!empty($arrayfields['t.element_date']['checked'])) {
2006 print_liste_field_titre($arrayfields['t.element_date']['label'], $_SERVER['PHP_SELF'], 't.element_date,t.element_datehour,t.rowid', '', $param, '', $sortfield, $sortorder);
2007 $totalarray['nbfield']++;
2008 }
2009 if (!empty($arrayfields['p.fk_soc']['checked'])) {
2010 print_liste_field_titre($arrayfields['p.fk_soc']['label'], $_SERVER['PHP_SELF'], 't.element_date,t.element_datehour,t.rowid', '', $param, '', $sortfield, $sortorder);
2011 $totalarray['nbfield']++;
2012 }
2013 if (!empty($arrayfields['s.name_alias']['checked'])) {
2014 print_liste_field_titre($arrayfields['s.name_alias']['label'], $_SERVER['PHP_SELF'], 's.name_alias', '', $param, '', $sortfield, $sortorder);
2015 $totalarray['nbfield']++;
2016 }
2017 if (!empty($allprojectforuser)) {
2018 if (!empty($arrayfields['p.project_ref']['checked'])) {
2019 print_liste_field_titre("Project", $_SERVER['PHP_SELF'], 'p.ref', '', $param, '', $sortfield, $sortorder);
2020 $totalarray['nbfield']++;
2021 }
2022 if (!empty($arrayfields['p.project_label']['checked'])) {
2023 print_liste_field_titre("ProjectLabel", $_SERVER['PHP_SELF'], 'p.title', '', $param, '', $sortfield, $sortorder);
2024 $totalarray['nbfield']++;
2025 }
2026 }
2027 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2028 if (!empty($arrayfields['t.element_ref']['checked'])) {
2029 print_liste_field_titre($arrayfields['t.element_ref']['label'], $_SERVER['PHP_SELF'], 'pt.ref', '', $param, '', $sortfield, $sortorder);
2030 $totalarray['nbfield']++;
2031 }
2032 if (!empty($arrayfields['t.element_label']['checked'])) {
2033 print_liste_field_titre($arrayfields['t.element_label']['label'], $_SERVER['PHP_SELF'], 'pt.label', '', $param, '', $sortfield, $sortorder);
2034 $totalarray['nbfield']++;
2035 }
2036 }
2037 if (!empty($arrayfields['author']['checked'])) {
2038 print_liste_field_titre($arrayfields['author']['label'], $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder);
2039 $totalarray['nbfield']++;
2040 }
2041 if (!empty($arrayfields['t.note']['checked'])) {
2042 print_liste_field_titre($arrayfields['t.note']['label'], $_SERVER['PHP_SELF'], 't.note', '', $param, '', $sortfield, $sortorder);
2043 $totalarray['nbfield']++;
2044 }
2045 if (!empty($arrayfields['t.element_duration']['checked'])) {
2046 print_liste_field_titre($arrayfields['t.element_duration']['label'], $_SERVER['PHP_SELF'], 't.element_duration', '', $param, '', $sortfield, $sortorder, 'right ');
2047 $totalarray['nbfield']++;
2048 }
2049 if (!empty($arrayfields['t.fk_product']['checked'])) {
2050 print_liste_field_titre($arrayfields['t.fk_product']['label'], $_SERVER['PHP_SELF'], 't.fk_product', '', $param, '', $sortfield, $sortorder);
2051 $totalarray['nbfield']++;
2052 }
2053
2054 if (!empty($arrayfields['value']['checked'])) {
2055 print_liste_field_titre($arrayfields['value']['label'], $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder, 'right ');
2056 $totalarray['nbfield']++;
2057 }
2058 if (!empty($arrayfields['valuebilled']['checked'])) {
2059 print_liste_field_titre($arrayfields['valuebilled']['label'], $_SERVER['PHP_SELF'], 'il.total_ht', '', $param, '', $sortfield, $sortorder, 'center ', $langs->trans("SelectLinesOfTimeSpentToInvoice"));
2060 $totalarray['nbfield']++;
2061 }
2062 /*
2063 // Extra fields
2064 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
2065 */
2066 // Hook fields
2067 $parameters = array('arrayfields' => $arrayfields, 'param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder);
2068 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook
2069 print $hookmanager->resPrint;
2070 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2071 print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', 'width="80"', $sortfield, $sortorder, 'center maxwidthsearch ');
2072 $totalarray['nbfield']++;
2073 }
2074 print "</tr>\n";
2075
2076 $tasktmp = new Task($db);
2077 $tmpinvoice = new Facture($db);
2078
2079 $i = 0;
2080 $total = 0;
2081 $totalvalue = 0;
2082
2083 $savnbfield = $totalarray['nbfield'];
2084 $totalarray = array();
2085 $totalarray['nbfield'] = 0;
2086 //$imaxinloop = ($limit ? min($num, $limit) : $num);
2087 foreach ($tasks as $task_time) {
2088 if ($i >= $limit) {
2089 break;
2090 }
2091
2092 $date1 = $db->jdate($task_time->element_date);
2093 $date2 = $db->jdate($task_time->element_datehour);
2094
2095 // Show here line of result
2096 $j = 0;
2097 print '<tr data-rowid="'.$object->id.'" class="oddeven">';
2098
2099 // Action column
2100 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2101 print '<td class="center nowraponall">';
2102 if (($action == 'editline' || $action == 'splitline') && GETPOST('lineid', 'int') == $task_time->rowid) {
2103 print '<input type="hidden" name="lineid" value="' . GETPOST('lineid', 'int') . '">';
2104 print '<input type="submit" class="button buttongen smallpaddingimp margintoponlyshort marginbottomonlyshort button-save" name="save" value="'.$langs->trans("Save").'">';
2105 print '<br>';
2106 print '<input type="submit" class="button buttongen smallpaddingimp margintoponlyshort marginbottomonlyshort button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
2107 } elseif ($user->hasRight('projet', 'time') || $user->hasRight('projet', 'all', 'creer')) { // Read project and enter time consumed on assigned tasks
2108 if (in_array($task_time->fk_user, $childids) || $user->hasRight('projet', 'all', 'creer')) {
2109 if (getDolGlobalString('MAIN_FEATURES_LEVEL') >= 2) {
2110 print '&nbsp;';
2111 print '<a class="reposition" href="' . $_SERVER["PHP_SELF"] . '?action=splitline&token=' . newToken() . '&lineid=' . $task_time->rowid . $param . ((empty($id) || $tab == 'timespent') ? '&tab=timespent' : '') . '">';
2112 print img_split('', 'class="pictofixedwidth"');
2113 print '</a>';
2114 }
2115
2116 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' : '').'">';
2117 print img_edit('default', 0, 'class="pictofixedwidth paddingleft"');
2118 print '</a>';
2119
2120 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' : '').'">';
2121 print img_delete('default', 'class="pictodelete paddingleft"');
2122 print '</a>';
2123
2124 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
2125 $selected = 0;
2126 if (in_array($task_time->rowid, $arrayofselected)) {
2127 $selected = 1;
2128 }
2129 print '&nbsp;';
2130 print '<input id="cb' . $task_time->rowid . '" class="flat checkforselect marginleftonly" type="checkbox" name="toselect[]" value="' . $task_time->rowid . '"' . ($selected ? ' checked="checked"' : '') . '>';
2131 }
2132 }
2133 }
2134 print '</td>';
2135 if (!$i) {
2136 $totalarray['nbfield']++;
2137 }
2138 }
2139 // Date
2140 if (!empty($arrayfields['t.element_date']['checked'])) {
2141 print '<td class="nowrap">';
2142 if ($action == 'editline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2143 if (empty($task_time->element_date_withhour)) {
2144 print $form->selectDate(($date2 ? $date2 : $date1), 'timeline', 3, 3, 2, "timespent_date", 1, 0);
2145 } else {
2146 print $form->selectDate(($date2 ? $date2 : $date1), 'timeline', 1, 1, 2, "timespent_date", 1, 0);
2147 }
2148 } else {
2149 print dol_print_date(($date2 ? $date2 : $date1), ($task_time->element_date_withhour ? 'dayhour' : 'day'));
2150 }
2151 print '</td>';
2152 if (!$i) {
2153 $totalarray['nbfield']++;
2154 }
2155 }
2156
2157 // Thirdparty
2158 if (!empty($arrayfields['p.fk_soc']['checked'])) {
2159 print '<td class="tdoverflowmax125">';
2160 if ($task_time->fk_soc > 0) {
2161 if (empty($conf->cache['thridparty'][$task_time->fk_soc])) {
2162 $tmpsociete = new Societe($db);
2163 $tmpsociete->fetch($task_time->fk_soc);
2164 $conf->cache['thridparty'][$task_time->fk_soc] = $tmpsociete;
2165 } else {
2166 $tmpsociete = $conf->cache['thridparty'][$task_time->fk_soc];
2167 }
2168 print $tmpsociete->getNomUrl(1, '', 100, 0, 1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1);
2169 }
2170 print '</td>';
2171 if (!$i) {
2172 $totalarray['nbfield']++;
2173 }
2174 }
2175
2176 // Thirdparty alias
2177 if (!empty($arrayfields['s.name_alias']['checked'])) {
2178 if ($task_time->fk_soc > 0) {
2179 if (empty($conf->cache['thridparty'][$task_time->fk_soc])) {
2180 $tmpsociete = new Societe($db);
2181 $tmpsociete->fetch($task_time->fk_soc);
2182 $conf->cache['thridparty'][$task_time->fk_soc] = $tmpsociete;
2183 } else {
2184 $tmpsociete = $conf->cache['thridparty'][$task_time->fk_soc];
2185 }
2186 $valtoshow = $tmpsociete->name_alias;
2187 }
2188 print '<td class="nowrap tdoverflowmax150" title="'.dol_escape_htmltag($valtoshow).'">';
2189 print $valtoshow;
2190 print '</td>';
2191 if (!$i) {
2192 $totalarray['nbfield']++;
2193 }
2194 }
2195
2196 // Project ref & label
2197 if (!empty($allprojectforuser)) {
2198 if (!empty($arrayfields['p.project_ref']['checked'])) {
2199 print '<td class="nowraponall">';
2200 if (empty($conf->cache['project'][$task_time->fk_projet])) {
2201 $tmpproject = new Project($db);
2202 $tmpproject->fetch($task_time->fk_projet);
2203 $conf->cache['project'][$task_time->fk_projet] = $tmpproject;
2204 } else {
2205 $tmpproject = $conf->cache['project'][$task_time->fk_projet];
2206 }
2207 print $tmpproject->getNomUrl(1);
2208 print '</td>';
2209 if (!$i) {
2210 $totalarray['nbfield']++;
2211 }
2212 }
2213 if (!empty($arrayfields['p.project_label']['checked'])) {
2214 if (empty($conf->cache['project'][$task_time->fk_projet])) {
2215 $tmpproject = new Project($db);
2216 $tmpproject->fetch($task_time->fk_projet);
2217 $conf->cache['project'][$task_time->fk_projet] = $tmpproject;
2218 } else {
2219 $tmpproject = $conf->cache['project'][$task_time->fk_projet];
2220 }
2221 print '<td class="tdoverflowmax250" title="'.dol_escape_htmltag($tmpproject->title).'">';
2222 print dol_escape_htmltag($tmpproject->title);
2223 print '</td>';
2224 if (!$i) {
2225 $totalarray['nbfield']++;
2226 }
2227 }
2228 }
2229
2230 // Task ref
2231 if (!empty($arrayfields['t.element_ref']['checked'])) {
2232 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2233 print '<td class="nowrap">';
2234 if ($action == 'editline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2235 $formproject->selectTasks(-1, GETPOST('taskid', 'int') ? GETPOST('taskid', 'int') : $task_time->fk_element, 'taskid', 0, 0, 1, 1, 0, 0, 'maxwidth300', $projectstatic->id, '');
2236 } else {
2237 $tasktmp->id = $task_time->fk_element;
2238 $tasktmp->ref = $task_time->ref;
2239 $tasktmp->label = $task_time->label;
2240 print $tasktmp->getNomUrl(1, 'withproject', 'time');
2241 }
2242 print '</td>';
2243 if (!$i) {
2244 $totalarray['nbfield']++;
2245 }
2246 }
2247 } elseif ($action !== 'createtime') {
2248 print '<input type="hidden" name="taskid" value="' . $id . '">';
2249 }
2250
2251 // Task label
2252 if (!empty($arrayfields['t.element_label']['checked'])) {
2253 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2254 print '<td class="tdoverflowmax300" title="'.dol_escape_htmltag($task_time->label).'">';
2255 print dol_escape_htmltag($task_time->label);
2256 print '</td>';
2257 if (!$i) {
2258 $totalarray['nbfield']++;
2259 }
2260 }
2261 }
2262
2263 // By User
2264 if (!empty($arrayfields['author']['checked'])) {
2265 print '<td class="tdoverflowmax100">';
2266 if ($action == 'editline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2267 if (empty($object->id)) {
2268 $object->fetch($id);
2269 }
2270 $contactsoftask = $object->getListContactId('internal');
2271 if (!in_array($task_time->fk_user, $contactsoftask)) {
2272 $contactsoftask[] = $task_time->fk_user;
2273 }
2274 if (count($contactsoftask) > 0) {
2275 print img_object('', 'user', 'class="hideonsmartphone"');
2276 print $form->select_dolusers($task_time->fk_user, 'userid_line', 0, '', 0, '', $contactsoftask, '0', 0, 0, '', 0, '', 'maxwidth200');
2277 } else {
2278 print img_error($langs->trans('FirstAddRessourceToAllocateTime')) . $langs->trans('FirstAddRessourceToAllocateTime');
2279 }
2280 } else {
2281 $userstatic->id = $task_time->fk_user;
2282 $userstatic->lastname = $task_time->lastname;
2283 $userstatic->firstname = $task_time->firstname;
2284 $userstatic->photo = $task_time->photo;
2285 $userstatic->statut = $task_time->user_status;
2286 print $userstatic->getNomUrl(-1);
2287 }
2288 print '</td>';
2289 if (!$i) {
2290 $totalarray['nbfield']++;
2291 }
2292 }
2293
2294 // Note
2295 if (!empty($arrayfields['t.note']['checked'])) {
2296 if ($action == 'editline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2297 print '<td class="small">';
2298 print '<textarea name="timespent_note_line" width="95%" rows="' . ROWS_1 . '">' . dol_escape_htmltag($task_time->note, 0, 1) . '</textarea>';
2299 print '</td>';
2300 } else {
2301 print '<td class="small tdoverflowmax150 classfortooltip" title="'.dol_string_onlythesehtmltags(dol_htmlentitiesbr($task_time->note)).'">';
2302 print dolGetFirstLineOfText($task_time->note);
2303 print '</td>';
2304 }
2305 if (!$i) {
2306 $totalarray['nbfield']++;
2307 }
2308 } elseif ($action == 'editline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2309 print '<input type="hidden" name="timespent_note_line" value="' . dol_escape_htmltag($task_time->note, 0, 1) . '">';
2310 }
2311
2312 // Time spent
2313 if (!empty($arrayfields['t.element_duration']['checked'])) {
2314 print '<td class="right nowraponall">';
2315 if ($action == 'editline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2316 print '<input type="hidden" name="old_duration" value="'.$task_time->element_duration.'">';
2317 print $form->select_duration('new_duration', $task_time->element_duration, 0, 'text');
2318 } else {
2319 print convertSecondToTime($task_time->element_duration, 'allhourmin');
2320 }
2321 print '</td>';
2322 if (!$i) {
2323 $totalarray['nbfield']++;
2324 }
2325 if (!$i) {
2326 $totalarray['pos'][$totalarray['nbfield']] = 't.element_duration';
2327 }
2328 if (empty($totalarray['val']['t.element_duration'])) {
2329 $totalarray['val']['t.element_duration'] = $task_time->element_duration;
2330 } else {
2331 $totalarray['val']['t.element_duration'] += $task_time->element_duration;
2332 }
2333 if (!$i) {
2334 $totalarray['totaldurationfield'] = $totalarray['nbfield'];
2335 }
2336 if (empty($totalarray['totalduration'])) {
2337 $totalarray['totalduration'] = $task_time->element_duration;
2338 } else {
2339 $totalarray['totalduration'] += $task_time->element_duration;
2340 }
2341 }
2342
2343 // Product
2344 if (!empty($arrayfields['t.fk_product']['checked'])) {
2345 print '<td class="nowraponall tdoverflowmax125">';
2346 if ($action == 'editline' && $_GET['lineid'] == $task_time->rowid) {
2347 $form->select_produits($task_time->fk_product, 'fk_product', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 0, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth500');
2348 } elseif (!empty($task_time->fk_product)) {
2349 $product = new Product($db);
2350 $resultFetch = $product->fetch($task_time->fk_product);
2351 if ($resultFetch < 0) {
2352 setEventMessages($product->error, $product->errors, 'errors');
2353 } else {
2354 print $product->getNomUrl(1);
2355 }
2356 }
2357 print '</td>';
2358 if (!$i) {
2359 $totalarray['nbfield']++;
2360 }
2361 }
2362
2363 // Value spent
2364 if (!empty($arrayfields['value']['checked'])) {
2365 $langs->load("salaries");
2366 $value = price2num($task_time->thm * $task_time->element_duration / 3600, 'MT', 1);
2367
2368 print '<td class="nowraponall right">';
2369 print '<span class="amount" title="' . $langs->trans("THM") . ': ' . price($task_time->thm) . '">';
2370 print price($value, 1, $langs, 1, -1, -1, $conf->currency);
2371 print '</span>';
2372 print '</td>';
2373 if (!$i) {
2374 $totalarray['nbfield']++;
2375 }
2376 if (!$i) {
2377 $totalarray['pos'][$totalarray['nbfield']] = 'value';
2378 }
2379 if (empty($totalarray['val']['value'])) {
2380 $totalarray['val']['value'] = $value;
2381 } else {
2382 $totalarray['val']['value'] += $value;
2383 }
2384 if (!$i) {
2385 $totalarray['totalvaluefield'] = $totalarray['nbfield'];
2386 }
2387 if (empty($totalarray['totalvalue'])) {
2388 $totalarray['totalvalue'] = $value;
2389 } else {
2390 $totalarray['totalvalue'] += $value;
2391 }
2392 }
2393
2394 // Invoiced
2395 if (!empty($arrayfields['valuebilled']['checked'])) {
2396 print '<td class="center">'; // invoice_id and invoice_line_id
2397 if (empty($conf->global->PROJECT_HIDE_TASKS) && !empty($conf->global->PROJECT_BILL_TIME_SPENT)) {
2398 if ($projectstatic->usage_bill_time) {
2399 if ($task_time->invoice_id) {
2400 $result = $tmpinvoice->fetch($task_time->invoice_id);
2401 if ($result > 0) {
2402 if ($action=='editline' && $_GET['lineid'] == $task_time->rowid) {
2403 print $formproject->selectInvoiceAndLine($task_time->invoice_id, $task_time->invoice_line_id, 'invoiceid', 'invoicelineid', 'maxwidth500', array('p.rowid'=>$projectstatic->id));
2404 } else {
2405 print $tmpinvoice->getNomUrl(1);
2406 if (!empty($task_time->invoice_line_id)) {
2407 $invoiceLine = new FactureLigne($db);
2408 $invoiceLine->fetch($task_time->invoice_line_id);
2409 if (!empty($invoiceLine->id)) {
2410 print '<br>'.$langs->trans('Qty').':'.$invoiceLine->qty;
2411 print ' '.$langs->trans('TotalHT').':'.price($invoiceLine->total_ht);
2412 }
2413 }
2414 }
2415 }
2416 } else {
2417 print $langs->trans("No");
2418 }
2419 } else {
2420 print '<span class="opacitymedium">' . $langs->trans("NA") . '</span>';
2421 }
2422 }
2423 print '</td>';
2424 if (!$i) {
2425 $totalarray['nbfield']++;
2426 }
2427 }
2428
2429 /*
2430 // Extra fields
2431 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
2432 */
2433
2434 // Fields from hook
2435 $parameters = array('arrayfields' => $arrayfields, 'obj' => $task_time, 'i' => $i, 'totalarray' => &$totalarray);
2436 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook
2437 print $hookmanager->resPrint;
2438
2439 // Action column
2440 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
2441 print '<td class="center nowraponall">';
2442 if (($action == 'editline' || $action == 'splitline') && GETPOST('lineid', 'int') == $task_time->rowid) {
2443 print '<input type="hidden" name="lineid" value="'.GETPOST('lineid', 'int').'">';
2444 print '<input type="submit" class="button buttongen margintoponlyshort marginbottomonlyshort button-save small" name="save" value="'.$langs->trans("Save").'">';
2445 print '<br>';
2446 print '<input type="submit" class="button buttongen margintoponlyshort marginbottomonlyshort button-cancel small" name="cancel" value="'.$langs->trans("Cancel").'">';
2447 } elseif ($user->hasRight('projet', 'time') || $user->hasRight('projet', 'all', 'creer')) { // Read project and enter time consumed on assigned tasks
2448 if (in_array($task_time->fk_user, $childids) || $user->hasRight('projet', 'all', 'creer')) {
2449 if (getDolGlobalString('MAIN_FEATURES_LEVEL') >= 2) {
2450 print '&nbsp;';
2451 print '<a class="reposition" href="' . $_SERVER["PHP_SELF"] . '?action=splitline&token=' . newToken() . '&lineid=' . $task_time->rowid . $param . ((empty($id) || $tab == 'timespent') ? '&tab=timespent' : '') . '">';
2452 print img_split('', 'class="pictofixedwidth"');
2453 print '</a>';
2454 }
2455
2456 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' : '').'">';
2457 print img_edit('default', 0, 'class="pictofixedwidth paddingleft"');
2458 print '</a>';
2459
2460 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' : '').'">';
2461 print img_delete('default', 'class="pictodelete paddingleft"');
2462 print '</a>';
2463
2464 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
2465 $selected = 0;
2466 if (in_array($task_time->rowid, $arrayofselected)) {
2467 $selected = 1;
2468 }
2469 print '&nbsp;';
2470 print '<input id="cb' . $task_time->rowid . '" class="flat checkforselect marginleftonly" type="checkbox" name="toselect[]" value="' . $task_time->rowid . '"' . ($selected ? ' checked="checked"' : '') . '>';
2471 }
2472 }
2473 }
2474 print '</td>';
2475 if (!$i) {
2476 $totalarray['nbfield']++;
2477 }
2478 }
2479
2480 print "</tr>\n";
2481
2482
2483 // Add line to split
2484
2485 if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2486 print '<!-- first line -->';
2487 print '<tr class="oddeven">';
2488
2489 // Date
2490 if (!empty($arrayfields['t.element_date']['checked'])) {
2491 print '<td class="nowrap">';
2492 if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2493 if (empty($task_time->element_date_withhour)) {
2494 print $form->selectDate(($date2 ? $date2 : $date1), 'timeline', 3, 3, 2, "timespent_date", 1, 0);
2495 } else {
2496 print $form->selectDate(($date2 ? $date2 : $date1), 'timeline', 1, 1, 2, "timespent_date", 1, 0);
2497 }
2498 } else {
2499 print dol_print_date(($date2 ? $date2 : $date1), ($task_time->element_date_withhour ? 'dayhour' : 'day'));
2500 }
2501 print '</td>';
2502 }
2503
2504 // Thirdparty
2505 if (!empty($arrayfields['p.fk_soc']['checked'])) {
2506 print '<td class="nowrap">';
2507 print '</td>';
2508 }
2509
2510 // Thirdparty alias
2511 if (!empty($arrayfields['s.name_alias']['checked'])) {
2512 print '<td class="nowrap">';
2513 print '</td>';
2514 }
2515
2516 // Project ref
2517 if (!empty($allprojectforuser)) {
2518 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2519 print '<td class="nowrap">';
2520 print '</td>';
2521 }
2522 }
2523
2524 // Task ref
2525 if (!empty($arrayfields['t.element_ref']['checked'])) {
2526 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2527 print '<td class="nowrap">';
2528 $tasktmp->id = $task_time->fk_element;
2529 $tasktmp->ref = $task_time->ref;
2530 $tasktmp->label = $task_time->label;
2531 print $tasktmp->getNomUrl(1, 'withproject', 'time');
2532 print '</td>';
2533 }
2534 }
2535
2536 // Task label
2537 if (!empty($arrayfields['t.element_label']['checked'])) {
2538 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2539 print '<td class="tdoverflowmax300" title="'.dol_escape_htmltag($task_time->label).'">';
2540 print dol_escape_htmltag($task_time->label);
2541 print '</td>';
2542 }
2543 }
2544
2545 // User
2546 if (!empty($arrayfields['author']['checked'])) {
2547 print '<td class="nowraponall">';
2548 if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2549 if (empty($object->id)) {
2550 $object->fetch($id);
2551 }
2552 $contactsoftask = $object->getListContactId('internal');
2553 if (!in_array($task_time->fk_user, $contactsoftask)) {
2554 $contactsoftask[] = $task_time->fk_user;
2555 }
2556 if (count($contactsoftask) > 0) {
2557 print img_object('', 'user', 'class="hideonsmartphone"');
2558 print $form->select_dolusers($task_time->fk_user, 'userid_line', 0, '', 0, '', $contactsoftask);
2559 } else {
2560 print img_error($langs->trans('FirstAddRessourceToAllocateTime')) . $langs->trans('FirstAddRessourceToAllocateTime');
2561 }
2562 } else {
2563 $userstatic->id = $task_time->fk_user;
2564 $userstatic->lastname = $task_time->lastname;
2565 $userstatic->firstname = $task_time->firstname;
2566 $userstatic->photo = $task_time->photo;
2567 $userstatic->statut = $task_time->user_status;
2568 print $userstatic->getNomUrl(-1);
2569 }
2570 print '</td>';
2571 }
2572
2573 // Note
2574 if (!empty($arrayfields['t.note']['checked'])) {
2575 print '<td class="tdoverflowmax300">';
2576 if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2577 print '<textarea name="timespent_note_line" width="95%" rows="' . ROWS_1 . '">' . dol_escape_htmltag($task_time->note, 0, 1) . '</textarea>';
2578 } else {
2579 print dol_nl2br($task_time->note);
2580 }
2581 print '</td>';
2582 } elseif ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2583 print '<input type="hidden" name="timespent_note_line" rows="' . ROWS_1 . '" value="' . dol_escape_htmltag($task_time->note, 0, 1) . '">';
2584 }
2585
2586 // Time spent
2587 if (!empty($arrayfields['t.element_duration']['checked'])) {
2588 print '<td class="right">';
2589 if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2590 print '<input type="hidden" name="old_duration" value="'.$task_time->element_duration.'">';
2591 print $form->select_duration('new_duration', $task_time->element_duration, 0, 'text');
2592 } else {
2593 print convertSecondToTime($task_time->element_duration, 'allhourmin');
2594 }
2595 print '</td>';
2596 }
2597
2598 // Product
2599 if (!empty($arrayfields['t.fk_product']['checked'])) {
2600 print '<td class="nowraponall tdoverflowmax125">';
2601 print '</td>';
2602 }
2603
2604 // Value spent
2605 if (!empty($arrayfields['value']['checked'])) {
2606 print '<td class="right">';
2607 print '<span class="amount">';
2608 $value = price2num($task_time->thm * $task_time->element_duration / 3600, 'MT', 1);
2609 print price($value, 1, $langs, 1, -1, -1, $conf->currency);
2610 print '</span>';
2611 print '</td>';
2612 }
2613
2614 // Value billed
2615 if (!empty($arrayfields['valuebilled']['checked'])) {
2616 print '<td class="right">';
2617 $valuebilled = price2num($task_time->total_ht, '', 1);
2618 if (isset($task_time->total_ht)) {
2619 print price($valuebilled, 1, $langs, 1, -1, -1, $conf->currency);
2620 }
2621 print '</td>';
2622 }
2623
2624 /*
2625 // Extra fields
2626 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
2627 */
2628
2629 // Fields from hook
2630 $parameters = array('arrayfields' => $arrayfields, 'obj' => $task_time, 'mode' => 'split1');
2631 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook
2632 print $hookmanager->resPrint;
2633
2634 // Action column
2635 print '<td class="center nowraponall">';
2636 print '</td>';
2637
2638 print "</tr>\n";
2639
2640
2641 // Line for second dispatching
2642
2643 print '<!-- second line --><tr class="oddeven">';
2644
2645 // Date
2646 if (!empty($arrayfields['t.element_date']['checked'])) {
2647 print '<td class="nowrap">';
2648 if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2649 if (empty($task_time->element_date_withhour)) {
2650 print $form->selectDate(($date2 ? $date2 : $date1), 'timeline_2', 3, 3, 2, "timespent_date", 1, 0);
2651 } else {
2652 print $form->selectDate(($date2 ? $date2 : $date1), 'timeline_2', 1, 1, 2, "timespent_date", 1, 0);
2653 }
2654 } else {
2655 print dol_print_date(($date2 ? $date2 : $date1), ($task_time->element_date_withhour ? 'dayhour' : 'day'));
2656 }
2657 print '</td>';
2658 }
2659
2660 // Thirdparty
2661 if (!empty($arrayfields['p.fk_soc']['checked'])) {
2662 print '<td class="nowrap">';
2663 print '</td>';
2664 }
2665
2666 // Thirdparty alias
2667 if (!empty($arrayfields['s.name_alias']['checked'])) {
2668 print '<td class="nowrap">';
2669 print '</td>';
2670 }
2671
2672 // Project ref
2673 if (!empty($allprojectforuser)) {
2674 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2675 print '<td class="nowrap">';
2676 print '</td>';
2677 }
2678 }
2679
2680 // Task ref
2681 if (!empty($arrayfields['t.element_ref']['checked'])) {
2682 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2683 print '<td class="nowrap">';
2684 $tasktmp->id = $task_time->fk_element;
2685 $tasktmp->ref = $task_time->ref;
2686 $tasktmp->label = $task_time->label;
2687 print $tasktmp->getNomUrl(1, 'withproject', 'time');
2688 print '</td>';
2689 }
2690 }
2691
2692 // Task label
2693 if (!empty($arrayfields['t.element_label']['checked'])) {
2694 if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
2695 print '<td class="nowrap">';
2696 print dol_escape_htmltag($task_time->label);
2697 print '</td>';
2698 }
2699 }
2700
2701 // User
2702 if (!empty($arrayfields['author']['checked'])) {
2703 print '<td class="nowraponall">';
2704 if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2705 if (empty($object->id)) {
2706 $object->fetch($id);
2707 }
2708 $contactsoftask = $object->getListContactId('internal');
2709 if (!in_array($task_time->fk_user, $contactsoftask)) {
2710 $contactsoftask[] = $task_time->fk_user;
2711 }
2712 if (count($contactsoftask) > 0) {
2713 print img_object('', 'user', 'class="hideonsmartphone"');
2714 print $form->select_dolusers($task_time->fk_user, 'userid_line_2', 0, '', 0, '', $contactsoftask);
2715 } else {
2716 print img_error($langs->trans('FirstAddRessourceToAllocateTime')) . $langs->trans('FirstAddRessourceToAllocateTime');
2717 }
2718 } else {
2719 $userstatic->id = $task_time->fk_user;
2720 $userstatic->lastname = $task_time->lastname;
2721 $userstatic->firstname = $task_time->firstname;
2722 $userstatic->photo = $task_time->photo;
2723 $userstatic->statut = $task_time->user_status;
2724 print $userstatic->getNomUrl(-1);
2725 }
2726 print '</td>';
2727 }
2728
2729 // Note
2730 if (!empty($arrayfields['t.note']['checked'])) {
2731 print '<td class="small tdoverflowmax300"">';
2732 if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2733 print '<textarea name="timespent_note_line_2" width="95%" rows="' . ROWS_1 . '">' . dol_escape_htmltag($task_time->note, 0, 1) . '</textarea>';
2734 } else {
2735 print dol_nl2br($task_time->note);
2736 }
2737 print '</td>';
2738 } elseif ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2739 print '<input type="hidden" name="timespent_note_line_2" value="' . dol_escape_htmltag($task_time->note, 0, 1) . '">';
2740 }
2741
2742 // Time spent
2743 if (!empty($arrayfields['t.element_duration']['checked'])) {
2744 print '<td class="right">';
2745 if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
2746 print '<input type="hidden" name="old_duration_2" value="0">';
2747 print $form->select_duration('new_duration_2', 0, 0, 'text');
2748 } else {
2749 print convertSecondToTime($task_time->element_duration, 'allhourmin');
2750 }
2751 print '</td>';
2752 }
2753
2754 // Product
2755 if (!empty($arrayfields['t.fk_product']['checked'])) {
2756 print '<td class="nowraponall tdoverflowmax125">';
2757 print '</td>';
2758 }
2759
2760 // Value spent
2761 if (!empty($arrayfields['value']['checked'])) {
2762 print '<td class="right">';
2763 print '<span class="amount">';
2764 $value = 0;
2765 print price($value, 1, $langs, 1, -1, -1, $conf->currency);
2766 print '</span>';
2767 print '</td>';
2768 }
2769
2770 // Value billed
2771 if (!empty($arrayfields['valuebilled']['checked'])) {
2772 print '<td class="right">';
2773 $valuebilled = price2num($task_time->total_ht, '', 1);
2774 if (isset($task_time->total_ht)) {
2775 print '<span class="amount">';
2776 print price($valuebilled, 1, $langs, 1, -1, -1, $conf->currency);
2777 print '</span>';
2778 }
2779 print '</td>';
2780 }
2781
2782 /*
2783 // Extra fields
2784 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
2785 */
2786
2787 // Fields from hook
2788 $parameters = array('arrayfields' => $arrayfields, 'obj' => $task_time, 'mode' => 'split2');
2789 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook
2790 print $hookmanager->resPrint;
2791
2792 // Action column
2793 print '<td class="center nowraponall">';
2794 print '</td>';
2795
2796 print "</tr>\n";
2797 }
2798
2799 $i++;
2800 }
2801
2802 // Show total line
2803 //include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
2804 if (isset($totalarray['totaldurationfield']) || isset($totalarray['totalvaluefield'])) {
2805 print '<tr class="liste_total">';
2806 $i = 0;
2807 while ($i < $totalarray['nbfield']) {
2808 $i++;
2809 if ($i == 1) {
2810 if ($num < $limit && empty($offset)) {
2811 print '<td class="left">' . $langs->trans("Total") . '</td>';
2812 } else {
2813 print '<td class="left">'.$form->textwithpicto($langs->trans("Total"), $langs->trans("Totalforthispage")).'</td>';
2814 }
2815 } elseif ($totalarray['totaldurationfield'] == $i) {
2816 print '<td class="right">' . convertSecondToTime($totalarray['totalduration'], 'allhourmin') . '</td>';
2817 } elseif ($totalarray['totalvaluefield'] == $i) {
2818 print '<td class="right">' . price($totalarray['totalvalue']) . '</td>';
2819 //} elseif ($totalarray['totalvaluebilledfield'] == $i) { print '<td class="center">'.price($totalarray['totalvaluebilled']).'</td>';
2820 } else {
2821 print '<td></td>';
2822 }
2823 }
2824 print '</tr>';
2825 }
2826
2827 if (!count($tasks)) {
2828 $totalnboffields = 1;
2829 foreach ($arrayfields as $value) {
2830 if (!empty($value['checked'])) {
2831 $totalnboffields++;
2832 }
2833 }
2834 print '<tr class="oddeven"><td colspan="' . $totalnboffields . '">';
2835 print '<span class="opacitymedium">' . $langs->trans("None") . '</span>';
2836 print '</td></tr>';
2837 }
2838
2839 $parameters = array('arrayfields' => $arrayfields, 'sql' => $sql);
2840 $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters); // Note that $action and $object may have been modified by hook
2841 print $hookmanager->resPrint;
2842
2843 print "</table>";
2844 print '</div>';
2845 print "</form>";
2846 }
2847}
2848
2849// End of page
2850llxFooter();
2851$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:56
llxFooter()
Empty footer.
Definition wrapper.php:70
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:360
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:240
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 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.