dolibarr 22.0.5
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');
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');
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, getDolGlobalString('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 {
333 dol_print_error($db);
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 {
349 dol_print_error($db);
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$distinct = '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 ".$distinct." p.rowid as projectid, p.ref as projectref, p.title as projecttitle, p.fk_statut as projectstatus, p.datee as projectdatee, p.fk_opp_status, p.public, p.fk_user_creat as projectusercreate, p.usage_bill_time,";
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 {
577 dol_print_error($db);
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) {
595 dol_print_error($db);
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 .= dolGetButtonTitleSeparator();
765$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);
766
767
768// Show description of content
769$htmltooltip = '';
770if ($search_task_user == $user->id) {
771 $htmltooltip .= $langs->trans("MyTasksDesc");
772} else {
773 if ($user->hasRight('projet', 'all', 'lire') && !$socid) {
774 $htmltooltip .= $langs->trans("TasksOnProjectsDesc");
775 } else {
776 $htmltooltip .= $langs->trans("TasksOnProjectsPublicDesc");
777 }
778}
779
780print_barre_liste($form->textwithpicto($title, $htmltooltip), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'projecttask', 0, $newcardbutton, '', $limit, 0, 0, 1);
781
782$topicmail = "Information";
783$modelmail = "task";
784$objecttmp = new Task($db);
785$trackid = 'tas'.$object->id;
786include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
787
788if ($search_all) {
789 $setupstring = '';
790 foreach ($fieldstosearchall as $key => $val) {
791 $fieldstosearchall[$key] = $langs->trans($val);
792 $setupstring .= $key."=".$val.";";
793 }
794 print '<!-- Search done like if TASK_QUICKSEARCH_ON_FIELDS = '.$setupstring.' -->'."\n";
795 print '<div class="divsearchfieldfilter">'.$langs->trans("FilterOnInto", $search_all).implode(', ', $fieldstosearchall).'</div>'."\n";
796}
797
798$moreforfilter = '';
799
800// Filter on categories
801if (isModEnabled('category') && $user->hasRight('categorie', 'lire')) {
802 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
803 $moreforfilter .= '<div class="divsearchfield">';
804 $tmptitle = $langs->trans('ProjectCategories');
805 $moreforfilter .= img_picto($tmptitle, 'category', 'class="pictofixedwidth"').$formother->select_categories('project', (int) $search_categ, 'search_categ', 1, $tmptitle, 'maxwidth300');
806 $moreforfilter .= '</div>';
807}
808
809// If the user can view users
810$moreforfilter .= '<div class="divsearchfield">';
811$tmptitle = $langs->trans('ProjectsWithThisUserAsContact');
812$includeonly = '';
813if (!$user->hasRight('user', 'user', 'lire')) {
814 $includeonly = array($user->id);
815}
816$moreforfilter .= img_picto($tmptitle, 'user', 'class="pictofixedwidth"').$form->select_dolusers($search_project_user ? $search_project_user : '', 'search_project_user', $tmptitle, null, 0, $includeonly, '', '0', 0, 0, '', 0, '', 'maxwidth250');
817$moreforfilter .= '</div>';
818
819// If the user can view users
820$moreforfilter .= '<div class="divsearchfield">';
821$tmptitle = $langs->trans('TasksWithThisUserAsContact');
822$includeonly = '';
823if (!$user->hasRight('user', 'user', 'lire')) {
824 $includeonly = array($user->id);
825}
826$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');
827$moreforfilter .= '</div>';
828
829// Filter on customer categories
830if (getDolGlobalString('MAIN_SEARCH_CATEGORY_CUSTOMER_ON_TASK_LIST') && isModEnabled("category") && $user->hasRight('categorie', 'lire')) {
831 $formcategory = new FormCategory($db);
832 $moreforfilter .= $formcategory->getFilterBox(Categorie::TYPE_CUSTOMER, $searchCategoryCustomerList, 'minwidth300', $searchCategoryCustomerList ? $searchCategoryCustomerList : 0);
833}
834
835if (!empty($moreforfilter)) {
836 print '<div class="liste_titre liste_titre_bydiv centpercent">';
837 print $moreforfilter;
838 $parameters = array();
839 $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
840 print $hookmanager->resPrint;
841 print '</div>';
842}
843
844$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
845$htmlofselectarray = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')); // This also change content of $arrayfields with user setup
846$selectedfields = ($mode != 'kanban' ? $htmlofselectarray : '');
847$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
848
849print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
850print '<table class="tagtable nobottomiftotal liste'.($moreforfilter ? " listwithfilterbefore" : "").'" id="tablelines3">'."\n";
851
852// Fields title search
853// --------------------------------------------------------------------
854print '<tr class="liste_titre_filter">';
855// Action column
856if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
857 print '<td class="liste_titre center maxwidthsearch">';
858 $searchpicto = $form->showFilterButtons('left');
859 print $searchpicto;
860 print '</td>';
861}
862if (!empty($arrayfields['t.ref']['checked'])) {
863 print '<td class="liste_titre">';
864 print '<input type="text" class="flat" name="search_task_ref" value="'.dol_escape_htmltag($search_task_ref).'" size="4">';
865 print '</td>';
866}
867if (!empty($arrayfields['t.fk_task_parent']['checked'])) {
868 print '<td class="liste_titre">';
869 print '<input type="text" class="flat" name="search_task_ref_parent" value="'.dol_escape_htmltag($search_task_ref_parent).'" size="4">';
870 print '</td>';
871}
872if (!empty($arrayfields['t.label']['checked'])) {
873 print '<td class="liste_titre">';
874 print '<input type="text" class="flat" name="search_task_label" value="'.dol_escape_htmltag($search_task_label).'" size="8">';
875 print '</td>';
876}
877// Task Description
878if (!empty($arrayfields['t.description']['checked'])) {
879 print '<td class="liste_titre">';
880 print '<input type="text" class="flat" name="search_task_description" value="'.dol_escape_htmltag($search_task_description).'" size="8">';
881 print '</td>';
882}
883// Start date
884if (!empty($arrayfields['t.dateo']['checked'])) {
885 print '<td class="liste_titre center">';
886 print '<div class="nowrapfordate">';
887 print $form->selectDate($search_date_start ? $search_date_start : -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
888 print '</div>';
889 print '<div class="nowrapfordate">';
890 print $form->selectDate($search_date_end ? $search_date_end : -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
891 print '</div>';
892 print '</td>';
893}
894// End date
895if (!empty($arrayfields['t.datee']['checked'])) {
896 print '<td class="liste_titre center">';
897 print '<div class="nowrapfordate">';
898 print $form->selectDate($search_datelimit_start ? $search_datelimit_start : -1, 'search_datelimit_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
899 print '</div>';
900 print '<div class="nowrapfordate">';
901 print $form->selectDate($search_datelimit_end ? $search_datelimit_end : -1, 'search_datelimit_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
902 // TODO Add option late
903 //print '<br><input type="checkbox" name="search_option" value="late"'.($option == 'late' ? ' checked' : '').'> '.$langs->trans("Alert");
904 print '</div>';
905 print '</td>';
906}
907if (!empty($arrayfields['p.ref']['checked'])) {
908 print '<td class="liste_titre">';
909 print '<input type="text" class="flat" name="search_project_ref" value="'.$search_project_ref.'" size="4">';
910 print '</td>';
911}
912if (!empty($arrayfields['p.title']['checked'])) {
913 print '<td class="liste_titre">';
914 print '<input type="text" class="flat" name="search_project_title" value="'.$search_project_title.'" size="6">';
915 print '</td>';
916}
917if (!empty($arrayfields['s.nom']['checked'])) {
918 print '<td class="liste_titre">';
919 print '<input type="text" class="flat" name="search_societe" value="'.dol_escape_htmltag($search_societe).'" size="4">';
920 print '</td>';
921}
922if (!empty($arrayfields['s.name_alias']['checked'])) {
923 print '<td class="liste_titre">';
924 print '<input type="text" class="flat" name="search_societe_alias" value="'.dol_escape_htmltag($search_societe_alias).'" size="4">';
925 print '</td>';
926}
927if (!empty($arrayfields['p.fk_statut']['checked'])) {
928 print '<td class="liste_titre center">';
929 $arrayofstatus = array();
930 foreach ($projectstatic->labelStatusShort as $key => $val) {
931 $arrayofstatus[$key] = $langs->trans($val);
932 }
933 $arrayofstatus['99'] = $langs->trans("NotClosed").' ('.$langs->trans('Draft').'+'.$langs->trans('Opened').')';
934 print $form->selectarray('search_projectstatus', $arrayofstatus, $search_projectstatus, 1, 0, 0, '', 0, 0, 0, '', 'maxwidth100');
935 print '</td>';
936}
937if (!empty($arrayfields['t.planned_workload']['checked'])) {
938 print '<td class="liste_titre"></td>';
939}
940if (!empty($arrayfields['t.duration_effective']['checked'])) {
941 print '<td class="liste_titre"></td>';
942}
943if (!empty($arrayfields['t.progress_calculated']['checked'])) {
944 print '<td class="liste_titre"></td>';
945}
946if (!empty($arrayfields['t.progress']['checked'])) {
947 print '<td class="liste_titre center">';
948 print '<input type="text" class="flat" name="search_task_progress" value="'.$search_task_progress.'" size="4">';
949 print '</td>';
950}
951
952if (!empty($arrayfields['t.progress_summary']['checked'])) {
953 print '<td class="liste_titre"></td>';
954}
955if (!empty($arrayfields['t.fk_statut']['checked'])) {
956 print '<td class="liste_titre center">';
957 $arrayofstatus = array();
958 foreach ($object->labelStatusShort as $key => $val) {
959 $arrayofstatus[$key] = $langs->trans($val);
960 }
961 print $form->selectarray('search_task_status', $arrayofstatus, $search_task_status, 1, 0, 0, '', 0, 0, 0, '', 'maxwidth100');
962 print '</td>';
963}
964
965if (!empty($arrayfields['t.budget_amount']['checked'])) {
966 print '<td class="liste_titre center">';
967 print '<input type="text" class="flat" name="search_task_budget_amount" value="'.$search_task_budget_amount.'" size="4">';
968 print '</td>';
969}
970
971if (!empty($arrayfields['t.tobill']['checked'])) {
972 print '<td class="liste_titre"></td>';
973}
974if (!empty($arrayfields['t.billed']['checked'])) {
975 print '<td class="liste_titre"></td>';
976}
977// Extra fields
978include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
979// Fields from hook
980$parameters = array('arrayfields' => $arrayfields);
981$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
982print $hookmanager->resPrint;
983if (!empty($arrayfields['t.datec']['checked'])) {
984 // Date creation
985 print '<td class="liste_titre">';
986 print '</td>';
987}
988if (!empty($arrayfields['t.tms']['checked'])) {
989 // Date modification
990 print '<td class="liste_titre">';
991 print '</td>';
992}
993// Action column
994if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
995 print '<td class="liste_titre center maxwidthsearch">';
996 $searchpicto = $form->showFilterButtons();
997 print $searchpicto;
998 print '</td>';
999}
1000print '</tr>'."\n";
1001
1002$totalarray = array(
1003 'nbfield' => 0,
1004 'type' => [],
1005 'val' => array(
1006 't.planned_workload' => 0,
1007 't.duration_effective' => 0,
1008 't.progress' => 0,
1009 't.budget_amount' => 0,
1010 ),
1011 'totalplannedworkload' => 0,
1012 'totaldurationeffective' => 0,
1013 'totaldurationdeclared' => 0,
1014 'totaltobillfield' => 0,
1015 'totalbilledfield' => 0,
1016 'totalbudget_amountfield' => 0,
1017 'totalbudgetamount' => 0,
1018 'totalbudget' => 0,
1019 'totaltobill' => 0,
1020 'totalbilled' => 0,
1021 'totalizable' => [],
1022);
1023
1024// Fields title label
1025// --------------------------------------------------------------------
1026print '<tr class="liste_titre">';
1027// Action column
1028if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1029 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
1030 $totalarray['nbfield']++;
1031}
1032if (!empty($arrayfields['t.ref']['checked'])) {
1033 print_liste_field_titre($arrayfields['t.ref']['label'], $_SERVER["PHP_SELF"], "t.ref", "", $param, "", $sortfield, $sortorder);
1034 $totalarray['nbfield']++;
1035}
1036if (!empty($arrayfields['t.fk_task_parent']['checked'])) {
1037 print_liste_field_titre($arrayfields['t.fk_task_parent']['label'], $_SERVER["PHP_SELF"], "t.fk_task_parent", "", $param, "", $sortfield, $sortorder);
1038 $totalarray['nbfield']++;
1039}
1040if (!empty($arrayfields['t.label']['checked'])) {
1041 print_liste_field_titre($arrayfields['t.label']['label'], $_SERVER["PHP_SELF"], "t.label", "", $param, "", $sortfield, $sortorder);
1042 $totalarray['nbfield']++;
1043}
1044if (!empty($arrayfields['t.description']['checked'])) {
1045 print_liste_field_titre($arrayfields['t.description']['label'], $_SERVER["PHP_SELF"], "t.description", "", $param, "", $sortfield, $sortorder);
1046 $totalarray['nbfield']++;
1047}
1048if (!empty($arrayfields['t.dateo']['checked'])) {
1049 print_liste_field_titre($arrayfields['t.dateo']['label'], $_SERVER["PHP_SELF"], "t.dateo", "", $param, '', $sortfield, $sortorder, 'center ');
1050 $totalarray['nbfield']++;
1051}
1052if (!empty($arrayfields['t.datee']['checked'])) {
1053 print_liste_field_titre($arrayfields['t.datee']['label'], $_SERVER["PHP_SELF"], "t.datee", "", $param, '', $sortfield, $sortorder, 'center ');
1054 $totalarray['nbfield']++;
1055}
1056if (!empty($arrayfields['p.ref']['checked'])) {
1057 print_liste_field_titre($arrayfields['p.ref']['label'], $_SERVER["PHP_SELF"], "p.ref", "", $param, "", $sortfield, $sortorder);
1058 $totalarray['nbfield']++;
1059}
1060if (!empty($arrayfields['p.title']['checked'])) {
1061 print_liste_field_titre($arrayfields['p.title']['label'], $_SERVER["PHP_SELF"], "p.title", "", $param, "", $sortfield, $sortorder);
1062 $totalarray['nbfield']++;
1063}
1064if (!empty($arrayfields['s.nom']['checked'])) {
1065 print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER["PHP_SELF"], "s.nom", "", $param, "", $sortfield, $sortorder);
1066 $totalarray['nbfield']++;
1067}
1068if (!empty($arrayfields['s.name_alias']['checked'])) {
1069 print_liste_field_titre($arrayfields['s.name_alias']['label'], $_SERVER["PHP_SELF"], "s.name_alias", "", $param, "", $sortfield, $sortorder);
1070 $totalarray['nbfield']++;
1071}
1072if (!empty($arrayfields['p.fk_statut']['checked'])) {
1073 print_liste_field_titre($arrayfields['p.fk_statut']['label'], $_SERVER["PHP_SELF"], "p.fk_statut", "", $param, '', $sortfield, $sortorder, 'center ');
1074 $totalarray['nbfield']++;
1075}
1076if (!empty($arrayfields['t.planned_workload']['checked'])) {
1077 print_liste_field_titre($arrayfields['t.planned_workload']['label'], $_SERVER["PHP_SELF"], "t.planned_workload", "", $param, '', $sortfield, $sortorder, 'center ');
1078 $totalarray['nbfield']++;
1079}
1080if (!empty($arrayfields['t.duration_effective']['checked'])) {
1081 print_liste_field_titre($arrayfields['t.duration_effective']['label'], $_SERVER["PHP_SELF"], "t.duration_effective", "", $param, '', $sortfield, $sortorder, 'center ');
1082 $totalarray['nbfield']++;
1083}
1084if (!empty($arrayfields['t.progress_calculated']['checked'])) {
1085 print_liste_field_titre($arrayfields['t.progress_calculated']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', '', '', 'center ');
1086 $totalarray['nbfield']++;
1087}
1088if (!empty($arrayfields['t.progress']['checked'])) {
1089 print_liste_field_titre($arrayfields['t.progress']['label'], $_SERVER["PHP_SELF"], "t.progress", "", $param, '', $sortfield, $sortorder, 'center ');
1090 $totalarray['nbfield']++;
1091}
1092if (!empty($arrayfields['t.progress_summary']['checked'])) {
1093 print_liste_field_titre($arrayfields['t.progress_summary']['label'], $_SERVER["PHP_SELF"], "t.progress", "", $param, '', $sortfield, $sortorder, 'center ');
1094 $totalarray['nbfield']++;
1095}
1096if (!empty($arrayfields['t.fk_statut']['checked'])) {
1097 print_liste_field_titre($arrayfields['t.fk_statut']['label'], $_SERVER["PHP_SELF"], "t.fk_statut", "", $param, '', $sortfield, $sortorder, 'center ');
1098 $totalarray['nbfield']++;
1099}
1100if (!empty($arrayfields['t.budget_amount']['checked'])) {
1101 print_liste_field_titre($arrayfields['t.budget_amount']['label'], $_SERVER["PHP_SELF"], "t.budget_amount", "", $param, '', $sortfield, $sortorder, 'center ');
1102 $totalarray['nbfield']++;
1103}
1104if (!empty($arrayfields['t.tobill']['checked'])) {
1105 // @phan-suppress-next-line PhanTypeInvalidDimOffset
1106 print_liste_field_titre($arrayfields['t.tobill']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'center ');
1107 $totalarray['nbfield']++;
1108}
1109if (!empty($arrayfields['t.billed']['checked'])) {
1110 print_liste_field_titre($arrayfields['t.billed']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'center ');
1111 $totalarray['nbfield']++;
1112}
1113// Extra fields
1114include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
1115// Hook fields
1116$parameters = array(
1117 'arrayfields' => $arrayfields,
1118 'param' => $param,
1119 'sortfield' => $sortfield,
1120 'sortorder' => $sortorder,
1121 'totalarray' => &$totalarray,
1122);
1123$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1124print $hookmanager->resPrint;
1125if (!empty($arrayfields['t.datec']['checked'])) {
1126 print_liste_field_titre($arrayfields['t.datec']['label'], $_SERVER["PHP_SELF"], "t.datec", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
1127 $totalarray['nbfield']++;
1128}
1129if (!empty($arrayfields['t.tms']['checked'])) {
1130 print_liste_field_titre($arrayfields['t.tms']['label'], $_SERVER["PHP_SELF"], "t.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
1131 $totalarray['nbfield']++;
1132}
1133// Action column
1134if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1135 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
1136 $totalarray['nbfield']++;
1137}
1138print '</tr>'."\n";
1139
1140$plannedworkloadoutputformat = 'allhourmin';
1141$timespentoutputformat = 'allhourmin';
1142if (getDolGlobalString('PROJECT_PLANNED_WORKLOAD_FORMAT')) {
1143 $plannedworkloadoutputformat = getDolGlobalString('PROJECT_PLANNED_WORKLOAD_FORMAT');
1144}
1145if (getDolGlobalString('PROJECT_TIMES_SPENT_FORMAT')) {
1146 $timespentoutputformat = getDolGlobalString('PROJECT_TIME_SPENT_FORMAT');
1147}
1148
1149// Loop on record
1150// --------------------------------------------------------------------
1151$i = 0;
1152$savnbfield = $totalarray['nbfield'];
1153
1154$totalarray['nbfield'] = 0;
1155$imaxinloop = ($limit ? min($num, $limit) : $num);
1156while ($i < $imaxinloop) {
1157 $obj = $db->fetch_object($resql);
1158 if (empty($obj)) {
1159 break; // Should not happen
1160 }
1161
1162 // Store properties in $object
1163 $object->id = $obj->id;
1164 $object->ref = $obj->ref;
1165 $object->label = $obj->label;
1166 $object->description = $obj->description;
1167 $object->status = $obj->status;
1168 $object->progress = $obj->progress;
1169 $object->budget_amount = $obj->budget_amount;
1170 $object->date_start = $db->jdate($obj->date_start);
1171 $object->date_end = $db->jdate($obj->date_end);
1172 $object->planned_workload = $obj->planned_workload;
1173 $object->duration_effective = $obj->duration_effective;
1174 $object->fk_task_parent = $obj->fk_task_parent;
1175
1176 $projectstatic->id = $obj->projectid;
1177 $projectstatic->ref = $obj->projectref;
1178 $projectstatic->title = $obj->projecttitle;
1179 $projectstatic->public = $obj->public;
1180 $projectstatic->statut = $obj->projectstatus;
1181 $projectstatic->datee = $db->jdate($obj->projectdatee);
1182
1183 if ($obj->socid) {
1184 $socstatic->id = $obj->socid;
1185 $socstatic->name = $obj->name;
1186 $socstatic->name_alias = $obj->alias;
1187 }
1188 if ($mode == 'kanban') {
1189 if ($i == 0) {
1190 print '<tr class="trkanban"><td colspan="'.$savnbfield.'">';
1191 print '<div class="box-flex-container kanban">';
1192 }
1193 // Output Kanban
1194 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1195 $selected = 0;
1196 if (in_array($object->id, $arrayofselected)) {
1197 $selected = 1;
1198 }
1199 }
1200
1201 $arraydata = array();
1202 $arraydata['projectlink'] = $projectstatic->getNomUrl(1);
1203 $arraydata['selected'] = in_array($object->id, $arrayofselected);
1204
1205 print $object->getKanbanView('', $arraydata);
1206 if ($i == ($imaxinloop - 1)) {
1207 print '</div>';
1208 print '</td></tr>';
1209 }
1210 } else {
1211 $userAccess = $projectstatic->restrictedProjectArea($user); // why this ?
1212 if ($userAccess >= 0) {
1213 // Show here line of result
1214 $j = 0;
1215 print '<tr data-rowid="'.$object->id.'" class="oddeven">';
1216
1217 // Action column
1218 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1219 print '<td class="nowrap center">';
1220 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1221 $selected = 0;
1222 if (in_array($object->id, $arrayofselected)) {
1223 $selected = 1;
1224 }
1225 print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
1226 }
1227 print '</td>';
1228 if (!$i) {
1229 $totalarray['nbfield']++;
1230 }
1231 }
1232 // Ref
1233 if (!empty($arrayfields['t.ref']['checked'])) {
1234 print '<td class="nowraponall">';
1235 print $object->getNomUrl(1, 'withproject');
1236 if ($object->hasDelay()) {
1237 print img_warning("Late");
1238 }
1239 print '</td>';
1240 if (!$i) {
1241 $totalarray['nbfield']++;
1242 }
1243 }
1244 // Ref Parent
1245 if (!empty($arrayfields['t.fk_task_parent']['checked'])) {
1246 print '<td class="nowraponall">';
1247 if (!empty($object->fk_task_parent)) {
1248 $object_parent = new Task($db);
1249 $result = $object_parent->fetch($object->fk_task_parent);
1250 if ($result < 0) {
1251 setEventMessage($object_parent->error, 'errors');
1252 } else {
1253 print $object_parent->getNomUrl(1, 'withproject');
1254 if ($object_parent->hasDelay()) {
1255 print img_warning("Late");
1256 }
1257 }
1258 }
1259 print '</td>';
1260 if (!$i) {
1261 $totalarray['nbfield']++;
1262 }
1263 }
1264 // Label
1265 if (!empty($arrayfields['t.label']['checked'])) {
1266 print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($object->label).'">';
1267 print dol_escape_htmltag($object->label);
1268 print '</td>';
1269 if (!$i) {
1270 $totalarray['nbfield']++;
1271 }
1272 }
1273 // Description
1274 if (!empty($arrayfields['t.description']['checked'])) {
1275 print '<td>';
1276 print dolGetFirstLineOfText($object->description, 5);
1277 print '</td>';
1278 if (!$i) {
1279 $totalarray['nbfield']++;
1280 }
1281 }
1282
1283 // Date start project
1284 if (!empty($arrayfields['t.dateo']['checked'])) {
1285 print '<td class="center">';
1286 print dol_print_date($db->jdate($obj->date_start), 'day');
1287 print '</td>';
1288 if (!$i) {
1289 $totalarray['nbfield']++;
1290 }
1291 }
1292 // Date end project
1293 if (!empty($arrayfields['t.datee']['checked'])) {
1294 print '<td class="center">';
1295 print dol_print_date($db->jdate($obj->date_end), 'day');
1296 print '</td>';
1297 if (!$i) {
1298 $totalarray['nbfield']++;
1299 }
1300 }
1301 // Project ref
1302 if (!empty($arrayfields['p.ref']['checked'])) {
1303 print '<td class="nowraponall tdoverflowmax150">';
1304 print $projectstatic->getNomUrl(1, 'task');
1305 if ($projectstatic->hasDelay()) {
1306 print img_warning("Late");
1307 }
1308 print '</td>';
1309 if (!$i) {
1310 $totalarray['nbfield']++;
1311 }
1312 }
1313 // Project title
1314 if (!empty($arrayfields['p.title']['checked'])) {
1315 print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($obj->projecttitle).'">';
1316 print dol_escape_htmltag($obj->projecttitle);
1317 print '</td>';
1318 if (!$i) {
1319 $totalarray['nbfield']++;
1320 }
1321 }
1322 // Third party
1323 if (!empty($arrayfields['s.nom']['checked'])) {
1324 print '<td class="tdoverflowmax125">';
1325 if ($obj->socid) {
1326 print $socstatic->getNomUrl(1, '', 0, 0, -1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1);
1327 } else {
1328 print '&nbsp;';
1329 }
1330 print '</td>';
1331 if (!$i) {
1332 $totalarray['nbfield']++;
1333 }
1334 }
1335 // Alias
1336 if (!empty($arrayfields['s.name_alias']['checked'])) {
1337 $name_alias = '';
1338 if ($obj->socid) {
1339 $name_alias = $socstatic->name_alias;
1340 }
1341 print '<td class="tdoverflowmax125" title="'.dol_escape_htmltag($name_alias).'">';
1342 print dol_escape_htmltag($name_alias);
1343 print '</td>';
1344 if (!$i) {
1345 $totalarray['nbfield']++;
1346 }
1347 }
1348 // Project status
1349 if (!empty($arrayfields['p.fk_statut']['checked'])) {
1350 print '<td class="center">';
1351 print $projectstatic->getLibStatut(1);
1352 print '</td>';
1353 if (!$i) {
1354 $totalarray['nbfield']++;
1355 }
1356 }
1357
1358 // Planned workload
1359 if (!empty($arrayfields['t.planned_workload']['checked'])) {
1360 print '<td class="center">';
1361 $fullhour = convertSecondToTime($obj->planned_workload, $plannedworkloadoutputformat);
1362 $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
1363 if ($obj->planned_workload != '') {
1364 print $fullhour;
1365 // TODO Add delay taking account of working hours per day and working day per week
1366 //if ($workingdelay != $fullhour) print '<br>('.$workingdelay.')';
1367 }
1368 //else print '--:--';
1369 print '</td>';
1370 if (!$i) {
1371 $totalarray['nbfield']++;
1372 }
1373 if (!$i) {
1374 $totalarray['pos'][$totalarray['nbfield']] = 't.planned_workload';
1375 }
1376 if (!isset($totalarray['val']['t.planned_workload'])) {
1377 $totalarray['val']['t.planned_workload'] = 0;
1378 }
1379 $totalarray['val']['t.planned_workload'] += $obj->planned_workload;
1380 if (!$i) {
1381 $totalarray['totalplannedworkloadfield'] = $totalarray['nbfield'];
1382 }
1383 if (!isset($totalarray['totalplannedworkload'])) {
1384 $totalarray['totalplannedworkload'] = 0;
1385 }
1386 $totalarray['totalplannedworkload'] += $obj->planned_workload;
1387 }
1388 // Time spent
1389 if (!empty($arrayfields['t.duration_effective']['checked'])) {
1390 $showlineingray = 0;
1391 $showproject = 1;
1392 print '<td class="center">';
1393 if ($showlineingray) {
1394 print '<i>';
1395 } else {
1396 print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$object->id.($showproject ? '' : '&withproject=1').'">';
1397 }
1398 if ($obj->duration_effective) {
1399 print convertSecondToTime($obj->duration_effective, $timespentoutputformat);
1400 } else {
1401 print '--:--';
1402 }
1403 if ($showlineingray) {
1404 print '</i>';
1405 } else {
1406 print '</a>';
1407 }
1408 if (empty($arrayfields['t.progress_calculated']['checked'])) {
1409 if ($obj->planned_workload || $obj->duration_effective) {
1410 if ($obj->planned_workload) {
1411 print ' <span class="opacitymedium">('.round(100 * $obj->duration_effective / $obj->planned_workload, 2).' %)</span>';
1412 } else {
1413 print $form->textwithpicto('', $langs->trans('WorkloadNotDefined'), 1, 'help');
1414 }
1415 }
1416 }
1417 print '</td>';
1418 if (!$i) {
1419 $totalarray['nbfield']++;
1420 }
1421 if (!$i) {
1422 $totalarray['pos'][$totalarray['nbfield']] = 't.duration_effective';
1423 }
1424 if (!isset($totalarray['val']['t.duration_effective'])) {
1425 $totalarray['val']['t.duration_effective'] = 0;
1426 }
1427 $totalarray['val']['t.duration_effective'] += $obj->duration_effective;
1428 if (!$i) {
1429 $totalarray['totaldurationeffectivefield'] = $totalarray['nbfield'];
1430 }
1431 if (!isset($totalarray['totaldurationeffective'])) {
1432 $totalarray['totaldurationeffective'] = 0;
1433 }
1434 $totalarray['totaldurationeffective'] += $obj->duration_effective;
1435 }
1436 // Calculated progress
1437 if (!empty($arrayfields['t.progress_calculated']['checked'])) {
1438 print '<td class="center">';
1439 if ($obj->planned_workload || $obj->duration_effective) {
1440 if ($obj->planned_workload) {
1441 print round(100 * $obj->duration_effective / $obj->planned_workload, 2).' %';
1442 } else {
1443 print $form->textwithpicto('', $langs->trans('WorkloadNotDefined'), 1, 'help');
1444 }
1445 }
1446 print '</td>';
1447 if (!$i) {
1448 $totalarray['nbfield']++;
1449 }
1450 if (!$i) {
1451 $totalarray['totalprogress_calculatedfield'] = $totalarray['nbfield'];
1452 }
1453 }
1454 // Declared progress
1455 if (!empty($arrayfields['t.progress']['checked'])) {
1456 print '<td class="center">';
1457 if ($obj->progress != '') {
1458 print getTaskProgressBadge($object);
1459 }
1460 print '</td>';
1461 if (!$i) {
1462 $totalarray['nbfield']++;
1463 }
1464 if (!$i) {
1465 $totalarray['pos'][$totalarray['nbfield']] = 't.progress';
1466 }
1467 if (!isset($totalarray['val']['t.progress'])) {
1468 $totalarray['val']['t.progress'] = 0;
1469 }
1470 $totalarray['val']['t.progress'] += ($obj->planned_workload * $obj->progress / 100);
1471 if (!$i) {
1472 $totalarray['totalprogress_declaredfield'] = $totalarray['nbfield'];
1473 }
1474 if (!isset($totalarray['totaldurationdeclared'])) {
1475 $totalarray['totaldurationdeclared'] = 0;
1476 }
1477 $totalarray['totaldurationdeclared'] += $obj->planned_workload * $obj->progress / 100;
1478 }
1479 // Progress summary
1480 if (!empty($arrayfields['t.progress_summary']['checked'])) {
1481 print '<td class="center">';
1482 //if ($obj->progress != '') {
1483 print getTaskProgressView($object, false, false);
1484 //}
1485 print '</td>';
1486 if (!$i) {
1487 $totalarray['nbfield']++;
1488 }
1489 if (!$i) {
1490 $totalarray['totalprogress_summary'] = $totalarray['nbfield'];
1491 }
1492 }
1493 // Task status
1494 if (!empty($arrayfields['t.fk_statut']['checked'])) {
1495 print '<td class="center">';
1496 print $object->getLibStatut(4);
1497 print '</td>';
1498 if (!$i) {
1499 $totalarray['nbfield']++;
1500 }
1501 }
1502 // Budget for task
1503 if (!empty($arrayfields['t.budget_amount']['checked'])) {
1504 print '<td class="center">';
1505 if ($object->budget_amount) {
1506 print '<span class="amount">'.price($object->budget_amount, 0, $langs, 1, 0, 0, $conf->currency).'</span>';
1507 }
1508 print '</td>';
1509 if (!$i) {
1510 $totalarray['nbfield']++;
1511 }
1512 if (!$i) {
1513 $totalarray['pos'][$totalarray['nbfield']] = 't.budget_amount';
1514 }
1515 $totalarray['val']['t.budget_amount'] += $obj->budget_amount;
1516 if (!$i) {
1517 $totalarray['totalbudget_amountfield'] = $totalarray['nbfield'];
1518 }
1519 $totalarray['totalbudgetamount'] += $obj->budget_amount;
1520 }
1521 // Time not billed
1522 if (!empty($arrayfields['t.tobill']['checked'])) {
1523 print '<td class="center">';
1524 if ($obj->usage_bill_time) {
1525 print convertSecondToTime($obj->tobill, 'allhourmin');
1526 $totalarray['val']['t.tobill'] += $obj->tobill;
1527 $totalarray['totaltobill'] += $obj->tobill;
1528 } else {
1529 print '<span class="opacitymedium">'.$langs->trans("NA").'</span>';
1530 }
1531 print '</td>';
1532 if (!$i) {
1533 $totalarray['nbfield']++;
1534 }
1535 if (!$i) {
1536 $totalarray['pos'][$totalarray['nbfield']] = 't.tobill';
1537 }
1538 if (!$i) {
1539 $totalarray['totaltobillfield'] = $totalarray['nbfield'];
1540 }
1541 }
1542 // Time billed
1543 if (!empty($arrayfields['t.billed']['checked'])) {
1544 print '<td class="center">';
1545 if ($obj->usage_bill_time) {
1546 print convertSecondToTime($obj->billed, 'allhourmin');
1547 $totalarray['val']['t.billed'] += $obj->billed;
1548 $totalarray['totalbilled'] += $obj->billed;
1549 } else {
1550 print '<span class="opacitymedium">'.$langs->trans("NA").'</span>';
1551 }
1552 print '</td>';
1553 if (!$i) {
1554 $totalarray['nbfield']++;
1555 }
1556 if (!$i) {
1557 $totalarray['pos'][$totalarray['nbfield']] = 't.billed';
1558 }
1559 if (!$i) {
1560 $totalarray['totalbilledfield'] = $totalarray['nbfield'];
1561 }
1562 }
1563 // Extra fields
1564 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
1565 // Fields from hook
1566 $parameters = array('arrayfields' => $arrayfields, 'object' => $object, 'obj' => $obj, 'i' => $i, 'totalarray' => &$totalarray);
1567 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1568 print $hookmanager->resPrint;
1569 // Date creation
1570 if (!empty($arrayfields['t.datec']['checked'])) {
1571 print '<td class="center">';
1572 print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser');
1573 print '</td>';
1574 if (!$i) {
1575 $totalarray['nbfield']++;
1576 }
1577 }
1578 // Date modification
1579 if (!empty($arrayfields['t.tms']['checked'])) {
1580 print '<td class="center">';
1581 print dol_print_date($db->jdate($obj->date_modification), 'dayhour', 'tzuser');
1582 print '</td>';
1583 if (!$i) {
1584 $totalarray['nbfield']++;
1585 }
1586 }
1587 // Status
1588 /*if (!empty($arrayfields['p.fk_statut']['checked'])) {
1589 $projectstatic->status = $obj->fk_statut;
1590 print '<td class="right">'.$projectstatic->getLibStatut(5).'</td>';
1591 }*/
1592 // Action column
1593 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1594 print '<td class="nowrap center">';
1595 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1596 $selected = 0;
1597 if (in_array($object->id, $arrayofselected)) {
1598 $selected = 1;
1599 }
1600 print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
1601 }
1602 print '</td>';
1603 if (!$i) {
1604 $totalarray['nbfield']++;
1605 }
1606 }
1607
1608 print '</tr>'."\n";
1609 }
1610 }
1611
1612 $i++;
1613}
1614
1615// Show total line
1616if (!empty($totalarray['totalizable']) && is_array($totalarray['totalizable'])) {
1617 foreach ($totalarray['totalizable'] as $keytotalizable => $valtotalizable) {
1618 $totalarray['pos'][$valtotalizable['pos']] = $keytotalizable;
1619 $totalarray['val'][$keytotalizable] = $valtotalizable['total'];
1620 }
1621}
1622
1623// Show total line
1624//include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
1625if (isset($totalarray['totaldurationeffectivefield']) || isset($totalarray['totalplannedworkloadfield']) || isset($totalarray['totalprogress_calculatedfield'])
1626 || isset($totalarray['totaltobill']) || isset($totalarray['totalbilled']) || isset($totalarray['totalbudget'])) {
1627 print '<tr class="liste_total">';
1628 $i = 0;
1629 while ($i < $totalarray['nbfield']) {
1630 $i++;
1631 if ($i == 1) {
1632 if ((is_null($limit) || $num < $limit) && empty($offset)) {
1633 print '<td>'.$langs->trans("Total").'</td>';
1634 } else {
1635 print '<td>';
1636 if (is_object($form)) {
1637 print $form->textwithpicto($langs->trans("Total"), $langs->transnoentitiesnoconv("Totalforthispage"));
1638 } else {
1639 print $langs->trans("Totalforthispage");
1640 }
1641 print '</td>';
1642 }
1643 /*
1644 if ($num < $limit && empty($offset)) {
1645 print '<td class="left">'.$langs->trans("Total").'</td>';
1646 } else {
1647 print '<td class="left">'.$langs->trans("Totalforthispage").'</td>';
1648 }*/
1649 } elseif (isset($totalarray['totalplannedworkloadfield']) && $totalarray['totalplannedworkloadfield'] == $i) {
1650 print '<td class="center">'.convertSecondToTime($totalarray['totalplannedworkload'], $plannedworkloadoutputformat).'</td>';
1651 } elseif (isset($totalarray['totaldurationeffectivefield']) && $totalarray['totaldurationeffectivefield'] == $i) {
1652 print '<td class="center">'.convertSecondToTime($totalarray['totaldurationeffective'], $timespentoutputformat).'</td>';
1653 } elseif (isset($totalarray['totalprogress_calculatedfield']) && $totalarray['totalprogress_calculatedfield'] == $i) {
1654 print '<td class="center">'.($totalarray['totalplannedworkload'] > 0 ? round(100 * $totalarray['totaldurationeffective'] / $totalarray['totalplannedworkload'], 2).' %' : '').'</td>';
1655 } elseif (isset($totalarray['totalprogress_declaredfield']) && $totalarray['totalprogress_declaredfield'] == $i) {
1656 print '<td class="center">'.($totalarray['totalplannedworkload'] > 0 ? round(100 * $totalarray['totaldurationdeclared'] / $totalarray['totalplannedworkload'], 2).' %' : '').'</td>';
1657 } elseif (isset($totalarray['totaltobillfield']) && $totalarray['totaltobillfield'] == $i) {
1658 print '<td class="center">'.convertSecondToTime($totalarray['totaltobill'], $plannedworkloadoutputformat).'</td>';
1659 } elseif (isset($totalarray['totalbilledfield']) && $totalarray['totalbilledfield'] == $i) {
1660 print '<td class="center">'.convertSecondToTime($totalarray['totalbilled'], $plannedworkloadoutputformat).'</td>';
1661 } elseif (isset($totalarray['totalbudget_amountfield']) && $totalarray['totalbudget_amountfield'] == $i) {
1662 print '<td class="center">'.price((float) $totalarray['totalbudgetamount'], 0, $langs, 1, 0, 0, $conf->currency).'</td>';
1663 } elseif (!empty($totalarray['pos'][$i])) {
1664 print '<td class="right">';
1665 // @phan-suppress-next-line PhanTypeInvalidDimOffset
1666 if (isset($totalarray['type']) && $totalarray['type'][$i] == 'duration') {
1667 print(!empty($totalarray['val'][$totalarray['pos'][$i]]) ? convertSecondToTime($totalarray['val'][$totalarray['pos'][$i]], 'allhourmin') : 0);
1668 } else {
1669 print price(!empty($totalarray['val'][$totalarray['pos'][$i]]) ? $totalarray['val'][$totalarray['pos'][$i]] : 0);
1670 }
1671 print '</td>';
1672 } else {
1673 print '<td></td>';
1674 }
1675 }
1676 print '</tr>';
1677}
1678
1679$db->free($resql);
1680
1681$parameters = array('arrayfields' => $arrayfields, 'sql' => $sql);
1682$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1683print $hookmanager->resPrint;
1684
1685print '</table>'."\n";
1686print '</div>'."\n";
1687
1688print '</form>'."\n";
1689
1690// End of page
1691llxFooter();
1692$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:48
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:67
$totalarray
Definition export.php:1206
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 permettant la generation de composants html autre Only common components are here.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage tasks.
Class to manage Dolibarr users.
convertSecondToTime($iSecond, $format='all', $lengthOfDay=86400, $lengthOfWeek=7)
Return, in clear text, value of a number of seconds in days, hours and minutes.
Definition date.lib.php:244
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.
dolGetButtonTitle($label, $helpText='', $iconClass='fa fa-file', $url='', $id='', $status=1, $params=array())
Function dolGetButtonTitle : this kind of buttons are used in title in list.
natural_search($fields, $value, $mode=0, $nofirstand=0)
Generate natural SQL search string for a criteria (this criteria can be tested on one or several fiel...
setEventMessage($mesgs, $style='mesgs', $noduplicate=0, $attop=0)
Set event message in dol_events session object.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by the value of a given key, which produces ascending (default) or descending out...
getTitleFieldOfList($name, $thead=0, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $disablesortlink=0, $tooltip='', $forcenowrapcolumntitle=0)
Get title line of an array.
dolGetButtonTitleSeparator($moreClass="")
Add space between dolGetButtonTitle.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
getTaskProgressView($task, $label=true, $progressNumber=true, $hideOnProgressNull=false, $spaced=false)
getTaskProgressBadge($task, $label='', $tooltip='')
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.