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