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