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