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