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