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