list.php 64 KB

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