dolibarr 19.0.3
list.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2006-2019 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2006-2010 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2018 Ferran Marcet <fmarcet@2byte.es>
6 * Copyright (C) 2021 Alexandre Spangaro <aspangaro@open-dsi.fr>
7 * Copyright (C) 2023 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
29require "../../main.inc.php";
30require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
31require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
32require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
33require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
34require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
35
36// Load translation files required by the page
37$langs->loadLangs(array('projects', 'users', 'companies'));
38
39$action = GETPOST('action', 'aZ09');
40$massaction = GETPOST('massaction', 'alpha');
41$show_files = GETPOST('show_files', 'int');
42$confirm = GETPOST('confirm', 'alpha');
43$toselect = GETPOST('toselect', 'array');
44$optioncss = GETPOST('optioncss', 'aZ09');
45$mode = GETPOST('mode', 'aZ');
46
47$id = GETPOST('id', 'int');
48
49$search_all = trim((GETPOST('search_all', 'alphanohtml') != '') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml'));
50$search_categ = GETPOST("search_categ", 'int');
51
52$search_projectstatus = GETPOST('search_projectstatus');
53if (!isset($search_projectstatus) || $search_projectstatus === '') {
54 if ($search_all != '') {
55 $search_projectstatus = -1;
56 } else {
57 $search_projectstatus = 1;
58 }
59}
60
61$search_project_ref = GETPOST('search_project_ref');
62$search_project_title = GETPOST('search_project_title');
63$search_task_ref = GETPOST('search_task_ref');
64$search_task_label = GETPOST('search_task_label');
65$search_task_description = GETPOST('search_task_description');
66$search_task_ref_parent = GETPOST('search_task_ref_parent');
67$search_project_user = GETPOST('search_project_user', 'int');
68$search_task_user = GETPOST('search_task_user', 'int');
69$search_task_progress = GETPOST('search_task_progress');
70$search_task_budget_amount = GETPOST('search_task_budget_amount');
71$search_societe = GETPOST('search_societe');
72$search_societe_alias = GETPOST('search_societe_alias');
73$search_opp_status = GETPOST("search_opp_status", 'alpha');
74$searchCategoryCustomerOperator = 0;
75if (GETPOSTISSET('formfilteraction')) {
76 $searchCategoryCustomerOperator = GETPOST('search_category_customer_operator', 'int');
77} elseif (getDolGlobalString('MAIN_SEARCH_CAT_OR_BY_DEFAULT')) {
78 $searchCategoryCustomerOperator = $conf->global->MAIN_SEARCH_CAT_OR_BY_DEFAULT;
79}
80$searchCategoryCustomerList = GETPOST('search_category_customer_list', 'array');
81
82$mine = GETPOST('mode', 'alpha') == 'mine' ? 1 : 0;
83if ($mine) {
84 $search_task_user = $user->id;
85 $mine = 0;
86}
87$type = GETPOST('type');
88
89$search_date_startday = GETPOST('search_date_startday', 'int');
90$search_date_startmonth = GETPOST('search_date_startmonth', 'int');
91$search_date_startyear = GETPOST('search_date_startyear', 'int');
92$search_date_endday = GETPOST('search_date_endday', 'int');
93$search_date_endmonth = GETPOST('search_date_endmonth', 'int');
94$search_date_endyear = GETPOST('search_date_endyear', 'int');
95$search_date_start = dol_mktime(0, 0, 0, $search_date_startmonth, $search_date_startday, $search_date_startyear); // Use tzserver
96$search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_endday, $search_date_endyear);
97$search_datelimit_startday = GETPOST('search_datelimit_startday', 'int');
98$search_datelimit_startmonth = GETPOST('search_datelimit_startmonth', 'int');
99$search_datelimit_startyear = GETPOST('search_datelimit_startyear', 'int');
100$search_datelimit_endday = GETPOST('search_datelimit_endday', 'int');
101$search_datelimit_endmonth = GETPOST('search_datelimit_endmonth', 'int');
102$search_datelimit_endyear = GETPOST('search_datelimit_endyear', 'int');
103$search_datelimit_start = dol_mktime(0, 0, 0, $search_datelimit_startmonth, $search_datelimit_startday, $search_datelimit_startyear);
104$search_datelimit_end = dol_mktime(23, 59, 59, $search_datelimit_endmonth, $search_datelimit_endday, $search_datelimit_endyear);
105
106// Initialize context for list
107$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'tasklist';
108
109// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
110$object = new Task($db);
111$hookmanager->initHooks(array('tasklist'));
112$extrafields = new ExtraFields($db);
113
114// fetch optionals attributes and labels
115$extrafields->fetch_name_optionals_label($object->table_element);
116$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
117
118// Security check
119$socid = 0;
120//if ($user->socid > 0) $socid = $user->socid; // For external user, no check is done on company because readability is managed by public status of project and assignement.
121if (!$user->hasRight('projet', 'lire')) {
123}
124
125$diroutputmassaction = $conf->project->dir_output.'/tasks/temp/massgeneration/'.$user->id;
126
127$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit;
128$sortfield = GETPOST('sortfield', 'aZ09comma');
129$sortorder = GETPOST('sortorder', 'aZ09comma');
130$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
131if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
132 // If $page is not defined, or '' or -1 or if we click on clear filters
133 $page = 0;
134}
135$offset = $limit * $page;
136$pageprev = $page - 1;
137$pagenext = $page + 1;
138if (!$sortfield) {
139 $sortfield = 'p.ref';
140}
141if (!$sortorder) {
142 $sortorder = 'DESC';
143}
144
145// List of fields to search into when doing a "search in all"
146$fieldstosearchall = array(
147 't.ref'=>"Ref",
148 't.label'=>"Label",
149 't.description'=>"Description",
150 't.note_public'=>"NotePublic",
151);
152if (empty($user->socid)) {
153 $fieldstosearchall['t.note_private'] = "NotePrivate";
154}
155
156$arrayfields = array(
157 't.fk_task_parent'=>array('label'=>"RefTaskParent", 'checked'=>0, 'position'=>70),
158 't.ref'=>array('label'=>"RefTask", 'checked'=>1, 'position'=>80),
159 't.label'=>array('label'=>"LabelTask", 'checked'=>1, 'position'=>80),
160 't.description'=>array('label'=>"Description", 'checked'=>0, 'position'=>80),
161 't.dateo'=>array('label'=>"DateStart", 'checked'=>1, 'position'=>100),
162 't.datee'=>array('label'=>"Deadline", 'checked'=>1, 'position'=>101),
163 'p.ref'=>array('label'=>"ProjectRef", 'checked'=>1, 'position'=>151),
164 'p.title'=>array('label'=>"ProjectLabel", 'checked'=>0, 'position'=>152),
165 's.nom'=>array('label'=>"ThirdParty", 'checked'=>1, 'csslist'=>'tdoverflowmax125', 'position'=>200),
166 's.name_alias'=>array('label'=>"AliasNameShort", 'checked'=>0, 'csslist'=>'tdoverflowmax125', 'position'=>201),
167 'p.fk_statut'=>array('label'=>"ProjectStatus", 'checked'=>1, 'position'=>205),
168 't.planned_workload'=>array('label'=>"PlannedWorkload", 'checked'=>1, 'position'=>302),
169 't.duration_effective'=>array('label'=>"TimeSpent", 'checked'=>1, 'position'=>303),
170 't.progress_calculated'=>array('label'=>"ProgressCalculated", 'checked'=>1, 'position'=>304),
171 't.progress'=>array('label'=>"ProgressDeclared", 'checked'=>1, 'position'=>305),
172 't.progress_summary'=>array('label'=>"TaskProgressSummary", 'checked'=>1, 'position'=>306),
173 't.budget_amount'=>array('label'=>"Budget", 'checked'=>0, 'position'=>307),
174 't.tobill'=>array('label'=>"TimeToBill", 'checked'=>0, 'position'=>310),
175 't.billed'=>array('label'=>"TimeBilled", 'checked'=>0, 'position'=>311),
176 't.datec'=>array('label'=>"DateCreation", 'checked'=>0, 'position'=>500),
177 't.tms'=>array('label'=>"DateModificationShort", 'checked'=>0, 'position'=>501),
178 //'t.fk_statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>1000),
179);
180// Extra fields
181include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php';
182
183$object->fields = dol_sort_array($object->fields, 'position');
184$arrayfields = dol_sort_array($arrayfields, 'position');
185
186$permissiontoread = $user->hasRight('projet', 'lire');
187$permissiontocreate = $user->hasRight('projet', 'creer');
188$permissiontodelete = $user->hasRight('projet', 'supprimer');
189
190if (!$permissiontoread) {
192}
193
194
195/*
196 * Actions
197 */
198
199if (GETPOST('cancel', 'alpha')) {
200 $action = 'list';
201 $massaction = '';
202}
203if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
204 $massaction = '';
205}
206
207$parameters = array('socid'=>$socid);
208$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
209if ($reshook < 0) {
210 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
211}
212
213if (empty($reshook)) {
214 // Selection of new fields
215 include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
216
217 // Purge search criteria
218 if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
219 $search_all = "";
220 $search_categ = "";
221 $search_projectstatus = -1;
222 $search_project_ref = "";
223 $search_societe = "";
224 $search_societe_alias = "";
225 $search_project_title = "";
226 $search_task_ref = "";
227 $search_task_label = "";
228 $search_task_description = "";
229 $search_task_ref_parent = "";
230 $search_task_progress = "";
231 $search_task_budget_amount = "";
232 $search_task_user = -1;
233 $search_project_user = -1;
234 $search_date_startday = '';
235 $search_date_startmonth = '';
236 $search_date_startyear = '';
237 $search_date_endday = '';
238 $search_date_endmonth = '';
239 $search_date_endyear = '';
240 $search_date_start = '';
241 $search_date_end = '';
242 $search_datelimit_startday = '';
243 $search_datelimit_startmonth = '';
244 $search_datelimit_startyear = '';
245 $search_datelimit_endday = '';
246 $search_datelimit_endmonth = '';
247 $search_datelimit_endyear = '';
248 $search_datelimit_start = '';
249 $search_datelimit_end = '';
250 $toselect = array();
251 $searchCategoryCustomerList = array();
252 $search_array_options = array();
253 }
254
255 // Mass actions
256 $objectclass = 'Task';
257 $objectlabel = 'Tasks';
258 $uploaddir = $conf->project->dir_output.'/tasks';
259 include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
260}
261
262if (empty($search_projectstatus) && $search_projectstatus == '') {
263 $search_projectstatus = 1;
264}
265
266
267
268
269/*
270 * View
271 */
272
273$form = new Form($db);
274$formother = new FormOther($db);
275$socstatic = new Societe($db);
276$projectstatic = new Project($db);
277$puser = new User($db);
278$tuser = new User($db);
279
280$now = dol_now();
281
282$title = $langs->trans("Activities");
283$help_url = "EN:Module_Projects|FR:Module_Projets|ES:M&oacute;dulo_Proyectos";
284$morejs = array();
285$morecss = array();
286
287if ($search_project_user > 0) {
288 $puser->fetch($search_project_user);
289}
290if ($search_task_user > 0) {
291 $tuser->fetch($search_task_user);
292}
293
294
295$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
296$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')); // This also change content of $arrayfields
297
298
299if ($id) {
300 $projectstatic->fetch($id);
301 $projectstatic->fetch_thirdparty();
302}
303
304// Get list of project id allowed to user (in a string list separated by coma)
305if (!$user->hasRight('projet', 'all', 'lire')) {
306 $projectsListId = $projectstatic->getProjectsAuthorizedForUser($user, 0, 1, $socid);
307}
308//var_dump($projectsListId);
309
310// Get id of types of contacts for projects (This list never contains a lot of elements)
311$listofprojectcontacttype = array();
312$sql = "SELECT ctc.rowid, ctc.code FROM ".MAIN_DB_PREFIX."c_type_contact as ctc";
313$sql .= " WHERE ctc.element = '".$db->escape($projectstatic->element)."'";
314$sql .= " AND ctc.source = 'internal'";
315$resql = $db->query($sql);
316if ($resql) {
317 while ($obj = $db->fetch_object($resql)) {
318 $listofprojectcontacttype[$obj->rowid] = $obj->code;
319 }
320} else {
321 dol_print_error($db);
322}
323if (count($listofprojectcontacttype) == 0) {
324 $listofprojectcontacttype[0] = '0'; // To avoid sql syntax error if not found
325}
326// Get id of types of contacts for tasks (This list never contains a lot of elements)
327$listoftaskcontacttype = array();
328$sql = "SELECT ctc.rowid, ctc.code FROM ".MAIN_DB_PREFIX."c_type_contact as ctc";
329$sql .= " WHERE ctc.element = '".$db->escape($object->element)."'";
330$sql .= " AND ctc.source = 'internal'";
331$resql = $db->query($sql);
332if ($resql) {
333 while ($obj = $db->fetch_object($resql)) {
334 $listoftaskcontacttype[$obj->rowid] = $obj->code;
335 }
336} else {
337 dol_print_error($db);
338}
339if (count($listoftaskcontacttype) == 0) {
340 $listoftaskcontacttype[0] = '0'; // To avoid sql syntax error if not found
341}
342
343// Build and execute select
344// --------------------------------------------------------------------
345$distinct = 'DISTINCT'; // We add distinct until we are added a protection to be sure a contact of a project and task is assigned only once.
346$sql = "SELECT ".$distinct." p.rowid as projectid, p.ref as projectref, p.title as projecttitle, p.fk_statut as projectstatus, p.datee as projectdatee, p.fk_opp_status, p.public, p.fk_user_creat as projectusercreate, p.usage_bill_time,";
347$sql .= " s.nom as name, s.name_alias as alias, s.rowid as socid,";
348$sql .= " t.datec as date_creation, t.dateo as date_start, t.datee as date_end, t.tms as date_update,";
349$sql .= " t.rowid as id, t.ref, t.label, t.planned_workload, t.duration_effective, t.progress, t.fk_statut,";
350$sql .= " t.description, t.fk_task_parent";
351$sql .= " ,t.budget_amount";
352// Add sum fields
353if (!empty($arrayfields['t.tobill']['checked']) || !empty($arrayfields['t.billed']['checked'])) {
354 $sql .= " , SUM(tt.element_duration * ".$db->ifsql("invoice_id IS NULL", "1", "0").") as tobill, SUM(tt.element_duration * ".$db->ifsql("invoice_id IS NULL", "0", "1").") as billed";
355}
356// Add fields from extrafields
357if (!empty($extrafields->attributes[$object->table_element]['label'])) {
358 foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
359 $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key." as options_".$key : '');
360 }
361}
362// Add fields from hooks
363$parameters = array();
364$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
365$sql .= $hookmanager->resPrint;
366$sql = preg_replace('/,\s*$/', '', $sql);
367
368$sqlfields = $sql; // $sql fields to remove for count total
369
370$sql .= " FROM ".MAIN_DB_PREFIX."projet as p";
371$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on p.fk_soc = s.rowid";
372$sql .= ", ".MAIN_DB_PREFIX."projet_task as t";
373if (!empty($arrayfields['t.tobill']['checked']) || !empty($arrayfields['t.billed']['checked'])) {
374 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."element_time as tt ON (tt.fk_element = t.rowid AND tt.elementtype = 'task')";
375}
376if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) {
377 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)";
378}
379if ($search_project_user > 0) {
380 $sql .= ", ".MAIN_DB_PREFIX."element_contact as ecp";
381}
382if ($search_task_user > 0) {
383 $sql .= ", ".MAIN_DB_PREFIX."element_contact as ect";
384}
385$sql .= " WHERE t.fk_projet = p.rowid";
386$sql .= " AND p.entity IN (".getEntity('project').')';
387if (!$user->hasRight('projet', 'all', 'lire')) {
388 $sql .= " AND p.rowid IN (".$db->sanitize($projectsListId ? $projectsListId : '0').")"; // public and assigned to projects, or restricted to company for external users
389}
390if (is_object($projectstatic) && $projectstatic->id > 0) {
391 $sql .= " AND p.rowid = ".((int) $projectstatic->id);
392}
393// No need to check company, as filtering of projects must be done by getProjectsAuthorizedForUser
394if ($socid) {
395 $sql .= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".((int) $socid).")";
396}
397if ($search_project_ref) {
398 $sql .= natural_search('p.ref', $search_project_ref);
399}
400if ($search_project_title) {
401 $sql .= natural_search('p.title', $search_project_title);
402}
403if ($search_task_ref) {
404 $sql .= natural_search('t.ref', $search_task_ref);
405}
406if ($search_task_label) {
407 $sql .= natural_search('t.label', $search_task_label);
408}
409if ($search_task_description) {
410 $sql .= natural_search('t.description', $search_task_description);
411}
412if ($search_task_ref_parent) {
413 $sql .= ' AND t.fk_task_parent IN (SELECT ipt.rowid FROM '.MAIN_DB_PREFIX.'projet_task as ipt WHERE '.natural_search('ipt.ref', $search_task_ref_parent, 0, 1).')';
414}
415if ($search_task_progress) {
416 $sql .= natural_search('t.progress', $search_task_progress, 1);
417}
418if ($search_task_budget_amount) {
419 $sql .= natural_search('t.budget_amount', $search_task_budget_amount, 1);
420}
421if (empty($arrayfields['s.name_alias']['checked']) && $search_societe) {
422 $sql .= natural_search(array("s.nom", "s.name_alias"), $search_societe);
423} else {
424 if ($search_societe) {
425 $sql .= natural_search('s.nom', $search_societe);
426 }
427 if ($search_societe_alias) {
428 $sql .= natural_search('s.name_alias', $search_societe_alias);
429 }
430}
431if ($search_date_start) {
432 $sql .= " AND t.dateo >= '".$db->idate($search_date_start)."'";
433}
434if ($search_date_end) {
435 $sql .= " AND t.dateo <= '".$db->idate($search_date_end)."'";
436}
437if ($search_datelimit_start) {
438 $sql .= " AND t.datee >= '".$db->idate($search_datelimit_start)."'";
439}
440if ($search_datelimit_end) {
441 $sql .= " AND t.datee <= '".$db->idate($search_datelimit_end)."'";
442}
443if ($search_all) {
444 $sql .= natural_search(array_keys($fieldstosearchall), $search_all);
445}
446if ($search_projectstatus >= 0) {
447 if ($search_projectstatus == 99) {
448 $sql .= " AND p.fk_statut <> 2";
449 } else {
450 $sql .= " AND p.fk_statut = ".((int) $search_projectstatus);
451 }
452}
453if ($search_project_user > 0) {
454 $sql .= " AND ecp.fk_c_type_contact IN (".$db->sanitize(join(',', array_keys($listofprojectcontacttype))).") AND ecp.element_id = p.rowid AND ecp.fk_socpeople = ".((int) $search_project_user);
455}
456if ($search_task_user > 0) {
457 $sql .= " AND ect.fk_c_type_contact IN (".$db->sanitize(join(',', array_keys($listoftaskcontacttype))).") AND ect.element_id = t.rowid AND ect.fk_socpeople = ".((int) $search_task_user);
458}
459// Search for tag/category ($searchCategoryProjectList is an array of ID)
460$searchCategoryProjectList = array($search_categ);
461$searchCategoryProjectOperator = 0;
462if (!empty($searchCategoryProjectList)) {
463 $searchCategoryProjectSqlList = array();
464 $listofcategoryid = '';
465 foreach ($searchCategoryProjectList as $searchCategoryProject) {
466 if (intval($searchCategoryProject) == -2) {
467 $searchCategoryProjectSqlList[] = "NOT EXISTS (SELECT ck.fk_project FROM ".MAIN_DB_PREFIX."categorie_project as ck WHERE p.rowid = ck.fk_project)";
468 } elseif (intval($searchCategoryProject) > 0) {
469 if ($searchCategoryProjectOperator == 0) {
470 $searchCategoryProjectSqlList[] = " EXISTS (SELECT ck.fk_project FROM ".MAIN_DB_PREFIX."categorie_project as ck WHERE p.rowid = ck.fk_project AND ck.fk_categorie = ".((int) $searchCategoryProject).")";
471 } else {
472 $listofcategoryid .= ($listofcategoryid ? ', ' : '') .((int) $searchCategoryProject);
473 }
474 }
475 }
476 if ($listofcategoryid) {
477 $searchCategoryProjectSqlList[] = " EXISTS (SELECT ck.fk_project FROM ".MAIN_DB_PREFIX."categorie_project as ck WHERE p.rowid = ck.fk_project AND ck.fk_categorie IN (".$db->sanitize($listofcategoryid)."))";
478 }
479 if ($searchCategoryProjectOperator == 1) {
480 if (!empty($searchCategoryProjectSqlList)) {
481 $sql .= " AND (".implode(' OR ', $searchCategoryProjectSqlList).")";
482 }
483 } else {
484 if (!empty($searchCategoryProjectSqlList)) {
485 $sql .= " AND (".implode(' AND ', $searchCategoryProjectSqlList).")";
486 }
487 }
488}
489$searchCategoryCustomerSqlList = array();
490if ($searchCategoryCustomerOperator == 1) {
491 $existsCategoryCustomerList = array();
492 foreach ($searchCategoryCustomerList as $searchCategoryCustomer) {
493 if (intval($searchCategoryCustomer) == -2) {
494 $sqlCategoryCustomerNotExists = " NOT EXISTS (";
495 $sqlCategoryCustomerNotExists .= " SELECT cat_cus.fk_soc";
496 $sqlCategoryCustomerNotExists .= " FROM ".$db->prefix()."categorie_societe AS cat_cus";
497 $sqlCategoryCustomerNotExists .= " WHERE cat_cus.fk_soc = p.fk_soc";
498 $sqlCategoryCustomerNotExists .= " )";
499 $searchCategoryCustomerSqlList[] = $sqlCategoryCustomerNotExists;
500 } elseif (intval($searchCategoryCustomer) > 0) {
501 $existsCategoryCustomerList[] = $db->escape($searchCategoryCustomer);
502 }
503 }
504 if (!empty($existsCategoryCustomerList)) {
505 $sqlCategoryCustomerExists = " EXISTS (";
506 $sqlCategoryCustomerExists .= " SELECT cat_cus.fk_soc";
507 $sqlCategoryCustomerExists .= " FROM ".$db->prefix()."categorie_societe AS cat_cus";
508 $sqlCategoryCustomerExists .= " WHERE cat_cus.fk_soc = p.fk_soc";
509 $sqlCategoryCustomerExists .= " AND cat_cus.fk_categorie IN (".$db->sanitize(implode(',', $existsCategoryCustomerList)).")";
510 $sqlCategoryCustomerExists .= " )";
511 $searchCategoryCustomerSqlList[] = $sqlCategoryCustomerExists;
512 }
513 if (!empty($searchCategoryCustomerSqlList)) {
514 $sql .= " AND (".implode(' OR ', $searchCategoryCustomerSqlList).")";
515 }
516} else {
517 foreach ($searchCategoryCustomerList as $searchCategoryCustomer) {
518 if (intval($searchCategoryCustomer) == -2) {
519 $sqlCategoryCustomerNotExists = " NOT EXISTS (";
520 $sqlCategoryCustomerNotExists .= " SELECT cat_cus.fk_soc";
521 $sqlCategoryCustomerNotExists .= " FROM ".$db->prefix()."categorie_societe AS cat_cus";
522 $sqlCategoryCustomerNotExists .= " WHERE cat_cus.fk_soc = p.fk_soc";
523 $sqlCategoryCustomerNotExists .= " )";
524 $searchCategoryCustomerSqlList[] = $sqlCategoryCustomerNotExists;
525 } elseif (intval($searchCategoryCustomer) > 0) {
526 $searchCategoryCustomerSqlList[] = "p.fk_soc IN (SELECT fk_soc FROM ".$db->prefix()."categorie_societe WHERE fk_categorie = ".((int) $searchCategoryCustomer).")";
527 }
528 }
529 if (!empty($searchCategoryCustomerSqlList)) {
530 $sql .= " AND (".implode(' AND ', $searchCategoryCustomerSqlList).")";
531 }
532}
533// Add where from extra fields
534include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
535// Add where from hooks
536$parameters = array();
537$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
538$sql .= $hookmanager->resPrint;
539if (!empty($arrayfields['t.tobill']['checked']) || !empty($arrayfields['t.billed']['checked'])) {
540 $sql .= " GROUP BY p.rowid, p.ref, p.title, p.fk_statut, p.datee, p.fk_opp_status, p.public, p.fk_user_creat,";
541 $sql .= " s.nom, s.rowid,";
542 $sql .= " t.datec, t.dateo, t.datee, t.tms,";
543 $sql .= " t.rowid, t.ref, t.label, t.planned_workload, t.duration_effective, t.progress,t.budget_amount, t.fk_statut";
544 // Add fields from extrafields
545 if (!empty($extrafields->attributes[$object->table_element]['label'])) {
546 foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
547 $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key : '');
548 }
549 }
550}
551
552// Count total nb of records
553$nbtotalofrecords = '';
554if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
555 /* The fast and low memory method to get and count full list converts the sql into a sql count */
556 $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql);
557 $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount);
558 $resql = $db->query($sqlforcount);
559 if ($resql) {
560 $objforcount = $db->fetch_object($resql);
561 $nbtotalofrecords = $objforcount->nbtotalofrecords;
562 } else {
563 dol_print_error($db);
564 }
565
566 if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 0
567 $page = 0;
568 $offset = 0;
569 }
570 $db->free($resql);
571}
572
573// Complete request and execute it with limit
574$sql .= $db->order($sortfield, $sortorder);
575if ($limit) {
576 $sql .= $db->plimit($limit + 1, $offset);
577}
578
579$resql = $db->query($sql);
580if (!$resql) {
581 dol_print_error($db);
582 exit;
583}
584
585$num = $db->num_rows($resql);
586
587
588// Direct jump if only one record found
589if ($num == 1 && getDolGlobalString('MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE') && $search_all) {
590 $obj = $db->fetch_object($resql);
591 $id = $obj->id; // in select, task id has been aliases into 'id'
592 header("Location: ".DOL_URL_ROOT.'/projet/tasks/task.php?id='.$id.'&withproject=1');
593 exit;
594}
595
596
597// Output page
598// --------------------------------------------------------------------
599
600llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', 'bodyforlist'); // Can use also classforhorizontalscrolloftabs instead of bodyforlist for no horizontal scroll
601
602$arrayofselected = is_array($toselect) ? $toselect : array();
603
604$param = '';
605if (!empty($mode)) {
606 $param .= '&mode='.urlencode($mode);
607}
608if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
609 $param .= '&contextpage='.urlencode($contextpage);
610}
611if ($limit > 0 && $limit != $conf->liste_limit) {
612 $param .= '&limit='.((int) $limit);
613}
614if ($search_date_startday) {
615 $param .= '&search_date_startday='.urlencode($search_date_startday);
616}
617if ($search_date_startmonth) {
618 $param .= '&search_date_startmonth='.urlencode($search_date_startmonth);
619}
620if ($search_date_startyear) {
621 $param .= '&search_date_startyear='.urlencode($search_date_startyear);
622}
623if ($search_date_endday) {
624 $param .= '&search_date_endday='.urlencode($search_date_endday);
625}
626if ($search_date_endmonth) {
627 $param .= '&search_date_endmonth='.urlencode($search_date_endmonth);
628}
629if ($search_date_endyear) {
630 $param .= '&search_date_endyear='.urlencode($search_date_endyear);
631}
632if ($search_datelimit_startday) {
633 $param .= '&search_datelimit_startday='.urlencode($search_datelimit_startday);
634}
635if ($search_datelimit_startmonth) {
636 $param .= '&search_datelimit_startmonth='.urlencode($search_datelimit_startmonth);
637}
638if ($search_datelimit_startyear) {
639 $param .= '&search_datelimit_startyear='.urlencode($search_datelimit_startyear);
640}
641if ($search_datelimit_endday) {
642 $param .= '&search_datelimit_endday='.urlencode($search_datelimit_endday);
643}
644if ($search_datelimit_endmonth) {
645 $param .= '&search_datelimit_endmonth='.urlencode($search_datelimit_endmonth);
646}
647if ($search_datelimit_endyear) {
648 $param .= '&search_datelimit_endyear='.urlencode($search_datelimit_endyear);
649}
650if ($search_task_budget_amount) {
651 $param .= '&search_task_budget_amount='.urlencode($search_task_budget_amount);
652}
653if ($socid) {
654 $param .= '&socid='.urlencode($socid);
655}
656if ($search_all != '') {
657 $param .= '&search_all='.urlencode($search_all);
658}
659if ($search_project_ref != '') {
660 $param .= '&search_project_ref='.urlencode($search_project_ref);
661}
662if ($search_project_title != '') {
663 $param .= '&search_project_title='.urlencode($search_project_title);
664}
665if ($search_task_ref != '') {
666 $param .= '&search_task_ref='.urlencode($search_task_ref);
667}
668if ($search_task_label != '') {
669 $param .= '&search_task_label='.urlencode($search_task_label);
670}
671if ($search_task_description != '') {
672 $param .= '&search_task_description='.urlencode($search_task_description);
673}
674if ($search_task_ref_parent != '') {
675 $param .= '&search_task_ref_parent='.urlencode($search_task_ref_parent);
676}
677if ($search_task_progress != '') {
678 $param .= '&search_task_progress='.urlencode($search_task_progress);
679}
680if ($search_societe != '') {
681 $param .= '&search_societe='.urlencode($search_societe);
682}
683if ($search_societe != '') {
684 $param .= '&search_societe_alias='.urlencode($search_societe_alias);
685}
686if ($search_projectstatus != '') {
687 $param .= '&search_projectstatus='.urlencode($search_projectstatus);
688}
689if ((is_numeric($search_opp_status) && $search_opp_status >= 0) || in_array($search_opp_status, array('all', 'none'))) {
690 $param .= '&search_opp_status='.urlencode($search_opp_status);
691}
692if ($search_project_user != '') {
693 $param .= '&search_project_user='.urlencode($search_project_user);
694}
695if ($search_task_user > 0) {
696 $param .= '&search_task_user='.urlencode($search_task_user);
697}
698if ($optioncss != '') {
699 $param .= '&optioncss='.urlencode($optioncss);
700}
701foreach ($searchCategoryCustomerList as $searchCategoryCustomer) {
702 $param .= "&search_category_customer_list[]=".urlencode($searchCategoryCustomer);
703}
704// Add $param from extra fields
705include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
706// Add $param from hooks
707$parameters = array('param' => &$param);
708$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
709$param .= $hookmanager->resPrint;
710
711// List of mass actions available
712$arrayofmassactions = array(
713// 'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"),
714// 'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"),
715);
716//if($user->rights->societe->creer) $arrayofmassactions['createbills']=$langs->trans("CreateInvoiceForThisCustomer");
717if (!empty($permissiontodelete)) {
718 $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
719}
720if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) {
721 $arrayofmassactions = array();
722}
723$massactionbutton = $form->selectMassAction('', $arrayofmassactions);
724
725print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">'."\n";
726if ($optioncss != '') {
727 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
728}
729print '<input type="hidden" name="token" value="'.newToken().'">';
730print '<input type="hidden" name="action" value="list">';
731print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
732print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
733print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
734print '<input type="hidden" name="page" value="'.$page.'">';
735if (!empty($type)) {
736 print '<input type="hidden" name="type" value="'.$type.'">';
737}
738print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
739print '<input type="hidden" name="page_y" value="">';
740print '<input type="hidden" name="mode" value="'.$mode.'">';
741
742
743$newcardbutton = '';
744
745$newcardbutton .= dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars imgforviewmode', $_SERVER["PHP_SELF"].'?mode=common'.preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ((empty($mode) || $mode == 'common') ? 2 : 1), array('morecss'=>'reposition'));
746$newcardbutton .= dolGetButtonTitle($langs->trans('ViewKanban'), '', 'fa fa-th-list imgforviewmode', $_SERVER["PHP_SELF"].'?mode=kanban'.preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ($mode == 'kanban' ? 2 : 1), array('morecss'=>'reposition'));
747$newcardbutton .= dolGetButtonTitleSeparator();
748$newcardbutton .= dolGetButtonTitle($langs->trans('NewTask'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/projet/tasks.php?action=create', '', $permissiontocreate);
749
750
751// Show description of content
752$texthelp = '';
753if ($search_task_user == $user->id) {
754 $texthelp .= $langs->trans("MyTasksDesc");
755} else {
756 if ($user->hasRight('projet', 'all', 'lire') && !$socid) {
757 $texthelp .= $langs->trans("TasksOnProjectsDesc");
758 } else {
759 $texthelp .= $langs->trans("TasksOnProjectsPublicDesc");
760 }
761}
762
763print_barre_liste($form->textwithpicto($title, $texthelp), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'projecttask', 0, $newcardbutton, '', $limit, 0, 0, 1);
764
765$topicmail = "Information";
766$modelmail = "task";
767$objecttmp = new Task($db);
768$trackid = 'tas'.$object->id;
769include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
770
771if ($search_all) {
772 $setupstring = '';
773 foreach ($fieldstosearchall as $key => $val) {
774 $fieldstosearchall[$key] = $langs->trans($val);
775 $setupstring .= $key."=".$val.";";
776 }
777 print '<!-- Search done like if TASK_QUICKSEARCH_ON_FIELDS = '.$setupstring.' -->'."\n";
778 print '<div class="divsearchfieldfilter">'.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'</div>'."\n";
779}
780
781$moreforfilter = '';
782
783// Filter on categories
784if (isModEnabled('categorie') && $user->hasRight('categorie', 'lire')) {
785 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
786 $moreforfilter .= '<div class="divsearchfield">';
787 $tmptitle = $langs->trans('ProjectCategories');
788 $moreforfilter .= img_picto($tmptitle, 'category', 'class="pictofixedwidth"').$formother->select_categories('project', $search_categ, 'search_categ', 1, $tmptitle, 'maxwidth300');
789 $moreforfilter .= '</div>';
790}
791
792// If the user can view users
793$moreforfilter .= '<div class="divsearchfield">';
794$tmptitle = $langs->trans('ProjectsWithThisUserAsContact');
795$includeonly = '';
796if (!$user->hasRight('user', 'user', 'lire')) {
797 $includeonly = array($user->id);
798}
799$moreforfilter .= img_picto($tmptitle, 'user', 'class="pictofixedwidth"').$form->select_dolusers($search_project_user ? $search_project_user : '', 'search_project_user', $tmptitle, '', 0, $includeonly, '', 0, 0, 0, '', 0, '', 'maxwidth250');
800$moreforfilter .= '</div>';
801
802// If the user can view users
803$moreforfilter .= '<div class="divsearchfield">';
804$tmptitle = $langs->trans('TasksWithThisUserAsContact');
805$includeonly = '';
806if (!$user->hasRight('user', 'user', 'lire')) {
807 $includeonly = array($user->id);
808}
809$moreforfilter .= img_picto($tmptitle, 'user', 'class="pictofixedwidth"').$form->select_dolusers($search_task_user, 'search_task_user', $tmptitle, '', 0, $includeonly, '', 0, 0, 0, '', 0, '', 'maxwidth250');
810$moreforfilter .= '</div>';
811
812// Filter on customer categories
813if (getDolGlobalString('MAIN_SEARCH_CATEGORY_CUSTOMER_ON_TASK_LIST') && isModEnabled("categorie") && $user->hasRight('categorie', 'lire')) {
814 $moreforfilter .= '<div class="divsearchfield">';
815 $tmptitle = $langs->transnoentities('CustomersProspectsCategoriesShort');
816 $moreforfilter .= img_picto($tmptitle, 'category', 'class="pictofixedwidth"');
817 $categoriesArr = $form->select_all_categories(Categorie::TYPE_CUSTOMER, '', '', 64, 0, 1);
818 $categoriesArr[-2] = '- '.$langs->trans('NotCategorized').' -';
819 $moreforfilter .= Form::multiselectarray('search_category_customer_list', $categoriesArr, $searchCategoryCustomerList, 0, 0, 'minwidth300', 0, 0, '', 'category', $tmptitle);
820 $moreforfilter .= ' <input type="checkbox" class="valignmiddle" id="search_category_customer_operator" name="search_category_customer_operator" value="1"'.($searchCategoryCustomerOperator == 1 ? ' checked="checked"' : '').'/>';
821 $moreforfilter .= $form->textwithpicto('', $langs->trans('UseOrOperatorForCategories') . ' : ' . $tmptitle, 1, 'help', '', 0, 2, 'tooltip_cat_cus'); // Tooltip on click
822 $moreforfilter .= '</div>';
823}
824
825if (!empty($moreforfilter)) {
826 print '<div class="liste_titre liste_titre_bydiv centpercent">';
827 print $moreforfilter;
828 $parameters = array();
829 $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
830 print $hookmanager->resPrint;
831 print '</div>';
832}
833
834$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
835$selectedfields = ($mode != 'kanban' ? $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')) : ''); // This also change content of $arrayfields
836$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
837
838print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
839print '<table class="tagtable nobottomiftotal liste'.($moreforfilter ? " listwithfilterbefore" : "").'" id="tablelines3">'."\n";
840
841// Fields title search
842// --------------------------------------------------------------------
843print '<tr class="liste_titre_filter">';
844// Action column
845if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
846 print '<td class="liste_titre center maxwidthsearch">';
847 $searchpicto = $form->showFilterButtons('left');
848 print $searchpicto;
849 print '</td>';
850}
851if (!empty($arrayfields['t.fk_task_parent']['checked'])) {
852 print '<td class="liste_titre">';
853 print '<input type="text" class="flat" name="search_task_ref_parent" value="'.dol_escape_htmltag($search_task_ref_parent).'" size="4">';
854 print '</td>';
855}
856if (!empty($arrayfields['t.ref']['checked'])) {
857 print '<td class="liste_titre">';
858 print '<input type="text" class="flat" name="search_task_ref" value="'.dol_escape_htmltag($search_task_ref).'" size="4">';
859 print '</td>';
860}
861if (!empty($arrayfields['t.label']['checked'])) {
862 print '<td class="liste_titre">';
863 print '<input type="text" class="flat" name="search_task_label" value="'.dol_escape_htmltag($search_task_label).'" size="8">';
864 print '</td>';
865}
866// Task Description
867if (!empty($arrayfields['t.description']['checked'])) {
868 print '<td class="liste_titre">';
869 print '<input type="text" class="flat" name="search_task_description" value="'.dol_escape_htmltag($search_task_description).'" size="8">';
870 print '</td>';
871}
872// Start date
873if (!empty($arrayfields['t.dateo']['checked'])) {
874 print '<td class="liste_titre center">';
875 print '<div class="nowrapfordate">';
876 print $form->selectDate($search_date_start ? $search_date_start : -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
877 print '</div>';
878 print '<div class="nowrapfordate">';
879 print $form->selectDate($search_date_end ? $search_date_end : -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
880 print '</div>';
881 print '</td>';
882}
883// End date
884if (!empty($arrayfields['t.datee']['checked'])) {
885 print '<td class="liste_titre center">';
886 print '<div class="nowrapfordate">';
887 print $form->selectDate($search_datelimit_start ? $search_datelimit_start : -1, 'search_datelimit_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
888 print '</div>';
889 print '<div class="nowrapfordate">';
890 print $form->selectDate($search_datelimit_end ? $search_datelimit_end : -1, 'search_datelimit_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
891 // TODO Add option late
892 //print '<br><input type="checkbox" name="search_option" value="late"'.($option == 'late' ? ' checked' : '').'> '.$langs->trans("Alert");
893 print '</div>';
894 print '</td>';
895}
896if (!empty($arrayfields['p.ref']['checked'])) {
897 print '<td class="liste_titre">';
898 print '<input type="text" class="flat" name="search_project_ref" value="'.$search_project_ref.'" size="4">';
899 print '</td>';
900}
901if (!empty($arrayfields['p.title']['checked'])) {
902 print '<td class="liste_titre">';
903 print '<input type="text" class="flat" name="search_project_title" value="'.$search_project_title.'" size="6">';
904 print '</td>';
905}
906if (!empty($arrayfields['s.nom']['checked'])) {
907 print '<td class="liste_titre">';
908 print '<input type="text" class="flat" name="search_societe" value="'.dol_escape_htmltag($search_societe).'" size="4">';
909 print '</td>';
910}
911if (!empty($arrayfields['s.name_alias']['checked'])) {
912 print '<td class="liste_titre">';
913 print '<input type="text" class="flat" name="search_societe_alias" value="'.dol_escape_htmltag($search_societe_alias).'" size="4">';
914 print '</td>';
915}
916if (!empty($arrayfields['p.fk_statut']['checked'])) {
917 print '<td class="liste_titre center">';
918 $arrayofstatus = array();
919 foreach ($projectstatic->labelStatusShort as $key => $val) {
920 $arrayofstatus[$key] = $langs->trans($val);
921 }
922 $arrayofstatus['99'] = $langs->trans("NotClosed").' ('.$langs->trans('Draft').'+'.$langs->trans('Opened').')';
923 print $form->selectarray('search_projectstatus', $arrayofstatus, $search_projectstatus, 1, 0, 0, '', 0, 0, 0, '', 'maxwidth100');
924 print '</td>';
925}
926if (!empty($arrayfields['t.planned_workload']['checked'])) {
927 print '<td class="liste_titre"></td>';
928}
929if (!empty($arrayfields['t.duration_effective']['checked'])) {
930 print '<td class="liste_titre"></td>';
931}
932if (!empty($arrayfields['t.progress_calculated']['checked'])) {
933 print '<td class="liste_titre"></td>';
934}
935if (!empty($arrayfields['t.progress']['checked'])) {
936 print '<td class="liste_titre center">';
937 print '<input type="text" class="flat" name="search_task_progress" value="'.$search_task_progress.'" size="4">';
938 print '</td>';
939}
940
941if (!empty($arrayfields['t.progress_summary']['checked'])) {
942 print '<td class="liste_titre"></td>';
943}
944
945if (!empty($arrayfields['t.budget_amount']['checked'])) {
946 print '<td class="liste_titre center">';
947 print '<input type="text" class="flat" name="search_task_budget_amount" value="'.$search_task_budget_amount.'" size="4">';
948 print '</td>';
949}
950
951if (!empty($arrayfields['t.tobill']['checked'])) {
952 print '<td class="liste_titre"></td>';
953}
954if (!empty($arrayfields['t.billed']['checked'])) {
955 print '<td class="liste_titre"></td>';
956}
957// Extra fields
958include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
959// Fields from hook
960$parameters = array('arrayfields'=>$arrayfields);
961$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
962print $hookmanager->resPrint;
963if (!empty($arrayfields['t.datec']['checked'])) {
964 // Date creation
965 print '<td class="liste_titre">';
966 print '</td>';
967}
968if (!empty($arrayfields['t.tms']['checked'])) {
969 // Date modification
970 print '<td class="liste_titre">';
971 print '</td>';
972}
973// Action column
974if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
975 print '<td class="liste_titre center maxwidthsearch">';
976 $searchpicto = $form->showFilterButtons();
977 print $searchpicto;
978 print '</td>';
979}
980print '</tr>'."\n";
981
982$totalarray = array(
983 'nbfield' => 0,
984 'val' => array(
985 't.planned_workload' => 0,
986 't.duration_effective' => 0,
987 't.progress' => 0,
988 't.budget_amount' => 0,
989 ),
990 'totalplannedworkload' => 0,
991 'totaldurationeffective' => 0,
992 'totaldurationdeclared' => 0,
993 'totaltobillfield' => 0,
994 'totalbilledfield' => 0,
995 'totalbudget_amountfield' => 0,
996 'totalbudgetamount' => 0,
997 'totaltobill' => 0,
998 'totalbilled' => 0,
999);
1000
1001// Fields title label
1002// --------------------------------------------------------------------
1003print '<tr class="liste_titre">';
1004// Action column
1005if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1006 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
1007 $totalarray['nbfield']++;
1008}
1009if (!empty($arrayfields['t.fk_task_parent']['checked'])) {
1010 print_liste_field_titre($arrayfields['t.fk_task_parent']['label'], $_SERVER["PHP_SELF"], "t.fk_task_parent", "", $param, "", $sortfield, $sortorder);
1011 $totalarray['nbfield']++;
1012}
1013if (!empty($arrayfields['t.ref']['checked'])) {
1014 print_liste_field_titre($arrayfields['t.ref']['label'], $_SERVER["PHP_SELF"], "t.ref", "", $param, "", $sortfield, $sortorder);
1015 $totalarray['nbfield']++;
1016}
1017if (!empty($arrayfields['t.label']['checked'])) {
1018 print_liste_field_titre($arrayfields['t.label']['label'], $_SERVER["PHP_SELF"], "t.label", "", $param, "", $sortfield, $sortorder);
1019 $totalarray['nbfield']++;
1020}
1021if (!empty($arrayfields['t.description']['checked'])) {
1022 print_liste_field_titre($arrayfields['t.description']['label'], $_SERVER["PHP_SELF"], "t.description", "", $param, "", $sortfield, $sortorder);
1023 $totalarray['nbfield']++;
1024}
1025if (!empty($arrayfields['t.dateo']['checked'])) {
1026 print_liste_field_titre($arrayfields['t.dateo']['label'], $_SERVER["PHP_SELF"], "t.dateo", "", $param, '', $sortfield, $sortorder, 'center ');
1027 $totalarray['nbfield']++;
1028}
1029if (!empty($arrayfields['t.datee']['checked'])) {
1030 print_liste_field_titre($arrayfields['t.datee']['label'], $_SERVER["PHP_SELF"], "t.datee", "", $param, '', $sortfield, $sortorder, 'center ');
1031 $totalarray['nbfield']++;
1032}
1033if (!empty($arrayfields['p.ref']['checked'])) {
1034 print_liste_field_titre($arrayfields['p.ref']['label'], $_SERVER["PHP_SELF"], "p.ref", "", $param, "", $sortfield, $sortorder);
1035 $totalarray['nbfield']++;
1036}
1037if (!empty($arrayfields['p.title']['checked'])) {
1038 print_liste_field_titre($arrayfields['p.title']['label'], $_SERVER["PHP_SELF"], "p.title", "", $param, "", $sortfield, $sortorder);
1039 $totalarray['nbfield']++;
1040}
1041if (!empty($arrayfields['s.nom']['checked'])) {
1042 print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER["PHP_SELF"], "s.nom", "", $param, "", $sortfield, $sortorder);
1043 $totalarray['nbfield']++;
1044}
1045if (!empty($arrayfields['s.name_alias']['checked'])) {
1046 print_liste_field_titre($arrayfields['s.name_alias']['label'], $_SERVER["PHP_SELF"], "s.name_alias", "", $param, "", $sortfield, $sortorder);
1047 $totalarray['nbfield']++;
1048}
1049if (!empty($arrayfields['p.fk_statut']['checked'])) {
1050 print_liste_field_titre($arrayfields['p.fk_statut']['label'], $_SERVER["PHP_SELF"], "p.fk_statut", "", $param, '', $sortfield, $sortorder, 'center ');
1051 $totalarray['nbfield']++;
1052}
1053if (!empty($arrayfields['t.planned_workload']['checked'])) {
1054 print_liste_field_titre($arrayfields['t.planned_workload']['label'], $_SERVER["PHP_SELF"], "t.planned_workload", "", $param, '', $sortfield, $sortorder, 'center ');
1055 $totalarray['nbfield']++;
1056}
1057if (!empty($arrayfields['t.duration_effective']['checked'])) {
1058 print_liste_field_titre($arrayfields['t.duration_effective']['label'], $_SERVER["PHP_SELF"], "t.duration_effective", "", $param, '', $sortfield, $sortorder, 'center ');
1059 $totalarray['nbfield']++;
1060}
1061if (!empty($arrayfields['t.progress_calculated']['checked'])) {
1062 print_liste_field_titre($arrayfields['t.progress_calculated']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', '', '', 'center ');
1063 $totalarray['nbfield']++;
1064}
1065if (!empty($arrayfields['t.progress']['checked'])) {
1066 print_liste_field_titre($arrayfields['t.progress']['label'], $_SERVER["PHP_SELF"], "t.progress", "", $param, '', $sortfield, $sortorder, 'center ');
1067 $totalarray['nbfield']++;
1068}
1069if (!empty($arrayfields['t.progress_summary']['checked'])) {
1070 print_liste_field_titre($arrayfields['t.progress_summary']['label'], $_SERVER["PHP_SELF"], "t.progress", "", $param, '', $sortfield, $sortorder, 'center ');
1071 $totalarray['nbfield']++;
1072}
1073if (!empty($arrayfields['t.budget_amount']['checked'])) {
1074 print_liste_field_titre($arrayfields['t.budget_amount']['label'], $_SERVER["PHP_SELF"], "t.budget_amount", "", $param, '', $sortfield, $sortorder, 'center ');
1075 $totalarray['nbfield']++;
1076}
1077if (!empty($arrayfields['t.tobill']['checked'])) {
1078 print_liste_field_titre($arrayfields['t.tobill']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'center ');
1079 $totalarray['nbfield']++;
1080}
1081if (!empty($arrayfields['t.billed']['checked'])) {
1082 print_liste_field_titre($arrayfields['t.billed']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'center ');
1083 $totalarray['nbfield']++;
1084}
1085// Extra fields
1086include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
1087// Hook fields
1088$parameters = array(
1089 'arrayfields' => $arrayfields,
1090 'param' => $param,
1091 'sortfield' => $sortfield,
1092 'sortorder' => $sortorder,
1093 'totalarray' => &$totalarray,
1094);
1095$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1096print $hookmanager->resPrint;
1097if (!empty($arrayfields['t.datec']['checked'])) {
1098 print_liste_field_titre($arrayfields['t.datec']['label'], $_SERVER["PHP_SELF"], "t.datec", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
1099 $totalarray['nbfield']++;
1100}
1101if (!empty($arrayfields['t.tms']['checked'])) {
1102 print_liste_field_titre($arrayfields['t.tms']['label'], $_SERVER["PHP_SELF"], "t.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
1103 $totalarray['nbfield']++;
1104}
1105// Action column
1106if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1107 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
1108 $totalarray['nbfield']++;
1109}
1110print '</tr>'."\n";
1111
1112$plannedworkloadoutputformat = 'allhourmin';
1113$timespentoutputformat = 'allhourmin';
1114if (getDolGlobalString('PROJECT_PLANNED_WORKLOAD_FORMAT')) {
1115 $plannedworkloadoutputformat = $conf->global->PROJECT_PLANNED_WORKLOAD_FORMAT;
1116}
1117if (getDolGlobalString('PROJECT_TIMES_SPENT_FORMAT')) {
1118 $timespentoutputformat = $conf->global->PROJECT_TIME_SPENT_FORMAT;
1119}
1120
1121// Loop on record
1122// --------------------------------------------------------------------
1123$i = 0;
1124$savnbfield = $totalarray['nbfield'];
1125$totalarray = array();
1126$totalarray['nbfield'] = 0;
1127$imaxinloop = ($limit ? min($num, $limit) : $num);
1128while ($i < $imaxinloop) {
1129 $obj = $db->fetch_object($resql);
1130 if (empty($obj)) {
1131 break; // Should not happen
1132 }
1133
1134 // Store properties in $object
1135 $object->id = $obj->id;
1136 $object->ref = $obj->ref;
1137 $object->label = $obj->label;
1138 $object->description = $obj->description;
1139 $object->fk_statut = $obj->fk_statut;
1140 $object->progress = $obj->progress;
1141 $object->budget_amount = $obj->budget_amount;
1142 $object->date_start = $db->jdate($obj->date_start);
1143 $object->date_end = $db->jdate($obj->date_end);
1144 $object->planned_workload = $obj->planned_workload;
1145 $object->duration_effective = $obj->duration_effective;
1146 $object->fk_task_parent = $obj->fk_task_parent;
1147
1148 $projectstatic->id = $obj->projectid;
1149 $projectstatic->ref = $obj->projectref;
1150 $projectstatic->title = $obj->projecttitle;
1151 $projectstatic->public = $obj->public;
1152 $projectstatic->statut = $obj->projectstatus;
1153 $projectstatic->datee = $db->jdate($obj->projectdatee);
1154
1155 if ($obj->socid) {
1156 $socstatic->id = $obj->socid;
1157 $socstatic->name = $obj->name;
1158 $socstatic->name_alias = $obj->alias;
1159 }
1160 if ($mode == 'kanban') {
1161 if ($i == 0) {
1162 print '<tr class="trkanban"><td colspan="'.$savnbfield.'">';
1163 print '<div class="box-flex-container kanban">';
1164 }
1165 // Output Kanban
1166 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1167 $selected = 0;
1168 if (in_array($object->id, $arrayofselected)) {
1169 $selected = 1;
1170 }
1171 }
1172
1173 $arraydata = array();
1174 $arraydata['projectlink'] = $projectstatic->getNomUrl(1);
1175 $arraydata['selected'] = in_array($object->id, $arrayofselected);
1176
1177 print $object->getKanbanView('', $arraydata);
1178 if ($i == ($imaxinloop - 1)) {
1179 print '</div>';
1180 print '</td></tr>';
1181 }
1182 } else {
1183 $userAccess = $projectstatic->restrictedProjectArea($user); // why this ?
1184 if ($userAccess >= 0) {
1185 // Show here line of result
1186 $j = 0;
1187 print '<tr data-rowid="'.$object->id.'" class="oddeven">';
1188
1189 // Action column
1190 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1191 print '<td class="nowrap center">';
1192 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1193 $selected = 0;
1194 if (in_array($object->id, $arrayofselected)) {
1195 $selected = 1;
1196 }
1197 print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
1198 }
1199 print '</td>';
1200 if (!$i) {
1201 $totalarray['nbfield']++;
1202 }
1203 }
1204 // Ref Parent
1205 if (!empty($arrayfields['t.fk_task_parent']['checked'])) {
1206 print '<td class="nowraponall">';
1207 if (!empty($object->fk_task_parent)) {
1208 $object_parent = new Task($db);
1209 $result = $object_parent->fetch($object->fk_task_parent);
1210 if ($result < 0) {
1211 setEventMessage($object_parent->error, 'errors');
1212 } else {
1213 print $object_parent->getNomUrl(1, 'withproject');
1214 if ($object_parent->hasDelay()) {
1215 print img_warning("Late");
1216 }
1217 }
1218 }
1219 print '</td>';
1220 if (!$i) {
1221 $totalarray['nbfield']++;
1222 }
1223 }
1224 // Ref
1225 if (!empty($arrayfields['t.ref']['checked'])) {
1226 print '<td class="nowraponall">';
1227 print $object->getNomUrl(1, 'withproject');
1228 if ($object->hasDelay()) {
1229 print img_warning("Late");
1230 }
1231 print '</td>';
1232 if (!$i) {
1233 $totalarray['nbfield']++;
1234 }
1235 }
1236 // Label
1237 if (!empty($arrayfields['t.label']['checked'])) {
1238 print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($object->label).'">';
1239 print dol_escape_htmltag($object->label);
1240 print '</td>';
1241 if (!$i) {
1242 $totalarray['nbfield']++;
1243 }
1244 }
1245 // Description
1246 if (!empty($arrayfields['t.description']['checked'])) {
1247 print '<td>';
1248 print dolGetFirstLineOfText($object->description, 5);
1249 print '</td>';
1250 if (!$i) {
1251 $totalarray['nbfield']++;
1252 }
1253 }
1254
1255 // Date start project
1256 if (!empty($arrayfields['t.dateo']['checked'])) {
1257 print '<td class="center">';
1258 print dol_print_date($db->jdate($obj->date_start), 'day');
1259 print '</td>';
1260 if (!$i) {
1261 $totalarray['nbfield']++;
1262 }
1263 }
1264 // Date end project
1265 if (!empty($arrayfields['t.datee']['checked'])) {
1266 print '<td class="center">';
1267 print dol_print_date($db->jdate($obj->date_end), 'day');
1268 print '</td>';
1269 if (!$i) {
1270 $totalarray['nbfield']++;
1271 }
1272 }
1273 // Project ref
1274 if (!empty($arrayfields['p.ref']['checked'])) {
1275 print '<td class="nowraponall tdoverflowmax150">';
1276 print $projectstatic->getNomUrl(1, 'task');
1277 if ($projectstatic->hasDelay()) {
1278 print img_warning("Late");
1279 }
1280 print '</td>';
1281 if (!$i) {
1282 $totalarray['nbfield']++;
1283 }
1284 }
1285 // Project title
1286 if (!empty($arrayfields['p.title']['checked'])) {
1287 print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($obj->projecttitle).'">';
1288 print dol_escape_htmltag($obj->projecttitle);
1289 print '</td>';
1290 if (!$i) {
1291 $totalarray['nbfield']++;
1292 }
1293 }
1294 // Third party
1295 if (!empty($arrayfields['s.nom']['checked'])) {
1296 print '<td class="tdoverflowmax125">';
1297 if ($obj->socid) {
1298 print $socstatic->getNomUrl(1, '', 0, 0, -1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1);
1299 } else {
1300 print '&nbsp;';
1301 }
1302 print '</td>';
1303 if (!$i) {
1304 $totalarray['nbfield']++;
1305 }
1306 }
1307 // Alias
1308 if (!empty($arrayfields['s.name_alias']['checked'])) {
1309 $name_alias = '';
1310 if ($obj->socid) {
1311 $name_alias = $socstatic->name_alias;
1312 }
1313 print '<td class="tdoverflowmax125" title="'.dol_escape_htmltag($name_alias).'">';
1314 print dol_escape_htmltag($name_alias);
1315 print '</td>';
1316 if (!$i) {
1317 $totalarray['nbfield']++;
1318 }
1319 }
1320 // Project status
1321 if (!empty($arrayfields['p.fk_statut']['checked'])) {
1322 print '<td class="center">';
1323 print $projectstatic->getLibStatut(1);
1324 print '</td>';
1325 if (!$i) {
1326 $totalarray['nbfield']++;
1327 }
1328 }
1329
1330 // Planned workload
1331 if (!empty($arrayfields['t.planned_workload']['checked'])) {
1332 print '<td class="center">';
1333 $fullhour = convertSecondToTime($obj->planned_workload, $plannedworkloadoutputformat);
1334 $workingdelay = convertSecondToTime($obj->planned_workload, 'all', 86400, 7); // TODO Replace 86400 and 7 to take account working hours per day and working day per weeks
1335 if ($obj->planned_workload != '') {
1336 print $fullhour;
1337 // TODO Add delay taking account of working hours per day and working day per week
1338 //if ($workingdelay != $fullhour) print '<br>('.$workingdelay.')';
1339 }
1340 //else print '--:--';
1341 print '</td>';
1342 if (!$i) {
1343 $totalarray['nbfield']++;
1344 }
1345 if (!$i) {
1346 $totalarray['pos'][$totalarray['nbfield']] = 't.planned_workload';
1347 }
1348 if (!isset($totalarray['val']['planned_workload'])) {
1349 $totalarray['val']['t.planned_workload'] = 0;
1350 }
1351 $totalarray['val']['t.planned_workload'] += $obj->planned_workload;
1352 if (!$i) {
1353 $totalarray['totalplannedworkloadfield'] = $totalarray['nbfield'];
1354 }
1355 if (!isset($totalarray['totalplannedworkload'])) {
1356 $totalarray['totalplannedworkload'] = 0;
1357 }
1358 $totalarray['totalplannedworkload'] += $obj->planned_workload;
1359 }
1360 // Time spent
1361 if (!empty($arrayfields['t.duration_effective']['checked'])) {
1362 $showlineingray = 0;
1363 $showproject = 1;
1364 print '<td class="center">';
1365 if ($showlineingray) {
1366 print '<i>';
1367 } else {
1368 print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$object->id.($showproject ? '' : '&withproject=1').'">';
1369 }
1370 if ($obj->duration_effective) {
1371 print convertSecondToTime($obj->duration_effective, $timespentoutputformat);
1372 } else {
1373 print '--:--';
1374 }
1375 if ($showlineingray) {
1376 print '</i>';
1377 } else {
1378 print '</a>';
1379 }
1380 print '</td>';
1381 if (!$i) {
1382 $totalarray['nbfield']++;
1383 }
1384 if (!$i) {
1385 $totalarray['pos'][$totalarray['nbfield']] = 't.duration_effective';
1386 }
1387 if (!isset($totalarray['val']['t.duration_effective'])) {
1388 $totalarray['val']['t.duration_effective'] = 0;
1389 }
1390 $totalarray['val']['t.duration_effective'] += $obj->duration_effective;
1391 if (!$i) {
1392 $totalarray['totaldurationeffectivefield'] = $totalarray['nbfield'];
1393 }
1394 if (!isset($totalarray['totaldurationeffective'])) {
1395 $totalarray['totaldurationeffective'] = 0;
1396 }
1397 $totalarray['totaldurationeffective'] += $obj->duration_effective;
1398 }
1399 // Calculated progress
1400 if (!empty($arrayfields['t.progress_calculated']['checked'])) {
1401 print '<td class="center">';
1402 if ($obj->planned_workload || $obj->duration_effective) {
1403 if ($obj->planned_workload) {
1404 print round(100 * $obj->duration_effective / $obj->planned_workload, 2).' %';
1405 } else {
1406 print $form->textwithpicto('', $langs->trans('WorkloadNotDefined'), 1, 'help');
1407 }
1408 }
1409 print '</td>';
1410 if (!$i) {
1411 $totalarray['nbfield']++;
1412 }
1413 if (!$i) {
1414 $totalarray['totalprogress_calculatedfield'] = $totalarray['nbfield'];
1415 }
1416 }
1417 // Declared progress
1418 if (!empty($arrayfields['t.progress']['checked'])) {
1419 print '<td class="center">';
1420 if ($obj->progress != '') {
1421 print getTaskProgressBadge($object);
1422 }
1423 print '</td>';
1424 if (!$i) {
1425 $totalarray['nbfield']++;
1426 }
1427 if (!$i) {
1428 $totalarray['pos'][$totalarray['nbfield']] = 't.progress';
1429 }
1430 if (!isset($totalarray['val']['t.progress'])) {
1431 $totalarray['val']['t.progress'] = 0;
1432 }
1433 $totalarray['val']['t.progress'] += ($obj->planned_workload * $obj->progress / 100);
1434 if (!$i) {
1435 $totalarray['totalprogress_declaredfield'] = $totalarray['nbfield'];
1436 }
1437 if (!isset($totalarray['totaldurationdeclared'])) {
1438 $totalarray['totaldurationdeclared'] = 0;
1439 }
1440 $totalarray['totaldurationdeclared'] += $obj->planned_workload * $obj->progress / 100;
1441 }
1442 // Progress summary
1443 if (!empty($arrayfields['t.progress_summary']['checked'])) {
1444 print '<td class="center">';
1445 if ($obj->progress != '' && $obj->duration_effective) {
1446 print getTaskProgressView($object, false, false);
1447 }
1448 print '</td>';
1449 if (!$i) {
1450 $totalarray['nbfield']++;
1451 }
1452 if (!$i) {
1453 $totalarray['totalprogress_summary'] = $totalarray['nbfield'];
1454 }
1455 }
1456 // Budget for task
1457 if (!empty($arrayfields['t.budget_amount']['checked'])) {
1458 print '<td class="center">';
1459 if ($object->budget_amount) {
1460 print '<span class="amount">'.price($object->budget_amount, 0, $langs, 1, 0, 0, $conf->currency).'</span>';
1461 }
1462 print '</td>';
1463 if (!$i) {
1464 $totalarray['nbfield']++;
1465 }
1466 if (!$i) {
1467 $totalarray['pos'][$totalarray['nbfield']] = 't.budget_amount';
1468 }
1469 $totalarray['val']['t.budget_amount'] += $obj->budget_amount;
1470 if (!$i) {
1471 $totalarray['totalbudget_amountfield'] = $totalarray['nbfield'];
1472 }
1473 $totalarray['totalbudgetamount'] += $obj->budget_amount;
1474 }
1475 // Time not billed
1476 if (!empty($arrayfields['t.tobill']['checked'])) {
1477 print '<td class="center">';
1478 if ($obj->usage_bill_time) {
1479 print convertSecondToTime($obj->tobill, 'allhourmin');
1480 $totalarray['val']['t.tobill'] += $obj->tobill;
1481 $totalarray['totaltobill'] += $obj->tobill;
1482 } else {
1483 print '<span class="opacitymedium">'.$langs->trans("NA").'</span>';
1484 }
1485 print '</td>';
1486 if (!$i) {
1487 $totalarray['nbfield']++;
1488 }
1489 if (!$i) {
1490 $totalarray['pos'][$totalarray['nbfield']] = 't.tobill';
1491 }
1492 if (!$i) {
1493 $totalarray['totaltobillfield'] = $totalarray['nbfield'];
1494 }
1495 }
1496 // Time billed
1497 if (!empty($arrayfields['t.billed']['checked'])) {
1498 print '<td class="center">';
1499 if ($obj->usage_bill_time) {
1500 print convertSecondToTime($obj->billed, 'allhourmin');
1501 $totalarray['val']['t.billed'] += $obj->billed;
1502 $totalarray['totalbilled'] += $obj->billed;
1503 } else {
1504 print '<span class="opacitymedium">'.$langs->trans("NA").'</span>';
1505 }
1506 print '</td>';
1507 if (!$i) {
1508 $totalarray['nbfield']++;
1509 }
1510 if (!$i) {
1511 $totalarray['pos'][$totalarray['nbfield']] = 't.billed';
1512 }
1513 if (!$i) {
1514 $totalarray['totalbilledfield'] = $totalarray['nbfield'];
1515 }
1516 }
1517 // Extra fields
1518 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
1519 // Fields from hook
1520 $parameters = array('arrayfields'=>$arrayfields, 'object'=>$object, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray);
1521 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1522 print $hookmanager->resPrint;
1523 // Date creation
1524 if (!empty($arrayfields['t.datec']['checked'])) {
1525 print '<td class="center">';
1526 print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser');
1527 print '</td>';
1528 if (!$i) {
1529 $totalarray['nbfield']++;
1530 }
1531 }
1532 // Date modification
1533 if (!empty($arrayfields['t.tms']['checked'])) {
1534 print '<td class="center">';
1535 print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser');
1536 print '</td>';
1537 if (!$i) {
1538 $totalarray['nbfield']++;
1539 }
1540 }
1541 // Status
1542 /*if (!empty($arrayfields['p.fk_statut']['checked']))
1543 {
1544 $projectstatic->statut = $obj->fk_statut;
1545 print '<td class="right">'.$projectstatic->getLibStatut(5).'</td>';
1546 }*/
1547 // Action column
1548 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1549 print '<td class="nowrap center">';
1550 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1551 $selected = 0;
1552 if (in_array($object->id, $arrayofselected)) {
1553 $selected = 1;
1554 }
1555 print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
1556 }
1557 print '</td>';
1558 if (!$i) {
1559 $totalarray['nbfield']++;
1560 }
1561 }
1562
1563 print '</tr>'."\n";
1564 }
1565 }
1566
1567 $i++;
1568}
1569
1570// Show total line
1571if (!empty($totalarray['totalizable']) && is_array($totalarray['totalizable'])) {
1572 foreach ($totalarray['totalizable'] as $keytotalizable => $valtotalizable) {
1573 $totalarray['pos'][$valtotalizable['pos']] = $keytotalizable;
1574 $totalarray['val'][$keytotalizable] = $valtotalizable['total'];
1575 }
1576}
1577
1578if (isset($totalarray['totaldurationeffectivefield']) || isset($totalarray['totalplannedworkloadfield']) || isset($totalarray['totalprogress_calculatedfield'])
1579 || isset($totalarray['totaltobill']) || isset($totalarray['totalbilled']) || isset($totalarray['totalbudget'])) {
1580 print '<tr class="liste_total">';
1581 $i = 0;
1582 while ($i < $totalarray['nbfield']) {
1583 $i++;
1584 if ($i == 1) {
1585 if ($num < $limit && empty($offset)) {
1586 print '<td class="left">'.$langs->trans("Total").'</td>';
1587 } else {
1588 print '<td class="left">'.$langs->trans("Totalforthispage").'</td>';
1589 }
1590 } elseif (isset($totalarray['totalplannedworkloadfield']) && $totalarray['totalplannedworkloadfield'] == $i) {
1591 print '<td class="center">'.convertSecondToTime($totalarray['totalplannedworkload'], $plannedworkloadoutputformat).'</td>';
1592 } elseif (isset($totalarray['totaldurationeffectivefield']) && $totalarray['totaldurationeffectivefield'] == $i) {
1593 print '<td class="center">'.convertSecondToTime($totalarray['totaldurationeffective'], $timespentoutputformat).'</td>';
1594 } elseif (isset($totalarray['totalprogress_calculatedfield']) && $totalarray['totalprogress_calculatedfield'] == $i) {
1595 print '<td class="center">'.($totalarray['totalplannedworkload'] > 0 ? round(100 * $totalarray['totaldurationeffective'] / $totalarray['totalplannedworkload'], 2).' %' : '').'</td>';
1596 } elseif (isset($totalarray['totalprogress_declaredfield']) && $totalarray['totalprogress_declaredfield'] == $i) {
1597 print '<td class="center">'.($totalarray['totalplannedworkload'] > 0 ? round(100 * $totalarray['totaldurationdeclared'] / $totalarray['totalplannedworkload'], 2).' %' : '').'</td>';
1598 } elseif (isset($totalarray['totaltobillfield']) && $totalarray['totaltobillfield'] == $i) {
1599 print '<td class="center">'.convertSecondToTime($totalarray['totaltobill'], $plannedworkloadoutputformat).'</td>';
1600 } elseif (isset($totalarray['totalbilledfield']) && $totalarray['totalbilledfield'] == $i) {
1601 print '<td class="center">'.convertSecondToTime($totalarray['totalbilled'], $plannedworkloadoutputformat).'</td>';
1602 } elseif (isset($totalarray['totalbudget_amountfield']) && $totalarray['totalbudget_amountfield'] == $i) {
1603 print '<td class="center">'.price($totalarray['totalbudgetamount'], 0, $langs, 1, 0, 0, $conf->currency).'</td>';
1604 } elseif (!empty($totalarray['pos'][$i])) {
1605 print '<td class="right">';
1606 if (isset($totalarray['type']) && $totalarray['type'][$i] == 'duration') {
1607 print(!empty($totalarray['val'][$totalarray['pos'][$i]]) ? convertSecondToTime($totalarray['val'][$totalarray['pos'][$i]], 'allhourmin') : 0);
1608 } else {
1609 print price(!empty($totalarray['val'][$totalarray['pos'][$i]]) ? $totalarray['val'][$totalarray['pos'][$i]] : 0);
1610 }
1611 print '</td>';
1612 } else {
1613 print '<td></td>';
1614 }
1615 }
1616 print '</tr>';
1617}
1618
1619$db->free($resql);
1620
1621$parameters = array('arrayfields'=>$arrayfields, 'sql' => $sql);
1622$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1623print $hookmanager->resPrint;
1624
1625print '</table>'."\n";
1626print '</div>'."\n";
1627
1628print '</form>'."\n";
1629
1630// End of page
1631llxFooter();
1632$db->close();
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader()
Empty header.
Definition wrapper.php:55
llxFooter()
Empty footer.
Definition wrapper.php:69
Class to manage standard extra fields.
Class to manage generation of HTML components Only common components must be here.
static multiselectarray($htmlname, $array, $selected=array(), $key_in_label=0, $value_as_key=0, $morecss='', $translate=0, $width=0, $moreattrib='', $elemtype='', $placeholder='', $addjscombo=-1)
Show a multiselect form from an array.
Classe permettant la generation de composants html autre Only common components are here.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage tasks.
Class to manage Dolibarr users.
convertSecondToTime($iSecond, $format='all', $lengthOfDay=86400, $lengthOfWeek=7)
Return, in clear text, value of a number of seconds in days, hours and minutes.
Definition date.lib.php:243
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
dolGetFirstLineOfText($text, $nboflines=1, $charset='UTF-8')
Return first line of text.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dolGetButtonTitle($label, $helpText='', $iconClass='fa fa-file', $url='', $id='', $status=1, $params=array())
Function dolGetButtonTitle : this kind of buttons are used in title in list.
setEventMessage($mesgs, $style='mesgs', $noduplicate=0)
Set event message in dol_events session object.
natural_search($fields, $value, $mode=0, $nofirstand=0)
Generate natural SQL search string for a criteria (this criteria can be tested on one or several fiel...
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by second index function, which produces ascending (default) or descending output...
print_liste_field_titre($name, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
getTitleFieldOfList($name, $thead=0, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $disablesortlink=0, $tooltip='', $forcenowrapcolumntitle=0)
Get title line of an array.
dolGetButtonTitleSeparator($moreClass="")
Add space between dolGetButtonTitle.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
print_barre_liste($titre, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $hideselectlimit=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
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...
getTaskProgressView($task, $label=true, $progressNumber=true, $hideOnProgressNull=false, $spaced=false)
getTaskProgressBadge($task, $label='', $tooltip='')
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.