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