list.php 60 KB

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