dolibarr 18.0.6
project.lib.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2006-2015 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2010 Regis Houssin <regis.houssin@inodbox.com>
4 * Copyright (C) 2011 Juanjo Menent <jmenent@2byte.es>
5 * Copyright (C) 2018-2021 Frédéric France <frederic.france@netlogic.fr>
6 * Copyright (C) 2022 Charlene Benke <charlene@patas-monkey.com>
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 * or see https://www.gnu.org/
22 */
23
29require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
30
31
39function project_prepare_head(Project $project, $moreparam = '')
40{
41 global $db, $langs, $conf, $user;
42
43 $h = 0;
44 $head = array();
45
46 $head[$h][0] = DOL_URL_ROOT.'/projet/card.php?id='.((int) $project->id).($moreparam ? '&'.$moreparam : '');
47 $head[$h][1] = $langs->trans("Project");
48 $head[$h][2] = 'project';
49 $h++;
50 $nbContacts = 0;
51 // Enable caching of project count Contacts
52 require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php';
53 $cachekey = 'count_contacts_project_'.$project->id;
54 $dataretrieved = dol_getcache($cachekey);
55
56 if (!is_null($dataretrieved)) {
57 $nbContacts = $dataretrieved;
58 } else {
59 $nbContacts = count($project->liste_contact(-1, 'internal')) + count($project->liste_contact(-1, 'external'));
60 dol_setcache($cachekey, $nbContacts, 120); // If setting cache fails, this is not a problem, so we do not test result.
61 }
62 $head[$h][0] = DOL_URL_ROOT.'/projet/contact.php?id='.((int) $project->id).($moreparam ? '&'.$moreparam : '');
63 $head[$h][1] = $langs->trans("ProjectContact");
64 if ($nbContacts > 0) {
65 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbContacts.'</span>';
66 }
67 $head[$h][2] = 'contact';
68 $h++;
69
70 if (empty($conf->global->PROJECT_HIDE_TASKS)) {
71 // Then tab for sub level of projet, i mean tasks
72 $nbTasks = 0;
73 // Enable caching of project count Tasks
74 require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php';
75 $cachekey = 'count_tasks_project_'.$project->id;
76 $dataretrieved = dol_getcache($cachekey);
77
78 if (!is_null($dataretrieved)) {
79 $nbTasks = $dataretrieved;
80 } else {
81 require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
82 $taskstatic = new Task($db);
83 $nbTasks = count($taskstatic->getTasksArray(0, 0, $project->id, 0, 0));
84 dol_setcache($cachekey, $nbTasks, 120); // If setting cache fails, this is not a problem, so we do not test result.
85 }
86 $head[$h][0] = DOL_URL_ROOT.'/projet/tasks.php?id='.((int) $project->id).($moreparam ? '&'.$moreparam : '');
87 $head[$h][1] = $langs->trans("Tasks");
88 if ($nbTasks > 0) {
89 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($nbTasks).'</span>';
90 }
91 $head[$h][2] = 'tasks';
92 $h++;
93
94 $nbTimeSpent = 0;
95 // Enable caching of project count Timespent
96 $cachekey = 'count_timespent_project_'.$project->id;
97 $dataretrieved = dol_getcache($cachekey);
98 if (!is_null($dataretrieved)) {
99 $nbTimeSpent = $dataretrieved;
100 } else {
101 $sql = "SELECT t.rowid";
102 //$sql .= " FROM ".MAIN_DB_PREFIX."element_time as t, ".MAIN_DB_PREFIX."projet_task as pt, ".MAIN_DB_PREFIX."user as u";
103 //$sql .= " WHERE t.fk_user = u.rowid AND t.fk_task = pt.rowid";
104 $sql .= " FROM ".MAIN_DB_PREFIX."element_time as t, ".MAIN_DB_PREFIX."projet_task as pt";
105 $sql .= " WHERE t.fk_element = pt.rowid";
106 $sql .= " AND t.elementtype = 'task'";
107 $sql .= " AND pt.fk_projet =".((int) $project->id);
108 $resql = $db->query($sql);
109 if ($resql) {
110 $obj = $db->fetch_object($resql);
111 if ($obj) {
112 $nbTimeSpent = 1;
113 dol_setcache($cachekey, $nbTimeSpent, 120); // If setting cache fails, this is not a problem, so we do not test result.
114 }
115 } else {
116 dol_print_error($db);
117 }
118 }
119
120 $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/time.php?withproject=1&projectid='.((int) $project->id).($moreparam ? '&'.$moreparam : '');
121 $head[$h][1] = $langs->trans("TimeSpent");
122 if ($nbTimeSpent > 0) {
123 $head[$h][1] .= '<span class="badge marginleftonlyshort">...</span>';
124 }
125 $head[$h][2] = 'timespent';
126 $h++;
127 }
128
129 if (isModEnabled("supplier_proposal") || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")
130 || isModEnabled("propal") || isModEnabled('commande')
131 || isModEnabled('facture') || isModEnabled('contrat')
132 || isModEnabled('ficheinter') || isModEnabled('agenda') || isModEnabled('deplacement') || isModEnabled('stock')) {
133 $nbElements = 0;
134 // Enable caching of thirdrparty count Contacts
135 $cachekey = 'count_elements_project_'.$project->id;
136 $dataretrieved = dol_getcache($cachekey);
137 if (!is_null($dataretrieved)) {
138 $nbElements = $dataretrieved;
139 } else {
140 if (isModEnabled('stock')) {
141 $nbElements += $project->getElementCount('stock', 'entrepot', 'fk_project');
142 }
143 if (isModEnabled("propal")) {
144 $nbElements += $project->getElementCount('propal', 'propal');
145 }
146 if (isModEnabled('commande')) {
147 $nbElements += $project->getElementCount('order', 'commande');
148 }
149 if (isModEnabled('facture')) {
150 $nbElements += $project->getElementCount('invoice', 'facture');
151 }
152 if (isModEnabled('facture')) {
153 $nbElements += $project->getElementCount('invoice_predefined', 'facture_rec');
154 }
155 if (isModEnabled('supplier_proposal')) {
156 $nbElements += $project->getElementCount('proposal_supplier', 'supplier_proposal');
157 }
158 if (isModEnabled("supplier_order")) {
159 $nbElements += $project->getElementCount('order_supplier', 'commande_fournisseur');
160 }
161 if (isModEnabled("supplier_invoice")) {
162 $nbElements += $project->getElementCount('invoice_supplier', 'facture_fourn');
163 }
164 if (isModEnabled('contrat')) {
165 $nbElements += $project->getElementCount('contract', 'contrat');
166 }
167 if (isModEnabled('ficheinter')) {
168 $nbElements += $project->getElementCount('intervention', 'fichinter');
169 }
170 if (isModEnabled("expedition")) {
171 $nbElements += $project->getElementCount('shipping', 'expedition');
172 }
173 if (isModEnabled('mrp')) {
174 $nbElements += $project->getElementCount('mrp', 'mrp_mo', 'fk_project');
175 }
176 if (isModEnabled('deplacement')) {
177 $nbElements += $project->getElementCount('trip', 'deplacement');
178 }
179 if (isModEnabled('expensereport')) {
180 $nbElements += $project->getElementCount('expensereport', 'expensereport');
181 }
182 if (isModEnabled('don')) {
183 $nbElements += $project->getElementCount('donation', 'don');
184 }
185 if (isModEnabled('loan')) {
186 $nbElements += $project->getElementCount('loan', 'loan');
187 }
188 if (isModEnabled('tax')) {
189 $nbElements += $project->getElementCount('chargesociales', 'chargesociales');
190 }
191 if (isModEnabled('project')) {
192 $nbElements += $project->getElementCount('project_task', 'projet_task');
193 }
194 if (isModEnabled('stock')) {
195 $nbElements += $project->getElementCount('stock_mouvement', 'stock');
196 }
197 if (isModEnabled('salaries')) {
198 $nbElements += $project->getElementCount('salaries', 'payment_salary');
199 }
200 if (isModEnabled("banque")) {
201 $nbElements += $project->getElementCount('variouspayment', 'payment_various');
202 }
203 dol_setcache($cachekey, $nbElements, 120); // If setting cache fails, this is not a problem, so we do not test result.
204 }
205 $head[$h][0] = DOL_URL_ROOT.'/projet/element.php?id='.$project->id;
206 $head[$h][1] = $langs->trans("ProjectOverview");
207 if ($nbElements > 0) {
208 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbElements.'</span>';
209 }
210 $head[$h][2] = 'element';
211 $h++;
212 }
213
214 if (isModEnabled('ticket') && $user->hasRight('ticket', 'read')) {
215 require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php';
216 $Tickettatic = new Ticket($db);
217 $nbTicket = count($Tickettatic->getAllItemsLinkedByObjectID($project->id, '*', 'fk_project', 'ticket'));
218 $head[$h][0] = DOL_URL_ROOT.'/ticket/list.php?projectid='.((int) $project->id);
219 $head[$h][1] = $langs->trans("Ticket");
220 if ($nbTicket > 0) {
221 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($nbTicket).'</span>';
222 }
223 $head[$h][2] = 'ticket';
224 $h++;
225 }
226
227 if (isModEnabled('eventorganization') && !empty($project->usage_organize_event)) {
228 $langs->load('eventorganization');
229 $head[$h][0] = DOL_URL_ROOT . '/eventorganization/conferenceorbooth_list.php?projectid=' . $project->id;
230 $head[$h][1] = $langs->trans("EventOrganization");
231
232 // Enable caching of conf or booth count
233 $nbConfOrBooth = 0; $nbAttendees = 0;
234 require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php';
235 $cachekey = 'count_conferenceorbooth_'.$project->id;
236 $dataretrieved = dol_getcache($cachekey);
237 if (!is_null($dataretrieved)) {
238 $nbConfOrBooth = $dataretrieved;
239 } else {
240 require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorbooth.class.php';
241 $conforbooth=new ConferenceOrBooth($db);
242 $result = $conforbooth->fetchAll('', '', 0, 0, array('t.fk_project'=>$project->id));
243 //,
244 if (!is_array($result) && $result<0) {
245 setEventMessages($conforbooth->error, $conforbooth->errors, 'errors');
246 } else {
247 $nbConfOrBooth = count($result);
248 }
249 dol_setcache($cachekey, $nbConfOrBooth, 120); // If setting cache fails, this is not a problem, so we do not test result.
250 }
251 $cachekey = 'count_attendees_'.$project->id;
252 $dataretrieved = dol_getcache($cachekey);
253 if (!is_null($dataretrieved)) {
254 $nbAttendees = $dataretrieved;
255 } else {
256 require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorboothattendee.class.php';
257 $conforboothattendee=new ConferenceOrBoothAttendee($db);
258 $result = $conforboothattendee->fetchAll('', '', 0, 0, array('t.fk_project'=>$project->id));
259 //,
260 if (!is_array($result) && $result<0) {
261 setEventMessages($conforboothattendee->error, $conforboothattendee->errors, 'errors');
262 } else {
263 $nbAttendees = count($result);
264 }
265 dol_setcache($cachekey, $nbAttendees, 120); // If setting cache fails, this is not a problem, so we do not test result.
266 }
267 if ($nbConfOrBooth > 0 || $nbAttendees > 0) {
268 $head[$h][1] .= '<span class="badge marginleftonlyshort">';
269 $head[$h][1] .= '<span title="'.dol_escape_htmltag($langs->trans("ConferenceOrBooth")).'">'.$nbConfOrBooth.'</span>';
270 if ($nbConfOrBooth > 0 && $nbAttendees > 0) {
271 $head[$h][1] .= ' + ';
272 }
273 $head[$h][1] .= '<span title="'.dol_escape_htmltag($langs->trans("Attendees")).'">'.$nbAttendees.'</span>';
274 $head[$h][1] .= '</span>';
275 }
276 $head[$h][2] = 'eventorganisation';
277 $h++;
278 }
279
280 // Show more tabs from modules
281 // Entries must be declared in modules descriptor with line
282 // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
283 // $this->tabs = array('entity:-tabname); to remove a tab
284 complete_head_from_modules($conf, $langs, $project, $head, $h, 'project', 'add', 'core');
285
286
287 if (empty($conf->global->MAIN_DISABLE_NOTES_TAB)) {
288 $nbNote = 0;
289 if (!empty($project->note_private)) {
290 $nbNote++;
291 }
292 if (!empty($project->note_public)) {
293 $nbNote++;
294 }
295 $head[$h][0] = DOL_URL_ROOT.'/projet/note.php?id='.$project->id;
296 $head[$h][1] = $langs->trans('Notes');
297 if ($nbNote > 0) {
298 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbNote.'</span>';
299 }
300 $head[$h][2] = 'notes';
301 $h++;
302 }
303
304 // Attached files and Links
305 $totalAttached = 0;
306 // Enable caching of thirdrparty count attached files and links
307 require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php';
308 $cachekey = 'count_attached_project_'.$project->id;
309 $dataretrieved = dol_getcache($cachekey);
310 if (!is_null($dataretrieved)) {
311 $totalAttached = $dataretrieved;
312 } else {
313 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
314 require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
315 $upload_dir = $conf->project->multidir_output[$project->entity]."/".dol_sanitizeFileName($project->ref);
316 $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$'));
317 $nbLinks = Link::count($db, $project->element, $project->id);
318 $totalAttached = $nbFiles + $nbLinks;
319 dol_setcache($cachekey, $totalAttached, 120); // If setting cache fails, this is not a problem, so we do not test result.
320 }
321 $head[$h][0] = DOL_URL_ROOT.'/projet/document.php?id='.$project->id;
322 $head[$h][1] = $langs->trans('Documents');
323 if (($totalAttached) > 0) {
324 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($totalAttached).'</span>';
325 }
326 $head[$h][2] = 'document';
327 $h++;
328
329 // Manage discussion
330 if (!empty($conf->global->PROJECT_ALLOW_COMMENT_ON_PROJECT)) {
331 $nbComments = 0;
332 // Enable caching of thirdrparty count attached files and links
333 require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php';
334 $cachekey = 'count_attached_project_'.$project->id;
335 $dataretrieved = dol_getcache($cachekey);
336 if (!is_null($dataretrieved)) {
337 $nbComments = $dataretrieved;
338 } else {
339 $nbComments = $project->getNbComments();
340 dol_setcache($cachekey, $nbComments, 120); // If setting cache fails, this is not a problem, so we do not test result.
341 }
342 $head[$h][0] = DOL_URL_ROOT.'/projet/comment.php?id='.$project->id;
343 $head[$h][1] = $langs->trans("CommentLink");
344 if ($nbComments > 0) {
345 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbComments.'</span>';
346 }
347 $head[$h][2] = 'project_comment';
348 $h++;
349 }
350
351 $head[$h][0] = DOL_URL_ROOT.'/projet/messaging.php?id='.$project->id;
352 $head[$h][1] = $langs->trans("Events");
353 if (isModEnabled('agenda') && ($user->hasRight('agenda', 'myactions', 'read') || $user->hasRight('agenda', 'allactions', 'read'))) {
354 $head[$h][1] .= '/';
355 $head[$h][1] .= $langs->trans("Agenda");
356 }
357 $head[$h][2] = 'agenda';
358 $h++;
359
360 complete_head_from_modules($conf, $langs, $project, $head, $h, 'project', 'add', 'external');
361
362 complete_head_from_modules($conf, $langs, $project, $head, $h, 'project', 'remove');
363
364 return $head;
365}
366
367
374function task_prepare_head($object)
375{
376 global $db, $langs, $conf, $user;
377 $h = 0;
378 $head = array();
379
380 $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/task.php?id='.$object->id.(GETPOST('withproject') ? '&withproject=1' : '');
381 $head[$h][1] = $langs->trans("Task");
382 $head[$h][2] = 'task_task';
383 $h++;
384
385 $nbContact = count($object->liste_contact(-1, 'internal')) + count($object->liste_contact(-1, 'external'));
386 $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/contact.php?id='.$object->id.(GETPOST('withproject') ? '&withproject=1' : '');
387 $head[$h][1] = $langs->trans("TaskRessourceLinks");
388 if ($nbContact > 0) {
389 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbContact.'</span>';
390 }
391 $head[$h][2] = 'task_contact';
392 $h++;
393
394 // Is there timespent ?
395 $nbTimeSpent = 0;
396 $sql = "SELECT t.rowid";
397 //$sql .= " FROM ".MAIN_DB_PREFIX."element_time as t, ".MAIN_DB_PREFIX."projet_task as pt, ".MAIN_DB_PREFIX."user as u";
398 //$sql .= " WHERE t.fk_user = u.rowid AND t.fk_task = pt.rowid";
399 $sql .= " FROM ".MAIN_DB_PREFIX."element_time as t";
400 $sql .= " WHERE t.elementtype='task' AND t.fk_element = ".((int) $object->id);
401 $resql = $db->query($sql);
402 if ($resql) {
403 $obj = $db->fetch_object($resql);
404 if ($obj) {
405 $nbTimeSpent = 1;
406 }
407 } else {
408 dol_print_error($db);
409 }
410
411 $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/time.php?id='.urlencode($object->id).(GETPOST('withproject') ? '&withproject=1' : '');
412 $head[$h][1] = $langs->trans("TimeSpent");
413 if ($nbTimeSpent > 0) {
414 $head[$h][1] .= '<span class="badge marginleftonlyshort">...</span>';
415 }
416 $head[$h][2] = 'task_time';
417 $h++;
418
419 // Show more tabs from modules
420 // Entries must be declared in modules descriptor with line
421 // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
422 // $this->tabs = array('entity:-tabname); to remove a tab
423 complete_head_from_modules($conf, $langs, $object, $head, $h, 'task', 'add', 'core');
424
425 if (empty($conf->global->MAIN_DISABLE_NOTES_TAB)) {
426 $nbNote = 0;
427 if (!empty($object->note_private)) {
428 $nbNote++;
429 }
430 if (!empty($object->note_public)) {
431 $nbNote++;
432 }
433 $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/note.php?id='.urlencode($object->id).(GETPOST('withproject') ? '&withproject=1' : '');
434 $head[$h][1] = $langs->trans('Notes');
435 if ($nbNote > 0) {
436 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbNote.'</span>';
437 }
438 $head[$h][2] = 'task_notes';
439 $h++;
440 }
441
442 $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/document.php?id='.$object->id.(GETPOST('withproject') ? '&withproject=1' : '');
443 $filesdir = $conf->project->multidir_output[$object->entity]."/".dol_sanitizeFileName($object->project->ref).'/'.dol_sanitizeFileName($object->ref);
444 include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
445 include_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
446 $nbFiles = count(dol_dir_list($filesdir, 'files', 0, '', '(\.meta|_preview.*\.png)$'));
447 $nbLinks = Link::count($db, $object->element, $object->id);
448 $head[$h][1] = $langs->trans('Documents');
449 if (($nbFiles + $nbLinks) > 0) {
450 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($nbFiles + $nbLinks).'</span>';
451 }
452 $head[$h][2] = 'task_document';
453 $h++;
454
455 // Manage discussion
456 if (!empty($conf->global->PROJECT_ALLOW_COMMENT_ON_TASK)) {
457 $nbComments = $object->getNbComments();
458 $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/comment.php?id='.$object->id.(GETPOST('withproject') ? '&withproject=1' : '');
459 $head[$h][1] = $langs->trans("CommentLink");
460 if ($nbComments > 0) {
461 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbComments.'</span>';
462 }
463 $head[$h][2] = 'task_comment';
464 $h++;
465 }
466
467 complete_head_from_modules($conf, $langs, $object, $head, $h, 'task', 'add', 'external');
468
469 complete_head_from_modules($conf, $langs, $object, $head, $h, 'task', 'remove');
470
471 return $head;
472}
473
481function project_timesheet_prepare_head($mode, $fuser = null)
482{
483 global $langs, $conf, $user;
484 $h = 0;
485 $head = array();
486
487 $h = 0;
488
489 $param = '';
490 $param .= ($mode ? '&mode='.$mode : '');
491 if (is_object($fuser) && $fuser->id > 0 && $fuser->id != $user->id) {
492 $param .= '&search_usertoprocessid='.$fuser->id;
493 }
494
495 if (empty($conf->global->PROJECT_DISABLE_TIMESHEET_PERMONTH)) {
496 $head[$h][0] = DOL_URL_ROOT."/projet/activity/permonth.php".($param ? '?'.$param : '');
497 $head[$h][1] = $langs->trans("InputPerMonth");
498 $head[$h][2] = 'inputpermonth';
499 $h++;
500 }
501
502 if (empty($conf->global->PROJECT_DISABLE_TIMESHEET_PERWEEK)) {
503 $head[$h][0] = DOL_URL_ROOT."/projet/activity/perweek.php".($param ? '?'.$param : '');
504 $head[$h][1] = $langs->trans("InputPerWeek");
505 $head[$h][2] = 'inputperweek';
506 $h++;
507 }
508
509 if (empty($conf->global->PROJECT_DISABLE_TIMESHEET_PERTIME)) {
510 $head[$h][0] = DOL_URL_ROOT."/projet/activity/perday.php".($param ? '?'.$param : '');
511 $head[$h][1] = $langs->trans("InputPerDay");
512 $head[$h][2] = 'inputperday';
513 $h++;
514 }
515
516 complete_head_from_modules($conf, $langs, null, $head, $h, 'project_timesheet');
517
518 complete_head_from_modules($conf, $langs, null, $head, $h, 'project_timesheet', 'remove');
519
520 return $head;
521}
522
523
530{
531 global $langs, $conf, $user, $db;
532
533 $extrafields = new ExtraFields($db);
534 $extrafields->fetch_name_optionals_label('projet');
535 $extrafields->fetch_name_optionals_label('projet_task');
536
537 $h = 0;
538 $head = array();
539
540 $head[$h][0] = DOL_URL_ROOT."/projet/admin/project.php";
541 $head[$h][1] = $langs->trans("Projects");
542 $head[$h][2] = 'project';
543 $h++;
544
545 complete_head_from_modules($conf, $langs, null, $head, $h, 'project_admin');
546
547 $head[$h][0] = DOL_URL_ROOT."/projet/admin/project_extrafields.php";
548 $head[$h][1] = $langs->trans("ExtraFieldsProject");
549 $nbExtrafields = $extrafields->attributes['projet']['count'];
550 if ($nbExtrafields > 0) {
551 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbExtrafields.'</span>';
552 }
553 $head[$h][2] = 'attributes';
554 $h++;
555
556 if (empty($conf->global->PROJECT_HIDE_TASKS)) {
557 $head[$h][0] = DOL_URL_ROOT . '/projet/admin/project_task_extrafields.php';
558 $head[$h][1] = $langs->trans("ExtraFieldsProjectTask");
559 $nbExtrafields = $extrafields->attributes['projet_task']['count'];
560 if ($nbExtrafields > 0) {
561 $head[$h][1] .= '<span class="badge marginleftonlyshort">' . $nbExtrafields . '</span>';
562 }
563 $head[$h][2] = 'attributes_task';
564 $h++;
565 }
566
567 if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) {
568 $langs->load("members");
569
570 $head[$h][0] = DOL_URL_ROOT.'/projet/admin/website.php';
571 $head[$h][1] = $langs->trans("BlankSubscriptionForm");
572 $head[$h][2] = 'website';
573 $h++;
574 }
575
576 complete_head_from_modules($conf, $langs, null, $head, $h, 'project_admin', 'remove');
577
578 return $head;
579}
580
581
601function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$taskrole, $projectsListId = '', $addordertick = 0, $projectidfortotallink = 0, $dummy = '', $showbilltime = 0, $arrayfields = array(), $arrayofselected = array())
602{
603 global $user, $langs, $conf, $db, $hookmanager;
604 global $projectstatic, $taskstatic, $extrafields;
605
606 $lastprojectid = 0;
607
608 $projectsArrayId = explode(',', $projectsListId);
609
610 $numlines = count($lines);
611
612 // We declare counter as global because we want to edit them into recursive call
613 global $total_projectlinesa_spent, $total_projectlinesa_planned, $total_projectlinesa_spent_if_planned, $total_projectlinesa_declared_if_planned, $total_projectlinesa_tobill, $total_projectlinesa_billed, $total_budget_amount;
614 global $totalarray;
615
616 if ($level == 0) {
617 $total_projectlinesa_spent = 0;
618 $total_projectlinesa_planned = 0;
619 $total_projectlinesa_spent_if_planned = 0;
620 $total_projectlinesa_declared_if_planned = 0;
621 $total_projectlinesa_tobill = 0;
622 $total_projectlinesa_billed = 0;
623 $total_budget_amount = 0;
624 $totalarray = array();
625 }
626
627 for ($i = 0; $i < $numlines; $i++) {
628 if ($parent == 0 && $level >= 0) {
629 $level = 0; // if $level = -1, we dont' use sublevel recursion, we show all lines
630 }
631
632 // Process line
633 // print "i:".$i."-".$lines[$i]->fk_project.'<br>';
634 if ($lines[$i]->fk_task_parent == $parent || $level < 0) { // if $level = -1, we dont' use sublevel recursion, we show all lines
635 // Show task line.
636 $showline = 1;
637 $showlineingray = 0;
638
639 // If there is filters to use
640 if (is_array($taskrole)) {
641 // If task not legitimate to show, search if a legitimate task exists later in tree
642 if (!isset($taskrole[$lines[$i]->id]) && $lines[$i]->id != $lines[$i]->fk_task_parent) {
643 // So search if task has a subtask legitimate to show
644 $foundtaskforuserdeeper = 0;
645 searchTaskInChild($foundtaskforuserdeeper, $lines[$i]->id, $lines, $taskrole);
646 //print '$foundtaskforuserpeeper='.$foundtaskforuserdeeper.'<br>';
647 if ($foundtaskforuserdeeper > 0) {
648 $showlineingray = 1; // We will show line but in gray
649 } else {
650 $showline = 0; // No reason to show line
651 }
652 }
653 } else {
654 // Caller did not ask to filter on tasks of a specific user (this probably means he want also tasks of all users, into public project
655 // or into all other projects if user has permission to).
656 if (empty($user->rights->projet->all->lire)) {
657 // User is not allowed on this project and project is not public, so we hide line
658 if (!in_array($lines[$i]->fk_project, $projectsArrayId)) {
659 // Note that having a user assigned to a task into a project user has no permission on, should not be possible
660 // because assignement on task can be done only on contact of project.
661 // If assignement was done and after, was removed from contact of project, then we can hide the line.
662 $showline = 0;
663 }
664 }
665 }
666
667 if ($showline) {
668 // Break on a new project
669 if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid) {
670 $var = !$var;
671 $lastprojectid = $lines[$i]->fk_project;
672 }
673
674 print '<tr class="oddeven" id="row-'.$lines[$i]->id.'">'."\n";
675
676 $projectstatic->id = $lines[$i]->fk_project;
677 $projectstatic->ref = $lines[$i]->projectref;
678 $projectstatic->public = $lines[$i]->public;
679 $projectstatic->title = $lines[$i]->projectlabel;
680 $projectstatic->usage_bill_time = $lines[$i]->usage_bill_time;
681 $projectstatic->status = $lines[$i]->projectstatus;
682
683 $taskstatic->id = $lines[$i]->id;
684 $taskstatic->ref = $lines[$i]->ref;
685 $taskstatic->label = (!empty($taskrole[$lines[$i]->id]) ? $langs->trans("YourRole").': '.$taskrole[$lines[$i]->id] : '');
686 $taskstatic->projectstatus = $lines[$i]->projectstatus;
687 $taskstatic->progress = $lines[$i]->progress;
688 $taskstatic->fk_statut = $lines[$i]->status;
689 $taskstatic->date_start = $lines[$i]->date_start;
690 $taskstatic->date_end = $lines[$i]->date_end;
691 $taskstatic->datee = $lines[$i]->date_end; // deprecated
692 $taskstatic->planned_workload = $lines[$i]->planned_workload;
693 $taskstatic->duration_effective = $lines[$i]->duration_effective;
694 $taskstatic->budget_amount = $lines[$i]->budget_amount;
695
696 // Action column
697 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
698 print '<td class="nowrap center">';
699 $selected = 0;
700 if (in_array($lines[$i]->id, $arrayofselected)) {
701 $selected = 1;
702 }
703 print '<input id="cb' . $lines[$i]->id . '" class="flat checkforselect" type="checkbox" name="toselect[]" value="' . $lines[$i]->id . '"' . ($selected ? ' checked="checked"' : '') . '>';
704 print '</td>';
705 }
706
707 if ($showproject) {
708 // Project ref
709 print '<td class="nowraponall">';
710 //if ($showlineingray) print '<i>';
711 if ($lines[$i]->public || in_array($lines[$i]->fk_project, $projectsArrayId) || !empty($user->rights->projet->all->lire)) {
712 print $projectstatic->getNomUrl(1);
713 } else {
714 print $projectstatic->getNomUrl(1, 'nolink');
715 }
716 //if ($showlineingray) print '</i>';
717 print "</td>";
718
719 // Project status
720 print '<td>';
721 $projectstatic->statut = $lines[$i]->projectstatus;
722 print $projectstatic->getLibStatut(2);
723 print "</td>";
724 }
725
726 // Ref of task
727 if (count($arrayfields) > 0 && !empty($arrayfields['t.ref']['checked'])) {
728 print '<td class="nowraponall">';
729 if ($showlineingray) {
730 print '<i>'.img_object('', 'projecttask').' '.$lines[$i]->ref.'</i>';
731 } else {
732 print $taskstatic->getNomUrl(1, 'withproject');
733 }
734 print '</td>';
735 }
736
737 // Title of task
738 if (count($arrayfields) > 0 && !empty($arrayfields['t.label']['checked'])) {
739 $labeltoshow = '';
740 if ($showlineingray) {
741 $labeltoshow .= '<i>';
742 }
743 //else print '<a href="'.DOL_URL_ROOT.'/projet/tasks/task.php?id='.$lines[$i]->id.'&withproject=1">';
744 for ($k = 0; $k < $level; $k++) {
745 $labeltoshow .= '<div class="marginleftonly">';
746 }
747 $labeltoshow .= dol_escape_htmltag($lines[$i]->label);
748 for ($k = 0; $k < $level; $k++) {
749 $labeltoshow .= '</div>';
750 }
751 if ($showlineingray) {
752 $labeltoshow .= '</i>';
753 }
754 print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($labeltoshow).'">';
755 print $labeltoshow;
756 print "</td>\n";
757 }
758
759 if (count($arrayfields) > 0 && !empty($arrayfields['t.description']['checked'])) {
760 print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($lines[$i]->description).'">';
761 print $lines[$i]->description;
762 print "</td>\n";
763 }
764
765 // Date start
766 if (count($arrayfields) > 0 && !empty($arrayfields['t.dateo']['checked'])) {
767 print '<td class="center nowraponall">';
768 print dol_print_date($lines[$i]->date_start, 'dayhour');
769 print '</td>';
770 }
771
772 // Date end
773 if (count($arrayfields) > 0 && !empty($arrayfields['t.datee']['checked'])) {
774 print '<td class="center nowraponall">';
775 print dol_print_date($lines[$i]->date_end, 'dayhour');
776 if ($taskstatic->hasDelay()) {
777 print img_warning($langs->trans("Late"));
778 }
779 print '</td>';
780 }
781
782 $plannedworkloadoutputformat = 'allhourmin';
783 $timespentoutputformat = 'allhourmin';
784 if (!empty($conf->global->PROJECT_PLANNED_WORKLOAD_FORMAT)) {
785 $plannedworkloadoutputformat = $conf->global->PROJECT_PLANNED_WORKLOAD_FORMAT;
786 }
787 if (!empty($conf->global->PROJECT_TIMES_SPENT_FORMAT)) {
788 $timespentoutputformat = $conf->global->PROJECT_TIME_SPENT_FORMAT;
789 }
790
791 // Planned Workload (in working hours)
792 if (count($arrayfields) > 0 && !empty($arrayfields['t.planned_workload']['checked'])) {
793 print '<td class="right">';
794 $fullhour = convertSecondToTime($lines[$i]->planned_workload, $plannedworkloadoutputformat);
795 $workingdelay = convertSecondToTime($lines[$i]->planned_workload, 'all', 86400, 7); // TODO Replace 86400 and 7 to take account working hours per day and working day per weeks
796 if ($lines[$i]->planned_workload != '') {
797 print $fullhour;
798 // TODO Add delay taking account of working hours per day and working day per week
799 //if ($workingdelay != $fullhour) print '<br>('.$workingdelay.')';
800 }
801 //else print '--:--';
802 print '</td>';
803 }
804
805 // Time spent
806 if (count($arrayfields) > 0 && !empty($arrayfields['t.duration_effective']['checked'])) {
807 print '<td class="right">';
808 if ($showlineingray) {
809 print '<i>';
810 } else {
811 print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$lines[$i]->id.($showproject ? '' : '&withproject=1').'">';
812 }
813 if ($lines[$i]->duration_effective) {
814 print convertSecondToTime($lines[$i]->duration_effective, $timespentoutputformat);
815 } else {
816 print '--:--';
817 }
818 if ($showlineingray) {
819 print '</i>';
820 } else {
821 print '</a>';
822 }
823 print '</td>';
824 }
825
826 // Progress calculated (Note: ->duration_effective is time spent)
827 if (count($arrayfields) > 0 && !empty($arrayfields['t.progress_calculated']['checked'])) {
828 $s = ''; $shtml = '';
829 if ($lines[$i]->planned_workload || $lines[$i]->duration_effective) {
830 if ($lines[$i]->planned_workload) {
831 $s = round(100 * $lines[$i]->duration_effective / $lines[$i]->planned_workload, 2).' %';
832 $shtml = $s;
833 } else {
834 $s = $langs->trans('WorkloadNotDefined');
835 $shtml = '<span class="opacitymedium">'.$s.'</span>';
836 }
837 }
838 print '<td class="right tdoverflowmax100" title="'.dol_escape_htmltag($s).'">';
839 print $shtml;
840 print '</td>';
841 }
842
843 // Progress declared
844 if (count($arrayfields) > 0 && !empty($arrayfields['t.progress']['checked'])) {
845 print '<td class="right">';
846 if ($lines[$i]->progress != '') {
847 print getTaskProgressBadge($taskstatic);
848 }
849 print '</td>';
850 }
851
852 // resume
853 if (count($arrayfields) > 0 && !empty($arrayfields['t.progress_summary']['checked'])) {
854 print '<td class="right">';
855 if ($lines[$i]->progress != '' && $lines[$i]->duration_effective) {
856 print getTaskProgressView($taskstatic, false, false);
857 }
858 print '</td>';
859 }
860
861 if ($showbilltime) {
862 // Time not billed
863 if (count($arrayfields) > 0 && !empty($arrayfields['t.tobill']['checked'])) {
864 print '<td class="right">';
865 if ($lines[$i]->usage_bill_time) {
866 print convertSecondToTime($lines[$i]->tobill, 'allhourmin');
867 $total_projectlinesa_tobill += $lines[$i]->tobill;
868 } else {
869 print '<span class="opacitymedium">'.$langs->trans("NA").'</span>';
870 }
871 print '</td>';
872 }
873
874 // Time billed
875 if (count($arrayfields) > 0 && !empty($arrayfields['t.billed']['checked'])) {
876 print '<td class="right">';
877 if ($lines[$i]->usage_bill_time) {
878 print convertSecondToTime($lines[$i]->billed, 'allhourmin');
879 $total_projectlinesa_billed += $lines[$i]->billed;
880 } else {
881 print '<span class="opacitymedium">'.$langs->trans("NA").'</span>';
882 }
883 print '</td>';
884 }
885 }
886
887 // Budget task
888 if (count($arrayfields) > 0 && !empty($arrayfields['t.budget_amount']['checked'])) {
889 print '<td class="center">';
890 if ($lines[$i]->budget_amount) {
891 print '<span class="amount">'.price($lines[$i]->budget_amount, 0, $langs, 1, 0, 0, $conf->currency).'</span>';
892 $total_budget_amount += $lines[$i]->budget_amount;
893 }
894 print '</td>';
895 }
896
897 // Contacts of task
898 if (count($arrayfields) > 0 && !empty($arrayfields['c.assigned']['checked'])) {
899 print '<td class="center">';
900 $ifisrt = 1;
901 foreach (array('internal', 'external') as $source) {
902 //$tab = $lines[$i]->liste_contact(-1, $source);
903 $tab = $lines[$i]->liste_contact(-1, $source, 0, '', 1);
904
905 $numcontact = count($tab);
906 if (!empty($numcontact)) {
907 foreach ($tab as $contacttask) {
908 //var_dump($contacttask);
909 if ($source == 'internal') {
910 $c = new User($db);
911 } else {
912 $c = new Contact($db);
913 }
914 $c->fetch($contacttask['id']);
915 if (!empty($c->photo)) {
916 if (get_class($c) == 'User') {
917 print $c->getNomUrl(-2, '', 0, 0, 24, 1, '', ($ifisrt ? '' : 'notfirst'));
918 } else {
919 print $c->getNomUrl(-2, '', 0, '', -1, 0, ($ifisrt ? '' : 'notfirst'));
920 }
921 } else {
922 if (get_class($c) == 'User') {
923 print $c->getNomUrl(2, '', 0, 0, 24, 1, '', ($ifisrt ? '' : 'notfirst'));
924 } else {
925 print $c->getNomUrl(2, '', 0, '', -1, 0, ($ifisrt ? '' : 'notfirst'));
926 }
927 }
928 $ifisrt = 0;
929 }
930 }
931 }
932 print '</td>';
933 }
934
935 // Extra fields
936 $extrafieldsobjectkey = $taskstatic->table_element;
937 $extrafieldsobjectprefix = 'efpt.';
938 $obj = $lines[$i]->obj;
939 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
940 // Fields from hook
941 $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$lines[$i]);
942 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook
943 print $hookmanager->resPrint;
944
945 // Tick to drag and drop
946 print '<td class="tdlineupdown center"></td>';
947
948 // Action column
949 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
950 print '<td class="nowrap center">';
951 $selected = 0;
952 if (in_array($lines[$i]->id, $arrayofselected)) {
953 $selected = 1;
954 }
955 print '<input id="cb' . $lines[$i]->id . '" class="flat checkforselect" type="checkbox" name="toselect[]" value="' . $lines[$i]->id . '"' . ($selected ? ' checked="checked"' : '') . '>';
956
957 print '</td>';
958 }
959
960 print "</tr>\n";
961
962 if (!$showlineingray) {
963 $inc++;
964 }
965
966 if ($level >= 0) { // Call sublevels
967 $level++;
968 if ($lines[$i]->id) {
969 projectLinesa($inc, $lines[$i]->id, $lines, $level, $var, $showproject, $taskrole, $projectsListId, $addordertick, $projectidfortotallink, '', $showbilltime, $arrayfields);
970 }
971 $level--;
972 }
973
974 $total_projectlinesa_spent += $lines[$i]->duration_effective;
975 $total_projectlinesa_planned += $lines[$i]->planned_workload;
976 if ($lines[$i]->planned_workload) {
977 $total_projectlinesa_spent_if_planned += $lines[$i]->duration_effective;
978 }
979 if ($lines[$i]->planned_workload) {
980 $total_projectlinesa_declared_if_planned += $lines[$i]->planned_workload * $lines[$i]->progress / 100;
981 }
982 }
983 } else {
984 //$level--;
985 }
986 }
987
988 // Total line
989 if (($total_projectlinesa_planned > 0 || $total_projectlinesa_spent > 0 || $total_projectlinesa_tobill > 0 || $total_projectlinesa_billed > 0 || $total_budget_amount > 0)
990 && $level <= 0) {
991 print '<tr class="liste_total nodrag nodrop">';
992
993 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
994 print '<td class="liste_total"></td>';
995 }
996
997 print '<td class="liste_total">'.$langs->trans("Total").'</td>';
998 if ($showproject) {
999 print '<td></td><td></td>';
1000 }
1001 if (count($arrayfields) > 0 && !empty($arrayfields['t.label']['checked'])) {
1002 print '<td></td>';
1003 }
1004 if (count($arrayfields) > 0 && !empty($arrayfields['t.description']['checked'])) {
1005 print '<td></td>';
1006 }
1007 if (count($arrayfields) > 0 && !empty($arrayfields['t.dateo']['checked'])) {
1008 print '<td></td>';
1009 }
1010 if (count($arrayfields) > 0 && !empty($arrayfields['t.datee']['checked'])) {
1011 print '<td></td>';
1012 }
1013 if (count($arrayfields) > 0 && !empty($arrayfields['t.planned_workload']['checked'])) {
1014 print '<td class="nowrap liste_total right">';
1015 print convertSecondToTime($total_projectlinesa_planned, 'allhourmin');
1016 print '</td>';
1017 }
1018 if (count($arrayfields) > 0 && !empty($arrayfields['t.duration_effective']['checked'])) {
1019 print '<td class="nowrap liste_total right">';
1020 if ($projectidfortotallink > 0) {
1021 print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?projectid='.$projectidfortotallink.($showproject ? '' : '&withproject=1').'">';
1022 }
1023 print convertSecondToTime($total_projectlinesa_spent, 'allhourmin');
1024 if ($projectidfortotallink > 0) {
1025 print '</a>';
1026 }
1027 print '</td>';
1028 }
1029
1030 if ($total_projectlinesa_planned) {
1031 $totalAverageDeclaredProgress = round(100 * $total_projectlinesa_declared_if_planned / $total_projectlinesa_planned, 2);
1032 $totalCalculatedProgress = round(100 * $total_projectlinesa_spent / $total_projectlinesa_planned, 2);
1033
1034 // this conf is actually hidden, by default we use 10% for "be carefull or warning"
1035 $warningRatio = !empty($conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT) ? (1 + $conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT / 100) : 1.10;
1036
1037 // define progress color according to time spend vs workload
1038 $progressBarClass = 'progress-bar-info';
1039 $badgeClass = 'badge ';
1040
1041 if ($totalCalculatedProgress > $totalAverageDeclaredProgress) {
1042 $progressBarClass = 'progress-bar-danger';
1043 $badgeClass .= 'badge-danger';
1044 } elseif ($totalCalculatedProgress * $warningRatio >= $totalAverageDeclaredProgress) { // warning if close at 1%
1045 $progressBarClass = 'progress-bar-warning';
1046 $badgeClass .= 'badge-warning';
1047 } else {
1048 $progressBarClass = 'progress-bar-success';
1049 $badgeClass .= 'badge-success';
1050 }
1051 }
1052
1053 // Computed progress
1054 if (count($arrayfields) > 0 && !empty($arrayfields['t.progress_calculated']['checked'])) {
1055 print '<td class="nowrap liste_total right">';
1056 if ($total_projectlinesa_planned) {
1057 print $totalCalculatedProgress.' %';
1058 }
1059 print '</td>';
1060 }
1061
1062 // Declared progress
1063 if (count($arrayfields) > 0 && !empty($arrayfields['t.progress']['checked'])) {
1064 print '<td class="nowrap liste_total right">';
1065 if ($total_projectlinesa_planned) {
1066 print '<span class="'.$badgeClass.'" >'.$totalAverageDeclaredProgress.' %</span>';
1067 }
1068 print '</td>';
1069 }
1070
1071
1072 // Progress
1073 if (count($arrayfields) > 0 && !empty($arrayfields['t.progress_summary']['checked'])) {
1074 print '<td class="right">';
1075 if ($total_projectlinesa_planned) {
1076 print '</span>';
1077 print ' <div class="progress sm" title="'.$totalAverageDeclaredProgress.'%" >';
1078 print ' <div class="progress-bar '.$progressBarClass.'" style="width: '.$totalAverageDeclaredProgress.'%"></div>';
1079 print ' </div>';
1080 print '</div>';
1081 }
1082 print '</td>';
1083 }
1084
1085 if ($showbilltime) {
1086 if (count($arrayfields) > 0 && !empty($arrayfields['t.tobill']['checked'])) {
1087 print '<td class="nowrap liste_total right">';
1088 print convertSecondToTime($total_projectlinesa_tobill, 'allhourmin');
1089 print '</td>';
1090 }
1091 if (count($arrayfields) > 0 && !empty($arrayfields['t.billed']['checked'])) {
1092 print '<td class="nowrap liste_total right">';
1093 print convertSecondToTime($total_projectlinesa_billed, 'allhourmin');
1094 print '</td>';
1095 }
1096 }
1097
1098 // Budget task
1099 if (count($arrayfields) > 0 && !empty($arrayfields['t.budget_amount']['checked'])) {
1100 print '<td class="nowrap liste_total center">';
1101 if (strcmp($total_budget_amount, '')) {
1102 print price($total_budget_amount, 0, $langs, 1, 0, 0, $conf->currency);
1103 }
1104 print '</td>';
1105 }
1106
1107 // Contacts of task for backward compatibility,
1108 if (!empty($conf->global->PROJECT_SHOW_CONTACTS_IN_LIST)) {
1109 print '<td></td>';
1110 }
1111 // Contacts of task
1112 if (count($arrayfields) > 0 && !empty($arrayfields['c.assigned']['checked'])) {
1113 print '<td></td>';
1114 }
1115
1116 // Check if Extrafields is totalizable
1117 foreach ($extrafields->attributes['projet_task']['totalizable'] as $key => $value) {
1118 if (!empty($arrayfields['efpt.'.$key]['checked']) && $arrayfields['efpt.'.$key]['checked'] == 1) {
1119 print '<td class="right">';
1120 if ($value == 1) {
1121 print empty($totalarray['totalizable'][$key]['total']) ? '' : $totalarray['totalizable'][$key]['total'];
1122 }
1123 print '</td>';
1124 }
1125 }
1126
1127 // Column for the drag and drop
1128 print '<td class="liste_total"></td>';
1129
1130 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1131 print '<td class="liste_total"></td>';
1132 }
1133
1134 print '</tr>';
1135 }
1136
1137 return $inc;
1138}
1139
1140
1158function projectLinesPerAction(&$inc, $parent, $fuser, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, $preselectedday, &$isavailable, $oldprojectforbreak = 0)
1159{
1160 global $conf, $db, $user, $langs;
1161 global $form, $formother, $projectstatic, $taskstatic, $thirdpartystatic;
1162
1163 $lastprojectid = 0;
1164 $totalforeachline = array();
1165 $workloadforid = array();
1166 $lineswithoutlevel0 = array();
1167
1168 $numlines = count($lines);
1169
1170 // Create a smaller array with sublevels only to be used later. This increase dramatically performances.
1171 if ($parent == 0) { // Always and only if at first level
1172 for ($i = 0; $i < $numlines; $i++) {
1173 if ($lines[$i]->fk_task_parent) {
1174 $lineswithoutlevel0[] = $lines[$i];
1175 }
1176 }
1177 }
1178
1179 if (empty($oldprojectforbreak)) {
1180 $oldprojectforbreak = (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT) ? 0 : -1); // 0 to start break , -1 no break
1181 }
1182
1183 //dol_syslog('projectLinesPerDay inc='.$inc.' preselectedday='.$preselectedday.' task parent id='.$parent.' level='.$level." count(lines)=".$numlines." count(lineswithoutlevel0)=".count($lineswithoutlevel0));
1184 for ($i = 0; $i < $numlines; $i++) {
1185 if ($parent == 0) {
1186 $level = 0;
1187 }
1188
1189 //if ($lines[$i]->fk_task_parent == $parent)
1190 //{
1191 // If we want all or we have a role on task, we show it
1192 if (empty($mine) || !empty($tasksrole[$lines[$i]->id])) {
1193 //dol_syslog("projectLinesPerWeek Found line ".$i.", a qualified task (i have role or want to show all tasks) with id=".$lines[$i]->id." project id=".$lines[$i]->fk_project);
1194
1195 // Break on a new project
1196 if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid) {
1197 $lastprojectid = $lines[$i]->fk_project;
1198 if ($preselectedday) {
1199 $projectstatic->id = $lines[$i]->fk_project;
1200 }
1201 }
1202
1203 if (empty($workloadforid[$projectstatic->id])) {
1204 if ($preselectedday) {
1205 $projectstatic->loadTimeSpent($preselectedday, 0, $fuser->id); // Load time spent from table element_time for the project into this->weekWorkLoad and this->weekWorkLoadPerTask for all days of a week
1206 $workloadforid[$projectstatic->id] = 1;
1207 }
1208 }
1209
1210 $projectstatic->id = $lines[$i]->fk_project;
1211 $projectstatic->ref = $lines[$i]->project_ref;
1212 $projectstatic->title = $lines[$i]->project_label;
1213 $projectstatic->public = $lines[$i]->public;
1214 $projectstatic->status = $lines[$i]->project->status;
1215
1216 $taskstatic->id = $lines[$i]->fk_statut;
1217 $taskstatic->ref = ($lines[$i]->task_ref ? $lines[$i]->task_ref : $lines[$i]->task_id);
1218 $taskstatic->label = $lines[$i]->task_label;
1219 $taskstatic->date_start = $lines[$i]->date_start;
1220 $taskstatic->date_end = $lines[$i]->date_end;
1221
1222 $thirdpartystatic->id = $lines[$i]->socid;
1223 $thirdpartystatic->name = $lines[$i]->thirdparty_name;
1224 $thirdpartystatic->email = $lines[$i]->thirdparty_email;
1225
1226 if (empty($oldprojectforbreak) || ($oldprojectforbreak != -1 && $oldprojectforbreak != $projectstatic->id)) {
1227 print '<tr class="oddeven trforbreak nobold">'."\n";
1228 print '<td colspan="11">';
1229 print $projectstatic->getNomUrl(1, '', 0, $langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]);
1230 if ($projectstatic->title) {
1231 print ' - ';
1232 print $projectstatic->title;
1233 }
1234 print '</td>';
1235 print '</tr>';
1236 }
1237
1238 if ($oldprojectforbreak != -1) {
1239 $oldprojectforbreak = $projectstatic->id;
1240 }
1241
1242 print '<tr class="oddeven">'."\n";
1243
1244 // User
1245 /*
1246 print '<td class="nowrap">';
1247 print $fuser->getNomUrl(1, 'withproject', 'time');
1248 print '</td>';
1249 */
1250
1251 // Project
1252 print "<td>";
1253 if ($oldprojectforbreak == -1) {
1254 print $projectstatic->getNomUrl(1, '', 0, $langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]);
1255 print '<br>'.$projectstatic->title;
1256 }
1257 print "</td>";
1258
1259 // Thirdparty
1260 print '<td class="tdoverflowmax100">';
1261 if ($thirdpartystatic->id > 0) {
1262 print $thirdpartystatic->getNomUrl(1, 'project', 10);
1263 }
1264 print '</td>';
1265
1266 // Ref
1267 print '<td>';
1268 print '<!-- Task id = '.$lines[$i]->id.' -->';
1269 for ($k = 0; $k < $level; $k++) {
1270 print "&nbsp;&nbsp;&nbsp;";
1271 }
1272 print $taskstatic->getNomUrl(1, 'withproject', 'time');
1273 // Label task
1274 print '<br>';
1275 for ($k = 0; $k < $level; $k++) {
1276 print "&nbsp;&nbsp;&nbsp;";
1277 }
1278 print $taskstatic->label;
1279 //print "<br>";
1280 //for ($k = 0 ; $k < $level ; $k++) print "&nbsp;&nbsp;&nbsp;";
1281 //print get_date_range($lines[$i]->date_start,$lines[$i]->date_end,'',$langs,0);
1282 print "</td>\n";
1283
1284 // Date
1285 print '<td class="center">';
1286 print dol_print_date($lines[$i]->timespent_datehour, 'day');
1287 print '</td>';
1288
1289 $disabledproject = 1;
1290 $disabledtask = 1;
1291 //print "x".$lines[$i]->fk_project;
1292 //var_dump($lines[$i]);
1293 //var_dump($projectsrole[$lines[$i]->fk_project]);
1294 // If at least one role for project
1295 if ($lines[$i]->public || !empty($projectsrole[$lines[$i]->fk_project]) || $user->rights->projet->all->creer) {
1296 $disabledproject = 0;
1297 $disabledtask = 0;
1298 }
1299 // If $restricteditformytask is on and I have no role on task, i disable edit
1300 if ($restricteditformytask && empty($tasksrole[$lines[$i]->id])) {
1301 $disabledtask = 1;
1302 }
1303
1304 // Hour
1305 print '<td class="nowrap center">';
1306 print dol_print_date($lines[$i]->timespent_datehour, 'hour');
1307 print '</td>';
1308
1309 $cssonholiday = '';
1310 if (!$isavailable[$preselectedday]['morning'] && !$isavailable[$preselectedday]['afternoon']) {
1311 $cssonholiday .= 'onholidayallday ';
1312 } elseif (!$isavailable[$preselectedday]['morning']) {
1313 $cssonholiday .= 'onholidaymorning ';
1314 } elseif (!$isavailable[$preselectedday]['afternoon']) {
1315 $cssonholiday .= 'onholidayafternoon ';
1316 }
1317
1318 // Duration
1319 print '<td class="duration'.($cssonholiday ? ' '.$cssonholiday : '').' center">';
1320
1321 $dayWorkLoad = $lines[$i]->timespent_duration;
1322 $totalforeachline[$preselectedday] += $lines[$i]->timespent_duration;
1323
1324 $alreadyspent = '';
1325 if ($dayWorkLoad > 0) {
1326 $alreadyspent = convertSecondToTime($lines[$i]->timespent_duration, 'allhourmin');
1327 }
1328
1329 print convertSecondToTime($lines[$i]->timespent_duration, 'allhourmin');
1330
1331 print '</td>';
1332
1333 // Note
1334 print '<td class="center">';
1335 print '<textarea name="'.$lines[$i]->id.'note" rows="'.ROWS_2.'" id="'.$lines[$i]->id.'note"'.($disabledtask ? ' disabled="disabled"' : '').'>';
1336 print $lines[$i]->timespent_note;
1337 print '</textarea>';
1338 print '</td>';
1339
1340 // Warning
1341 print '<td class="right">';
1342 /*if ((! $lines[$i]->public) && $disabledproject) print $form->textwithpicto('',$langs->trans("UserIsNotContactOfProject"));
1343 elseif ($disabledtask)
1344 {
1345 $titleassigntask = $langs->trans("AssignTaskToMe");
1346 if ($fuser->id != $user->id) $titleassigntask = $langs->trans("AssignTaskToUser", '...');
1347
1348 print $form->textwithpicto('',$langs->trans("TaskIsNotAssignedToUser", $titleassigntask));
1349 }*/
1350 print '</td>';
1351
1352 print "</tr>\n";
1353 }
1354 //}
1355 //else
1356 //{
1357 //$level--;
1358 //}
1359 }
1360
1361 return $totalforeachline;
1362}
1363
1364
1384function projectLinesPerDay(&$inc, $parent, $fuser, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, $preselectedday, &$isavailable, $oldprojectforbreak = 0, $arrayfields = array(), $extrafields = null)
1385{
1386 global $conf, $db, $user, $langs;
1387 global $form, $formother, $projectstatic, $taskstatic, $thirdpartystatic;
1388
1389 $lastprojectid = 0;
1390 $totalforeachday = array();
1391 $workloadforid = array();
1392 $lineswithoutlevel0 = array();
1393
1394 $numlines = count($lines);
1395
1396 // Create a smaller array with sublevels only to be used later. This increase dramatically performances.
1397 if ($parent == 0) { // Always and only if at first level
1398 for ($i = 0; $i < $numlines; $i++) {
1399 if ($lines[$i]->fk_task_parent) {
1400 $lineswithoutlevel0[] = $lines[$i];
1401 }
1402 }
1403 }
1404
1405 if (empty($oldprojectforbreak)) {
1406 $oldprojectforbreak = (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT) ? 0 : -1); // 0 to start break , -1 no break
1407 }
1408
1409 $restrictBefore = null;
1410
1411 if (!empty($conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS)) {
1412 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
1413 $restrictBefore = dol_time_plus_duree(dol_now(), - $conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS, 'm');
1414 }
1415
1416 //dol_syslog('projectLinesPerDay inc='.$inc.' preselectedday='.$preselectedday.' task parent id='.$parent.' level='.$level." count(lines)=".$numlines." count(lineswithoutlevel0)=".count($lineswithoutlevel0));
1417 for ($i = 0; $i < $numlines; $i++) {
1418 if ($parent == 0) {
1419 $level = 0;
1420 }
1421
1422 if ($lines[$i]->fk_task_parent == $parent) {
1423 $obj = &$lines[$i]; // To display extrafields
1424
1425 // If we want all or we have a role on task, we show it
1426 if (empty($mine) || !empty($tasksrole[$lines[$i]->id])) {
1427 //dol_syslog("projectLinesPerWeek Found line ".$i.", a qualified task (i have role or want to show all tasks) with id=".$lines[$i]->id." project id=".$lines[$i]->fk_project);
1428
1429 if ($restricteditformytask == 2 && empty($tasksrole[$lines[$i]->id])) { // we have no role on task and we request to hide such cases
1430 continue;
1431 }
1432
1433 // Break on a new project
1434 if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid) {
1435 $lastprojectid = $lines[$i]->fk_project;
1436 if ($preselectedday) {
1437 $projectstatic->id = $lines[$i]->fk_project;
1438 }
1439 }
1440
1441 if (empty($workloadforid[$projectstatic->id])) {
1442 if ($preselectedday) {
1443 $projectstatic->loadTimeSpent($preselectedday, 0, $fuser->id); // Load time spent from table element_time for the project into this->weekWorkLoad and this->weekWorkLoadPerTask for all days of a week
1444 $workloadforid[$projectstatic->id] = 1;
1445 }
1446 }
1447
1448 $projectstatic->id = $lines[$i]->fk_project;
1449 $projectstatic->ref = $lines[$i]->projectref;
1450 $projectstatic->title = $lines[$i]->projectlabel;
1451 $projectstatic->public = $lines[$i]->public;
1452 $projectstatic->status = $lines[$i]->projectstatus;
1453
1454 $taskstatic->id = $lines[$i]->id;
1455 $taskstatic->ref = ($lines[$i]->ref ? $lines[$i]->ref : $lines[$i]->id);
1456 $taskstatic->label = $lines[$i]->label;
1457 $taskstatic->date_start = $lines[$i]->date_start;
1458 $taskstatic->date_end = $lines[$i]->date_end;
1459
1460 $thirdpartystatic->id = $lines[$i]->socid;
1461 $thirdpartystatic->name = $lines[$i]->thirdparty_name;
1462 $thirdpartystatic->email = $lines[$i]->thirdparty_email;
1463
1464 if (empty($oldprojectforbreak) || ($oldprojectforbreak != -1 && $oldprojectforbreak != $projectstatic->id)) {
1465 $addcolspan = 0;
1466 if (!empty($arrayfields['t.planned_workload']['checked'])) {
1467 $addcolspan++;
1468 }
1469 if (!empty($arrayfields['t.progress']['checked'])) {
1470 $addcolspan++;
1471 }
1472 foreach ($arrayfields as $key => $val) {
1473 if ($val['checked'] && substr($key, 0, 5) == 'efpt.') {
1474 $addcolspan++;
1475 }
1476 }
1477
1478 print '<tr class="oddeven trforbreak nobold">'."\n";
1479 print '<td colspan="'.(7 + $addcolspan).'">';
1480 print $projectstatic->getNomUrl(1, '', 0, '<strong>'.$langs->transnoentitiesnoconv("YourRole").':</strong> '.$projectsrole[$lines[$i]->fk_project]);
1481 if ($thirdpartystatic->id > 0) {
1482 print ' - '.$thirdpartystatic->getNomUrl(1);
1483 }
1484 if ($projectstatic->title) {
1485 print ' - ';
1486 print '<span class="secondary">'.$projectstatic->title.'</span>';
1487 }
1488 /*
1489 $colspan=5+(empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)?0:2);
1490 print '<table class="">';
1491
1492 print '<tr class="liste_titre">';
1493
1494 // PROJECT fields
1495 if (!empty($arrayfields['p.fk_opp_status']['checked'])) print_liste_field_titre($arrayfields['p.fk_opp_status']['label'], $_SERVER["PHP_SELF"], 'p.fk_opp_status', "", $param, '', $sortfield, $sortorder, 'center ');
1496 if (!empty($arrayfields['p.opp_amount']['checked'])) print_liste_field_titre($arrayfields['p.opp_amount']['label'], $_SERVER["PHP_SELF"], 'p.opp_amount', "", $param, '', $sortfield, $sortorder, 'right ');
1497 if (!empty($arrayfields['p.opp_percent']['checked'])) print_liste_field_titre($arrayfields['p.opp_percent']['label'], $_SERVER["PHP_SELF"], 'p.opp_percent', "", $param, '', $sortfield, $sortorder, 'right ');
1498 if (!empty($arrayfields['p.budget_amount']['checked'])) print_liste_field_titre($arrayfields['p.budget_amount']['label'], $_SERVER["PHP_SELF"], 'p.budget_amount', "", $param, '', $sortfield, $sortorder, 'right ');
1499 if (!empty($arrayfields['p.usage_bill_time']['checked'])) print_liste_field_titre($arrayfields['p.usage_bill_time']['label'], $_SERVER["PHP_SELF"], 'p.usage_bill_time', "", $param, '', $sortfield, $sortorder, 'right ');
1500
1501 $extrafieldsobjectkey='projet';
1502 $extrafieldsobjectprefix='efp.';
1503 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
1504
1505 print '</tr>';
1506 print '<tr>';
1507
1508 // PROJECT fields
1509 if (!empty($arrayfields['p.fk_opp_status']['checked']))
1510 {
1511 print '<td class="nowrap">';
1512 $code = dol_getIdFromCode($db, $lines[$i]->fk_opp_status, 'c_lead_status', 'rowid', 'code');
1513 if ($code) print $langs->trans("OppStatus".$code);
1514 print "</td>\n";
1515 }
1516 if (!empty($arrayfields['p.opp_amount']['checked']))
1517 {
1518 print '<td class="nowrap">';
1519 print price($lines[$i]->opp_amount, 0, $langs, 1, 0, -1, $conf->currency);
1520 print "</td>\n";
1521 }
1522 if (!empty($arrayfields['p.opp_percent']['checked']))
1523 {
1524 print '<td class="nowrap">';
1525 print price($lines[$i]->opp_percent, 0, $langs, 1, 0).' %';
1526 print "</td>\n";
1527 }
1528 if (!empty($arrayfields['p.budget_amount']['checked']))
1529 {
1530 print '<td class="nowrap">';
1531 print price($lines[$i]->budget_amount, 0, $langs, 1, 0, 0, $conf->currency);
1532 print "</td>\n";
1533 }
1534 if (!empty($arrayfields['p.usage_bill_time']['checked']))
1535 {
1536 print '<td class="nowrap">';
1537 print yn($lines[$i]->usage_bill_time);
1538 print "</td>\n";
1539 }
1540
1541 $extrafieldsobjectkey='projet';
1542 $extrafieldsobjectprefix='efp.';
1543 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
1544
1545 print '</tr>';
1546 print '</table>';
1547
1548 */
1549 print '</td>';
1550 print '</tr>';
1551 }
1552
1553 if ($oldprojectforbreak != -1) {
1554 $oldprojectforbreak = $projectstatic->id;
1555 }
1556
1557 print '<tr class="oddeven" data-taskid="'.$lines[$i]->id.'">'."\n";
1558
1559 // User
1560 /*
1561 print '<td class="nowrap">';
1562 print $fuser->getNomUrl(1, 'withproject', 'time');
1563 print '</td>';
1564 */
1565
1566 // Project
1567 if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) {
1568 print "<td>";
1569 if ($oldprojectforbreak == -1) {
1570 print $projectstatic->getNomUrl(1, '', 0, $langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]);
1571 }
1572 print "</td>";
1573 }
1574
1575 // Thirdparty
1576 if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) {
1577 print '<td class="tdoverflowmax100">';
1578 if ($thirdpartystatic->id > 0) {
1579 print $thirdpartystatic->getNomUrl(1, 'project', 10);
1580 }
1581 print '</td>';
1582 }
1583
1584 // Ref
1585 print '<td>';
1586 print '<!-- Task id = '.$lines[$i]->id.' -->';
1587 for ($k = 0; $k < $level; $k++) {
1588 print '<div class="marginleftonly">';
1589 }
1590 print $taskstatic->getNomUrl(1, 'withproject', 'time');
1591 // Label task
1592 print '<br>';
1593 print '<span class="opacitymedium">'.$taskstatic->label.'</a>';
1594 for ($k = 0; $k < $level; $k++) {
1595 print "</div>";
1596 }
1597 print "</td>\n";
1598
1599 // TASK extrafields
1600 $extrafieldsobjectkey = 'projet_task';
1601 $extrafieldsobjectprefix = 'efpt.';
1602 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
1603
1604 // Planned Workload
1605 if (!empty($arrayfields['t.planned_workload']['checked'])) {
1606 print '<td class="leftborder plannedworkload right">';
1607 if ($lines[$i]->planned_workload) {
1608 print convertSecondToTime($lines[$i]->planned_workload, 'allhourmin');
1609 } else {
1610 print '--:--';
1611 }
1612 print '</td>';
1613 }
1614
1615 // Progress declared %
1616 if (!empty($arrayfields['t.progress']['checked'])) {
1617 print '<td class="right">';
1618 print $formother->select_percent($lines[$i]->progress, $lines[$i]->id.'progress');
1619 print '</td>';
1620 }
1621
1622 if (!empty($arrayfields['timeconsumed']['checked'])) {
1623 // Time spent by everybody
1624 print '<td class="right">';
1625 // $lines[$i]->duration_effective is a denormalised field = summ of time spent by everybody for task. What we need is time consumed by user
1626 if ($lines[$i]->duration_effective) {
1627 print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$lines[$i]->id.'">';
1628 print convertSecondToTime($lines[$i]->duration_effective, 'allhourmin');
1629 print '</a>';
1630 } else {
1631 print '--:--';
1632 }
1633 print "</td>\n";
1634
1635 // Time spent by user
1636 print '<td class="right">';
1637 $tmptimespent = $taskstatic->getSummaryOfTimeSpent($fuser->id);
1638 if ($tmptimespent['total_duration']) {
1639 print convertSecondToTime($tmptimespent['total_duration'], 'allhourmin');
1640 } else {
1641 print '--:--';
1642 }
1643 print "</td>\n";
1644 }
1645
1646 $disabledproject = 1;
1647 $disabledtask = 1;
1648 //print "x".$lines[$i]->fk_project;
1649 //var_dump($lines[$i]);
1650 //var_dump($projectsrole[$lines[$i]->fk_project]);
1651 // If at least one role for project
1652 if ($lines[$i]->public || !empty($projectsrole[$lines[$i]->fk_project]) || $user->rights->projet->all->creer) {
1653 $disabledproject = 0;
1654 $disabledtask = 0;
1655 }
1656 // If $restricteditformytask is on and I have no role on task, i disable edit
1657 if ($restricteditformytask && empty($tasksrole[$lines[$i]->id])) {
1658 $disabledtask = 1;
1659 }
1660
1661 if ($restrictBefore && $preselectedday < $restrictBefore) {
1662 $disabledtask = 1;
1663 }
1664
1665 // Select hour
1666 print '<td class="nowraponall leftborder center minwidth150imp">';
1667 $tableCell = $form->selectDate($preselectedday, $lines[$i]->id, 1, 1, 2, "addtime", 0, 0, $disabledtask);
1668 print $tableCell;
1669 print '</td>';
1670
1671 $cssonholiday = '';
1672 if (!$isavailable[$preselectedday]['morning'] && !$isavailable[$preselectedday]['afternoon']) {
1673 $cssonholiday .= 'onholidayallday ';
1674 } elseif (!$isavailable[$preselectedday]['morning']) {
1675 $cssonholiday .= 'onholidaymorning ';
1676 } elseif (!$isavailable[$preselectedday]['afternoon']) {
1677 $cssonholiday .= 'onholidayafternoon ';
1678 }
1679
1680 global $daytoparse;
1681 $tmparray = dol_getdate($daytoparse, true); // detail of current day
1682
1683 $idw = ($tmparray['wday'] - (empty($conf->global->MAIN_START_WEEK) ? 0 : 1));
1684 global $numstartworkingday, $numendworkingday;
1685 $cssweekend = '';
1686 if ((($idw + 1) < $numstartworkingday) || (($idw + 1) > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css.
1687 $cssweekend = 'weekend';
1688 }
1689
1690 // Duration
1691 print '<td class="center duration'.($cssonholiday ? ' '.$cssonholiday : '').($cssweekend ? ' '.$cssweekend : '').'">';
1692 $dayWorkLoad = empty($projectstatic->weekWorkLoadPerTask[$preselectedday][$lines[$i]->id]) ? 0 : $projectstatic->weekWorkLoadPerTask[$preselectedday][$lines[$i]->id];
1693 if (!isset($totalforeachday[$preselectedday])) {
1694 $totalforeachday[$preselectedday] = 0;
1695 }
1696 $totalforeachday[$preselectedday] += $dayWorkLoad;
1697
1698 $alreadyspent = '';
1699 if ($dayWorkLoad > 0) {
1700 $alreadyspent = convertSecondToTime($dayWorkLoad, 'allhourmin');
1701 }
1702
1703 $idw = 0;
1704
1705 $tableCell = '';
1706 $tableCell .= '<span class="timesheetalreadyrecorded" title="texttoreplace"><input type="text" class="center" size="2" disabled id="timespent['.$inc.']['.$idw.']" name="task['.$lines[$i]->id.']['.$idw.']" value="'.$alreadyspent.'"></span>';
1707 $tableCell .= '<span class="hideonsmartphone"> + </span>';
1708 //$tableCell.='&nbsp;&nbsp;&nbsp;';
1709 $tableCell .= $form->select_duration($lines[$i]->id.'duration', '', $disabledtask, 'text', 0, 1);
1710 //$tableCell.='&nbsp;<input type="submit" class="button"'.($disabledtask?' disabled':'').' value="'.$langs->trans("Add").'">';
1711 print $tableCell;
1712
1713 print '</td>';
1714
1715 // Note
1716 print '<td class="center">';
1717 print '<textarea name="'.$lines[$i]->id.'note" rows="'.ROWS_2.'" id="'.$lines[$i]->id.'note"'.($disabledtask ? ' disabled="disabled"' : '').'>';
1718 print '</textarea>';
1719 print '</td>';
1720
1721 // Warning
1722 print '<td class="right">';
1723 if ((!$lines[$i]->public) && $disabledproject) {
1724 print $form->textwithpicto('', $langs->trans("UserIsNotContactOfProject"));
1725 } elseif ($disabledtask) {
1726 $titleassigntask = $langs->trans("AssignTaskToMe");
1727 if ($fuser->id != $user->id) {
1728 $titleassigntask = $langs->trans("AssignTaskToUser", '...');
1729 }
1730
1731 print $form->textwithpicto('', $langs->trans("TaskIsNotAssignedToUser", $titleassigntask));
1732 }
1733 print '</td>';
1734
1735 print "</tr>\n";
1736 }
1737
1738 $inc++;
1739 $level++;
1740 if ($lines[$i]->id > 0) {
1741 //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level);
1742 //var_dump($totalforeachday);
1743 $ret = projectLinesPerDay($inc, $lines[$i]->id, $fuser, ($parent == 0 ? $lineswithoutlevel0 : $lines), $level, $projectsrole, $tasksrole, $mine, $restricteditformytask, $preselectedday, $isavailable, $oldprojectforbreak, $arrayfields, $extrafields);
1744 //var_dump('ret with parent='.$lines[$i]->id.' level='.$level);
1745 //var_dump($ret);
1746 foreach ($ret as $key => $val) {
1747 $totalforeachday[$key] += $val;
1748 }
1749 //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level.' + subtasks');
1750 //var_dump($totalforeachday);
1751 }
1752 $level--;
1753 } else {
1754 //$level--;
1755 }
1756 }
1757
1758 return $totalforeachday;
1759}
1760
1761
1781function projectLinesPerWeek(&$inc, $firstdaytoshow, $fuser, $parent, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, &$isavailable, $oldprojectforbreak = 0, $arrayfields = array(), $extrafields = null)
1782{
1783 global $conf, $db, $user, $langs;
1784 global $form, $formother, $projectstatic, $taskstatic, $thirdpartystatic;
1785
1786 $numlines = count($lines);
1787
1788 $lastprojectid = 0;
1789 $workloadforid = array();
1790 $totalforeachday = array();
1791 $lineswithoutlevel0 = array();
1792
1793 // Create a smaller array with sublevels only to be used later. This increase dramatically performances.
1794 if ($parent == 0) { // Always and only if at first level
1795 for ($i = 0; $i < $numlines; $i++) {
1796 if ($lines[$i]->fk_task_parent) {
1797 $lineswithoutlevel0[] = $lines[$i];
1798 }
1799 }
1800 }
1801
1802 //dol_syslog('projectLinesPerWeek inc='.$inc.' firstdaytoshow='.$firstdaytoshow.' task parent id='.$parent.' level='.$level." count(lines)=".$numlines." count(lineswithoutlevel0)=".count($lineswithoutlevel0));
1803
1804 if (empty($oldprojectforbreak)) {
1805 $oldprojectforbreak = (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT) ? 0 : -1); // 0 = start break, -1 = never break
1806 }
1807
1808 $restrictBefore = null;
1809
1810 if (!empty($conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS)) {
1811 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
1812 $restrictBefore = dol_time_plus_duree(dol_now(), - $conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS, 'm');
1813 }
1814
1815 for ($i = 0; $i < $numlines; $i++) {
1816 if ($parent == 0) {
1817 $level = 0;
1818 }
1819
1820 if ($lines[$i]->fk_task_parent == $parent) {
1821 $obj = &$lines[$i]; // To display extrafields
1822
1823 // If we want all or we have a role on task, we show it
1824 if (empty($mine) || !empty($tasksrole[$lines[$i]->id])) {
1825 //dol_syslog("projectLinesPerWeek Found line ".$i.", a qualified task (i have role or want to show all tasks) with id=".$lines[$i]->id." project id=".$lines[$i]->fk_project);
1826
1827 if ($restricteditformytask == 2 && empty($tasksrole[$lines[$i]->id])) { // we have no role on task and we request to hide such cases
1828 continue;
1829 }
1830
1831 // Break on a new project
1832 if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid) {
1833 $lastprojectid = $lines[$i]->fk_project;
1834 $projectstatic->id = $lines[$i]->fk_project;
1835 }
1836
1837 //var_dump('--- '.$level.' '.$firstdaytoshow.' '.$fuser->id.' '.$projectstatic->id.' '.$workloadforid[$projectstatic->id]);
1838 //var_dump($projectstatic->weekWorkLoadPerTask);
1839 if (empty($workloadforid[$projectstatic->id])) {
1840 $projectstatic->loadTimeSpent($firstdaytoshow, 0, $fuser->id); // Load time spent from table element_time for the project into this->weekWorkLoad and this->weekWorkLoadPerTask for all days of a week
1841 $workloadforid[$projectstatic->id] = 1;
1842 }
1843 //var_dump($projectstatic->weekWorkLoadPerTask);
1844 //var_dump('--- '.$projectstatic->id.' '.$workloadforid[$projectstatic->id]);
1845
1846 $projectstatic->id = $lines[$i]->fk_project;
1847 $projectstatic->ref = $lines[$i]->projectref;
1848 $projectstatic->title = $lines[$i]->projectlabel;
1849 $projectstatic->public = $lines[$i]->public;
1850 $projectstatic->thirdparty_name = $lines[$i]->thirdparty_name;
1851 $projectstatic->status = $lines[$i]->projectstatus;
1852
1853 $taskstatic->id = $lines[$i]->id;
1854 $taskstatic->ref = ($lines[$i]->ref ? $lines[$i]->ref : $lines[$i]->id);
1855 $taskstatic->label = $lines[$i]->label;
1856 $taskstatic->date_start = $lines[$i]->date_start;
1857 $taskstatic->date_end = $lines[$i]->date_end;
1858
1859 $thirdpartystatic->id = $lines[$i]->thirdparty_id;
1860 $thirdpartystatic->name = $lines[$i]->thirdparty_name;
1861 $thirdpartystatic->email = $lines[$i]->thirdparty_email;
1862
1863 if (empty($oldprojectforbreak) || ($oldprojectforbreak != -1 && $oldprojectforbreak != $projectstatic->id)) {
1864 $addcolspan = 0;
1865 if (!empty($arrayfields['t.planned_workload']['checked'])) {
1866 $addcolspan++;
1867 }
1868 if (!empty($arrayfields['t.progress']['checked'])) {
1869 $addcolspan++;
1870 }
1871 foreach ($arrayfields as $key => $val) {
1872 if ($val['checked'] && substr($key, 0, 5) == 'efpt.') {
1873 $addcolspan++;
1874 }
1875 }
1876
1877 print '<tr class="oddeven trforbreak nobold">'."\n";
1878 print '<td colspan="'.(11 + $addcolspan).'">';
1879 print $projectstatic->getNomUrl(1, '', 0, '<strong>'.$langs->transnoentitiesnoconv("YourRole").':</strong> '.$projectsrole[$lines[$i]->fk_project]);
1880 if ($thirdpartystatic->id > 0) {
1881 print ' - '.$thirdpartystatic->getNomUrl(1);
1882 }
1883 if ($projectstatic->title) {
1884 print ' - ';
1885 print '<span class="secondary">'.$projectstatic->title.'</span>';
1886 }
1887
1888 /*$colspan=5+(empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)?0:2);
1889 print '<table class="">';
1890
1891 print '<tr class="liste_titre">';
1892
1893 // PROJECT fields
1894 if (!empty($arrayfields['p.fk_opp_status']['checked'])) print_liste_field_titre($arrayfields['p.fk_opp_status']['label'], $_SERVER["PHP_SELF"], 'p.fk_opp_status', "", $param, '', $sortfield, $sortorder, 'center ');
1895 if (!empty($arrayfields['p.opp_amount']['checked'])) print_liste_field_titre($arrayfields['p.opp_amount']['label'], $_SERVER["PHP_SELF"], 'p.opp_amount', "", $param, '', $sortfield, $sortorder, 'right ');
1896 if (!empty($arrayfields['p.opp_percent']['checked'])) print_liste_field_titre($arrayfields['p.opp_percent']['label'], $_SERVER["PHP_SELF"], 'p.opp_percent', "", $param, '', $sortfield, $sortorder, 'right ');
1897 if (!empty($arrayfields['p.budget_amount']['checked'])) print_liste_field_titre($arrayfields['p.budget_amount']['label'], $_SERVER["PHP_SELF"], 'p.budget_amount', "", $param, '', $sortfield, $sortorder, 'right ');
1898 if (!empty($arrayfields['p.usage_bill_time']['checked'])) print_liste_field_titre($arrayfields['p.usage_bill_time']['label'], $_SERVER["PHP_SELF"], 'p.usage_bill_time', "", $param, '', $sortfield, $sortorder, 'right ');
1899
1900 $extrafieldsobjectkey='projet';
1901 $extrafieldsobjectprefix='efp.';
1902 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
1903
1904 print '</tr>';
1905 print '<tr>';
1906
1907 // PROJECT fields
1908 if (!empty($arrayfields['p.fk_opp_status']['checked']))
1909 {
1910 print '<td class="nowrap">';
1911 $code = dol_getIdFromCode($db, $lines[$i]->fk_opp_status, 'c_lead_status', 'rowid', 'code');
1912 if ($code) print $langs->trans("OppStatus".$code);
1913 print "</td>\n";
1914 }
1915 if (!empty($arrayfields['p.opp_amount']['checked']))
1916 {
1917 print '<td class="nowrap">';
1918 print price($lines[$i]->opp_amount, 0, $langs, 1, 0, -1, $conf->currency);
1919 print "</td>\n";
1920 }
1921 if (!empty($arrayfields['p.opp_percent']['checked']))
1922 {
1923 print '<td class="nowrap">';
1924 print price($lines[$i]->opp_percent, 0, $langs, 1, 0).' %';
1925 print "</td>\n";
1926 }
1927 if (!empty($arrayfields['p.budget_amount']['checked']))
1928 {
1929 print '<td class="nowrap">';
1930 print price($lines[$i]->budget_amount, 0, $langs, 1, 0, 0, $conf->currency);
1931 print "</td>\n";
1932 }
1933 if (!empty($arrayfields['p.usage_bill_time']['checked']))
1934 {
1935 print '<td class="nowrap">';
1936 print yn($lines[$i]->usage_bill_time);
1937 print "</td>\n";
1938 }
1939
1940 $extrafieldsobjectkey='projet';
1941 $extrafieldsobjectprefix='efp.';
1942 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
1943
1944 print '</tr>';
1945 print '</table>';
1946 */
1947
1948 print '</td>';
1949 print '</tr>';
1950 }
1951
1952 if ($oldprojectforbreak != -1) {
1953 $oldprojectforbreak = $projectstatic->id;
1954 }
1955
1956 print '<tr class="oddeven" data-taskid="'.$lines[$i]->id.'">'."\n";
1957
1958 // User
1959 /*
1960 print '<td class="nowrap">';
1961 print $fuser->getNomUrl(1, 'withproject', 'time');
1962 print '</td>';
1963 */
1964
1965 // Project
1966 if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) {
1967 print '<td class="nowrap">';
1968 if ($oldprojectforbreak == -1) {
1969 print $projectstatic->getNomUrl(1, '', 0, $langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]);
1970 }
1971 print "</td>";
1972 }
1973
1974 // Thirdparty
1975 if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) {
1976 print '<td class="tdoverflowmax100">';
1977 if ($thirdpartystatic->id > 0) {
1978 print $thirdpartystatic->getNomUrl(1, 'project');
1979 }
1980 print '</td>';
1981 }
1982
1983 // Ref
1984 print '<td class="nowrap">';
1985 print '<!-- Task id = '.$lines[$i]->id.' -->';
1986 for ($k = 0; $k < $level; $k++) {
1987 print '<div class="marginleftonly">';
1988 }
1989 print $taskstatic->getNomUrl(1, 'withproject', 'time');
1990 // Label task
1991 print '<br>';
1992 print '<span class="opacitymedium">'.$taskstatic->label.'</span>';
1993 for ($k = 0; $k < $level; $k++) {
1994 print "</div>";
1995 }
1996 print "</td>\n";
1997
1998 // TASK extrafields
1999 $extrafieldsobjectkey = 'projet_task';
2000 $extrafieldsobjectprefix = 'efpt.';
2001 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
2002
2003 // Planned Workload
2004 if (!empty($arrayfields['t.planned_workload']['checked'])) {
2005 print '<td class="leftborder plannedworkload right">';
2006 if ($lines[$i]->planned_workload) {
2007 print convertSecondToTime($lines[$i]->planned_workload, 'allhourmin');
2008 } else {
2009 print '--:--';
2010 }
2011 print '</td>';
2012 }
2013
2014 if (!empty($arrayfields['t.progress']['checked'])) {
2015 // Progress declared %
2016 print '<td class="right">';
2017 print $formother->select_percent($lines[$i]->progress, $lines[$i]->id.'progress');
2018 print '</td>';
2019 }
2020
2021 if (!empty($arrayfields['timeconsumed']['checked'])) {
2022 // Time spent by everybody
2023 print '<td class="right">';
2024 // $lines[$i]->duration_effective is a denormalised field = summ of time spent by everybody for task. What we need is time consumed by user
2025 if ($lines[$i]->duration_effective) {
2026 print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$lines[$i]->id.'">';
2027 print convertSecondToTime($lines[$i]->duration_effective, 'allhourmin');
2028 print '</a>';
2029 } else {
2030 print '--:--';
2031 }
2032 print "</td>\n";
2033
2034 // Time spent by user
2035 print '<td class="right">';
2036 $tmptimespent = $taskstatic->getSummaryOfTimeSpent($fuser->id);
2037 if ($tmptimespent['total_duration']) {
2038 print convertSecondToTime($tmptimespent['total_duration'], 'allhourmin');
2039 } else {
2040 print '--:--';
2041 }
2042 print "</td>\n";
2043 }
2044
2045 $disabledproject = 1;
2046 $disabledtask = 1;
2047 //print "x".$lines[$i]->fk_project;
2048 //var_dump($lines[$i]);
2049 //var_dump($projectsrole[$lines[$i]->fk_project]);
2050 // If at least one role for project
2051 if ($lines[$i]->public || !empty($projectsrole[$lines[$i]->fk_project]) || $user->rights->projet->all->creer) {
2052 $disabledproject = 0;
2053 $disabledtask = 0;
2054 }
2055 // If $restricteditformytask is on and I have no role on task, i disable edit
2056 if ($restricteditformytask && empty($tasksrole[$lines[$i]->id])) {
2057 $disabledtask = 1;
2058 }
2059
2060 //var_dump($projectstatic->weekWorkLoadPerTask);
2061
2062 // Fields to show current time
2063 $tableCell = '';
2064 $modeinput = 'hours';
2065 for ($idw = 0; $idw < 7; $idw++) {
2066 $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd');
2067 if (!isset($totalforeachday[$tmpday])) $totalforeachday[$tmpday] = 0;
2068 $cssonholiday = '';
2069 if (!$isavailable[$tmpday]['morning'] && !$isavailable[$tmpday]['afternoon']) {
2070 $cssonholiday .= 'onholidayallday ';
2071 } elseif (!$isavailable[$tmpday]['morning']) {
2072 $cssonholiday .= 'onholidaymorning ';
2073 } elseif (!$isavailable[$tmpday]['afternoon']) {
2074 $cssonholiday .= 'onholidayafternoon ';
2075 }
2076
2077 $tmparray = dol_getdate($tmpday);
2078 $dayWorkLoad = (!empty($projectstatic->weekWorkLoadPerTask[$tmpday][$lines[$i]->id]) ? $projectstatic->weekWorkLoadPerTask[$tmpday][$lines[$i]->id] : 0);
2079 $totalforeachday[$tmpday] += $dayWorkLoad;
2080
2081 $alreadyspent = '';
2082 if ($dayWorkLoad > 0) {
2083 $alreadyspent = convertSecondToTime($dayWorkLoad, 'allhourmin');
2084 }
2085 $alttitle = $langs->trans("AddHereTimeSpentForDay", !empty($tmparray['day']) ? $tmparray['day'] : 0, $tmparray['mon']);
2086
2087 global $numstartworkingday, $numendworkingday;
2088 $cssweekend = '';
2089 if (($idw + 1 < $numstartworkingday) || ($idw + 1 > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css.
2090 $cssweekend = 'weekend';
2091 }
2092
2093 $disabledtaskday = $disabledtask;
2094
2095 if (! $disabledtask && $restrictBefore && $tmpday < $restrictBefore) {
2096 $disabledtaskday = 1;
2097 }
2098
2099 $tableCell = '<td class="center hide'.$idw.($cssonholiday ? ' '.$cssonholiday : '').($cssweekend ? ' '.$cssweekend : '').'">';
2100 //$tableCell .= 'idw='.$idw.' '.$conf->global->MAIN_START_WEEK.' '.$numstartworkingday.'-'.$numendworkingday;
2101 $placeholder = '';
2102 if ($alreadyspent) {
2103 $tableCell .= '<span class="timesheetalreadyrecorded" title="texttoreplace"><input type="text" class="center smallpadd" size="2" disabled id="timespent['.$inc.']['.$idw.']" name="task['.$lines[$i]->id.']['.$idw.']" value="'.$alreadyspent.'"></span>';
2104 //$placeholder=' placeholder="00:00"';
2105 //$tableCell.='+';
2106 }
2107 $tableCell .= '<input type="text" alt="'.($disabledtaskday ? '' : $alttitle).'" title="'.($disabledtaskday ? '' : $alttitle).'" '.($disabledtaskday ? 'disabled' : $placeholder).' class="center smallpadd" size="2" id="timeadded['.$inc.']['.$idw.']" name="task['.$lines[$i]->id.']['.$idw.']" value="" cols="2" maxlength="5"';
2108 $tableCell .= ' onkeypress="return regexEvent(this,event,\'timeChar\')"';
2109 $tableCell .= ' onkeyup="updateTotal('.$idw.',\''.$modeinput.'\')"';
2110 $tableCell .= ' onblur="regexEvent(this,event,\''.$modeinput.'\'); updateTotal('.$idw.',\''.$modeinput.'\')" />';
2111 $tableCell .= '</td>';
2112 print $tableCell;
2113 }
2114
2115 // Warning
2116 print '<td class="right">';
2117 if ((!$lines[$i]->public) && $disabledproject) {
2118 print $form->textwithpicto('', $langs->trans("UserIsNotContactOfProject"));
2119 } elseif ($disabledtask) {
2120 $titleassigntask = $langs->trans("AssignTaskToMe");
2121 if ($fuser->id != $user->id) {
2122 $titleassigntask = $langs->trans("AssignTaskToUser", '...');
2123 }
2124
2125 print $form->textwithpicto('', $langs->trans("TaskIsNotAssignedToUser", $titleassigntask));
2126 }
2127 print '</td>';
2128
2129 print "</tr>\n";
2130 }
2131
2132 // Call to show task with a lower level (task under the current task)
2133 $inc++;
2134 $level++;
2135 if ($lines[$i]->id > 0) {
2136 //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level);
2137 //var_dump($totalforeachday);
2138 $ret = projectLinesPerWeek($inc, $firstdaytoshow, $fuser, $lines[$i]->id, ($parent == 0 ? $lineswithoutlevel0 : $lines), $level, $projectsrole, $tasksrole, $mine, $restricteditformytask, $isavailable, $oldprojectforbreak, $arrayfields, $extrafields);
2139 //var_dump('ret with parent='.$lines[$i]->id.' level='.$level);
2140 //var_dump($ret);
2141 foreach ($ret as $key => $val) {
2142 $totalforeachday[$key] += $val;
2143 }
2144 //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level.' + subtasks');
2145 //var_dump($totalforeachday);
2146 }
2147 $level--;
2148 } else {
2149 //$level--;
2150 }
2151 }
2152
2153 return $totalforeachday;
2154}
2155
2174function projectLinesPerMonth(&$inc, $firstdaytoshow, $fuser, $parent, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, &$isavailable, $oldprojectforbreak = 0, $TWeek = array())
2175{
2176 global $conf, $db, $user, $langs;
2177 global $form, $formother, $projectstatic, $taskstatic, $thirdpartystatic;
2178
2179 $numlines = count($lines);
2180
2181 $lastprojectid = 0;
2182 $workloadforid = array();
2183 $totalforeachweek = array();
2184 $lineswithoutlevel0 = array();
2185
2186 // Create a smaller array with sublevels only to be used later. This increase dramatically performances.
2187 if ($parent == 0) { // Always and only if at first level
2188 for ($i = 0; $i < $numlines; $i++) {
2189 if ($lines[$i]->fk_task_parent) {
2190 $lineswithoutlevel0[] = $lines[$i];
2191 }
2192 }
2193 }
2194
2195 //dol_syslog('projectLinesPerWeek inc='.$inc.' firstdaytoshow='.$firstdaytoshow.' task parent id='.$parent.' level='.$level." count(lines)=".$numlines." count(lineswithoutlevel0)=".count($lineswithoutlevel0));
2196
2197 if (empty($oldprojectforbreak)) {
2198 $oldprojectforbreak = (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT) ? 0 : -1); // 0 = start break, -1 = never break
2199 }
2200
2201 $restrictBefore = null;
2202
2203 if (!empty($conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS)) {
2204 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
2205 $restrictBefore = dol_time_plus_duree(dol_now(), - $conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS, 'm');
2206 }
2207
2208 for ($i = 0; $i < $numlines; $i++) {
2209 if ($parent == 0) {
2210 $level = 0;
2211 }
2212
2213 if ($lines[$i]->fk_task_parent == $parent) {
2214 // If we want all or we have a role on task, we show it
2215 if (empty($mine) || !empty($tasksrole[$lines[$i]->id])) {
2216 //dol_syslog("projectLinesPerWeek Found line ".$i.", a qualified task (i have role or want to show all tasks) with id=".$lines[$i]->id." project id=".$lines[$i]->fk_project);
2217
2218 // Break on a new project
2219 if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid) {
2220 $lastprojectid = $lines[$i]->fk_project;
2221 $projectstatic->id = $lines[$i]->fk_project;
2222 }
2223
2224 //var_dump('--- '.$level.' '.$firstdaytoshow.' '.$fuser->id.' '.$projectstatic->id.' '.$workloadforid[$projectstatic->id]);
2225 //var_dump($projectstatic->weekWorkLoadPerTask);
2226 if (empty($workloadforid[$projectstatic->id])) {
2227 $projectstatic->loadTimeSpentMonth($firstdaytoshow, 0, $fuser->id); // Load time spent from table element_time for the project into this->weekWorkLoad and this->weekWorkLoadPerTask for all days of a week
2228 $workloadforid[$projectstatic->id] = 1;
2229 }
2230 //var_dump($projectstatic->weekWorkLoadPerTask);
2231 //var_dump('--- '.$projectstatic->id.' '.$workloadforid[$projectstatic->id]);
2232
2233 $projectstatic->id = $lines[$i]->fk_project;
2234 $projectstatic->ref = $lines[$i]->projectref;
2235 $projectstatic->title = $lines[$i]->projectlabel;
2236 $projectstatic->public = $lines[$i]->public;
2237 $projectstatic->thirdparty_name = $lines[$i]->thirdparty_name;
2238 $projectstatic->status = $lines[$i]->projectstatus;
2239
2240 $taskstatic->id = $lines[$i]->id;
2241 $taskstatic->ref = ($lines[$i]->ref ? $lines[$i]->ref : $lines[$i]->id);
2242 $taskstatic->label = $lines[$i]->label;
2243 $taskstatic->date_start = $lines[$i]->date_start;
2244 $taskstatic->date_end = $lines[$i]->date_end;
2245
2246 $thirdpartystatic->id = $lines[$i]->thirdparty_id;
2247 $thirdpartystatic->name = $lines[$i]->thirdparty_name;
2248 $thirdpartystatic->email = $lines[$i]->thirdparty_email;
2249
2250 if (empty($oldprojectforbreak) || ($oldprojectforbreak != -1 && $oldprojectforbreak != $projectstatic->id)) {
2251 print '<tr class="oddeven trforbreak nobold">'."\n";
2252 print '<td colspan="'.(6 + count($TWeek)).'">';
2253 print $projectstatic->getNomUrl(1, '', 0, '<strong>'.$langs->transnoentitiesnoconv("YourRole").':</strong> '.$projectsrole[$lines[$i]->fk_project]);
2254 if ($thirdpartystatic->id > 0) {
2255 print ' - '.$thirdpartystatic->getNomUrl(1);
2256 }
2257 if ($projectstatic->title) {
2258 print ' - ';
2259 print '<span class="secondary">'.$projectstatic->title.'</span>';
2260 }
2261 print '</td>';
2262 print '</tr>';
2263 }
2264
2265 if ($oldprojectforbreak != -1) {
2266 $oldprojectforbreak = $projectstatic->id;
2267 }
2268 print '<tr class="oddeven" data-taskid="'.$lines[$i]->id.'">'."\n";
2269
2270 // User
2271 /*
2272 print '<td class="nowrap">';
2273 print $fuser->getNomUrl(1, 'withproject', 'time');
2274 print '</td>';
2275 */
2276
2277 // Project
2278 /*print '<td class="nowrap">';
2279 if ($oldprojectforbreak == -1) print $projectstatic->getNomUrl(1,'',0,$langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]);
2280 print "</td>";*/
2281
2282 // Thirdparty
2283 /*print '<td class="tdoverflowmax100">';
2284 if ($thirdpartystatic->id > 0) print $thirdpartystatic->getNomUrl(1, 'project');
2285 print '</td>';*/
2286
2287 // Ref
2288 print '<td class="nowrap">';
2289 print '<!-- Task id = '.$lines[$i]->id.' -->';
2290 for ($k = 0; $k < $level; $k++) {
2291 print '<div class="marginleftonly">';
2292 }
2293 print $taskstatic->getNomUrl(1, 'withproject', 'time');
2294 // Label task
2295 print '<br>';
2296 print '<span class="opacitymedium">'.$taskstatic->label.'</span>';
2297 for ($k = 0; $k < $level; $k++) {
2298 print "</div>";
2299 }
2300 print "</td>\n";
2301
2302 // Planned Workload
2303 print '<td class="leftborder plannedworkload right">';
2304 if ($lines[$i]->planned_workload) {
2305 print convertSecondToTime($lines[$i]->planned_workload, 'allhourmin');
2306 } else {
2307 print '--:--';
2308 }
2309 print '</td>';
2310
2311 // Progress declared %
2312 print '<td class="right">';
2313 print $formother->select_percent($lines[$i]->progress, $lines[$i]->id.'progress');
2314 print '</td>';
2315
2316 // Time spent by everybody
2317 print '<td class="right">';
2318 // $lines[$i]->duration_effective is a denormalised field = summ of time spent by everybody for task. What we need is time consumed by user
2319 if ($lines[$i]->duration_effective) {
2320 print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$lines[$i]->id.'">';
2321 print convertSecondToTime($lines[$i]->duration_effective, 'allhourmin');
2322 print '</a>';
2323 } else {
2324 print '--:--';
2325 }
2326 print "</td>\n";
2327
2328 // Time spent by user
2329 print '<td class="right">';
2330 $tmptimespent = $taskstatic->getSummaryOfTimeSpent($fuser->id);
2331 if ($tmptimespent['total_duration']) {
2332 print convertSecondToTime($tmptimespent['total_duration'], 'allhourmin');
2333 } else {
2334 print '--:--';
2335 }
2336 print "</td>\n";
2337
2338 $disabledproject = 1;
2339 $disabledtask = 1;
2340 //print "x".$lines[$i]->fk_project;
2341 //var_dump($lines[$i]);
2342 //var_dump($projectsrole[$lines[$i]->fk_project]);
2343 // If at least one role for project
2344 if ($lines[$i]->public || !empty($projectsrole[$lines[$i]->fk_project]) || $user->rights->projet->all->creer) {
2345 $disabledproject = 0;
2346 $disabledtask = 0;
2347 }
2348 // If $restricteditformytask is on and I have no role on task, i disable edit
2349 if ($restricteditformytask && empty($tasksrole[$lines[$i]->id])) {
2350 $disabledtask = 1;
2351 }
2352
2353 //var_dump($projectstatic->weekWorkLoadPerTask);
2354 //TODO
2355 // Fields to show current time
2356 $tableCell = '';
2357 $modeinput = 'hours';
2358 $TFirstDay = getFirstDayOfEachWeek($TWeek, date('Y', $firstdaytoshow));
2359 $TFirstDay[reset($TWeek)] = 1;
2360
2361 $firstdaytoshowarray = dol_getdate($firstdaytoshow);
2362 $year = $firstdaytoshowarray['year'];
2363 $month = $firstdaytoshowarray['mon'];
2364 foreach ($TWeek as $weekIndex => $weekNb) {
2365 $weekWorkLoad = !empty($projectstatic->monthWorkLoadPerTask[$weekNb][$lines[$i]->id]) ? $projectstatic->monthWorkLoadPerTask[$weekNb][$lines[$i]->id] : 0 ;
2366 if (!isset($totalforeachweek[$weekNb])) $totalforeachweek[$weekNb] = 0;
2367 $totalforeachweek[$weekNb] += $weekWorkLoad;
2368
2369 $alreadyspent = '';
2370 if ($weekWorkLoad > 0) {
2371 $alreadyspent = convertSecondToTime($weekWorkLoad, 'allhourmin');
2372 }
2373 $alttitle = $langs->trans("AddHereTimeSpentForWeek", $weekNb);
2374
2375 $disabledtaskweek = $disabledtask;
2376 $firstdayofweek = dol_mktime(0, 0, 0, $month, $TFirstDay[$weekIndex], $year);
2377
2378 if (! $disabledtask && $restrictBefore && $firstdayofweek < $restrictBefore) {
2379 $disabledtaskweek = 1;
2380 }
2381
2382 $tableCell = '<td class="center hide weekend">';
2383 $placeholder = '';
2384 if ($alreadyspent) {
2385 $tableCell .= '<span class="timesheetalreadyrecorded" title="texttoreplace"><input type="text" class="center smallpadd" size="2" disabled id="timespent['.$inc.']['.((int) $weekNb).']" name="task['.$lines[$i]->id.']['.$weekNb.']" value="'.$alreadyspent.'"></span>';
2386 //$placeholder=' placeholder="00:00"';
2387 //$tableCell.='+';
2388 }
2389
2390 $tableCell .= '<input type="text" alt="'.($disabledtaskweek ? '' : $alttitle).'" title="'.($disabledtaskweek ? '' : $alttitle).'" '.($disabledtaskweek ? 'disabled' : $placeholder).' class="center smallpadd" size="2" id="timeadded['.$inc.']['.((int) $weekNb).']" name="task['.$lines[$i]->id.']['.($TFirstDay[$weekNb] - 1).']" value="" cols="2" maxlength="5"';
2391 $tableCell .= ' onkeypress="return regexEvent(this,event,\'timeChar\')"';
2392 $tableCell .= ' onkeyup="updateTotal('.$weekNb.',\''.$modeinput.'\')"';
2393 $tableCell .= ' onblur="regexEvent(this,event,\''.$modeinput.'\'); updateTotal('.$weekNb.',\''.$modeinput.'\')" />';
2394 $tableCell .= '</td>';
2395 print $tableCell;
2396 }
2397
2398 // Warning
2399 print '<td class="right">';
2400 if ((!$lines[$i]->public) && $disabledproject) {
2401 print $form->textwithpicto('', $langs->trans("UserIsNotContactOfProject"));
2402 } elseif ($disabledtask) {
2403 $titleassigntask = $langs->trans("AssignTaskToMe");
2404 if ($fuser->id != $user->id) {
2405 $titleassigntask = $langs->trans("AssignTaskToUser", '...');
2406 }
2407
2408 print $form->textwithpicto('', $langs->trans("TaskIsNotAssignedToUser", $titleassigntask));
2409 }
2410 print '</td>';
2411
2412 print "</tr>\n";
2413 }
2414
2415 // Call to show task with a lower level (task under the current task)
2416 $inc++;
2417 $level++;
2418 if ($lines[$i]->id > 0) {
2419 //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level);
2420 //var_dump($totalforeachday);
2421 $ret = projectLinesPerMonth($inc, $firstdaytoshow, $fuser, $lines[$i]->id, ($parent == 0 ? $lineswithoutlevel0 : $lines), $level, $projectsrole, $tasksrole, $mine, $restricteditformytask, $isavailable, $oldprojectforbreak, $TWeek);
2422 //var_dump('ret with parent='.$lines[$i]->id.' level='.$level);
2423 //var_dump($ret);
2424 foreach ($ret as $key => $val) {
2425 $totalforeachweek[$key] += $val;
2426 }
2427 //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level.' + subtasks');
2428 //var_dump($totalforeachday);
2429 }
2430 $level--;
2431 } else {
2432 //$level--;
2433 }
2434 }
2435
2436 return $totalforeachweek;
2437}
2438
2439
2449function searchTaskInChild(&$inc, $parent, &$lines, &$taskrole)
2450{
2451 //print 'Search in line with parent id = '.$parent.'<br>';
2452 $numlines = count($lines);
2453 for ($i = 0; $i < $numlines; $i++) {
2454 // Process line $lines[$i]
2455 if ($lines[$i]->fk_task_parent == $parent && $lines[$i]->id != $lines[$i]->fk_task_parent) {
2456 // If task is legitimate to show, no more need to search deeper
2457 if (isset($taskrole[$lines[$i]->id])) {
2458 //print 'Found a legitimate task id='.$lines[$i]->id.'<br>';
2459 $inc++;
2460 return $inc;
2461 }
2462
2463 searchTaskInChild($inc, $lines[$i]->id, $lines, $taskrole);
2464 //print 'Found inc='.$inc.'<br>';
2465
2466 if ($inc > 0) {
2467 return $inc;
2468 }
2469 }
2470 }
2471
2472 return $inc;
2473}
2474
2489function print_projecttasks_array($db, $form, $socid, $projectsListId, $mytasks = 0, $status = -1, $listofoppstatus = array(), $hiddenfields = array(), $max = 0)
2490{
2491 global $langs, $conf, $user;
2492 global $theme_datacolor;
2493
2494 $maxofloop = (empty($conf->global->MAIN_MAXLIST_OVERLOAD) ? 500 : $conf->global->MAIN_MAXLIST_OVERLOAD);
2495
2496 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
2497
2498 $listofstatus = array_keys($listofoppstatus);
2499
2500 if (is_array($listofstatus) && !empty($conf->global->USE_COLOR_FOR_PROSPECTION_STATUS)) {
2501 // Define $themeColorId and array $statusOppList for each $listofstatus
2502 $themeColorId = 0;
2503 $statusOppList = array();
2504 foreach ($listofstatus as $oppStatus) {
2505 $oppStatusCode = dol_getIdFromCode($db, $oppStatus, 'c_lead_status', 'rowid', 'code');
2506 if ($oppStatusCode) {
2507 $statusOppList[$oppStatus]['code'] = $oppStatusCode;
2508 $statusOppList[$oppStatus]['color'] = isset($theme_datacolor[$themeColorId]) ? implode(', ', $theme_datacolor[$themeColorId]) : '';
2509 }
2510 $themeColorId++;
2511 }
2512 }
2513
2514 $projectstatic = new Project($db);
2515 $thirdpartystatic = new Societe($db);
2516
2517 $sortfield = '';
2518 $sortorder = '';
2519 $project_year_filter = 0;
2520
2521 $title = $langs->trans("Projects");
2522 if (strcmp($status, '') && $status >= 0) {
2523 $title = $langs->trans("Projects").' '.$langs->trans($projectstatic->statuts_long[$status]);
2524 }
2525
2526 print '<!-- print_projecttasks_array -->';
2527 print '<div class="div-table-responsive-no-min">';
2528 print '<table class="noborder centpercent">';
2529
2530 $sql = " FROM ".MAIN_DB_PREFIX."projet as p";
2531 if ($mytasks) {
2532 $sql .= ", ".MAIN_DB_PREFIX."projet_task as t";
2533 $sql .= ", ".MAIN_DB_PREFIX."element_contact as ec";
2534 $sql .= ", ".MAIN_DB_PREFIX."c_type_contact as ctc";
2535 } else {
2536 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task as t ON p.rowid = t.fk_projet";
2537 }
2538 $sql .= " WHERE p.entity IN (".getEntity('project').")";
2539 $sql .= " AND p.rowid IN (".$db->sanitize($projectsListId).")";
2540 if ($socid) {
2541 $sql .= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".((int) $socid).")";
2542 }
2543 if ($mytasks) {
2544 $sql .= " AND p.rowid = t.fk_projet";
2545 $sql .= " AND ec.element_id = t.rowid";
2546 $sql .= " AND ec.fk_socpeople = ".((int) $user->id);
2547 $sql .= " AND ec.fk_c_type_contact = ctc.rowid"; // Replace the 2 lines with ec.fk_c_type_contact in $arrayidtypeofcontact
2548 $sql .= " AND ctc.element = 'project_task'";
2549 }
2550 if ($status >= 0) {
2551 $sql .= " AND p.fk_statut = ".(int) $status;
2552 }
2553 if (!empty($conf->global->PROJECT_LIMIT_YEAR_RANGE)) {
2554 $project_year_filter = GETPOST("project_year_filter");
2555 //Check if empty or invalid year. Wildcard ignores the sql check
2556 if ($project_year_filter != "*") {
2557 if (empty($project_year_filter) || !ctype_digit($project_year_filter)) {
2558 $project_year_filter = date("Y");
2559 }
2560 $sql .= " AND (p.dateo IS NULL OR p.dateo <= ".$db->idate(dol_get_last_day($project_year_filter, 12, false)).")";
2561 $sql .= " AND (p.datee IS NULL OR p.datee >= ".$db->idate(dol_get_first_day($project_year_filter, 1, false)).")";
2562 }
2563 }
2564
2565 // Get id of project we must show tasks
2566 $arrayidofprojects = array();
2567 $sql1 = "SELECT p.rowid as projectid";
2568 $sql1 .= $sql;
2569 $resql = $db->query($sql1);
2570 if ($resql) {
2571 $i = 0;
2572 $num = $db->num_rows($resql);
2573 while ($i < $num) {
2574 $objp = $db->fetch_object($resql);
2575 $arrayidofprojects[$objp->projectid] = $objp->projectid;
2576 $i++;
2577 }
2578 } else {
2579 dol_print_error($db);
2580 }
2581 if (empty($arrayidofprojects)) {
2582 $arrayidofprojects[0] = -1;
2583 }
2584
2585 // Get list of project with calculation on tasks
2586 $sql2 = "SELECT p.rowid as projectid, p.ref, p.title, p.fk_soc,";
2587 $sql2 .= " s.rowid as socid, s.nom as socname, s.name_alias,";
2588 $sql2 .= " s.code_client, s.code_compta, s.client,";
2589 $sql2 .= " s.code_fournisseur, s.code_compta_fournisseur, s.fournisseur,";
2590 $sql2 .= " s.logo, s.email, s.entity,";
2591 $sql2 .= " p.fk_user_creat, p.public, p.fk_statut as status, p.fk_opp_status as opp_status, p.opp_percent, p.opp_amount,";
2592 $sql2 .= " p.dateo, p.datee,";
2593 $sql2 .= " COUNT(t.rowid) as nb, SUM(t.planned_workload) as planned_workload, SUM(t.planned_workload * t.progress / 100) as declared_progess_workload";
2594 $sql2 .= " FROM ".MAIN_DB_PREFIX."projet as p";
2595 $sql2 .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = p.fk_soc";
2596 $sql2 .= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task as t ON p.rowid = t.fk_projet";
2597 $sql2 .= " WHERE p.rowid IN (".$db->sanitize(join(',', $arrayidofprojects)).")";
2598 $sql2 .= " GROUP BY p.rowid, p.ref, p.title, p.fk_soc, s.rowid, s.nom, s.name_alias, s.code_client, s.code_compta, s.client, s.code_fournisseur, s.code_compta_fournisseur, s.fournisseur,";
2599 $sql2 .= " s.logo, s.email, s.entity, p.fk_user_creat, p.public, p.fk_statut, p.fk_opp_status, p.opp_percent, p.opp_amount, p.dateo, p.datee";
2600 $sql2 .= " ORDER BY p.title, p.ref";
2601
2602 $resql = $db->query($sql2);
2603 if ($resql) {
2604 $othernb = 0;
2605 $total_task = 0;
2606 $total_opp_amount = 0;
2607 $ponderated_opp_amount = 0;
2608 $total_plannedworkload = 0;
2609 $total_declaredprogressworkload = 0;
2610
2611 $num = $db->num_rows($resql);
2612 $nbofloop = min($num, (empty($conf->global->MAIN_MAXLIST_OVERLOAD) ? 500 : $conf->global->MAIN_MAXLIST_OVERLOAD));
2613 $i = 0;
2614
2615 print '<tr class="liste_titre">';
2616 print_liste_field_titre($title.'<a href="'.DOL_URL_ROOT.'/projet/list.php?search_status='.((int) $status).'"><span class="badge marginleftonlyshort">'.$num.'</span></a>', $_SERVER["PHP_SELF"], "", "", "", "", $sortfield, $sortorder);
2617 print_liste_field_titre("ThirdParty", $_SERVER["PHP_SELF"], "", "", "", "", $sortfield, $sortorder);
2618 if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) {
2619 if (!in_array('prospectionstatus', $hiddenfields)) {
2620 print_liste_field_titre("OpportunityStatus", "", "", "", "", 'style="max-width: 100px"', $sortfield, $sortorder, 'center ');
2621 }
2622 print_liste_field_titre($form->textwithpicto($langs->trans("Amount"), $langs->trans("OpportunityAmount").' ('.$langs->trans("Tooltip").' = '.$langs->trans("OpportunityWeightedAmount").')'), "", "", "", "", 'style="max-width: 100px"', $sortfield, $sortorder, 'right ');
2623 //print_liste_field_titre('OpportunityWeightedAmount', '', '', '', '', 'align="right"', $sortfield, $sortorder);
2624 }
2625 if (empty($conf->global->PROJECT_HIDE_TASKS)) {
2626 print_liste_field_titre("Tasks", "", "", "", "", 'align="right"', $sortfield, $sortorder);
2627 if (!in_array('plannedworkload', $hiddenfields)) {
2628 print_liste_field_titre("PlannedWorkload", "", "", "", "", 'style="max-width: 100px"', $sortfield, $sortorder, 'right ');
2629 }
2630 if (!in_array('declaredprogress', $hiddenfields)) {
2631 print_liste_field_titre("%", "", "", "", "", '', $sortfield, $sortorder, 'right ', $langs->trans("ProgressDeclared"));
2632 }
2633 }
2634 if (!in_array('projectstatus', $hiddenfields)) {
2635 print_liste_field_titre("Status", "", "", "", "", '', $sortfield, $sortorder, 'right ');
2636 }
2637 print "</tr>\n";
2638
2639 while ($i < $nbofloop) {
2640 $objp = $db->fetch_object($resql);
2641
2642 if ($max && $i >= $max) {
2643 $othernb++;
2644 $i++;
2645 $total_task += $objp->nb;
2646 $total_opp_amount += $objp->opp_amount;
2647 $opp_weighted_amount = $objp->opp_percent * $objp->opp_amount / 100;
2648 $ponderated_opp_amount += price2num($opp_weighted_amount);
2649 $plannedworkload = $objp->planned_workload;
2650 $total_plannedworkload += $plannedworkload;
2651 $declaredprogressworkload = $objp->declared_progess_workload;
2652 $total_declaredprogressworkload += $declaredprogressworkload;
2653 continue;
2654 }
2655
2656 $projectstatic->id = $objp->projectid;
2657 $projectstatic->user_author_id = $objp->fk_user_creat;
2658 $projectstatic->public = $objp->public;
2659
2660 // Check is user has read permission on project
2661 $userAccess = $projectstatic->restrictedProjectArea($user);
2662 if ($userAccess >= 0) {
2663 $projectstatic->ref = $objp->ref;
2664 $projectstatic->status = $objp->status;
2665 $projectstatic->title = $objp->title;
2666 $projectstatic->date_end = $db->jdate($objp->datee);
2667 $projectstatic->date_start = $db->jdate($objp->dateo);
2668
2669 print '<tr class="oddeven">';
2670
2671 print '<td class="tdoverflowmax150">';
2672 print $projectstatic->getNomUrl(1, '', 0, '', '-', 0, -1, 'nowraponall');
2673 if (!in_array('projectlabel', $hiddenfields)) {
2674 print '<br><span class="opacitymedium small">'.dol_escape_htmltag($objp->title).'</span>';
2675 }
2676 print '</td>';
2677
2678 print '<td class="nowraponall tdoverflowmax100">';
2679 if ($objp->fk_soc > 0) {
2680 $thirdpartystatic->id = $objp->socid;
2681 $thirdpartystatic->name = $objp->socname;
2682 //$thirdpartystatic->name_alias = $objp->name_alias;
2683 //$thirdpartystatic->code_client = $objp->code_client;
2684 $thirdpartystatic->code_compta = $objp->code_compta;
2685 $thirdpartystatic->client = $objp->client;
2686 //$thirdpartystatic->code_fournisseur = $objp->code_fournisseur;
2687 $thirdpartystatic->code_compta_fournisseur = $objp->code_compta_fournisseur;
2688 $thirdpartystatic->fournisseur = $objp->fournisseur;
2689 $thirdpartystatic->logo = $objp->logo;
2690 $thirdpartystatic->email = $objp->email;
2691 $thirdpartystatic->entity = $objp->entity;
2692 print $thirdpartystatic->getNomUrl(1);
2693 }
2694 print '</td>';
2695
2696 if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) {
2697 if (!in_array('prospectionstatus', $hiddenfields)) {
2698 print '<td class="center tdoverflowmax75">';
2699 // Because color of prospection status has no meaning yet, it is used if hidden constant is set
2700 if (empty($conf->global->USE_COLOR_FOR_PROSPECTION_STATUS)) {
2701 $oppStatusCode = dol_getIdFromCode($db, $objp->opp_status, 'c_lead_status', 'rowid', 'code');
2702 if ($langs->trans("OppStatus".$oppStatusCode) != "OppStatus".$oppStatusCode) {
2703 print $langs->trans("OppStatus".$oppStatusCode);
2704 }
2705 } else {
2706 if (isset($statusOppList[$objp->opp_status])) {
2707 $oppStatusCode = $statusOppList[$objp->opp_status]['code'];
2708 $oppStatusColor = $statusOppList[$objp->opp_status]['color'];
2709 } else {
2710 $oppStatusCode = dol_getIdFromCode($db, $objp->opp_status, 'c_lead_status', 'rowid', 'code');
2711 $oppStatusColor = '';
2712 }
2713 if ($oppStatusCode) {
2714 if (!empty($oppStatusColor)) {
2715 print '<a href="'.dol_buildpath('/projet/list.php?search_opp_status='.$objp->opp_status, 1).'" style="display: inline-block; width: 4px; border: 5px solid rgb('.$oppStatusColor.'); border-radius: 2px;" title="'.$langs->trans("OppStatus".$oppStatusCode).'"></a>';
2716 } else {
2717 print '<a href="'.dol_buildpath('/projet/list.php?search_opp_status='.$objp->opp_status, 1).'" title="'.$langs->trans("OppStatus".$oppStatusCode).'">'.$oppStatusCode.'</a>';
2718 }
2719 }
2720 }
2721 print '</td>';
2722 }
2723
2724 print '<td class="right">';
2725 if ($objp->opp_percent && $objp->opp_amount) {
2726 $opp_weighted_amount = $objp->opp_percent * $objp->opp_amount / 100;
2727 $alttext = $langs->trans("OpportunityWeightedAmount").' '.price($opp_weighted_amount, 0, '', 1, -1, 0, $conf->currency);
2728 $ponderated_opp_amount += price2num($opp_weighted_amount);
2729 }
2730 if ($objp->opp_amount) {
2731 print '<span class="amount" title="'.$alttext.'">'.$form->textwithpicto(price($objp->opp_amount, 0, '', 1, -1, 0), $alttext).'</span>';
2732 }
2733 print '</td>';
2734 }
2735
2736 if (empty($conf->global->PROJECT_HIDE_TASKS)) {
2737 print '<td class="right">'.$objp->nb.'</td>';
2738
2739 $plannedworkload = $objp->planned_workload;
2740 $total_plannedworkload += $plannedworkload;
2741 if (!in_array('plannedworkload', $hiddenfields)) {
2742 print '<td class="right nowraponall">'.($plannedworkload ?convertSecondToTime($plannedworkload) : '').'</td>';
2743 }
2744 if (!in_array('declaredprogress', $hiddenfields)) {
2745 $declaredprogressworkload = $objp->declared_progess_workload;
2746 $total_declaredprogressworkload += $declaredprogressworkload;
2747 print '<td class="right nowraponall">';
2748 //print $objp->planned_workload.'-'.$objp->declared_progess_workload."<br>";
2749 print ($plannedworkload ?round(100 * $declaredprogressworkload / $plannedworkload, 0).'%' : '');
2750 print '</td>';
2751 }
2752 }
2753
2754 if (!in_array('projectstatus', $hiddenfields)) {
2755 print '<td class="right">';
2756 print $projectstatic->getLibStatut(3);
2757 print '</td>';
2758 }
2759
2760 print "</tr>\n";
2761
2762 $total_task += $objp->nb;
2763 $total_opp_amount += $objp->opp_amount;
2764 }
2765
2766 $i++;
2767 }
2768
2769 if ($othernb) {
2770 print '<tr class="oddeven">';
2771 print '<td class="nowrap" colspan="5">';
2772 print '<span class="opacitymedium">'.$langs->trans("More").'...'.($othernb < $maxofloop ? ' ('.$othernb.')' : '').'</span>';
2773 print '</td>';
2774 print "</tr>\n";
2775 }
2776
2777 print '<tr class="liste_total">';
2778 print '<td>'.$langs->trans("Total")."</td><td></td>";
2779 if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) {
2780 if (!in_array('prospectionstatus', $hiddenfields)) {
2781 print '<td class="liste_total"></td>';
2782 }
2783 print '<td class="liste_total right">';
2784 //$form->textwithpicto(price($ponderated_opp_amount, 0, '', 1, -1, -1, $conf->currency), $langs->trans("OpportunityPonderatedAmountDesc"), 1);
2785 print $form->textwithpicto(price($total_opp_amount, 0, '', 1, -1, 0), $langs->trans("OpportunityPonderatedAmountDesc").' : '.price($ponderated_opp_amount, 0, '', 1, -1, 0, $conf->currency));
2786 print '</td>';
2787 }
2788 if (empty($conf->global->PROJECT_HIDE_TASKS)) {
2789 print '<td class="liste_total right">'.$total_task.'</td>';
2790 if (!in_array('plannedworkload', $hiddenfields)) {
2791 print '<td class="liste_total right">'.($total_plannedworkload ?convertSecondToTime($total_plannedworkload) : '').'</td>';
2792 }
2793 if (!in_array('declaredprogress', $hiddenfields)) {
2794 print '<td class="liste_total right">'.($total_plannedworkload ?round(100 * $total_declaredprogressworkload / $total_plannedworkload, 0).'%' : '').'</td>';
2795 }
2796 }
2797 if (!in_array('projectstatus', $hiddenfields)) {
2798 print '<td class="liste_total"></td>';
2799 }
2800 print '</tr>';
2801
2802 $db->free($resql);
2803 } else {
2804 dol_print_error($db);
2805 }
2806
2807 print "</table>";
2808 print '</div>';
2809
2810 if (!empty($conf->global->PROJECT_LIMIT_YEAR_RANGE)) {
2811 //Add the year filter input
2812 print '<form method="get" action="'.$_SERVER["PHP_SELF"].'">';
2813 print '<table width="100%">';
2814 print '<tr>';
2815 print '<td>'.$langs->trans("Year").'</td>';
2816 print '<td class="right"><input type="text" size="4" class="flat" name="project_year_filter" value="'.$project_year_filter.'"/>';
2817 print "</tr>\n";
2818 print '</table></form>';
2819 }
2820}
2821
2831function getTaskProgressView($task, $label = true, $progressNumber = true, $hideOnProgressNull = false, $spaced = false)
2832{
2833 global $langs, $conf;
2834
2835 $out = '';
2836
2837 $plannedworkloadoutputformat = 'allhourmin';
2838 $timespentoutputformat = 'allhourmin';
2839 if (!empty($conf->global->PROJECT_PLANNED_WORKLOAD_FORMAT)) {
2840 $plannedworkloadoutputformat = $conf->global->PROJECT_PLANNED_WORKLOAD_FORMAT;
2841 }
2842 if (!empty($conf->global->PROJECT_TIMES_SPENT_FORMAT)) {
2843 $timespentoutputformat = $conf->global->PROJECT_TIME_SPENT_FORMAT;
2844 }
2845
2846 if (empty($task->progress) && !empty($hideOnProgressNull)) {
2847 return '';
2848 }
2849
2850 $spaced = !empty($spaced) ? 'spaced' : '';
2851
2852 $diff = '';
2853
2854 // define progress color according to time spend vs workload
2855 $progressBarClass = 'progress-bar-info';
2856 $progressCalculated = 0;
2857 if ($task->planned_workload) {
2858 $progressCalculated = round(100 * floatval($task->duration_effective) / floatval($task->planned_workload), 2);
2859
2860 // this conf is actually hidden, by default we use 10% for "be carefull or warning"
2861 $warningRatio = !empty($conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT) ? (1 + $conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT / 100) : 1.10;
2862
2863 $diffTitle = '<br>'.$langs->trans('ProgressDeclared').' : '.$task->progress.(isset($task->progress) ? '%' : '');
2864 $diffTitle .= '<br>'.$langs->trans('ProgressCalculated').' : '.$progressCalculated.(isset($progressCalculated) ? '%' : '');
2865
2866 //var_dump($progressCalculated.' '.$warningRatio.' '.$task->progress.' '.floatval($task->progress * $warningRatio));
2867 if (floatval($progressCalculated) > floatval($task->progress * $warningRatio)) {
2868 $progressBarClass = 'progress-bar-danger';
2869 $title = $langs->trans('TheReportedProgressIsLessThanTheCalculatedProgressionByX', abs($task->progress - $progressCalculated).' '.$langs->trans("point"));
2870 $diff = '<span class="text-danger classfortooltip paddingrightonly" title="'.dol_htmlentities($title.$diffTitle).'" ><i class="fa fa-caret-down"></i> '.($task->progress - $progressCalculated).'%</span>';
2871 } elseif (floatval($progressCalculated) > floatval($task->progress)) { // warning if close at 10%
2872 $progressBarClass = 'progress-bar-warning';
2873 $title = $langs->trans('TheReportedProgressIsLessThanTheCalculatedProgressionByX', abs($task->progress - $progressCalculated).' '.$langs->trans("point"));
2874 $diff = '<span class="text-warning classfortooltip paddingrightonly" title="'.dol_htmlentities($title.$diffTitle).'" ><i class="fa fa-caret-left"></i> '.($task->progress - $progressCalculated).'%</span>';
2875 } else {
2876 $progressBarClass = 'progress-bar-success';
2877 $title = $langs->trans('TheReportedProgressIsMoreThanTheCalculatedProgressionByX', ($task->progress - $progressCalculated).' '.$langs->trans("point"));
2878 $diff = '<span class="text-success classfortooltip paddingrightonly" title="'.dol_htmlentities($title.$diffTitle).'" ><i class="fa fa-caret-up"></i> '.($task->progress - $progressCalculated).'%</span>';
2879 }
2880 }
2881
2882 $out .= '<div class="progress-group">';
2883
2884 if ($label !== false) {
2885 $out .= ' <span class="progress-text">';
2886
2887 if ($label !== true) {
2888 $out .= $label; // replace label by param
2889 } else {
2890 $out .= $task->getNomUrl(1).' '.dol_htmlentities($task->label);
2891 }
2892 $out .= ' </span>';
2893 }
2894
2895
2896 if ($progressNumber !== false) {
2897 $out .= ' <span class="progress-number">';
2898 if ($progressNumber !== true) {
2899 $out .= $progressNumber; // replace label by param
2900 } else {
2901 if ($task->hasDelay()) {
2902 $out .= img_warning($langs->trans("Late")).' ';
2903 }
2904
2905 $url = DOL_URL_ROOT.'/projet/tasks/time.php?id='.$task->id;
2906
2907 $out .= !empty($diff) ? $diff.' ' : '';
2908 $out .= '<a href="'.$url.'" >';
2909 $out .= '<b title="'.$langs->trans('TimeSpent').'" >';
2910 if ($task->duration_effective) {
2911 $out .= convertSecondToTime($task->duration_effective, $timespentoutputformat);
2912 } else {
2913 $out .= '--:--';
2914 }
2915 $out .= '</b>';
2916 $out .= '</a>';
2917
2918 $out .= ' / ';
2919
2920 $out .= '<a href="'.$url.'" >';
2921 $out .= '<span title="'.$langs->trans('PlannedWorkload').'" >';
2922 if ($task->planned_workload) {
2923 $out .= convertSecondToTime($task->planned_workload, $plannedworkloadoutputformat);
2924 } else {
2925 $out .= '--:--';
2926 }
2927 $out .= '</a>';
2928 }
2929 $out .= ' </span>';
2930 }
2931
2932
2933 $out .= '</span>';
2934 $out .= ' <div class="progress sm '.$spaced.'">';
2935 $diffval = floatval($task->progress) - floatval($progressCalculated);
2936 if ($diffval >= 0) {
2937 // good
2938 $out .= ' <div class="progress-bar '.$progressBarClass.'" style="width: '.floatval($task->progress).'%" title="'.floatval($task->progress).'%">';
2939 if (!empty($task->progress)) {
2940 $out .= ' <div class="progress-bar progress-bar-consumed" style="width: '.floatval($progressCalculated / (floatval($task->progress) == 0 ? 1 : $task->progress) * 100).'%" title="'.floatval($progressCalculated).'%"></div>';
2941 }
2942 $out .= ' </div>';
2943 } else {
2944 // bad
2945 $out .= ' <div class="progress-bar progress-bar-consumed-late" style="width: '.floatval($progressCalculated).'%" title="'.floatval($progressCalculated).'%">';
2946 $out .= ' <div class="progress-bar '.$progressBarClass.'" style="width: '.($task->progress ? floatval($task->progress / (floatval($progressCalculated) == 0 ? 1 : $progressCalculated) * 100).'%' : '1px').'" title="'.floatval($task->progress).'%"></div>';
2947 $out .= ' </div>';
2948 }
2949 $out .= ' </div>';
2950 $out .= '</div>';
2951
2952
2953
2954 return $out;
2955}
2963function getTaskProgressBadge($task, $label = '', $tooltip = '')
2964{
2965 global $conf, $langs;
2966
2967 $out = '';
2968 $badgeClass = '';
2969 if ($task->progress != '') {
2970 // TODO : manage 100%
2971
2972 // define color according to time spend vs workload
2973 $badgeClass = 'badge ';
2974 if ($task->planned_workload) {
2975 $progressCalculated = round(100 * floatval($task->duration_effective) / floatval($task->planned_workload), 2);
2976
2977 // this conf is actually hidden, by default we use 10% for "be carefull or warning"
2978 $warningRatio = !empty($conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT) ? (1 + $conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT / 100) : 1.10;
2979
2980 if (floatval($progressCalculated) > floatval($task->progress * $warningRatio)) {
2981 $badgeClass .= 'badge-danger';
2982 if (empty($tooltip)) {
2983 $tooltip = $task->progress.'% < '.$langs->trans("TimeConsumed").' '.$progressCalculated.'%';
2984 }
2985 } elseif (floatval($progressCalculated) > floatval($task->progress)) { // warning if close at 10%
2986 $badgeClass .= 'badge-warning';
2987 if (empty($tooltip)) {
2988 $tooltip = $task->progress.'% < '.$langs->trans("TimeConsumed").' '.$progressCalculated.'%';
2989 }
2990 } else {
2991 $badgeClass .= 'badge-success';
2992 if (empty($tooltip)) {
2993 $tooltip = $task->progress.'% >= '.$langs->trans("TimeConsumed").' '.$progressCalculated.'%';
2994 }
2995 }
2996 }
2997 }
2998
2999 $title = '';
3000 if (!empty($tooltip)) {
3001 $badgeClass .= ' classfortooltip';
3002 $title = 'title="'.dol_htmlentities($tooltip).'"';
3003 }
3004
3005 if (empty($label)) {
3006 $label = $task->progress.' %';
3007 }
3008
3009 if (!empty($label)) {
3010 $out = '<span class="'.$badgeClass.'" '.$title.' >'.$label.'</span>';
3011 }
3012
3013 return $out;
3014}
$object ref
Definition info.php:78
Class for ConferenceOrBoothAttendee.
Class for ConferenceOrBooth.
Class to manage contact/addresses.
Class to manage standard extra fields.
Class to manage projects.
Class to manage tasks.
Class to manage Dolibarr users.
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition date.lib.php:123
convertSecondToTime($iSecond, $format='all', $lengthOfDay=86400, $lengthOfWeek=7)
Return, in clear text, value of a number of seconds in days, hours and minutes.
Definition date.lib.php:241
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition files.lib.php:62
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='')
Return an id or code from a code or id.
print_liste_field_titre($name, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
dol_htmlentities($string, $flags=ENT_QUOTES|ENT_SUBSTITUTE, $encoding='UTF-8', $double_encode=false)
Replace htmlentities functions.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
complete_head_from_modules($conf, $langs, $object, &$head, &$h, $type, $mode='add', $filterorigmodule='')
Complete or removed entries into a head array (used to build tabs).
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
publicphonebutton2 phonegreen basiclayout basiclayout TotalHT VATCode TotalVAT TotalLT1 TotalLT2 TotalTTC TotalHT clearboth nowraponall right right takeposterminal SELECT e rowid
Definition invoice.php:1632
if(!defined( 'CSRFCHECK_WITH_TOKEN'))
dol_setcache($memoryid, $data, $expire=0)
Save data into a memory area shared by all users, all sessions on server.
dol_getcache($memoryid)
Read a memory area shared by all users, all sessions on server.
Class to generate the form for creating a new ticket.
projectLinesPerDay(&$inc, $parent, $fuser, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, $preselectedday, &$isavailable, $oldprojectforbreak=0, $arrayfields=array(), $extrafields=null)
Output a task line into a pertime intput mode.
task_prepare_head($object)
Prepare array with list of tabs.
searchTaskInChild(&$inc, $parent, &$lines, &$taskrole)
Search in task lines with a particular parent if there is a task for a particular user (in taskrole)
getTaskProgressView($task, $label=true, $progressNumber=true, $hideOnProgressNull=false, $spaced=false)
projectLinesPerAction(&$inc, $parent, $fuser, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, $preselectedday, &$isavailable, $oldprojectforbreak=0)
Output a task line into a pertime intput mode.
project_timesheet_prepare_head($mode, $fuser=null)
Prepare array with list of tabs.
project_admin_prepare_head()
Prepare array with list of tabs.
getTaskProgressBadge($task, $label='', $tooltip='')
projectLinesPerWeek(&$inc, $firstdaytoshow, $fuser, $parent, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, &$isavailable, $oldprojectforbreak=0, $arrayfields=array(), $extrafields=null)
Output a task line into a perday intput mode.
projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$taskrole, $projectsListId='', $addordertick=0, $projectidfortotallink=0, $dummy='', $showbilltime=0, $arrayfields=array(), $arrayofselected=array())
Show task lines with a particular parent.
project_prepare_head(Project $project, $moreparam='')
Prepare array with list of tabs.