dolibarr 20.0.0
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 technical object to manage hooks of page. Note that conf->hooks_modules contains 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 as status";
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'); // 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 print_liste_field_titre($arrayfields['t.tobill']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'center ');
1086 $totalarray['nbfield']++;
1087}
1088if (!empty($arrayfields['t.billed']['checked'])) {
1089 print_liste_field_titre($arrayfields['t.billed']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'center ');
1090 $totalarray['nbfield']++;
1091}
1092// Extra fields
1093include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
1094// Hook fields
1095$parameters = array(
1096 'arrayfields' => $arrayfields,
1097 'param' => $param,
1098 'sortfield' => $sortfield,
1099 'sortorder' => $sortorder,
1100 'totalarray' => &$totalarray,
1101);
1102$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1103print $hookmanager->resPrint;
1104if (!empty($arrayfields['t.datec']['checked'])) {
1105 print_liste_field_titre($arrayfields['t.datec']['label'], $_SERVER["PHP_SELF"], "t.datec", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
1106 $totalarray['nbfield']++;
1107}
1108if (!empty($arrayfields['t.tms']['checked'])) {
1109 print_liste_field_titre($arrayfields['t.tms']['label'], $_SERVER["PHP_SELF"], "t.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
1110 $totalarray['nbfield']++;
1111}
1112// Action column
1113if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1114 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
1115 $totalarray['nbfield']++;
1116}
1117print '</tr>'."\n";
1118
1119$plannedworkloadoutputformat = 'allhourmin';
1120$timespentoutputformat = 'allhourmin';
1121if (getDolGlobalString('PROJECT_PLANNED_WORKLOAD_FORMAT')) {
1122 $plannedworkloadoutputformat = getDolGlobalString('PROJECT_PLANNED_WORKLOAD_FORMAT');
1123}
1124if (getDolGlobalString('PROJECT_TIMES_SPENT_FORMAT')) {
1125 $timespentoutputformat = getDolGlobalString('PROJECT_TIME_SPENT_FORMAT');
1126}
1127
1128// Loop on record
1129// --------------------------------------------------------------------
1130$i = 0;
1131$savnbfield = $totalarray['nbfield'];
1132
1133$totalarray['nbfield'] = 0;
1134$imaxinloop = ($limit ? min($num, $limit) : $num);
1135while ($i < $imaxinloop) {
1136 $obj = $db->fetch_object($resql);
1137 if (empty($obj)) {
1138 break; // Should not happen
1139 }
1140
1141 // Store properties in $object
1142 $object->id = $obj->id;
1143 $object->ref = $obj->ref;
1144 $object->label = $obj->label;
1145 $object->description = $obj->description;
1146 $object->status = $obj->status;
1147 $object->progress = $obj->progress;
1148 $object->budget_amount = $obj->budget_amount;
1149 $object->date_start = $db->jdate($obj->date_start);
1150 $object->date_end = $db->jdate($obj->date_end);
1151 $object->planned_workload = $obj->planned_workload;
1152 $object->duration_effective = $obj->duration_effective;
1153 $object->fk_task_parent = $obj->fk_task_parent;
1154
1155 $projectstatic->id = $obj->projectid;
1156 $projectstatic->ref = $obj->projectref;
1157 $projectstatic->title = $obj->projecttitle;
1158 $projectstatic->public = $obj->public;
1159 $projectstatic->statut = $obj->projectstatus;
1160 $projectstatic->datee = $db->jdate($obj->projectdatee);
1161
1162 if ($obj->socid) {
1163 $socstatic->id = $obj->socid;
1164 $socstatic->name = $obj->name;
1165 $socstatic->name_alias = $obj->alias;
1166 }
1167 if ($mode == 'kanban') {
1168 if ($i == 0) {
1169 print '<tr class="trkanban"><td colspan="'.$savnbfield.'">';
1170 print '<div class="box-flex-container kanban">';
1171 }
1172 // Output Kanban
1173 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1174 $selected = 0;
1175 if (in_array($object->id, $arrayofselected)) {
1176 $selected = 1;
1177 }
1178 }
1179
1180 $arraydata = array();
1181 $arraydata['projectlink'] = $projectstatic->getNomUrl(1);
1182 $arraydata['selected'] = in_array($object->id, $arrayofselected);
1183
1184 print $object->getKanbanView('', $arraydata);
1185 if ($i == ($imaxinloop - 1)) {
1186 print '</div>';
1187 print '</td></tr>';
1188 }
1189 } else {
1190 $userAccess = $projectstatic->restrictedProjectArea($user); // why this ?
1191 if ($userAccess >= 0) {
1192 // Show here line of result
1193 $j = 0;
1194 print '<tr data-rowid="'.$object->id.'" class="oddeven">';
1195
1196 // Action column
1197 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1198 print '<td class="nowrap center">';
1199 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1200 $selected = 0;
1201 if (in_array($object->id, $arrayofselected)) {
1202 $selected = 1;
1203 }
1204 print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
1205 }
1206 print '</td>';
1207 if (!$i) {
1208 $totalarray['nbfield']++;
1209 }
1210 }
1211 // Ref
1212 if (!empty($arrayfields['t.ref']['checked'])) {
1213 print '<td class="nowraponall">';
1214 print $object->getNomUrl(1, 'withproject');
1215 if ($object->hasDelay()) {
1216 print img_warning("Late");
1217 }
1218 print '</td>';
1219 if (!$i) {
1220 $totalarray['nbfield']++;
1221 }
1222 }
1223 // Ref Parent
1224 if (!empty($arrayfields['t.fk_task_parent']['checked'])) {
1225 print '<td class="nowraponall">';
1226 if (!empty($object->fk_task_parent)) {
1227 $object_parent = new Task($db);
1228 $result = $object_parent->fetch($object->fk_task_parent);
1229 if ($result < 0) {
1230 setEventMessage($object_parent->error, 'errors');
1231 } else {
1232 print $object_parent->getNomUrl(1, 'withproject');
1233 if ($object_parent->hasDelay()) {
1234 print img_warning("Late");
1235 }
1236 }
1237 }
1238 print '</td>';
1239 if (!$i) {
1240 $totalarray['nbfield']++;
1241 }
1242 }
1243 // Label
1244 if (!empty($arrayfields['t.label']['checked'])) {
1245 print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($object->label).'">';
1246 print dol_escape_htmltag($object->label);
1247 print '</td>';
1248 if (!$i) {
1249 $totalarray['nbfield']++;
1250 }
1251 }
1252 // Description
1253 if (!empty($arrayfields['t.description']['checked'])) {
1254 print '<td>';
1255 print dolGetFirstLineOfText($object->description, 5);
1256 print '</td>';
1257 if (!$i) {
1258 $totalarray['nbfield']++;
1259 }
1260 }
1261
1262 // Date start project
1263 if (!empty($arrayfields['t.dateo']['checked'])) {
1264 print '<td class="center">';
1265 print dol_print_date($db->jdate($obj->date_start), 'day');
1266 print '</td>';
1267 if (!$i) {
1268 $totalarray['nbfield']++;
1269 }
1270 }
1271 // Date end project
1272 if (!empty($arrayfields['t.datee']['checked'])) {
1273 print '<td class="center">';
1274 print dol_print_date($db->jdate($obj->date_end), 'day');
1275 print '</td>';
1276 if (!$i) {
1277 $totalarray['nbfield']++;
1278 }
1279 }
1280 // Project ref
1281 if (!empty($arrayfields['p.ref']['checked'])) {
1282 print '<td class="nowraponall tdoverflowmax150">';
1283 print $projectstatic->getNomUrl(1, 'task');
1284 if ($projectstatic->hasDelay()) {
1285 print img_warning("Late");
1286 }
1287 print '</td>';
1288 if (!$i) {
1289 $totalarray['nbfield']++;
1290 }
1291 }
1292 // Project title
1293 if (!empty($arrayfields['p.title']['checked'])) {
1294 print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($obj->projecttitle).'">';
1295 print dol_escape_htmltag($obj->projecttitle);
1296 print '</td>';
1297 if (!$i) {
1298 $totalarray['nbfield']++;
1299 }
1300 }
1301 // Third party
1302 if (!empty($arrayfields['s.nom']['checked'])) {
1303 print '<td class="tdoverflowmax125">';
1304 if ($obj->socid) {
1305 print $socstatic->getNomUrl(1, '', 0, 0, -1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1);
1306 } else {
1307 print '&nbsp;';
1308 }
1309 print '</td>';
1310 if (!$i) {
1311 $totalarray['nbfield']++;
1312 }
1313 }
1314 // Alias
1315 if (!empty($arrayfields['s.name_alias']['checked'])) {
1316 $name_alias = '';
1317 if ($obj->socid) {
1318 $name_alias = $socstatic->name_alias;
1319 }
1320 print '<td class="tdoverflowmax125" title="'.dol_escape_htmltag($name_alias).'">';
1321 print dol_escape_htmltag($name_alias);
1322 print '</td>';
1323 if (!$i) {
1324 $totalarray['nbfield']++;
1325 }
1326 }
1327 // Project status
1328 if (!empty($arrayfields['p.fk_statut']['checked'])) {
1329 print '<td class="center">';
1330 print $projectstatic->getLibStatut(1);
1331 print '</td>';
1332 if (!$i) {
1333 $totalarray['nbfield']++;
1334 }
1335 }
1336
1337 // Planned workload
1338 if (!empty($arrayfields['t.planned_workload']['checked'])) {
1339 print '<td class="center">';
1340 $fullhour = convertSecondToTime($obj->planned_workload, $plannedworkloadoutputformat);
1341 $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
1342 if ($obj->planned_workload != '') {
1343 print $fullhour;
1344 // TODO Add delay taking account of working hours per day and working day per week
1345 //if ($workingdelay != $fullhour) print '<br>('.$workingdelay.')';
1346 }
1347 //else print '--:--';
1348 print '</td>';
1349 if (!$i) {
1350 $totalarray['nbfield']++;
1351 }
1352 if (!$i) {
1353 $totalarray['pos'][$totalarray['nbfield']] = 't.planned_workload';
1354 }
1355 if (!isset($totalarray['val']['t.planned_workload'])) {
1356 $totalarray['val']['t.planned_workload'] = 0;
1357 }
1358 $totalarray['val']['t.planned_workload'] += $obj->planned_workload;
1359 if (!$i) {
1360 $totalarray['totalplannedworkloadfield'] = $totalarray['nbfield'];
1361 }
1362 if (!isset($totalarray['totalplannedworkload'])) {
1363 $totalarray['totalplannedworkload'] = 0;
1364 }
1365 $totalarray['totalplannedworkload'] += $obj->planned_workload;
1366 }
1367 // Time spent
1368 if (!empty($arrayfields['t.duration_effective']['checked'])) {
1369 $showlineingray = 0;
1370 $showproject = 1;
1371 print '<td class="center">';
1372 if ($showlineingray) {
1373 print '<i>';
1374 } else {
1375 print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$object->id.($showproject ? '' : '&withproject=1').'">';
1376 }
1377 if ($obj->duration_effective) {
1378 print convertSecondToTime($obj->duration_effective, $timespentoutputformat);
1379 } else {
1380 print '--:--';
1381 }
1382 if ($showlineingray) {
1383 print '</i>';
1384 } else {
1385 print '</a>';
1386 }
1387 if (empty($arrayfields['t.progress_calculated']['checked'])) {
1388 if ($obj->planned_workload || $obj->duration_effective) {
1389 if ($obj->planned_workload) {
1390 print ' <span class="opacitymedium">('.round(100 * $obj->duration_effective / $obj->planned_workload, 2).' %)</span>';
1391 } else {
1392 print $form->textwithpicto('', $langs->trans('WorkloadNotDefined'), 1, 'help');
1393 }
1394 }
1395 }
1396 print '</td>';
1397 if (!$i) {
1398 $totalarray['nbfield']++;
1399 }
1400 if (!$i) {
1401 $totalarray['pos'][$totalarray['nbfield']] = 't.duration_effective';
1402 }
1403 if (!isset($totalarray['val']['t.duration_effective'])) {
1404 $totalarray['val']['t.duration_effective'] = 0;
1405 }
1406 $totalarray['val']['t.duration_effective'] += $obj->duration_effective;
1407 if (!$i) {
1408 $totalarray['totaldurationeffectivefield'] = $totalarray['nbfield'];
1409 }
1410 if (!isset($totalarray['totaldurationeffective'])) {
1411 $totalarray['totaldurationeffective'] = 0;
1412 }
1413 $totalarray['totaldurationeffective'] += $obj->duration_effective;
1414 }
1415 // Calculated progress
1416 if (!empty($arrayfields['t.progress_calculated']['checked'])) {
1417 print '<td class="center">';
1418 if ($obj->planned_workload || $obj->duration_effective) {
1419 if ($obj->planned_workload) {
1420 print round(100 * $obj->duration_effective / $obj->planned_workload, 2).' %';
1421 } else {
1422 print $form->textwithpicto('', $langs->trans('WorkloadNotDefined'), 1, 'help');
1423 }
1424 }
1425 print '</td>';
1426 if (!$i) {
1427 $totalarray['nbfield']++;
1428 }
1429 if (!$i) {
1430 $totalarray['totalprogress_calculatedfield'] = $totalarray['nbfield'];
1431 }
1432 }
1433 // Declared progress
1434 if (!empty($arrayfields['t.progress']['checked'])) {
1435 print '<td class="center">';
1436 if ($obj->progress != '') {
1437 print getTaskProgressBadge($object);
1438 }
1439 print '</td>';
1440 if (!$i) {
1441 $totalarray['nbfield']++;
1442 }
1443 if (!$i) {
1444 $totalarray['pos'][$totalarray['nbfield']] = 't.progress';
1445 }
1446 if (!isset($totalarray['val']['t.progress'])) {
1447 $totalarray['val']['t.progress'] = 0;
1448 }
1449 $totalarray['val']['t.progress'] += ($obj->planned_workload * $obj->progress / 100);
1450 if (!$i) {
1451 $totalarray['totalprogress_declaredfield'] = $totalarray['nbfield'];
1452 }
1453 if (!isset($totalarray['totaldurationdeclared'])) {
1454 $totalarray['totaldurationdeclared'] = 0;
1455 }
1456 $totalarray['totaldurationdeclared'] += $obj->planned_workload * $obj->progress / 100;
1457 }
1458 // Progress summary
1459 if (!empty($arrayfields['t.progress_summary']['checked'])) {
1460 print '<td class="center">';
1461 //if ($obj->progress != '') {
1462 print getTaskProgressView($object, false, false);
1463 //}
1464 print '</td>';
1465 if (!$i) {
1466 $totalarray['nbfield']++;
1467 }
1468 if (!$i) {
1469 $totalarray['totalprogress_summary'] = $totalarray['nbfield'];
1470 }
1471 }
1472 // Budget for task
1473 if (!empty($arrayfields['t.budget_amount']['checked'])) {
1474 print '<td class="center">';
1475 if ($object->budget_amount) {
1476 print '<span class="amount">'.price($object->budget_amount, 0, $langs, 1, 0, 0, $conf->currency).'</span>';
1477 }
1478 print '</td>';
1479 if (!$i) {
1480 $totalarray['nbfield']++;
1481 }
1482 if (!$i) {
1483 $totalarray['pos'][$totalarray['nbfield']] = 't.budget_amount';
1484 }
1485 $totalarray['val']['t.budget_amount'] += $obj->budget_amount;
1486 if (!$i) {
1487 $totalarray['totalbudget_amountfield'] = $totalarray['nbfield'];
1488 }
1489 $totalarray['totalbudgetamount'] += $obj->budget_amount;
1490 }
1491 // Time not billed
1492 if (!empty($arrayfields['t.tobill']['checked'])) {
1493 print '<td class="center">';
1494 if ($obj->usage_bill_time) {
1495 print convertSecondToTime($obj->tobill, 'allhourmin');
1496 $totalarray['val']['t.tobill'] += $obj->tobill;
1497 $totalarray['totaltobill'] += $obj->tobill;
1498 } else {
1499 print '<span class="opacitymedium">'.$langs->trans("NA").'</span>';
1500 }
1501 print '</td>';
1502 if (!$i) {
1503 $totalarray['nbfield']++;
1504 }
1505 if (!$i) {
1506 $totalarray['pos'][$totalarray['nbfield']] = 't.tobill';
1507 }
1508 if (!$i) {
1509 $totalarray['totaltobillfield'] = $totalarray['nbfield'];
1510 }
1511 }
1512 // Time billed
1513 if (!empty($arrayfields['t.billed']['checked'])) {
1514 print '<td class="center">';
1515 if ($obj->usage_bill_time) {
1516 print convertSecondToTime($obj->billed, 'allhourmin');
1517 $totalarray['val']['t.billed'] += $obj->billed;
1518 $totalarray['totalbilled'] += $obj->billed;
1519 } else {
1520 print '<span class="opacitymedium">'.$langs->trans("NA").'</span>';
1521 }
1522 print '</td>';
1523 if (!$i) {
1524 $totalarray['nbfield']++;
1525 }
1526 if (!$i) {
1527 $totalarray['pos'][$totalarray['nbfield']] = 't.billed';
1528 }
1529 if (!$i) {
1530 $totalarray['totalbilledfield'] = $totalarray['nbfield'];
1531 }
1532 }
1533 // Extra fields
1534 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
1535 // Fields from hook
1536 $parameters = array('arrayfields' => $arrayfields, 'object' => $object, 'obj' => $obj, 'i' => $i, 'totalarray' => &$totalarray);
1537 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1538 print $hookmanager->resPrint;
1539 // Date creation
1540 if (!empty($arrayfields['t.datec']['checked'])) {
1541 print '<td class="center">';
1542 print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser');
1543 print '</td>';
1544 if (!$i) {
1545 $totalarray['nbfield']++;
1546 }
1547 }
1548 // Date modification
1549 if (!empty($arrayfields['t.tms']['checked'])) {
1550 print '<td class="center">';
1551 print dol_print_date($db->jdate($obj->date_modification), 'dayhour', 'tzuser');
1552 print '</td>';
1553 if (!$i) {
1554 $totalarray['nbfield']++;
1555 }
1556 }
1557 // Status
1558 /*if (!empty($arrayfields['p.fk_statut']['checked']))
1559 {
1560 $projectstatic->statut = $obj->fk_statut;
1561 print '<td class="right">'.$projectstatic->getLibStatut(5).'</td>';
1562 }*/
1563 // Action column
1564 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1565 print '<td class="nowrap center">';
1566 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1567 $selected = 0;
1568 if (in_array($object->id, $arrayofselected)) {
1569 $selected = 1;
1570 }
1571 print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
1572 }
1573 print '</td>';
1574 if (!$i) {
1575 $totalarray['nbfield']++;
1576 }
1577 }
1578
1579 print '</tr>'."\n";
1580 }
1581 }
1582
1583 $i++;
1584}
1585
1586// Show total line
1587if (!empty($totalarray['totalizable']) && is_array($totalarray['totalizable'])) {
1588 foreach ($totalarray['totalizable'] as $keytotalizable => $valtotalizable) {
1589 $totalarray['pos'][$valtotalizable['pos']] = $keytotalizable;
1590 $totalarray['val'][$keytotalizable] = $valtotalizable['total'];
1591 }
1592}
1593
1594// Show total line
1595//include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
1596if (isset($totalarray['totaldurationeffectivefield']) || isset($totalarray['totalplannedworkloadfield']) || isset($totalarray['totalprogress_calculatedfield'])
1597 || isset($totalarray['totaltobill']) || isset($totalarray['totalbilled']) || isset($totalarray['totalbudget'])) {
1598 print '<tr class="liste_total">';
1599 $i = 0;
1600 while ($i < $totalarray['nbfield']) {
1601 $i++;
1602 if ($i == 1) {
1603 if ((is_null($limit) || $num < $limit) && empty($offset)) {
1604 print '<td>'.$langs->trans("Total").'</td>';
1605 } else {
1606 print '<td>';
1607 if (is_object($form)) {
1608 print $form->textwithpicto($langs->trans("Total"), $langs->transnoentitiesnoconv("Totalforthispage"));
1609 } else {
1610 print $langs->trans("Totalforthispage");
1611 }
1612 print '</td>';
1613 }
1614 /*
1615 if ($num < $limit && empty($offset)) {
1616 print '<td class="left">'.$langs->trans("Total").'</td>';
1617 } else {
1618 print '<td class="left">'.$langs->trans("Totalforthispage").'</td>';
1619 }*/
1620 } elseif (isset($totalarray['totalplannedworkloadfield']) && $totalarray['totalplannedworkloadfield'] == $i) {
1621 print '<td class="center">'.convertSecondToTime($totalarray['totalplannedworkload'], $plannedworkloadoutputformat).'</td>';
1622 } elseif (isset($totalarray['totaldurationeffectivefield']) && $totalarray['totaldurationeffectivefield'] == $i) {
1623 print '<td class="center">'.convertSecondToTime($totalarray['totaldurationeffective'], $timespentoutputformat).'</td>';
1624 } elseif (isset($totalarray['totalprogress_calculatedfield']) && $totalarray['totalprogress_calculatedfield'] == $i) {
1625 print '<td class="center">'.($totalarray['totalplannedworkload'] > 0 ? round(100 * $totalarray['totaldurationeffective'] / $totalarray['totalplannedworkload'], 2).' %' : '').'</td>';
1626 } elseif (isset($totalarray['totalprogress_declaredfield']) && $totalarray['totalprogress_declaredfield'] == $i) {
1627 print '<td class="center">'.($totalarray['totalplannedworkload'] > 0 ? round(100 * $totalarray['totaldurationdeclared'] / $totalarray['totalplannedworkload'], 2).' %' : '').'</td>';
1628 } elseif (isset($totalarray['totaltobillfield']) && $totalarray['totaltobillfield'] == $i) {
1629 print '<td class="center">'.convertSecondToTime($totalarray['totaltobill'], $plannedworkloadoutputformat).'</td>';
1630 } elseif (isset($totalarray['totalbilledfield']) && $totalarray['totalbilledfield'] == $i) {
1631 print '<td class="center">'.convertSecondToTime($totalarray['totalbilled'], $plannedworkloadoutputformat).'</td>';
1632 } elseif (isset($totalarray['totalbudget_amountfield']) && $totalarray['totalbudget_amountfield'] == $i) {
1633 print '<td class="center">'.price((float) $totalarray['totalbudgetamount'], 0, $langs, 1, 0, 0, $conf->currency).'</td>';
1634 } elseif (!empty($totalarray['pos'][$i])) {
1635 print '<td class="right">';
1636 if (isset($totalarray['type']) && $totalarray['type'][$i] == 'duration') {
1637 print(!empty($totalarray['val'][$totalarray['pos'][$i]]) ? convertSecondToTime($totalarray['val'][$totalarray['pos'][$i]], 'allhourmin') : 0);
1638 } else {
1639 print price(!empty($totalarray['val'][$totalarray['pos'][$i]]) ? $totalarray['val'][$totalarray['pos'][$i]] : 0);
1640 }
1641 print '</td>';
1642 } else {
1643 print '<td></td>';
1644 }
1645 }
1646 print '</tr>';
1647}
1648
1649$db->free($resql);
1650
1651$parameters = array('arrayfields' => $arrayfields, 'sql' => $sql);
1652$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1653print $hookmanager->resPrint;
1654
1655print '</table>'."\n";
1656print '</div>'."\n";
1657
1658print '</form>'."\n";
1659
1660// End of page
1661llxFooter();
1662$db->close();
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()
Empty header.
Definition wrapper.php:55
llxFooter()
Empty footer.
Definition wrapper.php:69
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:241
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...
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.
setEventMessage($mesgs, $style='mesgs', $noduplicate=0)
Set event message in dol_events session object.
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...
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.
print_barre_liste($title, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $hideselectlimit=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
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 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.