dolibarr 19.0.3
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 (!getDolGlobalString('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 = $Tickettatic->getCountOfItemsLinkedByObjectID($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;
234 $nbAttendees = 0;
235 require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php';
236 $cachekey = 'count_conferenceorbooth_'.$project->id;
237 $dataretrieved = dol_getcache($cachekey);
238 if (!is_null($dataretrieved)) {
239 $nbConfOrBooth = $dataretrieved;
240 } else {
241 require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorbooth.class.php';
242 $conforbooth=new ConferenceOrBooth($db);
243 $result = $conforbooth->fetchAll('', '', 0, 0, array('t.fk_project'=>$project->id));
244 //,
245 if (!is_array($result) && $result<0) {
246 setEventMessages($conforbooth->error, $conforbooth->errors, 'errors');
247 } else {
248 $nbConfOrBooth = count($result);
249 }
250 dol_setcache($cachekey, $nbConfOrBooth, 120); // If setting cache fails, this is not a problem, so we do not test result.
251 }
252 $cachekey = 'count_attendees_'.$project->id;
253 $dataretrieved = dol_getcache($cachekey);
254 if (!is_null($dataretrieved)) {
255 $nbAttendees = $dataretrieved;
256 } else {
257 require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorboothattendee.class.php';
258 $conforboothattendee=new ConferenceOrBoothAttendee($db);
259 $result = $conforboothattendee->fetchAll('', '', 0, 0, array('t.fk_project'=>$project->id));
260 //,
261 if (!is_array($result) && $result<0) {
262 setEventMessages($conforboothattendee->error, $conforboothattendee->errors, 'errors');
263 } else {
264 $nbAttendees = count($result);
265 }
266 dol_setcache($cachekey, $nbAttendees, 120); // If setting cache fails, this is not a problem, so we do not test result.
267 }
268 if ($nbConfOrBooth > 0 || $nbAttendees > 0) {
269 $head[$h][1] .= '<span class="badge marginleftonlyshort">';
270 $head[$h][1] .= '<span title="'.dol_escape_htmltag($langs->trans("ConferenceOrBooth")).'">'.$nbConfOrBooth.'</span>';
271 $head[$h][1] .= ' + ';
272 $head[$h][1] .= '<span title="'.dol_escape_htmltag($langs->trans("Attendees")).'">'.$nbAttendees.'</span>';
273 $head[$h][1] .= '</span>';
274 }
275 $head[$h][2] = 'eventorganisation';
276 $h++;
277 }
278
279 // Show more tabs from modules
280 // Entries must be declared in modules descriptor with line
281 // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
282 // $this->tabs = array('entity:-tabname); to remove a tab
283 complete_head_from_modules($conf, $langs, $project, $head, $h, 'project', 'add', 'core');
284
285
286 if (!getDolGlobalString('MAIN_DISABLE_NOTES_TAB')) {
287 $nbNote = 0;
288 if (!empty($project->note_private)) {
289 $nbNote++;
290 }
291 if (!empty($project->note_public)) {
292 $nbNote++;
293 }
294 $head[$h][0] = DOL_URL_ROOT.'/projet/note.php?id='.$project->id;
295 $head[$h][1] = $langs->trans('Notes');
296 if ($nbNote > 0) {
297 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbNote.'</span>';
298 }
299 $head[$h][2] = 'notes';
300 $h++;
301 }
302
303 // Attached files and Links
304 $totalAttached = 0;
305 // Enable caching of thirdrparty count attached files and links
306 require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php';
307 $cachekey = 'count_attached_project_'.$project->id;
308 $dataretrieved = dol_getcache($cachekey);
309 if (!is_null($dataretrieved)) {
310 $totalAttached = $dataretrieved;
311 } else {
312 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
313 require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
314 $upload_dir = $conf->project->multidir_output[empty($project->entity) ? 1 : $project->entity]."/".dol_sanitizeFileName($project->ref);
315 $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$'));
316 $nbLinks = Link::count($db, $project->element, $project->id);
317 $totalAttached = $nbFiles + $nbLinks;
318 dol_setcache($cachekey, $totalAttached, 120); // If setting cache fails, this is not a problem, so we do not test result.
319 }
320 $head[$h][0] = DOL_URL_ROOT.'/projet/document.php?id='.$project->id;
321 $head[$h][1] = $langs->trans('Documents');
322 if (($totalAttached) > 0) {
323 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($totalAttached).'</span>';
324 }
325 $head[$h][2] = 'document';
326 $h++;
327
328 // Manage discussion
329 if (getDolGlobalString('PROJECT_ALLOW_COMMENT_ON_PROJECT')) {
330 $nbComments = 0;
331 // Enable caching of thirdrparty count attached files and links
332 require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php';
333 $cachekey = 'count_attached_project_'.$project->id;
334 $dataretrieved = dol_getcache($cachekey);
335 if (!is_null($dataretrieved)) {
336 $nbComments = $dataretrieved;
337 } else {
338 $nbComments = $project->getNbComments();
339 dol_setcache($cachekey, $nbComments, 120); // If setting cache fails, this is not a problem, so we do not test result.
340 }
341 $head[$h][0] = DOL_URL_ROOT.'/projet/comment.php?id='.$project->id;
342 $head[$h][1] = $langs->trans("CommentLink");
343 if ($nbComments > 0) {
344 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbComments.'</span>';
345 }
346 $head[$h][2] = 'project_comment';
347 $h++;
348 }
349
350 $head[$h][0] = DOL_URL_ROOT.'/projet/messaging.php?id='.$project->id;
351 $head[$h][1] = $langs->trans("Events");
352 if (isModEnabled('agenda') && ($user->hasRight('agenda', 'myactions', 'read') || $user->hasRight('agenda', 'allactions', 'read'))) {
353 $head[$h][1] .= '/';
354 $head[$h][1] .= $langs->trans("Agenda");
355 }
356 $head[$h][2] = 'agenda';
357 $h++;
358
359 complete_head_from_modules($conf, $langs, $project, $head, $h, 'project', 'add', 'external');
360
361 complete_head_from_modules($conf, $langs, $project, $head, $h, 'project', 'remove');
362
363 return $head;
364}
365
366
373function task_prepare_head($object)
374{
375 global $db, $langs, $conf, $user;
376 $h = 0;
377 $head = array();
378
379 $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/task.php?id='.$object->id.(GETPOST('withproject') ? '&withproject=1' : '');
380 $head[$h][1] = $langs->trans("Task");
381 $head[$h][2] = 'task_task';
382 $h++;
383
384 $nbContact = count($object->liste_contact(-1, 'internal')) + count($object->liste_contact(-1, 'external'));
385 $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/contact.php?id='.$object->id.(GETPOST('withproject') ? '&withproject=1' : '');
386 $head[$h][1] = $langs->trans("TaskRessourceLinks");
387 if ($nbContact > 0) {
388 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbContact.'</span>';
389 }
390 $head[$h][2] = 'task_contact';
391 $h++;
392
393 // Is there timespent ?
394 $nbTimeSpent = 0;
395 $sql = "SELECT t.rowid";
396 //$sql .= " FROM ".MAIN_DB_PREFIX."element_time as t, ".MAIN_DB_PREFIX."projet_task as pt, ".MAIN_DB_PREFIX."user as u";
397 //$sql .= " WHERE t.fk_user = u.rowid AND t.fk_task = pt.rowid";
398 $sql .= " FROM ".MAIN_DB_PREFIX."element_time as t";
399 $sql .= " WHERE t.elementtype='task' AND t.fk_element = ".((int) $object->id);
400 $resql = $db->query($sql);
401 if ($resql) {
402 $obj = $db->fetch_object($resql);
403 if ($obj) {
404 $nbTimeSpent = 1;
405 }
406 } else {
407 dol_print_error($db);
408 }
409
410 $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/time.php?id='.urlencode($object->id).(GETPOST('withproject') ? '&withproject=1' : '');
411 $head[$h][1] = $langs->trans("TimeSpent");
412 if ($nbTimeSpent > 0) {
413 $head[$h][1] .= '<span class="badge marginleftonlyshort">...</span>';
414 }
415 $head[$h][2] = 'task_time';
416 $h++;
417
418 // Show more tabs from modules
419 // Entries must be declared in modules descriptor with line
420 // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
421 // $this->tabs = array('entity:-tabname); to remove a tab
422 complete_head_from_modules($conf, $langs, $object, $head, $h, 'task', 'add', 'core');
423
424 if (!getDolGlobalString('MAIN_DISABLE_NOTES_TAB')) {
425 $nbNote = 0;
426 if (!empty($object->note_private)) {
427 $nbNote++;
428 }
429 if (!empty($object->note_public)) {
430 $nbNote++;
431 }
432 $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/note.php?id='.urlencode($object->id).(GETPOST('withproject') ? '&withproject=1' : '');
433 $head[$h][1] = $langs->trans('Notes');
434 if ($nbNote > 0) {
435 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbNote.'</span>';
436 }
437 $head[$h][2] = 'task_notes';
438 $h++;
439 }
440
441 $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/document.php?id='.$object->id.(GETPOST('withproject') ? '&withproject=1' : '');
442 $filesdir = $conf->project->multidir_output[$object->entity]."/".dol_sanitizeFileName($object->project->ref).'/'.dol_sanitizeFileName($object->ref);
443 include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
444 include_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
445 $nbFiles = count(dol_dir_list($filesdir, 'files', 0, '', '(\.meta|_preview.*\.png)$'));
446 $nbLinks = Link::count($db, $object->element, $object->id);
447 $head[$h][1] = $langs->trans('Documents');
448 if (($nbFiles + $nbLinks) > 0) {
449 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($nbFiles + $nbLinks).'</span>';
450 }
451 $head[$h][2] = 'task_document';
452 $h++;
453
454 // Manage discussion
455 if (getDolGlobalString('PROJECT_ALLOW_COMMENT_ON_TASK')) {
456 $nbComments = $object->getNbComments();
457 $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/comment.php?id='.$object->id.(GETPOST('withproject') ? '&withproject=1' : '');
458 $head[$h][1] = $langs->trans("CommentLink");
459 if ($nbComments > 0) {
460 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbComments.'</span>';
461 }
462 $head[$h][2] = 'task_comment';
463 $h++;
464 }
465
466 complete_head_from_modules($conf, $langs, $object, $head, $h, 'task', 'add', 'external');
467
468 complete_head_from_modules($conf, $langs, $object, $head, $h, 'task', 'remove');
469
470 return $head;
471}
472
480function project_timesheet_prepare_head($mode, $fuser = null)
481{
482 global $langs, $conf, $user;
483 $h = 0;
484 $head = array();
485
486 $h = 0;
487
488 $param = '';
489 $param .= ($mode ? '&mode='.$mode : '');
490 if (is_object($fuser) && $fuser->id > 0 && $fuser->id != $user->id) {
491 $param .= '&search_usertoprocessid='.$fuser->id;
492 }
493
494 if (!getDolGlobalString('PROJECT_DISABLE_TIMESHEET_PERMONTH')) {
495 $head[$h][0] = DOL_URL_ROOT."/projet/activity/permonth.php".($param ? '?'.$param : '');
496 $head[$h][1] = $langs->trans("InputPerMonth");
497 $head[$h][2] = 'inputpermonth';
498 $h++;
499 }
500
501 if (!getDolGlobalString('PROJECT_DISABLE_TIMESHEET_PERWEEK')) {
502 $head[$h][0] = DOL_URL_ROOT."/projet/activity/perweek.php".($param ? '?'.$param : '');
503 $head[$h][1] = $langs->trans("InputPerWeek");
504 $head[$h][2] = 'inputperweek';
505 $h++;
506 }
507
508 if (!getDolGlobalString('PROJECT_DISABLE_TIMESHEET_PERTIME')) {
509 $head[$h][0] = DOL_URL_ROOT."/projet/activity/perday.php".($param ? '?'.$param : '');
510 $head[$h][1] = $langs->trans("InputPerDay");
511 $head[$h][2] = 'inputperday';
512 $h++;
513 }
514
515 complete_head_from_modules($conf, $langs, null, $head, $h, 'project_timesheet');
516
517 complete_head_from_modules($conf, $langs, null, $head, $h, 'project_timesheet', 'remove');
518
519 return $head;
520}
521
522
529{
530 global $langs, $conf, $user, $db;
531
532 $extrafields = new ExtraFields($db);
533 $extrafields->fetch_name_optionals_label('projet');
534 $extrafields->fetch_name_optionals_label('projet_task');
535
536 $h = 0;
537 $head = array();
538
539 $head[$h][0] = DOL_URL_ROOT."/projet/admin/project.php";
540 $head[$h][1] = $langs->trans("Projects");
541 $head[$h][2] = 'project';
542 $h++;
543
544 complete_head_from_modules($conf, $langs, null, $head, $h, 'project_admin');
545
546 $head[$h][0] = DOL_URL_ROOT."/projet/admin/project_extrafields.php";
547 $head[$h][1] = $langs->trans("ExtraFieldsProject");
548 $nbExtrafields = $extrafields->attributes['projet']['count'];
549 if ($nbExtrafields > 0) {
550 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbExtrafields.'</span>';
551 }
552 $head[$h][2] = 'attributes';
553 $h++;
554
555 if (empty($conf->global->PROJECT_HIDE_TASKS)) {
556 $head[$h][0] = DOL_URL_ROOT . '/projet/admin/project_task_extrafields.php';
557 $head[$h][1] = $langs->trans("ExtraFieldsProjectTask");
558 $nbExtrafields = $extrafields->attributes['projet_task']['count'];
559 if ($nbExtrafields > 0) {
560 $head[$h][1] .= '<span class="badge marginleftonlyshort">' . $nbExtrafields . '</span>';
561 }
562 $head[$h][2] = 'attributes_task';
563 $h++;
564 }
565
566 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
567 $langs->load("members");
568
569 $head[$h][0] = DOL_URL_ROOT.'/projet/admin/website.php';
570 $head[$h][1] = $langs->trans("BlankSubscriptionForm");
571 $head[$h][2] = 'website';
572 $h++;
573 }
574
575 complete_head_from_modules($conf, $langs, null, $head, $h, 'project_admin', 'remove');
576
577 return $head;
578}
579
580
600function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$taskrole, $projectsListId = '', $addordertick = 0, $projectidfortotallink = 0, $dummy = '', $showbilltime = 0, $arrayfields = array(), $arrayofselected = array())
601{
602 global $user, $langs, $conf, $db, $hookmanager;
603 global $projectstatic, $taskstatic, $extrafields;
604
605 $lastprojectid = 0;
606
607 $projectsArrayId = explode(',', $projectsListId);
608
609 $numlines = count($lines);
610
611 // We declare counter as global because we want to edit them into recursive call
612 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;
613 global $totalarray;
614
615 if ($level == 0) {
616 $total_projectlinesa_spent = 0;
617 $total_projectlinesa_planned = 0;
618 $total_projectlinesa_spent_if_planned = 0;
619 $total_projectlinesa_declared_if_planned = 0;
620 $total_projectlinesa_tobill = 0;
621 $total_projectlinesa_billed = 0;
622 $total_budget_amount = 0;
623 $totalarray = array();
624 }
625
626 for ($i = 0; $i < $numlines; $i++) {
627 if ($parent == 0 && $level >= 0) {
628 $level = 0; // if $level = -1, we dont' use sublevel recursion, we show all lines
629 }
630
631 // Process line
632 // print "i:".$i."-".$lines[$i]->fk_project.'<br>';
633 if ($lines[$i]->fk_task_parent == $parent || $level < 0) { // if $level = -1, we dont' use sublevel recursion, we show all lines
634 // Show task line.
635 $showline = 1;
636 $showlineingray = 0;
637
638 // If there is filters to use
639 if (is_array($taskrole)) {
640 // If task not legitimate to show, search if a legitimate task exists later in tree
641 if (!isset($taskrole[$lines[$i]->id]) && $lines[$i]->id != $lines[$i]->fk_task_parent) {
642 // So search if task has a subtask legitimate to show
643 $foundtaskforuserdeeper = 0;
644 searchTaskInChild($foundtaskforuserdeeper, $lines[$i]->id, $lines, $taskrole);
645 //print '$foundtaskforuserpeeper='.$foundtaskforuserdeeper.'<br>';
646 if ($foundtaskforuserdeeper > 0) {
647 $showlineingray = 1; // We will show line but in gray
648 } else {
649 $showline = 0; // No reason to show line
650 }
651 }
652 } else {
653 // 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
654 // or into all other projects if user has permission to).
655 if (!$user->hasRight('projet', 'all', 'lire')) {
656 // User is not allowed on this project and project is not public, so we hide line
657 if (!in_array($lines[$i]->fk_project, $projectsArrayId)) {
658 // Note that having a user assigned to a task into a project user has no permission on, should not be possible
659 // because assignement on task can be done only on contact of project.
660 // If assignement was done and after, was removed from contact of project, then we can hide the line.
661 $showline = 0;
662 }
663 }
664 }
665
666 if ($showline) {
667 // Break on a new project
668 if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid) {
669 $var = !$var;
670 $lastprojectid = $lines[$i]->fk_project;
671 }
672
673 print '<tr class="oddeven" id="row-'.$lines[$i]->id.'">'."\n";
674
675 $projectstatic->id = $lines[$i]->fk_project;
676 $projectstatic->ref = $lines[$i]->projectref;
677 $projectstatic->public = $lines[$i]->public;
678 $projectstatic->title = $lines[$i]->projectlabel;
679 $projectstatic->usage_bill_time = $lines[$i]->usage_bill_time;
680 $projectstatic->status = $lines[$i]->projectstatus;
681
682 $taskstatic->id = $lines[$i]->id;
683 $taskstatic->ref = $lines[$i]->ref;
684 $taskstatic->label = (!empty($taskrole[$lines[$i]->id]) ? $langs->trans("YourRole").': '.$taskrole[$lines[$i]->id] : '');
685 $taskstatic->projectstatus = $lines[$i]->projectstatus;
686 $taskstatic->progress = $lines[$i]->progress;
687 $taskstatic->fk_statut = $lines[$i]->status;
688 $taskstatic->date_start = $lines[$i]->date_start;
689 $taskstatic->date_end = $lines[$i]->date_end;
690 $taskstatic->datee = $lines[$i]->date_end; // deprecated
691 $taskstatic->planned_workload = $lines[$i]->planned_workload;
692 $taskstatic->duration_effective = $lines[$i]->duration_effective;
693 $taskstatic->budget_amount = $lines[$i]->budget_amount;
694
695 // Action column
696 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
697 print '<td class="nowrap center">';
698 $selected = 0;
699 if (in_array($lines[$i]->id, $arrayofselected)) {
700 $selected = 1;
701 }
702 print '<input id="cb' . $lines[$i]->id . '" class="flat checkforselect" type="checkbox" name="toselect[]" value="' . $lines[$i]->id . '"' . ($selected ? ' checked="checked"' : '') . '>';
703 print '</td>';
704 }
705
706 if ($showproject) {
707 // Project ref
708 print '<td class="nowraponall">';
709 //if ($showlineingray) print '<i>';
710 if ($lines[$i]->public || in_array($lines[$i]->fk_project, $projectsArrayId) || $user->hasRight('projet', 'all', 'lire')) {
711 print $projectstatic->getNomUrl(1);
712 } else {
713 print $projectstatic->getNomUrl(1, 'nolink');
714 }
715 //if ($showlineingray) print '</i>';
716 print "</td>";
717
718 // Project status
719 print '<td>';
720 $projectstatic->statut = $lines[$i]->projectstatus;
721 print $projectstatic->getLibStatut(2);
722 print "</td>";
723 }
724
725 // Ref of task
726 if (count($arrayfields) > 0 && !empty($arrayfields['t.ref']['checked'])) {
727 print '<td class="nowraponall">';
728 if ($showlineingray) {
729 print '<i>'.img_object('', 'projecttask').' '.$lines[$i]->ref.'</i>';
730 } else {
731 print $taskstatic->getNomUrl(1, 'withproject');
732 }
733 print '</td>';
734 }
735
736 // Title of task
737 if (count($arrayfields) > 0 && !empty($arrayfields['t.label']['checked'])) {
738 $labeltoshow = '';
739 if ($showlineingray) {
740 $labeltoshow .= '<i>';
741 }
742 //else print '<a href="'.DOL_URL_ROOT.'/projet/tasks/task.php?id='.$lines[$i]->id.'&withproject=1">';
743 for ($k = 0; $k < $level; $k++) {
744 $labeltoshow .= '<div class="marginleftonly">';
745 }
746 $labeltoshow .= dol_escape_htmltag($lines[$i]->label);
747 for ($k = 0; $k < $level; $k++) {
748 $labeltoshow .= '</div>';
749 }
750 if ($showlineingray) {
751 $labeltoshow .= '</i>';
752 }
753 print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($labeltoshow).'">';
754 print $labeltoshow;
755 print "</td>\n";
756 }
757
758 if (count($arrayfields) > 0 && !empty($arrayfields['t.description']['checked'])) {
759 print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($lines[$i]->description).'">';
760 print $lines[$i]->description;
761 print "</td>\n";
762 }
763
764 // Date start
765 if (count($arrayfields) > 0 && !empty($arrayfields['t.dateo']['checked'])) {
766 print '<td class="center nowraponall">';
767 print dol_print_date($lines[$i]->date_start, 'dayhour');
768 print '</td>';
769 }
770
771 // Date end
772 if (count($arrayfields) > 0 && !empty($arrayfields['t.datee']['checked'])) {
773 print '<td class="center nowraponall">';
774 print dol_print_date($lines[$i]->date_end, 'dayhour');
775 if ($taskstatic->hasDelay()) {
776 print img_warning($langs->trans("Late"));
777 }
778 print '</td>';
779 }
780
781 $plannedworkloadoutputformat = 'allhourmin';
782 $timespentoutputformat = 'allhourmin';
783 if (getDolGlobalString('PROJECT_PLANNED_WORKLOAD_FORMAT')) {
784 $plannedworkloadoutputformat = $conf->global->PROJECT_PLANNED_WORKLOAD_FORMAT;
785 }
786 if (getDolGlobalString('PROJECT_TIMES_SPENT_FORMAT')) {
787 $timespentoutputformat = $conf->global->PROJECT_TIME_SPENT_FORMAT;
788 }
789
790 // Planned Workload (in working hours)
791 if (count($arrayfields) > 0 && !empty($arrayfields['t.planned_workload']['checked'])) {
792 print '<td class="right">';
793 $fullhour = convertSecondToTime($lines[$i]->planned_workload, $plannedworkloadoutputformat);
794 $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
795 if ($lines[$i]->planned_workload != '') {
796 print $fullhour;
797 // TODO Add delay taking account of working hours per day and working day per week
798 //if ($workingdelay != $fullhour) print '<br>('.$workingdelay.')';
799 }
800 //else print '--:--';
801 print '</td>';
802 }
803
804 // Time spent
805 if (count($arrayfields) > 0 && !empty($arrayfields['t.duration_effective']['checked'])) {
806 print '<td class="right">';
807 if ($showlineingray) {
808 print '<i>';
809 } else {
810 print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$lines[$i]->id.($showproject ? '' : '&withproject=1').'">';
811 }
812 if ($lines[$i]->duration_effective) {
813 print convertSecondToTime($lines[$i]->duration_effective, $timespentoutputformat);
814 } else {
815 print '--:--';
816 }
817 if ($showlineingray) {
818 print '</i>';
819 } else {
820 print '</a>';
821 }
822 print '</td>';
823 }
824
825 // Progress calculated (Note: ->duration_effective is time spent)
826 if (count($arrayfields) > 0 && !empty($arrayfields['t.progress_calculated']['checked'])) {
827 $s = '';
828 $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 = getDolGlobalString('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 (getDolGlobalString('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 if (!empty($extrafields->attributes['projet_task']['totalizable'])) {
1118 foreach ($extrafields->attributes['projet_task']['totalizable'] as $key => $value) {
1119 if (!empty($arrayfields['efpt.'.$key]['checked']) && $arrayfields['efpt.'.$key]['checked'] == 1) {
1120 print '<td class="right">';
1121 if ($value == 1) {
1122 print empty($totalarray['totalizable'][$key]['total']) ? '' : $totalarray['totalizable'][$key]['total'];
1123 }
1124 print '</td>';
1125 }
1126 }
1127 }
1128
1129 // Column for the drag and drop
1130 print '<td class="liste_total"></td>';
1131
1132 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1133 print '<td class="liste_total"></td>';
1134 }
1135
1136 print '</tr>';
1137 }
1138
1139 return $inc;
1140}
1141
1142
1160function projectLinesPerAction(&$inc, $parent, $fuser, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, $preselectedday, &$isavailable, $oldprojectforbreak = 0)
1161{
1162 global $conf, $db, $user, $langs;
1163 global $form, $formother, $projectstatic, $taskstatic, $thirdpartystatic;
1164
1165 $lastprojectid = 0;
1166 $totalforeachline = array();
1167 $workloadforid = array();
1168 $lineswithoutlevel0 = array();
1169
1170 $numlines = count($lines);
1171
1172 // Create a smaller array with sublevels only to be used later. This increase dramatically performances.
1173 if ($parent == 0) { // Always and only if at first level
1174 for ($i = 0; $i < $numlines; $i++) {
1175 if ($lines[$i]->fk_task_parent) {
1176 $lineswithoutlevel0[] = $lines[$i];
1177 }
1178 }
1179 }
1180
1181 if (empty($oldprojectforbreak)) {
1182 $oldprojectforbreak = (!getDolGlobalString('PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT') ? 0 : -1); // 0 to start break , -1 no break
1183 }
1184
1185 //dol_syslog('projectLinesPerDay inc='.$inc.' preselectedday='.$preselectedday.' task parent id='.$parent.' level='.$level." count(lines)=".$numlines." count(lineswithoutlevel0)=".count($lineswithoutlevel0));
1186 for ($i = 0; $i < $numlines; $i++) {
1187 if ($parent == 0) {
1188 $level = 0;
1189 }
1190
1191 //if ($lines[$i]->fk_task_parent == $parent)
1192 //{
1193 // If we want all or we have a role on task, we show it
1194 if (empty($mine) || !empty($tasksrole[$lines[$i]->id])) {
1195 //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);
1196
1197 // Break on a new project
1198 if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid) {
1199 $lastprojectid = $lines[$i]->fk_project;
1200 if ($preselectedday) {
1201 $projectstatic->id = $lines[$i]->fk_project;
1202 }
1203 }
1204
1205 if (empty($workloadforid[$projectstatic->id])) {
1206 if ($preselectedday) {
1207 $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
1208 $workloadforid[$projectstatic->id] = 1;
1209 }
1210 }
1211
1212 $projectstatic->id = $lines[$i]->fk_project;
1213 $projectstatic->ref = $lines[$i]->project_ref;
1214 $projectstatic->title = $lines[$i]->project_label;
1215 $projectstatic->public = $lines[$i]->public;
1216 $projectstatic->status = $lines[$i]->project->status;
1217
1218 $taskstatic->id = $lines[$i]->fk_statut;
1219 $taskstatic->ref = ($lines[$i]->task_ref ? $lines[$i]->task_ref : $lines[$i]->task_id);
1220 $taskstatic->label = $lines[$i]->task_label;
1221 $taskstatic->date_start = $lines[$i]->date_start;
1222 $taskstatic->date_end = $lines[$i]->date_end;
1223
1224 $thirdpartystatic->id = $lines[$i]->socid;
1225 $thirdpartystatic->name = $lines[$i]->thirdparty_name;
1226 $thirdpartystatic->email = $lines[$i]->thirdparty_email;
1227
1228 if (empty($oldprojectforbreak) || ($oldprojectforbreak != -1 && $oldprojectforbreak != $projectstatic->id)) {
1229 print '<tr class="oddeven trforbreak nobold">'."\n";
1230 print '<td colspan="11">';
1231 print $projectstatic->getNomUrl(1, '', 0, $langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]);
1232 if ($projectstatic->title) {
1233 print ' - ';
1234 print $projectstatic->title;
1235 }
1236 print '</td>';
1237 print '</tr>';
1238 }
1239
1240 if ($oldprojectforbreak != -1) {
1241 $oldprojectforbreak = $projectstatic->id;
1242 }
1243
1244 print '<tr class="oddeven">'."\n";
1245
1246 // User
1247 /*
1248 print '<td class="nowrap">';
1249 print $fuser->getNomUrl(1, 'withproject', 'time');
1250 print '</td>';
1251 */
1252
1253 // Project
1254 print "<td>";
1255 if ($oldprojectforbreak == -1) {
1256 print $projectstatic->getNomUrl(1, '', 0, $langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]);
1257 print '<br>'.$projectstatic->title;
1258 }
1259 print "</td>";
1260
1261 // Thirdparty
1262 print '<td class="tdoverflowmax100">';
1263 if ($thirdpartystatic->id > 0) {
1264 print $thirdpartystatic->getNomUrl(1, 'project', 10);
1265 }
1266 print '</td>';
1267
1268 // Ref
1269 print '<td>';
1270 print '<!-- Task id = '.$lines[$i]->id.' (projectlinesperaction) -->';
1271 for ($k = 0; $k < $level; $k++) {
1272 print '<div class="marginleftonly">';
1273 }
1274 print $taskstatic->getNomUrl(1, 'withproject', 'time');
1275 // Label task
1276 print '<br>';
1277 print '<div class="opacitymedium tdoverflowmax500" title="'.dol_escape_htmltag($taskstatic->label).'">'.dol_escape_htmltag($taskstatic->label).'</div>';
1278 for ($k = 0; $k < $level; $k++) {
1279 print "</div>";
1280 }
1281 print "</td>\n";
1282
1283 // Date
1284 print '<td class="center">';
1285 print dol_print_date($lines[$i]->timespent_datehour, 'day');
1286 print '</td>';
1287
1288 $disabledproject = 1;
1289 $disabledtask = 1;
1290 //print "x".$lines[$i]->fk_project;
1291 //var_dump($lines[$i]);
1292 //var_dump($projectsrole[$lines[$i]->fk_project]);
1293 // If at least one role for project
1294 if ($lines[$i]->public || !empty($projectsrole[$lines[$i]->fk_project]) || $user->hasRight('projet', 'all', 'creer')) {
1295 $disabledproject = 0;
1296 $disabledtask = 0;
1297 }
1298 // If $restricteditformytask is on and I have no role on task, i disable edit
1299 if ($restricteditformytask && empty($tasksrole[$lines[$i]->id])) {
1300 $disabledtask = 1;
1301 }
1302
1303 // Hour
1304 print '<td class="nowrap center">';
1305 print dol_print_date($lines[$i]->timespent_datehour, 'hour');
1306 print '</td>';
1307
1308 $cssonholiday = '';
1309 if (!$isavailable[$preselectedday]['morning'] && !$isavailable[$preselectedday]['afternoon']) {
1310 $cssonholiday .= 'onholidayallday ';
1311 } elseif (!$isavailable[$preselectedday]['morning']) {
1312 $cssonholiday .= 'onholidaymorning ';
1313 } elseif (!$isavailable[$preselectedday]['afternoon']) {
1314 $cssonholiday .= 'onholidayafternoon ';
1315 }
1316
1317 // Duration
1318 print '<td class="duration'.($cssonholiday ? ' '.$cssonholiday : '').' center">';
1319
1320 $dayWorkLoad = $lines[$i]->timespent_duration;
1321 $totalforeachline[$preselectedday] += $lines[$i]->timespent_duration;
1322
1323 $alreadyspent = '';
1324 if ($dayWorkLoad > 0) {
1325 $alreadyspent = convertSecondToTime($lines[$i]->timespent_duration, 'allhourmin');
1326 }
1327
1328 print convertSecondToTime($lines[$i]->timespent_duration, 'allhourmin');
1329
1330 print '</td>';
1331
1332 // Note
1333 print '<td class="center">';
1334 print '<textarea name="'.$lines[$i]->id.'note" rows="'.ROWS_2.'" id="'.$lines[$i]->id.'note"'.($disabledtask ? ' disabled="disabled"' : '').'>';
1335 print $lines[$i]->timespent_note;
1336 print '</textarea>';
1337 print '</td>';
1338
1339 // Warning
1340 print '<td class="right">';
1341 /*if ((! $lines[$i]->public) && $disabledproject) print $form->textwithpicto('',$langs->trans("UserIsNotContactOfProject"));
1342 elseif ($disabledtask)
1343 {
1344 $titleassigntask = $langs->trans("AssignTaskToMe");
1345 if ($fuser->id != $user->id) $titleassigntask = $langs->trans("AssignTaskToUser", '...');
1346
1347 print $form->textwithpicto('',$langs->trans("TaskIsNotAssignedToUser", $titleassigntask));
1348 }*/
1349 print '</td>';
1350
1351 print "</tr>\n";
1352 }
1353 //}
1354 //else
1355 //{
1356 //$level--;
1357 //}
1358 }
1359
1360 return $totalforeachline;
1361}
1362
1363
1383function projectLinesPerDay(&$inc, $parent, $fuser, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, $preselectedday, &$isavailable, $oldprojectforbreak = 0, $arrayfields = array(), $extrafields = null)
1384{
1385 global $conf, $db, $user, $langs;
1386 global $form, $formother, $projectstatic, $taskstatic, $thirdpartystatic;
1387
1388 $lastprojectid = 0;
1389 $totalforeachday = array();
1390 $workloadforid = array();
1391 $lineswithoutlevel0 = array();
1392
1393 $numlines = count($lines);
1394
1395 // Create a smaller array with sublevels only to be used later. This increase dramatically performances.
1396 if ($parent == 0) { // Always and only if at first level
1397 for ($i = 0; $i < $numlines; $i++) {
1398 if ($lines[$i]->fk_task_parent) {
1399 $lineswithoutlevel0[] = $lines[$i];
1400 }
1401 }
1402 }
1403
1404 if (empty($oldprojectforbreak)) {
1405 $oldprojectforbreak = (!getDolGlobalString('PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT') ? 0 : -1); // 0 to start break , -1 no break
1406 }
1407
1408 $restrictBefore = null;
1409
1410 if (getDolGlobalString('PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS')) {
1411 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
1412 $restrictBefore = dol_time_plus_duree(dol_now(), - $conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS, 'm');
1413 }
1414
1415 //dol_syslog('projectLinesPerDay inc='.$inc.' preselectedday='.$preselectedday.' task parent id='.$parent.' level='.$level." count(lines)=".$numlines." count(lineswithoutlevel0)=".count($lineswithoutlevel0));
1416 for ($i = 0; $i < $numlines; $i++) {
1417 if ($parent == 0) {
1418 $level = 0;
1419 }
1420
1421 if ($lines[$i]->fk_task_parent == $parent) {
1422 $obj = &$lines[$i]; // To display extrafields
1423
1424 // If we want all or we have a role on task, we show it
1425 if (empty($mine) || !empty($tasksrole[$lines[$i]->id])) {
1426 //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);
1427
1428 if ($restricteditformytask == 2 && empty($tasksrole[$lines[$i]->id])) { // we have no role on task and we request to hide such cases
1429 continue;
1430 }
1431
1432 // Break on a new project
1433 if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid) {
1434 $lastprojectid = $lines[$i]->fk_project;
1435 if ($preselectedday) {
1436 $projectstatic->id = $lines[$i]->fk_project;
1437 }
1438 }
1439
1440 if (empty($workloadforid[$projectstatic->id])) {
1441 if ($preselectedday) {
1442 $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
1443 $workloadforid[$projectstatic->id] = 1;
1444 }
1445 }
1446
1447 $projectstatic->id = $lines[$i]->fk_project;
1448 $projectstatic->ref = $lines[$i]->projectref;
1449 $projectstatic->title = $lines[$i]->projectlabel;
1450 $projectstatic->public = $lines[$i]->public;
1451 $projectstatic->status = $lines[$i]->projectstatus;
1452
1453 $taskstatic->id = $lines[$i]->id;
1454 $taskstatic->ref = ($lines[$i]->ref ? $lines[$i]->ref : $lines[$i]->id);
1455 $taskstatic->label = $lines[$i]->label;
1456 $taskstatic->date_start = $lines[$i]->date_start;
1457 $taskstatic->date_end = $lines[$i]->date_end;
1458
1459 $thirdpartystatic->id = $lines[$i]->socid;
1460 $thirdpartystatic->name = $lines[$i]->thirdparty_name;
1461 $thirdpartystatic->email = $lines[$i]->thirdparty_email;
1462
1463 if (empty($oldprojectforbreak) || ($oldprojectforbreak != -1 && $oldprojectforbreak != $projectstatic->id)) {
1464 $addcolspan = 0;
1465 if (!empty($arrayfields['t.planned_workload']['checked'])) {
1466 $addcolspan++;
1467 }
1468 if (!empty($arrayfields['t.progress']['checked'])) {
1469 $addcolspan++;
1470 }
1471 foreach ($arrayfields as $key => $val) {
1472 if ($val['checked'] && substr($key, 0, 5) == 'efpt.') {
1473 $addcolspan++;
1474 }
1475 }
1476
1477 print '<tr class="oddeven trforbreak nobold">'."\n";
1478 print '<td colspan="'.(7 + $addcolspan).'">';
1479 print $projectstatic->getNomUrl(1, '', 0, '<strong>'.$langs->transnoentitiesnoconv("YourRole").':</strong> '.$projectsrole[$lines[$i]->fk_project]);
1480 if ($thirdpartystatic->id > 0) {
1481 print ' - '.$thirdpartystatic->getNomUrl(1);
1482 }
1483 if ($projectstatic->title) {
1484 print ' - ';
1485 print '<span class="secondary">'.$projectstatic->title.'</span>';
1486 }
1487 /*
1488 $colspan=5+(empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)?0:2);
1489 print '<table class="">';
1490
1491 print '<tr class="liste_titre">';
1492
1493 // PROJECT fields
1494 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 ');
1495 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 ');
1496 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 ');
1497 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 ');
1498 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 ');
1499
1500 $extrafieldsobjectkey='projet';
1501 $extrafieldsobjectprefix='efp.';
1502 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
1503
1504 print '</tr>';
1505 print '<tr>';
1506
1507 // PROJECT fields
1508 if (!empty($arrayfields['p.fk_opp_status']['checked']))
1509 {
1510 print '<td class="nowrap">';
1511 $code = dol_getIdFromCode($db, $lines[$i]->fk_opp_status, 'c_lead_status', 'rowid', 'code');
1512 if ($code) print $langs->trans("OppStatus".$code);
1513 print "</td>\n";
1514 }
1515 if (!empty($arrayfields['p.opp_amount']['checked']))
1516 {
1517 print '<td class="nowrap">';
1518 print price($lines[$i]->opp_amount, 0, $langs, 1, 0, -1, $conf->currency);
1519 print "</td>\n";
1520 }
1521 if (!empty($arrayfields['p.opp_percent']['checked']))
1522 {
1523 print '<td class="nowrap">';
1524 print price($lines[$i]->opp_percent, 0, $langs, 1, 0).' %';
1525 print "</td>\n";
1526 }
1527 if (!empty($arrayfields['p.budget_amount']['checked']))
1528 {
1529 print '<td class="nowrap">';
1530 print price($lines[$i]->budget_amount, 0, $langs, 1, 0, 0, $conf->currency);
1531 print "</td>\n";
1532 }
1533 if (!empty($arrayfields['p.usage_bill_time']['checked']))
1534 {
1535 print '<td class="nowrap">';
1536 print yn($lines[$i]->usage_bill_time);
1537 print "</td>\n";
1538 }
1539
1540 $extrafieldsobjectkey='projet';
1541 $extrafieldsobjectprefix='efp.';
1542 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
1543
1544 print '</tr>';
1545 print '</table>';
1546
1547 */
1548 print '</td>';
1549 print '</tr>';
1550 }
1551
1552 if ($oldprojectforbreak != -1) {
1553 $oldprojectforbreak = $projectstatic->id;
1554 }
1555
1556 print '<tr class="oddeven" data-taskid="'.$lines[$i]->id.'">'."\n";
1557
1558 // User
1559 /*
1560 print '<td class="nowrap">';
1561 print $fuser->getNomUrl(1, 'withproject', 'time');
1562 print '</td>';
1563 */
1564
1565 // Project
1566 if (getDolGlobalString('PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT')) {
1567 print "<td>";
1568 if ($oldprojectforbreak == -1) {
1569 print $projectstatic->getNomUrl(1, '', 0, $langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]);
1570 }
1571 print "</td>";
1572 }
1573
1574 // Thirdparty
1575 if (getDolGlobalString('PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT')) {
1576 print '<td class="tdoverflowmax100">';
1577 if ($thirdpartystatic->id > 0) {
1578 print $thirdpartystatic->getNomUrl(1, 'project', 10);
1579 }
1580 print '</td>';
1581 }
1582
1583 // Ref
1584 print '<td>';
1585 print '<!-- Task id = '.$lines[$i]->id.' (projectlinesperday) -->';
1586 for ($k = 0; $k < $level; $k++) {
1587 print '<div class="marginleftonly">';
1588 }
1589 print $taskstatic->getNomUrl(1, 'withproject', 'time');
1590 // Label task
1591 print '<br>';
1592 print '<div class="opacitymedium tdoverflowmax500" title="'.dol_escape_htmltag($taskstatic->label).'">'.dol_escape_htmltag($taskstatic->label).'</div>';
1593 for ($k = 0; $k < $level; $k++) {
1594 print "</div>";
1595 }
1596 print "</td>\n";
1597
1598 // TASK extrafields
1599 $extrafieldsobjectkey = 'projet_task';
1600 $extrafieldsobjectprefix = 'efpt.';
1601 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
1602
1603 // Planned Workload
1604 if (!empty($arrayfields['t.planned_workload']['checked'])) {
1605 print '<td class="leftborder plannedworkload right">';
1606 if ($lines[$i]->planned_workload) {
1607 print convertSecondToTime($lines[$i]->planned_workload, 'allhourmin');
1608 } else {
1609 print '--:--';
1610 }
1611 print '</td>';
1612 }
1613
1614 // Progress declared %
1615 if (!empty($arrayfields['t.progress']['checked'])) {
1616 print '<td class="right">';
1617 print $formother->select_percent($lines[$i]->progress, $lines[$i]->id.'progress');
1618 print '</td>';
1619 }
1620
1621 if (!empty($arrayfields['timeconsumed']['checked'])) {
1622 // Time spent by everybody
1623 print '<td class="right">';
1624 // $lines[$i]->duration_effective is a denormalised field = summ of time spent by everybody for task. What we need is time consumed by user
1625 if ($lines[$i]->duration_effective) {
1626 print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$lines[$i]->id.'">';
1627 print convertSecondToTime($lines[$i]->duration_effective, 'allhourmin');
1628 print '</a>';
1629 } else {
1630 print '--:--';
1631 }
1632 print "</td>\n";
1633
1634 // Time spent by user
1635 print '<td class="right">';
1636 $tmptimespent = $taskstatic->getSummaryOfTimeSpent($fuser->id);
1637 if ($tmptimespent['total_duration']) {
1638 print convertSecondToTime($tmptimespent['total_duration'], 'allhourmin');
1639 } else {
1640 print '--:--';
1641 }
1642 print "</td>\n";
1643 }
1644
1645 $disabledproject = 1;
1646 $disabledtask = 1;
1647 //print "x".$lines[$i]->fk_project;
1648 //var_dump($lines[$i]);
1649 //var_dump($projectsrole[$lines[$i]->fk_project]);
1650 // If at least one role for project
1651 if ($lines[$i]->public || !empty($projectsrole[$lines[$i]->fk_project]) || $user->hasRight('projet', 'all', 'creer')) {
1652 $disabledproject = 0;
1653 $disabledtask = 0;
1654 }
1655 // If $restricteditformytask is on and I have no role on task, i disable edit
1656 if ($restricteditformytask && empty($tasksrole[$lines[$i]->id])) {
1657 $disabledtask = 1;
1658 }
1659
1660 if ($restrictBefore && $preselectedday < $restrictBefore) {
1661 $disabledtask = 1;
1662 }
1663
1664 // Select hour
1665 print '<td class="nowraponall leftborder center minwidth150imp">';
1666 $tableCell = $form->selectDate($preselectedday, $lines[$i]->id, 1, 1, 2, "addtime", 0, 0, $disabledtask);
1667 print $tableCell;
1668 print '</td>';
1669
1670 $cssonholiday = '';
1671 if (!$isavailable[$preselectedday]['morning'] && !$isavailable[$preselectedday]['afternoon']) {
1672 $cssonholiday .= 'onholidayallday ';
1673 } elseif (!$isavailable[$preselectedday]['morning']) {
1674 $cssonholiday .= 'onholidaymorning ';
1675 } elseif (!$isavailable[$preselectedday]['afternoon']) {
1676 $cssonholiday .= 'onholidayafternoon ';
1677 }
1678
1679 global $daytoparse;
1680 $tmparray = dol_getdate($daytoparse, true); // detail of current day
1681
1682 $idw = ($tmparray['wday'] - (!getDolGlobalString('MAIN_START_WEEK') ? 0 : 1));
1683 global $numstartworkingday, $numendworkingday;
1684 $cssweekend = '';
1685 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.
1686 $cssweekend = 'weekend';
1687 }
1688
1689 // Duration
1690 print '<td class="center duration'.($cssonholiday ? ' '.$cssonholiday : '').($cssweekend ? ' '.$cssweekend : '').'">';
1691 $dayWorkLoad = empty($projectstatic->weekWorkLoadPerTask[$preselectedday][$lines[$i]->id]) ? 0 : $projectstatic->weekWorkLoadPerTask[$preselectedday][$lines[$i]->id];
1692 if (!isset($totalforeachday[$preselectedday])) {
1693 $totalforeachday[$preselectedday] = 0;
1694 }
1695 $totalforeachday[$preselectedday] += $dayWorkLoad;
1696
1697 $alreadyspent = '';
1698 if ($dayWorkLoad > 0) {
1699 $alreadyspent = convertSecondToTime($dayWorkLoad, 'allhourmin');
1700 }
1701
1702 $idw = 0;
1703
1704 $tableCell = '';
1705 $tableCell .= '<span class="timesheetalreadyrecorded" title="texttoreplace"><input type="text" class="center width40" disabled id="timespent['.$inc.']['.$idw.']" name="task['.$lines[$i]->id.']['.$idw.']" value="'.$alreadyspent.'"></span>';
1706 $tableCell .= '<span class="hideonsmartphone"> + </span>';
1707 //$tableCell.='&nbsp;&nbsp;&nbsp;';
1708 $tableCell .= $form->select_duration($lines[$i]->id.'duration', '', $disabledtask, 'text', 0, 1);
1709 //$tableCell.='&nbsp;<input type="submit" class="button"'.($disabledtask?' disabled':'').' value="'.$langs->trans("Add").'">';
1710 print $tableCell;
1711
1712 print '</td>';
1713
1714 // Note
1715 print '<td class="center">';
1716 print '<textarea name="'.$lines[$i]->id.'note" rows="'.ROWS_2.'" id="'.$lines[$i]->id.'note"'.($disabledtask ? ' disabled="disabled"' : '').'>';
1717 print '</textarea>';
1718 print '</td>';
1719
1720 // Warning
1721 print '<td class="right">';
1722 if ((!$lines[$i]->public) && $disabledproject) {
1723 print $form->textwithpicto('', $langs->trans("UserIsNotContactOfProject"));
1724 } elseif ($disabledtask) {
1725 $titleassigntask = $langs->trans("AssignTaskToMe");
1726 if ($fuser->id != $user->id) {
1727 $titleassigntask = $langs->trans("AssignTaskToUser", '...');
1728 }
1729
1730 print $form->textwithpicto('', $langs->trans("TaskIsNotAssignedToUser", $titleassigntask));
1731 }
1732 print '</td>';
1733
1734 print "</tr>\n";
1735 }
1736
1737 $inc++;
1738 $level++;
1739 if ($lines[$i]->id > 0) {
1740 //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level);
1741 //var_dump($totalforeachday);
1742 $ret = projectLinesPerDay($inc, $lines[$i]->id, $fuser, ($parent == 0 ? $lineswithoutlevel0 : $lines), $level, $projectsrole, $tasksrole, $mine, $restricteditformytask, $preselectedday, $isavailable, $oldprojectforbreak, $arrayfields, $extrafields);
1743 //var_dump('ret with parent='.$lines[$i]->id.' level='.$level);
1744 //var_dump($ret);
1745 foreach ($ret as $key => $val) {
1746 $totalforeachday[$key] += $val;
1747 }
1748 //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level.' + subtasks');
1749 //var_dump($totalforeachday);
1750 }
1751 $level--;
1752 } else {
1753 //$level--;
1754 }
1755 }
1756
1757 return $totalforeachday;
1758}
1759
1760
1780function projectLinesPerWeek(&$inc, $firstdaytoshow, $fuser, $parent, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, &$isavailable, $oldprojectforbreak = 0, $arrayfields = array(), $extrafields = null)
1781{
1782 global $conf, $db, $user, $langs;
1783 global $form, $formother, $projectstatic, $taskstatic, $thirdpartystatic;
1784
1785 $numlines = count($lines);
1786
1787 $lastprojectid = 0;
1788 $workloadforid = array();
1789 $totalforeachday = array();
1790 $lineswithoutlevel0 = array();
1791
1792 // Create a smaller array with sublevels only to be used later. This increase dramatically performances.
1793 if ($parent == 0) { // Always and only if at first level
1794 for ($i = 0; $i < $numlines; $i++) {
1795 if ($lines[$i]->fk_task_parent) {
1796 $lineswithoutlevel0[] = $lines[$i];
1797 }
1798 }
1799 }
1800
1801 //dol_syslog('projectLinesPerWeek inc='.$inc.' firstdaytoshow='.$firstdaytoshow.' task parent id='.$parent.' level='.$level." count(lines)=".$numlines." count(lineswithoutlevel0)=".count($lineswithoutlevel0));
1802
1803 if (empty($oldprojectforbreak)) {
1804 $oldprojectforbreak = (!getDolGlobalString('PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT') ? 0 : -1); // 0 = start break, -1 = never break
1805 }
1806
1807 $restrictBefore = null;
1808
1809 if (getDolGlobalString('PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS')) {
1810 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
1811 $restrictBefore = dol_time_plus_duree(dol_now(), - $conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS, 'm');
1812 }
1813
1814 for ($i = 0; $i < $numlines; $i++) {
1815 if ($parent == 0) {
1816 $level = 0;
1817 }
1818
1819 if ($lines[$i]->fk_task_parent == $parent) {
1820 $obj = &$lines[$i]; // To display extrafields
1821
1822 // If we want all or we have a role on task, we show it
1823 if (empty($mine) || !empty($tasksrole[$lines[$i]->id])) {
1824 //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);
1825
1826 if ($restricteditformytask == 2 && empty($tasksrole[$lines[$i]->id])) { // we have no role on task and we request to hide such cases
1827 continue;
1828 }
1829
1830 // Break on a new project
1831 if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid) {
1832 $lastprojectid = $lines[$i]->fk_project;
1833 $projectstatic->id = $lines[$i]->fk_project;
1834 }
1835
1836 //var_dump('--- '.$level.' '.$firstdaytoshow.' '.$fuser->id.' '.$projectstatic->id.' '.$workloadforid[$projectstatic->id]);
1837 //var_dump($projectstatic->weekWorkLoadPerTask);
1838 if (empty($workloadforid[$projectstatic->id])) {
1839 $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
1840 $workloadforid[$projectstatic->id] = 1;
1841 }
1842 //var_dump($projectstatic->weekWorkLoadPerTask);
1843 //var_dump('--- '.$projectstatic->id.' '.$workloadforid[$projectstatic->id]);
1844
1845 $projectstatic->id = $lines[$i]->fk_project;
1846 $projectstatic->ref = $lines[$i]->projectref;
1847 $projectstatic->title = $lines[$i]->projectlabel;
1848 $projectstatic->public = $lines[$i]->public;
1849 $projectstatic->thirdparty_name = $lines[$i]->thirdparty_name;
1850 $projectstatic->status = $lines[$i]->projectstatus;
1851
1852 $taskstatic->id = $lines[$i]->id;
1853 $taskstatic->ref = ($lines[$i]->ref ? $lines[$i]->ref : $lines[$i]->id);
1854 $taskstatic->label = $lines[$i]->label;
1855 $taskstatic->date_start = $lines[$i]->date_start;
1856 $taskstatic->date_end = $lines[$i]->date_end;
1857
1858 $thirdpartystatic->id = $lines[$i]->thirdparty_id;
1859 $thirdpartystatic->name = $lines[$i]->thirdparty_name;
1860 $thirdpartystatic->email = $lines[$i]->thirdparty_email;
1861
1862 if (empty($oldprojectforbreak) || ($oldprojectforbreak != -1 && $oldprojectforbreak != $projectstatic->id)) {
1863 $addcolspan = 0;
1864 if (!empty($arrayfields['t.planned_workload']['checked'])) {
1865 $addcolspan++;
1866 }
1867 if (!empty($arrayfields['t.progress']['checked'])) {
1868 $addcolspan++;
1869 }
1870 foreach ($arrayfields as $key => $val) {
1871 if ($val['checked'] && substr($key, 0, 5) == 'efpt.') {
1872 $addcolspan++;
1873 }
1874 }
1875
1876 print '<tr class="oddeven trforbreak nobold">'."\n";
1877 print '<td colspan="'.(11 + $addcolspan).'">';
1878 print $projectstatic->getNomUrl(1, '', 0, '<strong>'.$langs->transnoentitiesnoconv("YourRole").':</strong> '.$projectsrole[$lines[$i]->fk_project]);
1879 if ($thirdpartystatic->id > 0) {
1880 print ' - '.$thirdpartystatic->getNomUrl(1);
1881 }
1882 if ($projectstatic->title) {
1883 print ' - ';
1884 print '<span class="secondary">'.$projectstatic->title.'</span>';
1885 }
1886
1887 /*$colspan=5+(empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)?0:2);
1888 print '<table class="">';
1889
1890 print '<tr class="liste_titre">';
1891
1892 // PROJECT fields
1893 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 ');
1894 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 ');
1895 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 ');
1896 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 ');
1897 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 ');
1898
1899 $extrafieldsobjectkey='projet';
1900 $extrafieldsobjectprefix='efp.';
1901 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
1902
1903 print '</tr>';
1904 print '<tr>';
1905
1906 // PROJECT fields
1907 if (!empty($arrayfields['p.fk_opp_status']['checked']))
1908 {
1909 print '<td class="nowrap">';
1910 $code = dol_getIdFromCode($db, $lines[$i]->fk_opp_status, 'c_lead_status', 'rowid', 'code');
1911 if ($code) print $langs->trans("OppStatus".$code);
1912 print "</td>\n";
1913 }
1914 if (!empty($arrayfields['p.opp_amount']['checked']))
1915 {
1916 print '<td class="nowrap">';
1917 print price($lines[$i]->opp_amount, 0, $langs, 1, 0, -1, $conf->currency);
1918 print "</td>\n";
1919 }
1920 if (!empty($arrayfields['p.opp_percent']['checked']))
1921 {
1922 print '<td class="nowrap">';
1923 print price($lines[$i]->opp_percent, 0, $langs, 1, 0).' %';
1924 print "</td>\n";
1925 }
1926 if (!empty($arrayfields['p.budget_amount']['checked']))
1927 {
1928 print '<td class="nowrap">';
1929 print price($lines[$i]->budget_amount, 0, $langs, 1, 0, 0, $conf->currency);
1930 print "</td>\n";
1931 }
1932 if (!empty($arrayfields['p.usage_bill_time']['checked']))
1933 {
1934 print '<td class="nowrap">';
1935 print yn($lines[$i]->usage_bill_time);
1936 print "</td>\n";
1937 }
1938
1939 $extrafieldsobjectkey='projet';
1940 $extrafieldsobjectprefix='efp.';
1941 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
1942
1943 print '</tr>';
1944 print '</table>';
1945 */
1946
1947 print '</td>';
1948 print '</tr>';
1949 }
1950
1951 if ($oldprojectforbreak != -1) {
1952 $oldprojectforbreak = $projectstatic->id;
1953 }
1954
1955 print '<tr class="oddeven" data-taskid="'.$lines[$i]->id.'">'."\n";
1956
1957 // User
1958 /*
1959 print '<td class="nowrap">';
1960 print $fuser->getNomUrl(1, 'withproject', 'time');
1961 print '</td>';
1962 */
1963
1964 // Project
1965 if (getDolGlobalString('PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT')) {
1966 print '<td class="nowrap">';
1967 if ($oldprojectforbreak == -1) {
1968 print $projectstatic->getNomUrl(1, '', 0, $langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]);
1969 }
1970 print "</td>";
1971 }
1972
1973 // Thirdparty
1974 if (getDolGlobalString('PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT')) {
1975 print '<td class="tdoverflowmax100">';
1976 if ($thirdpartystatic->id > 0) {
1977 print $thirdpartystatic->getNomUrl(1, 'project');
1978 }
1979 print '</td>';
1980 }
1981
1982 // Ref
1983 print '<td class="tdoverflowmax300">';
1984 print '<!-- Task id = '.$lines[$i]->id.' (projectlinesperweek) -->';
1985 for ($k = 0; $k < $level; $k++) {
1986 print '<div class="marginleftonly">';
1987 }
1988 print $taskstatic->getNomUrl(1, 'withproject', 'time');
1989 // Label task
1990 print '<br>';
1991 print '<div class="opacitymedium tdoverflowmax500" title="'.dol_escape_htmltag($taskstatic->label).'">'.dol_escape_htmltag($taskstatic->label).'</div>';
1992 for ($k = 0; $k < $level; $k++) {
1993 print "</div>";
1994 }
1995 print "</td>\n";
1996
1997 // TASK extrafields
1998 $extrafieldsobjectkey = 'projet_task';
1999 $extrafieldsobjectprefix = 'efpt.';
2000 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
2001
2002 // Planned Workload
2003 if (!empty($arrayfields['t.planned_workload']['checked'])) {
2004 print '<td class="leftborder plannedworkload right">';
2005 if ($lines[$i]->planned_workload) {
2006 print convertSecondToTime($lines[$i]->planned_workload, 'allhourmin');
2007 } else {
2008 print '--:--';
2009 }
2010 print '</td>';
2011 }
2012
2013 if (!empty($arrayfields['t.progress']['checked'])) {
2014 // Progress declared %
2015 print '<td class="right">';
2016 print $formother->select_percent($lines[$i]->progress, $lines[$i]->id.'progress');
2017 print '</td>';
2018 }
2019
2020 if (!empty($arrayfields['timeconsumed']['checked'])) {
2021 // Time spent by everybody
2022 print '<td class="right">';
2023 // $lines[$i]->duration_effective is a denormalised field = summ of time spent by everybody for task. What we need is time consumed by user
2024 if ($lines[$i]->duration_effective) {
2025 print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.((int) $lines[$i]->id).'">';
2026 print convertSecondToTime($lines[$i]->duration_effective, 'allhourmin');
2027 print '</a>';
2028 } else {
2029 print '--:--';
2030 }
2031 print "</td>\n";
2032
2033 // Time spent by user
2034 print '<td class="right">';
2035 $tmptimespent = $taskstatic->getSummaryOfTimeSpent($fuser->id);
2036 if ($tmptimespent['total_duration']) {
2037 print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.((int) $lines[$i]->id).'&search_user='.((int) $fuser->id).'">';
2038 print convertSecondToTime($tmptimespent['total_duration'], 'allhourmin');
2039 print '</a>';
2040 } else {
2041 print '--:--';
2042 }
2043 print "</td>\n";
2044 }
2045
2046 $disabledproject = 1;
2047 $disabledtask = 1;
2048 //print "x".$lines[$i]->fk_project;
2049 //var_dump($lines[$i]);
2050 //var_dump($projectsrole[$lines[$i]->fk_project]);
2051 // If at least one role for project
2052 if ($lines[$i]->public || !empty($projectsrole[$lines[$i]->fk_project]) || $user->hasRight('projet', 'all', 'creer')) {
2053 $disabledproject = 0;
2054 $disabledtask = 0;
2055 }
2056 // If $restricteditformytask is on and I have no role on task, i disable edit
2057 if ($restricteditformytask && empty($tasksrole[$lines[$i]->id])) {
2058 $disabledtask = 1;
2059 }
2060
2061 //var_dump($projectstatic->weekWorkLoadPerTask);
2062
2063 // Fields to show current time
2064 $tableCell = '';
2065 $modeinput = 'hours';
2066 for ($idw = 0; $idw < 7; $idw++) {
2067 $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd');
2068 if (!isset($totalforeachday[$tmpday])) {
2069 $totalforeachday[$tmpday] = 0;
2070 }
2071 $cssonholiday = '';
2072 if (!$isavailable[$tmpday]['morning'] && !$isavailable[$tmpday]['afternoon']) {
2073 $cssonholiday .= 'onholidayallday ';
2074 } elseif (!$isavailable[$tmpday]['morning']) {
2075 $cssonholiday .= 'onholidaymorning ';
2076 } elseif (!$isavailable[$tmpday]['afternoon']) {
2077 $cssonholiday .= 'onholidayafternoon ';
2078 }
2079
2080 $tmparray = dol_getdate($tmpday);
2081 $dayWorkLoad = (!empty($projectstatic->weekWorkLoadPerTask[$tmpday][$lines[$i]->id]) ? $projectstatic->weekWorkLoadPerTask[$tmpday][$lines[$i]->id] : 0);
2082 $totalforeachday[$tmpday] += $dayWorkLoad;
2083
2084 $alreadyspent = '';
2085 if ($dayWorkLoad > 0) {
2086 $alreadyspent = convertSecondToTime($dayWorkLoad, 'allhourmin');
2087 }
2088 $alttitle = $langs->trans("AddHereTimeSpentForDay", !empty($tmparray['day']) ? $tmparray['day'] : 0, $tmparray['mon']);
2089
2090 global $numstartworkingday, $numendworkingday;
2091 $cssweekend = '';
2092 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.
2093 $cssweekend = 'weekend';
2094 }
2095
2096 $disabledtaskday = $disabledtask;
2097
2098 if (! $disabledtask && $restrictBefore && $tmpday < $restrictBefore) {
2099 $disabledtaskday = 1;
2100 }
2101
2102 $tableCell = '<td class="center hide'.$idw.($cssonholiday ? ' '.$cssonholiday : '').($cssweekend ? ' '.$cssweekend : '').'">';
2103 //$tableCell .= 'idw='.$idw.' '.$conf->global->MAIN_START_WEEK.' '.$numstartworkingday.'-'.$numendworkingday;
2104 $placeholder = '';
2105 if ($alreadyspent) {
2106 $tableCell .= '<span class="timesheetalreadyrecorded" title="texttoreplace"><input type="text" class="center smallpadd width40" disabled id="timespent['.$inc.']['.$idw.']" name="task['.$lines[$i]->id.']['.$idw.']" value="'.$alreadyspent.'"></span>';
2107 //$placeholder=' placeholder="00:00"';
2108 //$tableCell.='+';
2109 }
2110 $tableCell .= '<input type="text" alt="'.($disabledtaskday ? '' : $alttitle).'" title="'.($disabledtaskday ? '' : $alttitle).'" '.($disabledtaskday ? 'disabled' : $placeholder).' class="center smallpadd width40" id="timeadded['.$inc.']['.$idw.']" name="task['.$lines[$i]->id.']['.$idw.']" value="" cols="2" maxlength="5"';
2111 $tableCell .= ' onkeypress="return regexEvent(this,event,\'timeChar\')"';
2112 $tableCell .= ' onkeyup="updateTotal('.$idw.',\''.$modeinput.'\')"';
2113 $tableCell .= ' onblur="regexEvent(this,event,\''.$modeinput.'\'); updateTotal('.$idw.',\''.$modeinput.'\')" />';
2114 $tableCell .= '</td>';
2115 print $tableCell;
2116 }
2117
2118 // Warning
2119 print '<td class="right">';
2120 if ((!$lines[$i]->public) && $disabledproject) {
2121 print $form->textwithpicto('', $langs->trans("UserIsNotContactOfProject"));
2122 } elseif ($disabledtask) {
2123 $titleassigntask = $langs->trans("AssignTaskToMe");
2124 if ($fuser->id != $user->id) {
2125 $titleassigntask = $langs->trans("AssignTaskToUser", '...');
2126 }
2127
2128 print $form->textwithpicto('', $langs->trans("TaskIsNotAssignedToUser", $titleassigntask));
2129 }
2130 print '</td>';
2131
2132 print "</tr>\n";
2133 }
2134
2135 // Call to show task with a lower level (task under the current task)
2136 $inc++;
2137 $level++;
2138 if ($lines[$i]->id > 0) {
2139 //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level);
2140 //var_dump($totalforeachday);
2141 $ret = projectLinesPerWeek($inc, $firstdaytoshow, $fuser, $lines[$i]->id, ($parent == 0 ? $lineswithoutlevel0 : $lines), $level, $projectsrole, $tasksrole, $mine, $restricteditformytask, $isavailable, $oldprojectforbreak, $arrayfields, $extrafields);
2142 //var_dump('ret with parent='.$lines[$i]->id.' level='.$level);
2143 //var_dump($ret);
2144 foreach ($ret as $key => $val) {
2145 $totalforeachday[$key] += $val;
2146 }
2147 //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level.' + subtasks');
2148 //var_dump($totalforeachday);
2149 }
2150 $level--;
2151 } else {
2152 //$level--;
2153 }
2154 }
2155
2156 return $totalforeachday;
2157}
2158
2177function projectLinesPerMonth(&$inc, $firstdaytoshow, $fuser, $parent, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, &$isavailable, $oldprojectforbreak = 0, $TWeek = array())
2178{
2179 global $conf, $db, $user, $langs;
2180 global $form, $formother, $projectstatic, $taskstatic, $thirdpartystatic;
2181
2182 $numlines = count($lines);
2183
2184 $lastprojectid = 0;
2185 $workloadforid = array();
2186 $totalforeachweek = array();
2187 $lineswithoutlevel0 = array();
2188
2189 // Create a smaller array with sublevels only to be used later. This increase dramatically performances.
2190 if ($parent == 0) { // Always and only if at first level
2191 for ($i = 0; $i < $numlines; $i++) {
2192 if ($lines[$i]->fk_task_parent) {
2193 $lineswithoutlevel0[] = $lines[$i];
2194 }
2195 }
2196 }
2197
2198 //dol_syslog('projectLinesPerWeek inc='.$inc.' firstdaytoshow='.$firstdaytoshow.' task parent id='.$parent.' level='.$level." count(lines)=".$numlines." count(lineswithoutlevel0)=".count($lineswithoutlevel0));
2199
2200 if (empty($oldprojectforbreak)) {
2201 $oldprojectforbreak = (!getDolGlobalString('PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT') ? 0 : -1); // 0 = start break, -1 = never break
2202 }
2203
2204 $restrictBefore = null;
2205
2206 if (getDolGlobalString('PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS')) {
2207 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
2208 $restrictBefore = dol_time_plus_duree(dol_now(), - $conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS, 'm');
2209 }
2210
2211 for ($i = 0; $i < $numlines; $i++) {
2212 if ($parent == 0) {
2213 $level = 0;
2214 }
2215
2216 if ($lines[$i]->fk_task_parent == $parent) {
2217 // If we want all or we have a role on task, we show it
2218 if (empty($mine) || !empty($tasksrole[$lines[$i]->id])) {
2219 //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);
2220
2221 if ($restricteditformytask == 2 && empty($tasksrole[$lines[$i]->id])) { // we have no role on task and we request to hide such cases
2222 continue;
2223 }
2224
2225 // Break on a new project
2226 if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid) {
2227 $lastprojectid = $lines[$i]->fk_project;
2228 $projectstatic->id = $lines[$i]->fk_project;
2229 }
2230
2231 //var_dump('--- '.$level.' '.$firstdaytoshow.' '.$fuser->id.' '.$projectstatic->id.' '.$workloadforid[$projectstatic->id]);
2232 //var_dump($projectstatic->weekWorkLoadPerTask);
2233 if (empty($workloadforid[$projectstatic->id])) {
2234 $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
2235 $workloadforid[$projectstatic->id] = 1;
2236 }
2237 //var_dump($projectstatic->weekWorkLoadPerTask);
2238 //var_dump('--- '.$projectstatic->id.' '.$workloadforid[$projectstatic->id]);
2239
2240 $projectstatic->id = $lines[$i]->fk_project;
2241 $projectstatic->ref = $lines[$i]->projectref;
2242 $projectstatic->title = $lines[$i]->projectlabel;
2243 $projectstatic->public = $lines[$i]->public;
2244 $projectstatic->thirdparty_name = $lines[$i]->thirdparty_name;
2245 $projectstatic->status = $lines[$i]->projectstatus;
2246
2247 $taskstatic->id = $lines[$i]->id;
2248 $taskstatic->ref = ($lines[$i]->ref ? $lines[$i]->ref : $lines[$i]->id);
2249 $taskstatic->label = $lines[$i]->label;
2250 $taskstatic->date_start = $lines[$i]->date_start;
2251 $taskstatic->date_end = $lines[$i]->date_end;
2252
2253 $thirdpartystatic->id = $lines[$i]->thirdparty_id;
2254 $thirdpartystatic->name = $lines[$i]->thirdparty_name;
2255 $thirdpartystatic->email = $lines[$i]->thirdparty_email;
2256
2257 if (empty($oldprojectforbreak) || ($oldprojectforbreak != -1 && $oldprojectforbreak != $projectstatic->id)) {
2258 print '<tr class="oddeven trforbreak nobold">'."\n";
2259 print '<td colspan="'.(6 + count($TWeek)).'">';
2260 print $projectstatic->getNomUrl(1, '', 0, '<strong>'.$langs->transnoentitiesnoconv("YourRole").':</strong> '.$projectsrole[$lines[$i]->fk_project]);
2261 if ($thirdpartystatic->id > 0) {
2262 print ' - '.$thirdpartystatic->getNomUrl(1);
2263 }
2264 if ($projectstatic->title) {
2265 print ' - ';
2266 print '<span class="secondary">'.$projectstatic->title.'</span>';
2267 }
2268 print '</td>';
2269 print '</tr>';
2270 }
2271
2272 if ($oldprojectforbreak != -1) {
2273 $oldprojectforbreak = $projectstatic->id;
2274 }
2275 print '<tr class="oddeven" data-taskid="'.$lines[$i]->id.'">'."\n";
2276
2277 // User
2278 /*
2279 print '<td class="nowrap">';
2280 print $fuser->getNomUrl(1, 'withproject', 'time');
2281 print '</td>';
2282 */
2283
2284 // Project
2285 /*print '<td class="nowrap">';
2286 if ($oldprojectforbreak == -1) print $projectstatic->getNomUrl(1,'',0,$langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]);
2287 print "</td>";*/
2288
2289 // Thirdparty
2290 /*print '<td class="tdoverflowmax100">';
2291 if ($thirdpartystatic->id > 0) print $thirdpartystatic->getNomUrl(1, 'project');
2292 print '</td>';*/
2293
2294 // Ref
2295 print '<td class="nowrap">';
2296 print '<!-- Task id = '.$lines[$i]->id.' (projectlinespermonth) -->';
2297 for ($k = 0; $k < $level; $k++) {
2298 print '<div class="marginleftonly">';
2299 }
2300 print $taskstatic->getNomUrl(1, 'withproject', 'time');
2301 // Label task
2302 print '<br>';
2303 print '<div class="opacitymedium tdoverflowmax500" title="'.dol_escape_htmltag($taskstatic->label).'">'.dol_escape_htmltag($taskstatic->label).'</div>';
2304 for ($k = 0; $k < $level; $k++) {
2305 print "</div>";
2306 }
2307 print "</td>\n";
2308
2309 // Planned Workload
2310 print '<td class="leftborder plannedworkload right">';
2311 if ($lines[$i]->planned_workload) {
2312 print convertSecondToTime($lines[$i]->planned_workload, 'allhourmin');
2313 } else {
2314 print '--:--';
2315 }
2316 print '</td>';
2317
2318 // Progress declared %
2319 print '<td class="right">';
2320 print $formother->select_percent($lines[$i]->progress, $lines[$i]->id.'progress');
2321 print '</td>';
2322
2323 // Time spent by everybody
2324 print '<td class="right">';
2325 // $lines[$i]->duration_effective is a denormalised field = summ of time spent by everybody for task. What we need is time consumed by user
2326 if ($lines[$i]->duration_effective) {
2327 print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$lines[$i]->id.'">';
2328 print convertSecondToTime($lines[$i]->duration_effective, 'allhourmin');
2329 print '</a>';
2330 } else {
2331 print '--:--';
2332 }
2333 print "</td>\n";
2334
2335 // Time spent by user
2336 print '<td class="right">';
2337 $tmptimespent = $taskstatic->getSummaryOfTimeSpent($fuser->id);
2338 if ($tmptimespent['total_duration']) {
2339 print convertSecondToTime($tmptimespent['total_duration'], 'allhourmin');
2340 } else {
2341 print '--:--';
2342 }
2343 print "</td>\n";
2344
2345 $disabledproject = 1;
2346 $disabledtask = 1;
2347 //print "x".$lines[$i]->fk_project;
2348 //var_dump($lines[$i]);
2349 //var_dump($projectsrole[$lines[$i]->fk_project]);
2350 // If at least one role for project
2351 if ($lines[$i]->public || !empty($projectsrole[$lines[$i]->fk_project]) || $user->hasRight('projet', 'all', 'creer')) {
2352 $disabledproject = 0;
2353 $disabledtask = 0;
2354 }
2355 // If $restricteditformytask is on and I have no role on task, i disable edit
2356 if ($restricteditformytask && empty($tasksrole[$lines[$i]->id])) {
2357 $disabledtask = 1;
2358 }
2359
2360 //var_dump($projectstatic->weekWorkLoadPerTask);
2361 //TODO
2362 // Fields to show current time
2363 $tableCell = '';
2364 $modeinput = 'hours';
2365 $TFirstDay = getFirstDayOfEachWeek($TWeek, date('Y', $firstdaytoshow));
2366 $TFirstDay[reset($TWeek)] = 1;
2367
2368 $firstdaytoshowarray = dol_getdate($firstdaytoshow);
2369 $year = $firstdaytoshowarray['year'];
2370 $month = $firstdaytoshowarray['mon'];
2371 foreach ($TWeek as $weekIndex => $weekNb) {
2372 $weekWorkLoad = !empty($projectstatic->monthWorkLoadPerTask[$weekNb][$lines[$i]->id]) ? $projectstatic->monthWorkLoadPerTask[$weekNb][$lines[$i]->id] : 0 ;
2373 if (!isset($totalforeachweek[$weekNb])) {
2374 $totalforeachweek[$weekNb] = 0;
2375 }
2376 $totalforeachweek[$weekNb] += $weekWorkLoad;
2377
2378 $alreadyspent = '';
2379 if ($weekWorkLoad > 0) {
2380 $alreadyspent = convertSecondToTime($weekWorkLoad, 'allhourmin');
2381 }
2382 $alttitle = $langs->trans("AddHereTimeSpentForWeek", $weekNb);
2383
2384 $disabledtaskweek = $disabledtask;
2385 $firstdayofweek = dol_mktime(0, 0, 0, $month, $TFirstDay[$weekIndex], $year);
2386
2387 if (! $disabledtask && $restrictBefore && $firstdayofweek < $restrictBefore) {
2388 $disabledtaskweek = 1;
2389 }
2390
2391 $tableCell = '<td class="center hide weekend">';
2392 $placeholder = '';
2393 if ($alreadyspent) {
2394 $tableCell .= '<span class="timesheetalreadyrecorded" title="texttoreplace"><input type="text" class="center smallpadd width40" disabled id="timespent['.$inc.']['.((int) $weekNb).']" name="task['.$lines[$i]->id.']['.$weekNb.']" value="'.$alreadyspent.'"></span>';
2395 //$placeholder=' placeholder="00:00"';
2396 //$tableCell.='+';
2397 }
2398
2399 $tableCell .= '<input type="text" alt="'.($disabledtaskweek ? '' : $alttitle).'" title="'.($disabledtaskweek ? '' : $alttitle).'" '.($disabledtaskweek ? 'disabled' : $placeholder).' class="center smallpadd width40" id="timeadded['.$inc.']['.((int) $weekNb).']" name="task['.$lines[$i]->id.']['.($TFirstDay[$weekNb] - 1).']" value="" cols="2" maxlength="5"';
2400 $tableCell .= ' onkeypress="return regexEvent(this,event,\'timeChar\')"';
2401 $tableCell .= ' onkeyup="updateTotal('.$weekNb.',\''.$modeinput.'\')"';
2402 $tableCell .= ' onblur="regexEvent(this,event,\''.$modeinput.'\'); updateTotal('.$weekNb.',\''.$modeinput.'\')" />';
2403 $tableCell .= '</td>';
2404 print $tableCell;
2405 }
2406
2407 // Warning
2408 print '<td class="right">';
2409 if ((!$lines[$i]->public) && $disabledproject) {
2410 print $form->textwithpicto('', $langs->trans("UserIsNotContactOfProject"));
2411 } elseif ($disabledtask) {
2412 $titleassigntask = $langs->trans("AssignTaskToMe");
2413 if ($fuser->id != $user->id) {
2414 $titleassigntask = $langs->trans("AssignTaskToUser", '...');
2415 }
2416
2417 print $form->textwithpicto('', $langs->trans("TaskIsNotAssignedToUser", $titleassigntask));
2418 }
2419 print '</td>';
2420
2421 print "</tr>\n";
2422 }
2423
2424 // Call to show task with a lower level (task under the current task)
2425 $inc++;
2426 $level++;
2427 if ($lines[$i]->id > 0) {
2428 //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level);
2429 //var_dump($totalforeachday);
2430 $ret = projectLinesPerMonth($inc, $firstdaytoshow, $fuser, $lines[$i]->id, ($parent == 0 ? $lineswithoutlevel0 : $lines), $level, $projectsrole, $tasksrole, $mine, $restricteditformytask, $isavailable, $oldprojectforbreak, $TWeek);
2431 //var_dump('ret with parent='.$lines[$i]->id.' level='.$level);
2432 //var_dump($ret);
2433 foreach ($ret as $key => $val) {
2434 $totalforeachweek[$key] += $val;
2435 }
2436 //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level.' + subtasks');
2437 //var_dump($totalforeachday);
2438 }
2439 $level--;
2440 } else {
2441 //$level--;
2442 }
2443 }
2444
2445 return $totalforeachweek;
2446}
2447
2448
2458function searchTaskInChild(&$inc, $parent, &$lines, &$taskrole)
2459{
2460 //print 'Search in line with parent id = '.$parent.'<br>';
2461 $numlines = count($lines);
2462 for ($i = 0; $i < $numlines; $i++) {
2463 // Process line $lines[$i]
2464 if ($lines[$i]->fk_task_parent == $parent && $lines[$i]->id != $lines[$i]->fk_task_parent) {
2465 // If task is legitimate to show, no more need to search deeper
2466 if (isset($taskrole[$lines[$i]->id])) {
2467 //print 'Found a legitimate task id='.$lines[$i]->id.'<br>';
2468 $inc++;
2469 return $inc;
2470 }
2471
2472 searchTaskInChild($inc, $lines[$i]->id, $lines, $taskrole);
2473 //print 'Found inc='.$inc.'<br>';
2474
2475 if ($inc > 0) {
2476 return $inc;
2477 }
2478 }
2479 }
2480
2481 return $inc;
2482}
2483
2498function print_projecttasks_array($db, $form, $socid, $projectsListId, $mytasks = 0, $status = -1, $listofoppstatus = array(), $hiddenfields = array(), $max = 0)
2499{
2500 global $langs, $conf, $user;
2501 global $theme_datacolor;
2502
2503 $maxofloop = (!getDolGlobalString('MAIN_MAXLIST_OVERLOAD') ? 500 : $conf->global->MAIN_MAXLIST_OVERLOAD);
2504
2505 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
2506
2507 $listofstatus = array_keys($listofoppstatus);
2508
2509 if (is_array($listofstatus) && getDolGlobalString('USE_COLOR_FOR_PROSPECTION_STATUS')) {
2510 // Define $themeColorId and array $statusOppList for each $listofstatus
2511 $themeColorId = 0;
2512 $statusOppList = array();
2513 foreach ($listofstatus as $oppStatus) {
2514 $oppStatusCode = dol_getIdFromCode($db, $oppStatus, 'c_lead_status', 'rowid', 'code');
2515 if ($oppStatusCode) {
2516 $statusOppList[$oppStatus]['code'] = $oppStatusCode;
2517 $statusOppList[$oppStatus]['color'] = isset($theme_datacolor[$themeColorId]) ? implode(', ', $theme_datacolor[$themeColorId]) : '';
2518 }
2519 $themeColorId++;
2520 }
2521 }
2522
2523 $projectstatic = new Project($db);
2524 $thirdpartystatic = new Societe($db);
2525
2526 $sortfield = '';
2527 $sortorder = '';
2528 $project_year_filter = 0;
2529
2530 $title = $langs->trans("Projects");
2531 if (strcmp($status, '') && $status >= 0) {
2532 $title = $langs->trans("Projects").' '.$langs->trans($projectstatic->labelStatus[$status]);
2533 }
2534
2535 print '<!-- print_projecttasks_array -->';
2536 print '<div class="div-table-responsive-no-min">';
2537 print '<table class="noborder centpercent">';
2538
2539 $sql = " FROM ".MAIN_DB_PREFIX."projet as p";
2540 if ($mytasks) {
2541 $sql .= ", ".MAIN_DB_PREFIX."projet_task as t";
2542 $sql .= ", ".MAIN_DB_PREFIX."element_contact as ec";
2543 $sql .= ", ".MAIN_DB_PREFIX."c_type_contact as ctc";
2544 } else {
2545 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task as t ON p.rowid = t.fk_projet";
2546 }
2547 $sql .= " WHERE p.entity IN (".getEntity('project').")";
2548 $sql .= " AND p.rowid IN (".$db->sanitize($projectsListId).")";
2549 if ($socid) {
2550 $sql .= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".((int) $socid).")";
2551 }
2552 if ($mytasks) {
2553 $sql .= " AND p.rowid = t.fk_projet";
2554 $sql .= " AND ec.element_id = t.rowid";
2555 $sql .= " AND ec.fk_socpeople = ".((int) $user->id);
2556 $sql .= " AND ec.fk_c_type_contact = ctc.rowid"; // Replace the 2 lines with ec.fk_c_type_contact in $arrayidtypeofcontact
2557 $sql .= " AND ctc.element = 'project_task'";
2558 }
2559 if ($status >= 0) {
2560 $sql .= " AND p.fk_statut = ".(int) $status;
2561 }
2562 if (getDolGlobalString('PROJECT_LIMIT_YEAR_RANGE')) {
2563 $project_year_filter = GETPOST("project_year_filter");
2564 //Check if empty or invalid year. Wildcard ignores the sql check
2565 if ($project_year_filter != "*") {
2566 if (empty($project_year_filter) || !ctype_digit($project_year_filter)) {
2567 $project_year_filter = date("Y");
2568 }
2569 $sql .= " AND (p.dateo IS NULL OR p.dateo <= ".$db->idate(dol_get_last_day($project_year_filter, 12, false)).")";
2570 $sql .= " AND (p.datee IS NULL OR p.datee >= ".$db->idate(dol_get_first_day($project_year_filter, 1, false)).")";
2571 }
2572 }
2573
2574 // Get id of project we must show tasks
2575 $arrayidofprojects = array();
2576 $sql1 = "SELECT p.rowid as projectid";
2577 $sql1 .= $sql;
2578 $resql = $db->query($sql1);
2579 if ($resql) {
2580 $i = 0;
2581 $num = $db->num_rows($resql);
2582 while ($i < $num) {
2583 $objp = $db->fetch_object($resql);
2584 $arrayidofprojects[$objp->projectid] = $objp->projectid;
2585 $i++;
2586 }
2587 } else {
2588 dol_print_error($db);
2589 }
2590 if (empty($arrayidofprojects)) {
2591 $arrayidofprojects[0] = -1;
2592 }
2593
2594 // Get list of project with calculation on tasks
2595 $sql2 = "SELECT p.rowid as projectid, p.ref, p.title, p.fk_soc,";
2596 $sql2 .= " s.rowid as socid, s.nom as socname, s.name_alias,";
2597 $sql2 .= " s.code_client, s.code_compta, s.client,";
2598 $sql2 .= " s.code_fournisseur, s.code_compta_fournisseur, s.fournisseur,";
2599 $sql2 .= " s.logo, s.email, s.entity,";
2600 $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,";
2601 $sql2 .= " p.dateo, p.datee,";
2602 $sql2 .= " COUNT(t.rowid) as nb, SUM(t.planned_workload) as planned_workload, SUM(t.planned_workload * t.progress / 100) as declared_progess_workload";
2603 $sql2 .= " FROM ".MAIN_DB_PREFIX."projet as p";
2604 $sql2 .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = p.fk_soc";
2605 $sql2 .= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task as t ON p.rowid = t.fk_projet";
2606 $sql2 .= " WHERE p.rowid IN (".$db->sanitize(join(',', $arrayidofprojects)).")";
2607 $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,";
2608 $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";
2609 $sql2 .= " ORDER BY p.title, p.ref";
2610
2611 $resql = $db->query($sql2);
2612 if ($resql) {
2613 $othernb = 0;
2614 $total_task = 0;
2615 $total_opp_amount = 0;
2616 $ponderated_opp_amount = 0;
2617 $total_plannedworkload = 0;
2618 $total_declaredprogressworkload = 0;
2619
2620 $num = $db->num_rows($resql);
2621 $nbofloop = min($num, (!getDolGlobalString('MAIN_MAXLIST_OVERLOAD') ? 500 : $conf->global->MAIN_MAXLIST_OVERLOAD));
2622 $i = 0;
2623
2624 print '<tr class="liste_titre">';
2625 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);
2626 print_liste_field_titre("ThirdParty", $_SERVER["PHP_SELF"], "", "", "", "", $sortfield, $sortorder);
2627 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
2628 if (!in_array('prospectionstatus', $hiddenfields)) {
2629 print_liste_field_titre("OpportunityStatus", "", "", "", "", 'style="max-width: 100px"', $sortfield, $sortorder, 'center ');
2630 }
2631 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 ');
2632 //print_liste_field_titre('OpportunityWeightedAmount', '', '', '', '', 'align="right"', $sortfield, $sortorder);
2633 }
2634 if (!getDolGlobalString('PROJECT_HIDE_TASKS')) {
2635 print_liste_field_titre("Tasks", "", "", "", "", 'align="right"', $sortfield, $sortorder);
2636 if (!in_array('plannedworkload', $hiddenfields)) {
2637 print_liste_field_titre("PlannedWorkload", "", "", "", "", 'style="max-width: 100px"', $sortfield, $sortorder, 'right ');
2638 }
2639 if (!in_array('declaredprogress', $hiddenfields)) {
2640 print_liste_field_titre("%", "", "", "", "", '', $sortfield, $sortorder, 'right ', $langs->trans("ProgressDeclared"));
2641 }
2642 }
2643 if (!in_array('projectstatus', $hiddenfields)) {
2644 print_liste_field_titre("Status", "", "", "", "", '', $sortfield, $sortorder, 'right ');
2645 }
2646 print "</tr>\n";
2647
2648 while ($i < $nbofloop) {
2649 $objp = $db->fetch_object($resql);
2650
2651 if ($max && $i >= $max) {
2652 $othernb++;
2653 $i++;
2654 $total_task += $objp->nb;
2655 $total_opp_amount += $objp->opp_amount;
2656 $opp_weighted_amount = $objp->opp_percent * $objp->opp_amount / 100;
2657 $ponderated_opp_amount += price2num($opp_weighted_amount);
2658 $plannedworkload = $objp->planned_workload;
2659 $total_plannedworkload += $plannedworkload;
2660 $declaredprogressworkload = $objp->declared_progess_workload;
2661 $total_declaredprogressworkload += $declaredprogressworkload;
2662 continue;
2663 }
2664
2665 $projectstatic->id = $objp->projectid;
2666 $projectstatic->user_author_id = $objp->fk_user_creat;
2667 $projectstatic->public = $objp->public;
2668
2669 // Check is user has read permission on project
2670 $userAccess = $projectstatic->restrictedProjectArea($user);
2671 if ($userAccess >= 0) {
2672 $projectstatic->ref = $objp->ref;
2673 $projectstatic->status = $objp->status;
2674 $projectstatic->title = $objp->title;
2675 $projectstatic->date_end = $db->jdate($objp->datee);
2676 $projectstatic->date_start = $db->jdate($objp->dateo);
2677
2678 print '<tr class="oddeven">';
2679
2680 print '<td class="tdoverflowmax150">';
2681 print $projectstatic->getNomUrl(1, '', 0, '', '-', 0, -1, 'nowraponall');
2682 if (!in_array('projectlabel', $hiddenfields)) {
2683 print '<br><span class="opacitymedium small">'.dol_escape_htmltag($objp->title).'</span>';
2684 }
2685 print '</td>';
2686
2687 print '<td class="nowraponall tdoverflowmax100">';
2688 if ($objp->fk_soc > 0) {
2689 $thirdpartystatic->id = $objp->socid;
2690 $thirdpartystatic->name = $objp->socname;
2691 //$thirdpartystatic->name_alias = $objp->name_alias;
2692 //$thirdpartystatic->code_client = $objp->code_client;
2693 $thirdpartystatic->code_compta = $objp->code_compta;
2694 $thirdpartystatic->client = $objp->client;
2695 //$thirdpartystatic->code_fournisseur = $objp->code_fournisseur;
2696 $thirdpartystatic->code_compta_fournisseur = $objp->code_compta_fournisseur;
2697 $thirdpartystatic->fournisseur = $objp->fournisseur;
2698 $thirdpartystatic->logo = $objp->logo;
2699 $thirdpartystatic->email = $objp->email;
2700 $thirdpartystatic->entity = $objp->entity;
2701 print $thirdpartystatic->getNomUrl(1);
2702 }
2703 print '</td>';
2704
2705 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
2706 if (!in_array('prospectionstatus', $hiddenfields)) {
2707 print '<td class="center tdoverflowmax75">';
2708 // Because color of prospection status has no meaning yet, it is used if hidden constant is set
2709 if (!getDolGlobalString('USE_COLOR_FOR_PROSPECTION_STATUS')) {
2710 $oppStatusCode = dol_getIdFromCode($db, $objp->opp_status, 'c_lead_status', 'rowid', 'code');
2711 if ($langs->trans("OppStatus".$oppStatusCode) != "OppStatus".$oppStatusCode) {
2712 print $langs->trans("OppStatus".$oppStatusCode);
2713 }
2714 } else {
2715 if (isset($statusOppList[$objp->opp_status])) {
2716 $oppStatusCode = $statusOppList[$objp->opp_status]['code'];
2717 $oppStatusColor = $statusOppList[$objp->opp_status]['color'];
2718 } else {
2719 $oppStatusCode = dol_getIdFromCode($db, $objp->opp_status, 'c_lead_status', 'rowid', 'code');
2720 $oppStatusColor = '';
2721 }
2722 if ($oppStatusCode) {
2723 if (!empty($oppStatusColor)) {
2724 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>';
2725 } else {
2726 print '<a href="'.dol_buildpath('/projet/list.php?search_opp_status='.$objp->opp_status, 1).'" title="'.$langs->trans("OppStatus".$oppStatusCode).'">'.$oppStatusCode.'</a>';
2727 }
2728 }
2729 }
2730 print '</td>';
2731 }
2732
2733 print '<td class="right">';
2734 if ($objp->opp_percent && $objp->opp_amount) {
2735 $opp_weighted_amount = $objp->opp_percent * $objp->opp_amount / 100;
2736 $alttext = $langs->trans("OpportunityWeightedAmount").' '.price($opp_weighted_amount, 0, '', 1, -1, 0, $conf->currency);
2737 $ponderated_opp_amount += price2num($opp_weighted_amount);
2738 }
2739 if ($objp->opp_amount) {
2740 print '<span class="amount" title="'.$alttext.'">'.$form->textwithpicto(price($objp->opp_amount, 0, '', 1, -1, 0), $alttext).'</span>';
2741 }
2742 print '</td>';
2743 }
2744
2745 if (!getDolGlobalString('PROJECT_HIDE_TASKS')) {
2746 print '<td class="right">'.$objp->nb.'</td>';
2747
2748 $plannedworkload = $objp->planned_workload;
2749 $total_plannedworkload += $plannedworkload;
2750 if (!in_array('plannedworkload', $hiddenfields)) {
2751 print '<td class="right nowraponall">'.($plannedworkload ? convertSecondToTime($plannedworkload) : '').'</td>';
2752 }
2753 if (!in_array('declaredprogress', $hiddenfields)) {
2754 $declaredprogressworkload = $objp->declared_progess_workload;
2755 $total_declaredprogressworkload += $declaredprogressworkload;
2756 print '<td class="right nowraponall">';
2757 //print $objp->planned_workload.'-'.$objp->declared_progess_workload."<br>";
2758 print($plannedworkload ? round(100 * $declaredprogressworkload / $plannedworkload, 0).'%' : '');
2759 print '</td>';
2760 }
2761 }
2762
2763 if (!in_array('projectstatus', $hiddenfields)) {
2764 print '<td class="right">';
2765 print $projectstatic->getLibStatut(3);
2766 print '</td>';
2767 }
2768
2769 print "</tr>\n";
2770
2771 $total_task += $objp->nb;
2772 $total_opp_amount += $objp->opp_amount;
2773 }
2774
2775 $i++;
2776 }
2777
2778 if ($othernb) {
2779 print '<tr class="oddeven">';
2780 print '<td class="nowrap" colspan="5">';
2781 print '<span class="opacitymedium">'.$langs->trans("More").'...'.($othernb < $maxofloop ? ' ('.$othernb.')' : '').'</span>';
2782 print '</td>';
2783 print "</tr>\n";
2784 }
2785
2786 print '<tr class="liste_total">';
2787 print '<td>'.$langs->trans("Total")."</td><td></td>";
2788 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
2789 if (!in_array('prospectionstatus', $hiddenfields)) {
2790 print '<td class="liste_total"></td>';
2791 }
2792 print '<td class="liste_total right">';
2793 //$form->textwithpicto(price($ponderated_opp_amount, 0, '', 1, -1, -1, $conf->currency), $langs->trans("OpportunityPonderatedAmountDesc"), 1);
2794 print $form->textwithpicto(price($total_opp_amount, 0, '', 1, -1, 0), $langs->trans("OpportunityPonderatedAmountDesc").' : '.price($ponderated_opp_amount, 0, '', 1, -1, 0, $conf->currency));
2795 print '</td>';
2796 }
2797 if (!getDolGlobalString('PROJECT_HIDE_TASKS')) {
2798 print '<td class="liste_total right">'.$total_task.'</td>';
2799 if (!in_array('plannedworkload', $hiddenfields)) {
2800 print '<td class="liste_total right">'.($total_plannedworkload ? convertSecondToTime($total_plannedworkload) : '').'</td>';
2801 }
2802 if (!in_array('declaredprogress', $hiddenfields)) {
2803 print '<td class="liste_total right">'.($total_plannedworkload ? round(100 * $total_declaredprogressworkload / $total_plannedworkload, 0).'%' : '').'</td>';
2804 }
2805 }
2806 if (!in_array('projectstatus', $hiddenfields)) {
2807 print '<td class="liste_total"></td>';
2808 }
2809 print '</tr>';
2810
2811 $db->free($resql);
2812 } else {
2813 dol_print_error($db);
2814 }
2815
2816 print "</table>";
2817 print '</div>';
2818
2819 if (getDolGlobalString('PROJECT_LIMIT_YEAR_RANGE')) {
2820 //Add the year filter input
2821 print '<form method="get" action="'.$_SERVER["PHP_SELF"].'">';
2822 print '<table width="100%">';
2823 print '<tr>';
2824 print '<td>'.$langs->trans("Year").'</td>';
2825 print '<td class="right"><input type="text" size="4" class="flat" name="project_year_filter" value="'.((int) $project_year_filter).'"/>';
2826 print "</tr>\n";
2827 print '</table></form>';
2828 }
2829}
2830
2840function getTaskProgressView($task, $label = true, $progressNumber = true, $hideOnProgressNull = false, $spaced = false)
2841{
2842 global $langs, $conf;
2843
2844 $out = '';
2845
2846 $plannedworkloadoutputformat = 'allhourmin';
2847 $timespentoutputformat = 'allhourmin';
2848 if (getDolGlobalString('PROJECT_PLANNED_WORKLOAD_FORMAT')) {
2849 $plannedworkloadoutputformat = $conf->global->PROJECT_PLANNED_WORKLOAD_FORMAT;
2850 }
2851 if (getDolGlobalString('PROJECT_TIMES_SPENT_FORMAT')) {
2852 $timespentoutputformat = $conf->global->PROJECT_TIME_SPENT_FORMAT;
2853 }
2854
2855 if (empty($task->progress) && !empty($hideOnProgressNull)) {
2856 return '';
2857 }
2858
2859 $spaced = !empty($spaced) ? 'spaced' : '';
2860
2861 $diff = '';
2862
2863 // define progress color according to time spend vs workload
2864 $progressBarClass = 'progress-bar-info';
2865 $progressCalculated = 0;
2866 if ($task->planned_workload) {
2867 $progressCalculated = round(100 * (float) $task->duration_effective / (float) $task->planned_workload, 2);
2868
2869 // this conf is actually hidden, by default we use 10% for "be carefull or warning"
2870 $warningRatio = getDolGlobalString('PROJECT_TIME_SPEND_WARNING_PERCENT') ? (1 + $conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT / 100) : 1.10;
2871
2872 $diffTitle = '<br>'.$langs->trans('ProgressDeclared').' : '.$task->progress.(isset($task->progress) ? '%' : '');
2873 $diffTitle .= '<br>'.$langs->trans('ProgressCalculated').' : '.$progressCalculated.(isset($progressCalculated) ? '%' : '');
2874
2875 //var_dump($progressCalculated.' '.$warningRatio.' '.$task->progress.' '.floatval($task->progress * $warningRatio));
2876 if ((float) $progressCalculated > (float) ($task->progress * $warningRatio)) {
2877 $progressBarClass = 'progress-bar-danger';
2878 $title = $langs->trans('TheReportedProgressIsLessThanTheCalculatedProgressionByX', abs($task->progress - $progressCalculated).' '.$langs->trans("point"));
2879 $diff = '<span class="text-danger classfortooltip paddingrightonly" title="'.dol_htmlentities($title.$diffTitle).'" ><i class="fa fa-caret-down"></i> '.($task->progress - $progressCalculated).'%</span>';
2880 } elseif ((float) $progressCalculated > (float) $task->progress) { // warning if close at 10%
2881 $progressBarClass = 'progress-bar-warning';
2882 $title = $langs->trans('TheReportedProgressIsLessThanTheCalculatedProgressionByX', abs($task->progress - $progressCalculated).' '.$langs->trans("point"));
2883 $diff = '<span class="text-warning classfortooltip paddingrightonly" title="'.dol_htmlentities($title.$diffTitle).'" ><i class="fa fa-caret-left"></i> '.($task->progress - $progressCalculated).'%</span>';
2884 } else {
2885 $progressBarClass = 'progress-bar-success';
2886 $title = $langs->trans('TheReportedProgressIsMoreThanTheCalculatedProgressionByX', ($task->progress - $progressCalculated).' '.$langs->trans("point"));
2887 $diff = '<span class="text-success classfortooltip paddingrightonly" title="'.dol_htmlentities($title.$diffTitle).'" ><i class="fa fa-caret-up"></i> '.($task->progress - $progressCalculated).'%</span>';
2888 }
2889 }
2890
2891 $out .= '<div class="progress-group">';
2892
2893 if ($label !== false) {
2894 $out .= ' <span class="progress-text">';
2895
2896 if ($label !== true) {
2897 $out .= $label; // replace label by param
2898 } else {
2899 $out .= $task->getNomUrl(1).' '.dol_htmlentities($task->label);
2900 }
2901 $out .= ' </span>';
2902 }
2903
2904
2905 if ($progressNumber !== false) {
2906 $out .= ' <span class="progress-number">';
2907 if ($progressNumber !== true) {
2908 $out .= $progressNumber; // replace label by param
2909 } else {
2910 if ($task->hasDelay()) {
2911 $out .= img_warning($langs->trans("Late")).' ';
2912 }
2913
2914 $url = DOL_URL_ROOT.'/projet/tasks/time.php?id='.$task->id;
2915
2916 $out .= !empty($diff) ? $diff.' ' : '';
2917 $out .= '<a href="'.$url.'" >';
2918 $out .= '<b title="'.$langs->trans('TimeSpent').'" >';
2919 if ($task->duration_effective) {
2920 $out .= convertSecondToTime($task->duration_effective, $timespentoutputformat);
2921 } else {
2922 $out .= '--:--';
2923 }
2924 $out .= '</b>';
2925 $out .= '</a>';
2926
2927 $out .= ' / ';
2928
2929 $out .= '<a href="'.$url.'" >';
2930 $out .= '<span title="'.$langs->trans('PlannedWorkload').'" >';
2931 if ($task->planned_workload) {
2932 $out .= convertSecondToTime($task->planned_workload, $plannedworkloadoutputformat);
2933 } else {
2934 $out .= '--:--';
2935 }
2936 $out .= '</a>';
2937 }
2938 $out .= ' </span>';
2939 }
2940
2941
2942 $out .= '</span>';
2943 $out .= ' <div class="progress sm '.$spaced.'">';
2944 $diffval = (float) $task->progress - (float) $progressCalculated;
2945 if ($diffval >= 0) {
2946 // good
2947 $out .= ' <div class="progress-bar '.$progressBarClass.'" style="width: '.(float) $task->progress.'%" title="'.(float) $task->progress.'%">';
2948 if (!empty($task->progress)) {
2949 $out .= ' <div class="progress-bar progress-bar-consumed" style="width: '.(float) ($progressCalculated / ((float) $task->progress == 0 ? 1 : $task->progress) * 100).'%" title="'.(float) $progressCalculated.'%"></div>';
2950 }
2951 $out .= ' </div>';
2952 } else {
2953 // bad
2954 $out .= ' <div class="progress-bar progress-bar-consumed-late" style="width: '.(float) $progressCalculated.'%" title="'.(float) $progressCalculated.'%">';
2955 $out .= ' <div class="progress-bar '.$progressBarClass.'" style="width: '.($task->progress ? (float) ($task->progress / ((float) $progressCalculated == 0 ? 1 : $progressCalculated) * 100).'%' : '1px').'" title="'.(float) $task->progress.'%"></div>';
2956 $out .= ' </div>';
2957 }
2958 $out .= ' </div>';
2959 $out .= '</div>';
2960
2961
2962
2963 return $out;
2964}
2972function getTaskProgressBadge($task, $label = '', $tooltip = '')
2973{
2974 global $conf, $langs;
2975
2976 $out = '';
2977 $badgeClass = '';
2978 if ($task->progress != '') {
2979 // TODO : manage 100%
2980
2981 // define color according to time spend vs workload
2982 $badgeClass = 'badge ';
2983 if ($task->planned_workload) {
2984 $progressCalculated = round(100 * (float) $task->duration_effective / (float) $task->planned_workload, 2);
2985
2986 // this conf is actually hidden, by default we use 10% for "be carefull or warning"
2987 $warningRatio = getDolGlobalString('PROJECT_TIME_SPEND_WARNING_PERCENT') ? (1 + $conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT / 100) : 1.10;
2988
2989 if ((float) $progressCalculated > (float) ($task->progress * $warningRatio)) {
2990 $badgeClass .= 'badge-danger';
2991 if (empty($tooltip)) {
2992 $tooltip = $task->progress.'% < '.$langs->trans("TimeConsumed").' '.$progressCalculated.'%';
2993 }
2994 } elseif ((float) $progressCalculated > (float) $task->progress) { // warning if close at 10%
2995 $badgeClass .= 'badge-warning';
2996 if (empty($tooltip)) {
2997 $tooltip = $task->progress.'% < '.$langs->trans("TimeConsumed").' '.$progressCalculated.'%';
2998 }
2999 } else {
3000 $badgeClass .= 'badge-success';
3001 if (empty($tooltip)) {
3002 $tooltip = $task->progress.'% >= '.$langs->trans("TimeConsumed").' '.$progressCalculated.'%';
3003 }
3004 }
3005 }
3006 }
3007
3008 $title = '';
3009 if (!empty($tooltip)) {
3010 $badgeClass .= ' classfortooltip';
3011 $title = 'title="'.dol_htmlentities($tooltip).'"';
3012 }
3013
3014 if (empty($label)) {
3015 $label = $task->progress.' %';
3016 }
3017
3018 if (!empty($label)) {
3019 $out = '<span class="'.$badgeClass.'" '.$title.' >'.$label.'</span>';
3020 }
3021
3022 return $out;
3023}
print $langs trans("AuditedSecurityEvents").'</strong >< span class="opacitymedium"></span >< br > status
Definition security.php:604
$object ref
Definition info.php:79
Class for ConferenceOrBoothAttendee.
Class for ConferenceOrBooth.
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:125
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:243
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:1926
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.
Contact()
Old copy.
Definition index.php:572