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