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