Passed
Branch develop (0646b1)
by
unknown
28:14
created

getTaskProgressBadge()   C

Complexity

Conditions 12
Paths 112

Size

Total Lines 48
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 26
c 0
b 0
f 0
nc 112
nop 3
dl 0
loc 48
rs 6.8666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/* Copyright (C) 2006-2015 Laurent Destailleur  <[email protected]>
3
 * Copyright (C) 2010      Regis Houssin        <[email protected]>
4
 * Copyright (C) 2011      Juanjo Menent        <[email protected]>
5
 * Copyright (C) 2018       Frédéric France         <[email protected]>
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19
 * or see https://www.gnu.org/
20
 */
21
22
/**
23
 *	    \file       htdocs/core/lib/project.lib.php
24
 *		\brief      Functions used by project module
25
 *      \ingroup    project
26
 */
27
require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
28
29
30
/**
31
 * Prepare array with list of tabs
32
 *
33
 * @param   Object	$object		Object related to tabs
34
 * @return  array				Array of tabs to show
35
 */
36
function project_prepare_head($object)
37
{
38
	global $db, $langs, $conf, $user;
39
40
	$h = 0;
41
	$head = array();
42
43
	$head[$h][0] = DOL_URL_ROOT.'/projet/card.php?id='.$object->id;
44
	$head[$h][1] = $langs->trans("Project");
45
	$head[$h][2] = 'project';
46
	$h++;
47
48
	$nbContact = count($object->liste_contact(-1, 'internal')) + count($object->liste_contact(-1, 'external'));
49
	$head[$h][0] = DOL_URL_ROOT.'/projet/contact.php?id='.$object->id;
50
	$head[$h][1] = $langs->trans("ProjectContact");
51
	if ($nbContact > 0) $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbContact.'</span>';
52
	$head[$h][2] = 'contact';
53
	$h++;
54
55
	if (empty($conf->global->PROJECT_HIDE_TASKS))
56
	{
57
		// Then tab for sub level of projet, i mean tasks
58
		$head[$h][0] = DOL_URL_ROOT.'/projet/tasks.php?id='.$object->id;
59
		$head[$h][1] = $langs->trans("Tasks");
60
61
		require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
62
		$taskstatic = new Task($db);
63
		$nbTasks = count($taskstatic->getTasksArray(0, 0, $object->id, 0, 0));
64
		if ($nbTasks > 0) $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($nbTasks).'</span>';
65
		$head[$h][2] = 'tasks';
66
		$h++;
67
68
		$nbTimeSpent = 0;
69
		$sql = "SELECT t.rowid";
70
		//$sql .= " FROM ".MAIN_DB_PREFIX."projet_task_time as t, ".MAIN_DB_PREFIX."projet_task as pt, ".MAIN_DB_PREFIX."user as u";
71
		//$sql .= " WHERE t.fk_user = u.rowid AND t.fk_task = pt.rowid";
72
		$sql .= " FROM ".MAIN_DB_PREFIX."projet_task_time as t, ".MAIN_DB_PREFIX."projet_task as pt";
73
		$sql .= " WHERE t.fk_task = pt.rowid";
74
		$sql .= " AND pt.fk_projet =".$object->id;
75
		$resql = $db->query($sql);
76
		if ($resql)
77
		{
78
			$obj = $db->fetch_object($resql);
79
			if ($obj) $nbTimeSpent = 1;
80
		}
81
		else dol_print_error($db);
82
83
		$head[$h][0] = DOL_URL_ROOT.'/projet/tasks/time.php?withproject=1&projectid='.$object->id;
84
		$head[$h][1] = $langs->trans("TimeSpent");
85
		if ($nbTimeSpent > 0) $head[$h][1] .= '<span class="badge marginleftonlyshort">...</span>';
86
		$head[$h][2] = 'timespent';
87
		$h++;
88
	}
89
90
	if (!empty($conf->fournisseur->enabled) || !empty($conf->propal->enabled) || !empty($conf->commande->enabled)
91
		|| !empty($conf->facture->enabled) || !empty($conf->contrat->enabled)
92
		|| !empty($conf->ficheinter->enabled) || !empty($conf->agenda->enabled) || !empty($conf->deplacement->enabled))
93
	{
94
		$head[$h][0] = DOL_URL_ROOT.'/projet/element.php?id='.$object->id;
95
		$head[$h][1] = $langs->trans("ProjectOverview");
96
		$head[$h][2] = 'element';
97
		$h++;
98
	}
99
100
	// Show more tabs from modules
101
	// Entries must be declared in modules descriptor with line
102
	// $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__');   to add new tab
103
	// $this->tabs = array('entity:-tabname);   												to remove a tab
104
	complete_head_from_modules($conf, $langs, $object, $head, $h, 'project');
105
106
107
	if (empty($conf->global->MAIN_DISABLE_NOTES_TAB))
108
	{
109
		$nbNote = 0;
110
		if (!empty($object->note_private)) $nbNote++;
111
		if (!empty($object->note_public)) $nbNote++;
112
		$head[$h][0] = DOL_URL_ROOT.'/projet/note.php?id='.$object->id;
113
		$head[$h][1] = $langs->trans('Notes');
114
		if ($nbNote > 0) $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbNote.'</span>';
115
		$head[$h][2] = 'notes';
116
		$h++;
117
	}
118
119
	require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
120
	require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
121
	$upload_dir = $conf->projet->dir_output."/".dol_sanitizeFileName($object->ref);
122
	$nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$'));
123
	$nbLinks = Link::count($db, $object->element, $object->id);
124
	$head[$h][0] = DOL_URL_ROOT.'/projet/document.php?id='.$object->id;
125
	$head[$h][1] = $langs->trans('Documents');
126
	if (($nbFiles + $nbLinks) > 0) $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($nbFiles + $nbLinks).'</span>';
127
	$head[$h][2] = 'document';
128
	$h++;
129
130
	// Manage discussion
131
	if (!empty($conf->global->PROJECT_ALLOW_COMMENT_ON_PROJECT))
132
	{
133
		$nbComments = $object->getNbComments();
134
		$head[$h][0] = DOL_URL_ROOT.'/projet/comment.php?id='.$object->id;
135
		$head[$h][1] = $langs->trans("CommentLink");
136
		if ($nbComments > 0) $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbComments.'</span>';
137
		$head[$h][2] = 'project_comment';
138
		$h++;
139
	}
140
141
	$head[$h][0] = DOL_URL_ROOT.'/projet/info.php?id='.$object->id;
142
	$head[$h][1] .= $langs->trans("Events");
143
	if (!empty($conf->agenda->enabled) && (!empty($user->rights->agenda->myactions->read) || !empty($user->rights->agenda->allactions->read)))
144
	{
145
		$head[$h][1] .= '/';
146
		$head[$h][1] .= $langs->trans("Agenda");
147
	}
148
	$head[$h][2] = 'agenda';
149
	$h++;
150
151
	complete_head_from_modules($conf, $langs, $object, $head, $h, 'project', 'remove');
152
153
	return $head;
154
}
155
156
157
/**
158
 * Prepare array with list of tabs
159
 *
160
 * @param   Object	$object		Object related to tabs
161
 * @return  array				Array of tabs to show
162
 */
163
function task_prepare_head($object)
164
{
165
	global $db, $langs, $conf, $user;
166
	$h = 0;
167
	$head = array();
168
169
	$head[$h][0] = DOL_URL_ROOT.'/projet/tasks/task.php?id='.$object->id.(GETPOST('withproject') ? '&withproject=1' : '');
170
	$head[$h][1] = $langs->trans("Card");
171
	$head[$h][2] = 'task_task';
172
	$h++;
173
174
	$nbContact = count($object->liste_contact(-1, 'internal')) + count($object->liste_contact(-1, 'external'));
175
	$head[$h][0] = DOL_URL_ROOT.'/projet/tasks/contact.php?id='.$object->id.(GETPOST('withproject') ? '&withproject=1' : '');
176
	$head[$h][1] = $langs->trans("TaskRessourceLinks");
177
	if ($nbContact > 0) $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbContact.'</span>';
178
	$head[$h][2] = 'task_contact';
179
	$h++;
180
181
	// Is there timespent ?
182
	$nbTimeSpent = 0;
183
	$sql = "SELECT t.rowid";
184
	//$sql .= " FROM ".MAIN_DB_PREFIX."projet_task_time as t, ".MAIN_DB_PREFIX."projet_task as pt, ".MAIN_DB_PREFIX."user as u";
185
	//$sql .= " WHERE t.fk_user = u.rowid AND t.fk_task = pt.rowid";
186
	$sql .= " FROM ".MAIN_DB_PREFIX."projet_task_time as t";
187
	$sql .= " WHERE t.fk_task =".$object->id;
188
	$resql = $db->query($sql);
189
	if ($resql)
190
	{
191
		$obj = $db->fetch_object($resql);
192
		if ($obj) $nbTimeSpent = 1;
193
	}
194
	else dol_print_error($db);
195
196
	$head[$h][0] = DOL_URL_ROOT.'/projet/tasks/time.php?id='.$object->id.(GETPOST('withproject') ? '&withproject=1' : '');
197
	$head[$h][1] = $langs->trans("TimeSpent");
198
	if ($nbTimeSpent > 0) $head[$h][1] .= '<span class="badge marginleftonlyshort">...</span>';
199
	$head[$h][2] = 'task_time';
200
	$h++;
201
202
	// Show more tabs from modules
203
	// Entries must be declared in modules descriptor with line
204
	// $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__');   to add new tab
205
	// $this->tabs = array('entity:-tabname);   												to remove a tab
206
	complete_head_from_modules($conf, $langs, $object, $head, $h, 'task');
207
208
	if (empty($conf->global->MAIN_DISABLE_NOTES_TAB))
209
	{
210
		$nbNote = 0;
211
		if (!empty($object->note_private)) $nbNote++;
212
		if (!empty($object->note_public)) $nbNote++;
213
		$head[$h][0] = DOL_URL_ROOT.'/projet/tasks/note.php?id='.$object->id.(GETPOST('withproject') ? '&withproject=1' : '');
214
		$head[$h][1] = $langs->trans('Notes');
215
		if ($nbNote > 0) $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbNote.'</span>';
216
		$head[$h][2] = 'task_notes';
217
		$h++;
218
	}
219
220
	$head[$h][0] = DOL_URL_ROOT.'/projet/tasks/document.php?id='.$object->id.(GETPOST('withproject') ? '&withproject=1' : '');
221
	$filesdir = $conf->projet->dir_output."/".dol_sanitizeFileName($object->project->ref).'/'.dol_sanitizeFileName($object->ref);
222
	include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
223
	include_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
224
	$nbFiles = count(dol_dir_list($filesdir, 'files', 0, '', '(\.meta|_preview.*\.png)$'));
225
	$nbLinks = Link::count($db, $object->element, $object->id);
226
	$head[$h][1] = $langs->trans('Documents');
227
	if (($nbFiles + $nbLinks) > 0) $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($nbFiles + $nbLinks).'</span>';
228
	$head[$h][2] = 'task_document';
229
	$h++;
230
231
	// Manage discussion
232
	if (!empty($conf->global->PROJECT_ALLOW_COMMENT_ON_TASK))
233
	{
234
		$nbComments = $object->getNbComments();
235
		$head[$h][0] = DOL_URL_ROOT.'/projet/tasks/comment.php?id='.$object->id.(GETPOST('withproject') ? '&withproject=1' : '');
236
		$head[$h][1] = $langs->trans("CommentLink");
237
		if ($nbComments > 0) $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbComments.'</span>';
238
		$head[$h][2] = 'task_comment';
239
		$h++;
240
	}
241
242
	complete_head_from_modules($conf, $langs, $object, $head, $h, 'task', 'remove');
243
244
	return $head;
245
}
246
247
/**
248
 * Prepare array with list of tabs
249
 *
250
 * @param	string	$mode		Mode
251
 * @param   string  $fuser      Filter on user
252
 * @return  array				Array of tabs to show
253
 */
254
function project_timesheet_prepare_head($mode, $fuser = null)
255
{
256
	global $langs, $conf, $user;
257
	$h = 0;
258
	$head = array();
259
260
	$h = 0;
261
262
	$param = '';
263
	$param .= ($mode ? '&mode='.$mode : '');
264
	if (is_object($fuser) && $fuser->id > 0 && $fuser->id != $user->id) $param .= '&search_usertoprocessid='.$fuser->id;
265
266
	if (empty($conf->global->PROJECT_DISABLE_TIMESHEET_PERMONTH))
267
	{
268
		$head[$h][0] = DOL_URL_ROOT."/projet/activity/permonth.php".($param ? '?'.$param : '');
269
		$head[$h][1] = $langs->trans("InputPerMonth");
270
		$head[$h][2] = 'inputpermonth';
271
		$h++;
272
	}
273
274
	if (empty($conf->global->PROJECT_DISABLE_TIMESHEET_PERWEEK))
275
	{
276
		$head[$h][0] = DOL_URL_ROOT."/projet/activity/perweek.php".($param ? '?'.$param : '');
277
		$head[$h][1] = $langs->trans("InputPerWeek");
278
		$head[$h][2] = 'inputperweek';
279
		$h++;
280
	}
281
282
	if (empty($conf->global->PROJECT_DISABLE_TIMESHEET_PERTIME))
283
	{
284
		$head[$h][0] = DOL_URL_ROOT."/projet/activity/perday.php".($param ? '?'.$param : '');
285
		$head[$h][1] = $langs->trans("InputPerDay");
286
		$head[$h][2] = 'inputperday';
287
		$h++;
288
	}
289
290
	/*if ($conf->global->MAIN_FEATURES_LEVEL >= 2)
291
	{
292
		$head[$h][0] = DOL_URL_ROOT."/projet/activity/perline.php".($param?'?'.$param:'');
293
		$head[$h][1] = $langs->trans("InputDetail");
294
		$head[$h][2] = 'inputperline';
295
		$h++;
296
	}*/
297
298
	complete_head_from_modules($conf, $langs, null, $head, $h, 'project_timesheet');
299
300
	complete_head_from_modules($conf, $langs, null, $head, $h, 'project_timesheet', 'remove');
301
302
	return $head;
303
}
304
305
306
/**
307
 * Prepare array with list of tabs
308
 *
309
 * @return  array				Array of tabs to show
310
 */
311
function project_admin_prepare_head()
312
{
313
	global $langs, $conf, $user;
314
	$h = 0;
315
	$head = array();
316
317
	$h = 0;
318
319
	$head[$h][0] = DOL_URL_ROOT."/projet/admin/project.php";
320
	$head[$h][1] = $langs->trans("Projects");
321
	$head[$h][2] = 'project';
322
	$h++;
323
324
	complete_head_from_modules($conf, $langs, null, $head, $h, 'project_admin');
325
326
	$head[$h][0] = DOL_URL_ROOT."/projet/admin/project_extrafields.php";
327
	$head[$h][1] = $langs->trans("ExtraFieldsProject");
328
	$head[$h][2] = 'attributes';
329
	$h++;
330
331
	$head[$h][0] = DOL_URL_ROOT.'/projet/admin/project_task_extrafields.php';
332
	$head[$h][1] = $langs->trans("ExtraFieldsProjectTask");
333
	$head[$h][2] = 'attributes_task';
334
	$h++;
335
336
	complete_head_from_modules($conf, $langs, null, $head, $h, 'project_admin', 'remove');
337
338
	return $head;
339
}
340
341
342
/**
343
 * Show task lines with a particular parent
344
 *
345
 * @param	string	   	$inc				    Line number (start to 0, then increased by recursive call)
346
 * @param   string		$parent				    Id of parent project to show (0 to show all)
347
 * @param   Task[]		$lines				    Array of lines
348
 * @param   int			$level				    Level (start to 0, then increased/decrease by recursive call), or -1 to show all level in order of $lines without the recursive groupment feature.
349
 * @param 	string		$var				    Color
350
 * @param 	int			$showproject		    Show project columns
351
 * @param	int			$taskrole			    Array of roles of user for each tasks
352
 * @param	int			$projectsListId		    List of id of project allowed to user (string separated with comma)
353
 * @param	int			$addordertick		    Add a tick to move task
354
 * @param   int         $projectidfortotallink  0 or Id of project to use on total line (link to see all time consumed for project)
355
 * @param   string      $filterprogresscalc     filter text
356
 * @param   string      $showbilltime           Add the column 'TimeToBill' and 'TimeBilled'
357
 * @return	int									Nb of tasks shown
358
 */
359
function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$taskrole, $projectsListId = '', $addordertick = 0, $projectidfortotallink = 0, $filterprogresscalc = '', $showbilltime = 0)
360
{
361
	global $user, $bc, $langs, $conf, $db;
362
	global $projectstatic, $taskstatic;
363
364
	$lastprojectid = 0;
365
366
	$projectsArrayId = explode(',', $projectsListId);
367
	if ($filterprogresscalc !== '') {
368
		foreach ($lines as $key=>$line) {
369
			if (!empty($line->planned_workload) && !empty($line->duration)) {
370
				$filterprogresscalc = str_replace(' = ', ' == ', $filterprogresscalc);
371
				if (!eval($filterprogresscalc)) {
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
372
					unset($lines[$key]);
373
				}
374
			}
375
		}
376
		$lines = array_values($lines);
377
	}
378
379
	$numlines = count($lines);
380
381
	// We declare counter as global because we want to edit them into recursive call
382
	global $total_projectlinesa_spent, $total_projectlinesa_planned, $total_projectlinesa_spent_if_planned, $total_projectlinesa_declared_if_planned, $total_projectlinesa_tobill, $total_projectlinesa_billed;
383
384
	if ($level == 0)
385
	{
386
		$total_projectlinesa_spent = 0;
387
		$total_projectlinesa_planned = 0;
388
		$total_projectlinesa_spent_if_planned = 0;
389
        $total_projectlinesa_declared_if_planned = 0;
390
		$total_projectlinesa_tobill = 0;
391
		$total_projectlinesa_billed = 0;
392
	}
393
394
	for ($i = 0; $i < $numlines; $i++)
395
	{
396
		if ($parent == 0 && $level >= 0) $level = 0; // if $level = -1, we dont' use sublevel recursion, we show all lines
397
398
		// Process line
399
		// print "i:".$i."-".$lines[$i]->fk_project.'<br>';
400
401
		if ($lines[$i]->fk_parent == $parent || $level < 0)       // if $level = -1, we dont' use sublevel recursion, we show all lines
402
		{
403
			// Show task line.
404
			$showline = 1;
405
			$showlineingray = 0;
406
407
			// If there is filters to use
408
			if (is_array($taskrole))
409
			{
410
				// If task not legitimate to show, search if a legitimate task exists later in tree
411
				if (!isset($taskrole[$lines[$i]->id]) && $lines[$i]->id != $lines[$i]->fk_parent)
412
				{
413
					// So search if task has a subtask legitimate to show
414
					$foundtaskforuserdeeper = 0;
415
					searchTaskInChild($foundtaskforuserdeeper, $lines[$i]->id, $lines, $taskrole);
416
					//print '$foundtaskforuserpeeper='.$foundtaskforuserdeeper.'<br>';
417
					if ($foundtaskforuserdeeper > 0)
418
					{
419
						$showlineingray = 1; // We will show line but in gray
420
					}
421
					else
422
					{
423
						$showline = 0; // No reason to show line
424
					}
425
				}
426
			}
427
			else
428
			{
429
				// 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
430
				// or into all other projects if user has permission to).
431
				if (empty($user->rights->projet->all->lire))
432
				{
433
					// User is not allowed on this project and project is not public, so we hide line
434
					if (!in_array($lines[$i]->fk_project, $projectsArrayId))
435
					{
436
						// Note that having a user assigned to a task into a project user has no permission on, should not be possible
437
						// because assignement on task can be done only on contact of project.
438
						// If assignement was done and after, was removed from contact of project, then we can hide the line.
439
						$showline = 0;
440
					}
441
				}
442
			}
443
444
			if ($showline)
445
			{
446
				// Break on a new project
447
				if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid)
448
				{
449
					$var = !$var;
450
					$lastprojectid = $lines[$i]->fk_project;
451
				}
452
453
				print '<tr '.$bc[$var].' id="row-'.$lines[$i]->id.'">'."\n";
454
455
				$projectstatic->id = $lines[$i]->fk_project;
456
				$projectstatic->ref = $lines[$i]->projectref;
457
				$projectstatic->public = $lines[$i]->public;
458
				$projectstatic->title = $lines[$i]->projectlabel;
459
				$projectstatic->usage_bill_time = $lines[$i]->usage_bill_time;
460
461
				$taskstatic->id = $lines[$i]->id;
462
				$taskstatic->ref = $lines[$i]->ref;
463
				$taskstatic->label = ($taskrole[$lines[$i]->id] ? $langs->trans("YourRole").': '.$taskrole[$lines[$i]->id] : '');
464
				$taskstatic->projectstatus = $lines[$i]->projectstatus;
465
				$taskstatic->progress = $lines[$i]->progress;
466
				$taskstatic->fk_statut = $lines[$i]->status;
467
				$taskstatic->datee = $lines[$i]->date_end;
468
                $taskstatic->planned_workload = $lines[$i]->planned_workload;
469
                $taskstatic->duration_effective = $lines[$i]->duration;
470
471
472
				if ($showproject)
473
				{
474
					// Project ref
475
					print "<td>";
476
					//if ($showlineingray) print '<i>';
477
					if ($lines[$i]->public || in_array($lines[$i]->fk_project, $projectsArrayId) || !empty($user->rights->projet->all->lire)) print $projectstatic->getNomUrl(1);
478
					else print $projectstatic->getNomUrl(1, 'nolink');
479
					//if ($showlineingray) print '</i>';
480
					print "</td>";
481
482
					// Project status
483
					print '<td>';
484
					$projectstatic->statut = $lines[$i]->projectstatus;
485
					print $projectstatic->getLibStatut(2);
486
					print "</td>";
487
				}
488
489
				// Ref of task
490
				print '<td class="nowraponall">';
491
				if ($showlineingray)
492
				{
493
					print '<i>'.img_object('', 'projecttask').' '.$lines[$i]->ref.'</i>';
494
				}
495
				else
496
				{
497
					print $taskstatic->getNomUrl(1, 'withproject');
498
				}
499
				print '</td>';
500
501
				// Title of task
502
				print "<td>";
503
				if ($showlineingray) print '<i>';
504
				//else print '<a href="'.DOL_URL_ROOT.'/projet/tasks/task.php?id='.$lines[$i]->id.'&withproject=1">';
505
				for ($k = 0; $k < $level; $k++)
506
				{
507
					print '<div class="marginleftonly">';
508
				}
509
				print $lines[$i]->label;
510
				for ($k = 0; $k < $level; $k++)
511
				{
512
					print '</div>';
513
				}
514
				if ($showlineingray) print '</i>';
515
				//else print '</a>';
516
				print "</td>\n";
517
518
				// Date start
519
				print '<td class="center">';
520
				print dol_print_date($lines[$i]->date_start, 'dayhour');
521
				print '</td>';
522
523
				// Date end
524
				print '<td class="center">';
525
				print dol_print_date($lines[$i]->date_end, 'dayhour');
526
				if ($taskstatic->hasDelay()) print img_warning($langs->trans("Late"));
527
				print '</td>';
528
529
				$plannedworkloadoutputformat = 'allhourmin';
530
				$timespentoutputformat = 'allhourmin';
531
				if (!empty($conf->global->PROJECT_PLANNED_WORKLOAD_FORMAT)) $plannedworkloadoutputformat = $conf->global->PROJECT_PLANNED_WORKLOAD_FORMAT;
532
				if (!empty($conf->global->PROJECT_TIMES_SPENT_FORMAT)) $timespentoutputformat = $conf->global->PROJECT_TIME_SPENT_FORMAT;
533
534
				// Planned Workload (in working hours)
535
				print '<td class="right">';
536
				$fullhour = convertSecondToTime($lines[$i]->planned_workload, $plannedworkloadoutputformat);
537
				$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
538
				if ($lines[$i]->planned_workload != '')
539
				{
540
					print $fullhour;
541
					// TODO Add delay taking account of working hours per day and working day per week
542
					//if ($workingdelay != $fullhour) print '<br>('.$workingdelay.')';
543
				}
544
				//else print '--:--';
545
				print '</td>';
546
547
				// Time spent
548
				print '<td class="right">';
549
				if ($showlineingray) print '<i>';
550
				else print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$lines[$i]->id.($showproject ? '' : '&withproject=1').'">';
551
				if ($lines[$i]->duration) print convertSecondToTime($lines[$i]->duration, $timespentoutputformat);
552
				else print '--:--';
553
				if ($showlineingray) print '</i>';
554
				else print '</a>';
555
				print '</td>';
556
557
				// Progress calculated (Note: ->duration is time spent)
558
				print '<td class="right">';
559
				if ($lines[$i]->planned_workload || $lines[$i]->duration)
560
				{
561
					if ($lines[$i]->planned_workload) print round(100 * $lines[$i]->duration / $lines[$i]->planned_workload, 2).' %';
562
					else print '<span class="opacitymedium">'.$langs->trans('WorkloadNotDefined').'</span>';
563
				}
564
				print '</td>';
565
566
				// Progress declared
567
				print '<td class="right">';
568
				if ($lines[$i]->progress != '')
569
				{
570
					print getTaskProgressBadge($taskstatic);
571
				}
572
				print '</td>';
573
574
				// resume
575
                print '<td class="right">';
576
                if ($lines[$i]->progress != '' && $lines[$i]->duration) {
577
                    print getTaskProgressView($taskstatic, false, false);
578
                }
579
                print '</td>';
580
581
				if ($showbilltime)
582
				{
583
    				// Time not billed
584
    				print '<td class="right">';
585
    				if ($lines[$i]->usage_bill_time)
586
    				{
587
    				    print convertSecondToTime($lines[$i]->tobill, 'allhourmin');
588
    				    $total_projectlinesa_tobill += $lines[$i]->tobill;
589
    				}
590
    				else
591
    				{
592
    				    print '<span class="opacitymedium">'.$langs->trans("NA").'</span>';
593
    				}
594
    				print '</td>';
595
596
    				// Time billed
597
    				print '<td class="right">';
598
    				if ($lines[$i]->usage_bill_time)
599
    				{
600
    				    print convertSecondToTime($lines[$i]->billed, 'allhourmin');
601
    				    $total_projectlinesa_billed += $lines[$i]->billed;
602
    				}
603
    				else
604
    				{
605
    				    print '<span class="opacitymedium">'.$langs->trans("NA").'</span>';
606
    				}
607
    				print '</td>';
608
				}
609
610
				// Contacts of task
611
				if (!empty($conf->global->PROJECT_SHOW_CONTACTS_IN_LIST))
612
				{
613
					print '<td>';
614
					foreach (array('internal', 'external') as $source)
615
					{
616
						$tab = $lines[$i]->liste_contact(-1, $source);
617
						$num = count($tab);
618
						if (!empty($num)) {
619
							foreach ($tab as $contacttask) {
620
								//var_dump($contacttask);
621
								if ($source == 'internal') $c = new User($db);
622
								else $c = new Contact($db);
623
								$c->fetch($contacttask['id']);
624
								print $c->getNomUrl(1).' ('.$contacttask['libelle'].')'.'<br>';
625
							}
626
						}
627
					}
628
					print '</td>';
629
				}
630
631
				// Tick to drag and drop
632
				if ($addordertick)
633
				{
634
					print '<td class="tdlineupdown hideonsmartphone center">&nbsp;</td>';
635
				}
636
637
				print "</tr>\n";
638
639
				if (!$showlineingray) $inc++;
640
641
				if ($level >= 0)    // Call sublevels
642
				{
643
					$level++;
644
					if ($lines[$i]->id) projectLinesa($inc, $lines[$i]->id, $lines, $level, $var, $showproject, $taskrole, $projectsListId, $addordertick, $projectidfortotallink, $filterprogresscalc, $showbilltime);
645
					$level--;
646
				}
647
648
				$total_projectlinesa_spent += $lines[$i]->duration;
649
				$total_projectlinesa_planned += $lines[$i]->planned_workload;
650
				if ($lines[$i]->planned_workload) $total_projectlinesa_spent_if_planned += $lines[$i]->duration;
651
                if ($lines[$i]->planned_workload) $total_projectlinesa_declared_if_planned += $lines[$i]->planned_workload * $lines[$i]->progress / 100;
652
			}
653
		}
654
		else
655
		{
656
			//$level--;
657
		}
658
	}
659
660
	if (($total_projectlinesa_planned > 0 || $total_projectlinesa_spent > 0 || $total_projectlinesa_tobill > 0 || $total_projectlinesa_billed > 0)
661
	    && $level <= 0)
662
	{
663
		print '<tr class="liste_total nodrag nodrop">';
664
		print '<td class="liste_total">'.$langs->trans("Total").'</td>';
665
		if ($showproject) print '<td></td><td></td>';
666
		print '<td></td>';
667
		print '<td></td>';
668
		print '<td></td>';
669
		print '<td class="nowrap liste_total right">';
670
		print convertSecondToTime($total_projectlinesa_planned, 'allhourmin');
671
		print '</td>';
672
		print '<td class="nowrap liste_total right">';
673
		if ($projectidfortotallink > 0) print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?projectid='.$projectidfortotallink.($showproject ? '' : '&withproject=1').'">';
674
		print convertSecondToTime($total_projectlinesa_spent, 'allhourmin');
675
		if ($projectidfortotallink > 0) print '</a>';
676
		print '</td>';
677
678
        if ($total_projectlinesa_planned) {
679
            $totalAverageDeclaredProgress = round(100 * $total_projectlinesa_declared_if_planned / $total_projectlinesa_planned, 2);
680
            $totalCalculatedProgress = round(100 * $total_projectlinesa_spent / $total_projectlinesa_planned, 2);
681
682
            // this conf is actually hidden, by default we use 10% for "be carefull or warning"
683
            $warningRatio = !empty($conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT) ? (1 + $conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT / 100) : 1.10;
684
685
            // define progress color according to time spend vs workload
686
            $progressBarClass = 'progress-bar-info';
687
            $badgeClass = 'badge ';
688
689
            if ($totalCalculatedProgress > $totalAverageDeclaredProgress) {
690
                $progressBarClass = 'progress-bar-danger';
691
                $badgeClass .= 'badge-danger';
692
            } elseif ($totalCalculatedProgress * $warningRatio >= $totalAverageDeclaredProgress) { // warning if close at 1%
693
                $progressBarClass = 'progress-bar-warning';
694
                $badgeClass .= 'badge-warning';
695
            } else {
696
                $progressBarClass = 'progress-bar-success';
697
                $badgeClass .= 'badge-success';
698
            }
699
        }
700
701
		print '<td class="nowrap liste_total right">';
702
		if ($total_projectlinesa_planned) print $totalCalculatedProgress.' %';
703
		print '</td>';
704
		print '<td class="nowrap liste_total right">';
705
        if ($total_projectlinesa_planned) print '<span class="'.$badgeClass.'" >'.$totalAverageDeclaredProgress.' %</span>';
706
		print '</td>';
707
708
709
        // resume
710
        print '<td class="right">';
711
        if ($total_projectlinesa_planned) {
712
            print '</span>';
713
            print '    <div class="progress sm" title="'.$totalAverageDeclaredProgress.'%" >';
714
            print '        <div class="progress-bar '.$progressBarClass.'" style="width: '.$totalAverageDeclaredProgress.'%"></div>';
715
            print '    </div>';
716
            print '</div>';
717
        }
718
        print '</td>';
719
720
		if ($showbilltime)
721
		{
722
    		print '<td class="nowrap liste_total right">';
723
    		print convertSecondToTime($total_projectlinesa_tobill, 'allhourmin');
724
    		print '</td>';
725
    		print '<td class="nowrap liste_total right">';
726
    		print convertSecondToTime($total_projectlinesa_billed, 'allhourmin');
727
    		print '</td>';
728
		}
729
		// Contacts of task
730
		if (!empty($conf->global->PROJECT_SHOW_CONTACTS_IN_LIST))
731
		{
732
			print '<td></td>';
733
		}
734
		if ($addordertick) print '<td class="hideonsmartphone"></td>';
735
		print '</tr>';
736
	}
737
738
	return $inc;
739
}
740
741
742
/**
743
 * Output a task line into a pertime intput mode
744
 *
745
 * @param	string	   	$inc					Line number (start to 0, then increased by recursive call)
746
 * @param   string		$parent					Id of parent task to show (0 to show all)
747
 * @param	User|null	$fuser					Restrict list to user if defined
748
 * @param   Task[]		$lines					Array of lines
749
 * @param   int			$level					Level (start to 0, then increased/decrease by recursive call)
750
 * @param   string		$projectsrole			Array of roles user has on project
751
 * @param   string		$tasksrole				Array of roles user has on task
752
 * @param	string		$mine					Show only task lines I am assigned to
753
 * @param   int			$restricteditformytask	0=No restriction, 1=Enable add time only if task is a task i am affected to
754
 * @param	int			$preselectedday			Preselected day
755
 * @param   array       $isavailable			Array with data that say if user is available for several days for morning and afternoon
756
 * @param	int			$oldprojectforbreak		Old project id of last project break
757
 * @return  array								Array with time spent for $fuser for each day of week on tasks in $lines and substasks
758
 */
759
function projectLinesPerAction(&$inc, $parent, $fuser, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, $preselectedday, &$isavailable, $oldprojectforbreak = 0)
760
{
761
	global $conf, $db, $user, $bc, $langs;
762
	global $form, $formother, $projectstatic, $taskstatic, $thirdpartystatic;
763
764
	$lastprojectid = 0;
765
	$totalforeachline = array();
766
	$workloadforid = array();
767
	$lineswithoutlevel0 = array();
768
769
	$numlines = count($lines);
770
771
	// Create a smaller array with sublevels only to be used later. This increase dramatically performances.
772
	if ($parent == 0) // Always and only if at first level
773
	{
774
		for ($i = 0; $i < $numlines; $i++)
775
		{
776
			if ($lines[$i]->fk_task_parent) $lineswithoutlevel0[] = $lines[$i];
777
		}
778
	}
779
780
	if (empty($oldprojectforbreak))
781
	{
782
		$oldprojectforbreak = (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT) ? 0 : -1); // 0 to start break , -1 no break
783
	}
784
785
	//dol_syslog('projectLinesPerDay inc='.$inc.' preselectedday='.$preselectedday.' task parent id='.$parent.' level='.$level." count(lines)=".$numlines." count(lineswithoutlevel0)=".count($lineswithoutlevel0));
786
	for ($i = 0; $i < $numlines; $i++)
787
	{
788
		if ($parent == 0) $level = 0;
789
790
		//if ($lines[$i]->fk_task_parent == $parent)
791
		//{
792
		// If we want all or we have a role on task, we show it
793
		if (empty($mine) || !empty($tasksrole[$lines[$i]->id]))
794
		{
795
			//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);
796
797
			// Break on a new project
798
			if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid)
799
			{
800
				$lastprojectid = $lines[$i]->fk_project;
801
				if ($preselectedday)
802
				{
803
					$projectstatic->id = $lines[$i]->fk_project;
804
				}
805
			}
806
807
			if (empty($workloadforid[$projectstatic->id]))
808
			{
809
				if ($preselectedday)
810
				{
811
					$projectstatic->loadTimeSpent($preselectedday, 0, $fuser->id); // Load time spent from table projet_task_time for the project into this->weekWorkLoad and this->weekWorkLoadPerTask for all days of a week
812
					$workloadforid[$projectstatic->id] = 1;
813
				}
814
			}
815
816
			$projectstatic->id = $lines[$i]->fk_project;
817
			$projectstatic->ref = $lines[$i]->project_ref;
818
			$projectstatic->title = $lines[$i]->project_label;
819
			$projectstatic->public = $lines[$i]->public;
820
821
			$taskstatic->id = $lines[$i]->task_id;
0 ignored issues
show
Bug introduced by
The property task_id does not seem to exist on Task.
Loading history...
822
			$taskstatic->ref = ($lines[$i]->task_ref ? $lines[$i]->task_ref : $lines[$i]->task_id);
823
			$taskstatic->label = $lines[$i]->task_label;
824
			$taskstatic->date_start = $lines[$i]->date_start;
825
			$taskstatic->date_end = $lines[$i]->date_end;
826
827
			$thirdpartystatic->id = $lines[$i]->socid;
828
			$thirdpartystatic->name = $lines[$i]->thirdparty_name;
829
			$thirdpartystatic->email = $lines[$i]->thirdparty_email;
830
831
			if (empty($oldprojectforbreak) || ($oldprojectforbreak != -1 && $oldprojectforbreak != $projectstatic->id))
832
			{
833
				print '<tr class="oddeven trforbreak">'."\n";
834
				print '<td colspan="11">';
835
				print $projectstatic->getNomUrl(1, '', 0, $langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]);
836
				if ($projectstatic->title)
837
				{
838
					print ' - ';
839
					print $projectstatic->title;
840
				}
841
				print '</td>';
842
				print '</tr>';
843
			}
844
845
			if ($oldprojectforbreak != -1) $oldprojectforbreak = $projectstatic->id;
846
847
			print '<tr class="oddeven">'."\n";
848
849
			// User
850
			/*
851
			 print '<td class="nowrap">';
852
			 print $fuser->getNomUrl(1, 'withproject', 'time');
853
			 print '</td>';
854
			 */
855
856
			// Project
857
			print "<td>";
858
			if ($oldprojectforbreak == -1)
859
			{
860
				print $projectstatic->getNomUrl(1, '', 0, $langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]);
861
				print '<br>'.$projectstatic->title;
862
			}
863
			print "</td>";
864
865
			// Thirdparty
866
			print '<td class="tdoverflowmax100">';
867
			if ($thirdpartystatic->id > 0) print $thirdpartystatic->getNomUrl(1, 'project', 10);
868
			print '</td>';
869
870
			// Ref
871
			print '<td>';
872
			print '<!-- Task id = '.$lines[$i]->id.' -->';
873
			for ($k = 0; $k < $level; $k++) print "&nbsp;&nbsp;&nbsp;";
874
			print $taskstatic->getNomUrl(1, 'withproject', 'time');
875
			// Label task
876
			print '<br>';
877
			for ($k = 0; $k < $level; $k++) print "&nbsp;&nbsp;&nbsp;";
878
			print $taskstatic->label;
879
			//print "<br>";
880
			//for ($k = 0 ; $k < $level ; $k++) print "&nbsp;&nbsp;&nbsp;";
881
			//print get_date_range($lines[$i]->date_start,$lines[$i]->date_end,'',$langs,0);
882
			print "</td>\n";
883
884
			// Date
885
			print '<td class="center">';
886
			print dol_print_date($lines[$i]->timespent_datehour, 'day');
887
			print '</td>';
888
889
			$disabledproject = 1; $disabledtask = 1;
890
			//print "x".$lines[$i]->fk_project;
891
			//var_dump($lines[$i]);
892
			//var_dump($projectsrole[$lines[$i]->fk_project]);
893
			// If at least one role for project
894
			if ($lines[$i]->public || !empty($projectsrole[$lines[$i]->fk_project]) || $user->rights->projet->all->creer)
895
			{
896
				$disabledproject = 0;
897
				$disabledtask = 0;
898
			}
899
			// If $restricteditformytask is on and I have no role on task, i disable edit
900
			if ($restricteditformytask && empty($tasksrole[$lines[$i]->id]))
901
			{
902
				$disabledtask = 1;
903
			}
904
905
			// Hour
906
			print '<td class="nowrap center">';
907
			print dol_print_date($lines[$i]->timespent_datehour, 'hour');
908
			print '</td>';
909
910
			$cssonholiday = '';
911
			if (!$isavailable[$preselectedday]['morning'] && !$isavailable[$preselectedday]['afternoon'])   $cssonholiday .= 'onholidayallday ';
912
			elseif (!$isavailable[$preselectedday]['morning'])   $cssonholiday .= 'onholidaymorning ';
913
			elseif (!$isavailable[$preselectedday]['afternoon']) $cssonholiday .= 'onholidayafternoon ';
914
915
			// Duration
916
			print '<td class="duration'.($cssonholiday ? ' '.$cssonholiday : '').' center">';
917
918
			$dayWorkLoad = $lines[$i]->timespent_duration;
919
			$totalforeachline[$preselectedday] += $lines[$i]->timespent_duration;
920
921
			$alreadyspent = '';
922
			if ($dayWorkLoad > 0) $alreadyspent = convertSecondToTime($lines[$i]->timespent_duration, 'allhourmin');
923
924
			print convertSecondToTime($lines[$i]->timespent_duration, 'allhourmin');
925
926
			$modeinput = 'hours';
927
928
			print '<script type="text/javascript">';
929
			print "jQuery(document).ready(function () {\n";
930
			print " 	jQuery('.inputhour, .inputminute').bind('keyup', function(e) { updateTotal(0, '".$modeinput."') });";
931
			print "})\n";
932
			print '</script>';
933
934
			print '</td>';
935
936
			// Note
937
			print '<td class="center">';
938
			print '<textarea name="'.$lines[$i]->id.'note" rows="'.ROWS_2.'" id="'.$lines[$i]->id.'note"'.($disabledtask ? ' disabled="disabled"' : '').'>';
939
			print $lines[$i]->timespent_note;
940
			print '</textarea>';
941
			print '</td>';
942
943
			// Warning
944
			print '<td class="right">';
945
			/*if ((! $lines[$i]->public) && $disabledproject) print $form->textwithpicto('',$langs->trans("UserIsNotContactOfProject"));
946
			elseif ($disabledtask)
947
			{
948
				$titleassigntask = $langs->trans("AssignTaskToMe");
949
				if ($fuser->id != $user->id) $titleassigntask = $langs->trans("AssignTaskToUser", '...');
950
951
				print $form->textwithpicto('',$langs->trans("TaskIsNotAssignedToUser", $titleassigntask));
952
			}*/
953
			print '</td>';
954
955
			print "</tr>\n";
956
		}
957
		//}
958
		//else
959
		//{
960
			//$level--;
961
		//}
962
	}
963
964
	return $totalforeachline;
965
}
966
967
968
/**
969
 * Output a task line into a pertime intput mode
970
 *
971
 * @param	string	   	$inc					Line number (start to 0, then increased by recursive call)
972
 * @param   string		$parent					Id of parent task to show (0 to show all)
973
 * @param	User|null	$fuser					Restrict list to user if defined
974
 * @param   Task[]		$lines					Array of lines
975
 * @param   int			$level					Level (start to 0, then increased/decrease by recursive call)
976
 * @param   string		$projectsrole			Array of roles user has on project
977
 * @param   string		$tasksrole				Array of roles user has on task
978
 * @param	string		$mine					Show only task lines I am assigned to
979
 * @param   int			$restricteditformytask	0=No restriction, 1=Enable add time only if task is assigned to me, 2=Enable add time only if tasks is assigned to me and hide others
980
 * @param	int			$preselectedday			Preselected day
981
 * @param   array       $isavailable			Array with data that say if user is available for several days for morning and afternoon
982
 * @param	int			$oldprojectforbreak		Old project id of last project break
983
 * @param	array		$arrayfields		    Array of additional column
984
 * @param	Extrafields	$extrafields		    Object extrafields
985
 * @return  array								Array with time spent for $fuser for each day of week on tasks in $lines and substasks
986
 */
987
function projectLinesPerDay(&$inc, $parent, $fuser, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, $preselectedday, &$isavailable, $oldprojectforbreak = 0, $arrayfields = array(), $extrafields = null)
988
{
989
	global $conf, $db, $user, $bc, $langs;
990
	global $form, $formother, $projectstatic, $taskstatic, $thirdpartystatic;
991
992
	$lastprojectid = 0;
993
	$totalforeachday = array();
994
	$workloadforid = array();
995
	$lineswithoutlevel0 = array();
996
997
	$numlines = count($lines);
998
999
	// Create a smaller array with sublevels only to be used later. This increase dramatically performances.
1000
	if ($parent == 0) // Always and only if at first level
1001
	{
1002
		for ($i = 0; $i < $numlines; $i++)
1003
		{
1004
			if ($lines[$i]->fk_task_parent) $lineswithoutlevel0[] = $lines[$i];
1005
		}
1006
	}
1007
1008
	if (empty($oldprojectforbreak))
1009
	{
1010
		$oldprojectforbreak = (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT) ? 0 : -1); // 0 to start break , -1 no break
1011
	}
1012
1013
	//dol_syslog('projectLinesPerDay inc='.$inc.' preselectedday='.$preselectedday.' task parent id='.$parent.' level='.$level." count(lines)=".$numlines." count(lineswithoutlevel0)=".count($lineswithoutlevel0));
1014
	for ($i = 0; $i < $numlines; $i++)
1015
	{
1016
		if ($parent == 0) $level = 0;
1017
1018
		if ($lines[$i]->fk_task_parent == $parent)
1019
		{
1020
            $obj = &$lines[$i]; // To display extrafields
1021
1022
			// If we want all or we have a role on task, we show it
1023
			if (empty($mine) || !empty($tasksrole[$lines[$i]->id]))
1024
			{
1025
				//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);
1026
1027
				if ($restricteditformytask == 2 && empty($tasksrole[$lines[$i]->id]))	// we have no role on task and we request to hide such cases
1028
				{
1029
					continue;
1030
				}
1031
1032
				// Break on a new project
1033
				if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid)
1034
				{
1035
					$lastprojectid = $lines[$i]->fk_project;
1036
					if ($preselectedday)
1037
					{
1038
						$projectstatic->id = $lines[$i]->fk_project;
1039
					}
1040
				}
1041
1042
				if (empty($workloadforid[$projectstatic->id]))
1043
				{
1044
					if ($preselectedday)
1045
					{
1046
						$projectstatic->loadTimeSpent($preselectedday, 0, $fuser->id); // Load time spent from table projet_task_time for the project into this->weekWorkLoad and this->weekWorkLoadPerTask for all days of a week
1047
		   				$workloadforid[$projectstatic->id] = 1;
1048
					}
1049
				}
1050
1051
				$projectstatic->id = $lines[$i]->fk_project;
1052
				$projectstatic->ref = $lines[$i]->projectref;
1053
				$projectstatic->title = $lines[$i]->projectlabel;
1054
				$projectstatic->public = $lines[$i]->public;
1055
1056
				$taskstatic->id = $lines[$i]->id;
1057
				$taskstatic->ref = ($lines[$i]->ref ? $lines[$i]->ref : $lines[$i]->id);
1058
				$taskstatic->label = $lines[$i]->label;
1059
				$taskstatic->date_start = $lines[$i]->date_start;
1060
				$taskstatic->date_end = $lines[$i]->date_end;
1061
1062
				$thirdpartystatic->id = $lines[$i]->socid;
1063
				$thirdpartystatic->name = $lines[$i]->thirdparty_name;
1064
				$thirdpartystatic->email = $lines[$i]->thirdparty_email;
1065
1066
				if (empty($oldprojectforbreak) || ($oldprojectforbreak != -1 && $oldprojectforbreak != $projectstatic->id))
1067
				{
1068
                    $addcolspan = 0;
1069
                    if (!empty($arrayfields['t.planned_workload']['checked'])) $addcolspan++;
1070
                    if (!empty($arrayfields['t.progress']['checked'])) $addcolspan++;
1071
                    foreach ($arrayfields as $key => $val)
1072
                    {
1073
                        if ($val['checked'] && substr($key, 0, 5) == 'efpt.') $addcolspan++;
1074
                    }
1075
1076
					print '<tr class="oddeven trforbreak">'."\n";
1077
					print '<td colspan="'.(7 + $addcolspan).'">';
1078
					print $projectstatic->getNomUrl(1, '', 0, '<strong>'.$langs->transnoentitiesnoconv("YourRole").':</strong> '.$projectsrole[$lines[$i]->fk_project]);
1079
					if ($thirdpartystatic->id > 0) print ' - '.$thirdpartystatic->getNomUrl(1);
1080
					if ($projectstatic->title)
1081
					{
1082
						print ' - ';
1083
						print '<span class="secondary">'.$projectstatic->title.'</span>';
1084
					}
1085
					/*
1086
                    $colspan=5+(empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)?0:2);
1087
                    print '<table class="">';
1088
1089
                    print '<tr class="liste_titre">';
1090
1091
                    // PROJECT fields
1092
                    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 ');
1093
                    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 ');
1094
                    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 ');
1095
                    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 ');
1096
                    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 ');
1097
1098
                    $extrafieldsobjectkey='projet';
1099
                    $extrafieldsobjectprefix='efp.';
1100
                    include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
1101
1102
                    print '</tr>';
1103
                    print '<tr>';
1104
1105
                    // PROJECT fields
1106
                    if (! empty($arrayfields['p.fk_opp_status']['checked']))
1107
                    {
1108
                        print '<td class="nowrap">';
1109
                        $code = dol_getIdFromCode($db, $lines[$i]->fk_opp_status, 'c_lead_status', 'rowid', 'code');
1110
                        if ($code) print $langs->trans("OppStatus".$code);
1111
                        print "</td>\n";
1112
                    }
1113
                    if (! empty($arrayfields['p.opp_amount']['checked']))
1114
                    {
1115
                        print '<td class="nowrap">';
1116
                        print price($lines[$i]->opp_amount, 0, $langs, 1, 0, -1, $conf->currency);
1117
                        print "</td>\n";
1118
                    }
1119
                    if (! empty($arrayfields['p.opp_percent']['checked']))
1120
                    {
1121
                        print '<td class="nowrap">';
1122
                        print price($lines[$i]->opp_percent, 0, $langs, 1, 0).' %';
1123
                        print "</td>\n";
1124
                    }
1125
                    if (! empty($arrayfields['p.budget_amount']['checked']))
1126
                    {
1127
                        print '<td class="nowrap">';
1128
                        print price($lines[$i]->budget_amount, 0, $langs, 1, 0, 0, $conf->currency);
1129
                        print "</td>\n";
1130
                    }
1131
                    if (! empty($arrayfields['p.usage_bill_time']['checked']))
1132
                    {
1133
                        print '<td class="nowrap">';
1134
                        print yn($lines[$i]->usage_bill_time);
1135
                        print "</td>\n";
1136
                    }
1137
1138
                    $extrafieldsobjectkey='projet';
1139
                    $extrafieldsobjectprefix='efp.';
1140
                    include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
1141
1142
                    print '</tr>';
1143
                    print '</table>';
1144
1145
					*/
1146
					print '</td>';
1147
					print '</tr>';
1148
				}
1149
1150
				if ($oldprojectforbreak != -1) $oldprojectforbreak = $projectstatic->id;
1151
1152
				print '<tr class="oddeven" data-taskid="'.$lines[$i]->id.'">'."\n";
1153
1154
				// User
1155
				/*
1156
				print '<td class="nowrap">';
1157
				print $fuser->getNomUrl(1, 'withproject', 'time');
1158
				print '</td>';
1159
				*/
1160
1161
				// Project
1162
				if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT))
1163
				{
1164
				    print "<td>";
1165
				    if ($oldprojectforbreak == -1) print $projectstatic->getNomUrl(1, '', 0, $langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]);
1166
				    print "</td>";
1167
				}
1168
1169
				// Thirdparty
1170
				if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT))
1171
				{
1172
				    print '<td class="tdoverflowmax100">';
1173
				    if ($thirdpartystatic->id > 0) print $thirdpartystatic->getNomUrl(1, 'project', 10);
1174
				    print '</td>';
1175
				}
1176
1177
				// Ref
1178
				print '<td>';
1179
				print '<!-- Task id = '.$lines[$i]->id.' -->';
1180
				for ($k = 0; $k < $level; $k++) print "&nbsp;&nbsp;&nbsp;";
1181
				print $taskstatic->getNomUrl(1, 'withproject', 'time');
1182
				// Label task
1183
				print '<br>';
1184
				for ($k = 0; $k < $level; $k++) print "&nbsp;&nbsp;&nbsp;";
1185
				print $taskstatic->label;
1186
				//print "<br>";
1187
				//for ($k = 0 ; $k < $level ; $k++) print "&nbsp;&nbsp;&nbsp;";
1188
				//print get_date_range($lines[$i]->date_start,$lines[$i]->date_end,'',$langs,0);
1189
				print "</td>\n";
1190
1191
                // TASK extrafields
1192
                $extrafieldsobjectkey = 'projet_task';
1193
                $extrafieldsobjectprefix = 'efpt.';
1194
                include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
1195
1196
                // Planned Workload
1197
                if (!empty($arrayfields['t.planned_workload']['checked']))
1198
                {
1199
                    print '<td class="leftborder plannedworkload right">';
1200
				    if ($lines[$i]->planned_workload) print convertSecondToTime($lines[$i]->planned_workload, 'allhourmin');
1201
				    else print '--:--';
1202
				    print '</td>';
1203
                }
1204
1205
				// Progress declared %
1206
                if (!empty($arrayfields['t.progress']['checked']))
1207
                {
1208
                    print '<td class="right">';
1209
				    print $formother->select_percent($lines[$i]->progress, $lines[$i]->id.'progress');
1210
				    print '</td>';
1211
                }
1212
1213
				// Time spent by everybody
1214
				print '<td class="right">';
1215
				// $lines[$i]->duration is a denormalised field = summ of time spent by everybody for task. What we need is time consummed by user
1216
				if ($lines[$i]->duration)
1217
				{
1218
					print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$lines[$i]->id.'">';
1219
					print convertSecondToTime($lines[$i]->duration, 'allhourmin');
1220
					print '</a>';
1221
				}
1222
				else print '--:--';
1223
				print "</td>\n";
1224
1225
				// Time spent by user
1226
				print '<td class="right">';
1227
				$tmptimespent = $taskstatic->getSummaryOfTimeSpent($fuser->id);
1228
				if ($tmptimespent['total_duration']) print convertSecondToTime($tmptimespent['total_duration'], 'allhourmin');
1229
				else print '--:--';
1230
				print "</td>\n";
1231
1232
				$disabledproject = 1; $disabledtask = 1;
1233
				//print "x".$lines[$i]->fk_project;
1234
				//var_dump($lines[$i]);
1235
				//var_dump($projectsrole[$lines[$i]->fk_project]);
1236
				// If at least one role for project
1237
				if ($lines[$i]->public || !empty($projectsrole[$lines[$i]->fk_project]) || $user->rights->projet->all->creer)
1238
				{
1239
					$disabledproject = 0;
1240
					$disabledtask = 0;
1241
				}
1242
				// If $restricteditformytask is on and I have no role on task, i disable edit
1243
				if ($restricteditformytask && empty($tasksrole[$lines[$i]->id]))
1244
				{
1245
					$disabledtask = 1;
1246
				}
1247
1248
				// Form to add new time
1249
				print '<td class="nowrap leftborder center">';
1250
				$tableCell = $form->selectDate($preselectedday, $lines[$i]->id, 1, 1, 2, "addtime", 0, 0, $disabledtask);
1251
				print $tableCell;
1252
				print '</td>';
1253
1254
				$cssonholiday = '';
1255
				if (!$isavailable[$preselectedday]['morning'] && !$isavailable[$preselectedday]['afternoon'])   $cssonholiday .= 'onholidayallday ';
1256
				elseif (!$isavailable[$preselectedday]['morning'])   $cssonholiday .= 'onholidaymorning ';
1257
				elseif (!$isavailable[$preselectedday]['afternoon']) $cssonholiday .= 'onholidayafternoon ';
1258
1259
				global $daytoparse;
1260
				$tmparray = dol_getdate($daytoparse, true); // detail of current day
1261
				$idw = $tmparray['wday'];
1262
1263
				global $numstartworkingday, $numendworkingday;
1264
				$cssweekend = '';
1265
				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.
1266
				{
1267
					$cssweekend = 'weekend';
1268
				}
1269
1270
				// Duration
1271
				print '<td class="center duration'.($cssonholiday ? ' '.$cssonholiday : '').($cssweekend ? ' '.$cssweekend : '').'">';
1272
				$dayWorkLoad = $projectstatic->weekWorkLoadPerTask[$preselectedday][$lines[$i]->id];
1273
				$totalforeachday[$preselectedday] += $dayWorkLoad;
1274
1275
				$alreadyspent = '';
1276
				if ($dayWorkLoad > 0) $alreadyspent = convertSecondToTime($dayWorkLoad, 'allhourmin');
1277
1278
				$idw = 0;
1279
1280
				$tableCell = '';
1281
				$tableCell .= '<span class="timesheetalreadyrecorded" title="texttoreplace"><input type="text" class="center" size="2" disabled id="timespent['.$inc.']['.$idw.']" name="task['.$lines[$i]->id.']['.$idw.']" value="'.$alreadyspent.'"></span>';
1282
				$tableCell .= '<span class="hideonsmartphone"> + </span>';
1283
				//$tableCell.='&nbsp;&nbsp;&nbsp;';
1284
				$tableCell .= $form->select_duration($lines[$i]->id.'duration', '', $disabledtask, 'text', 0, 1);
1285
				//$tableCell.='&nbsp;<input type="submit" class="button"'.($disabledtask?' disabled':'').' value="'.$langs->trans("Add").'">';
1286
				print $tableCell;
1287
1288
				$modeinput = 'hours';
1289
1290
				print '<script type="text/javascript">';
1291
				print "jQuery(document).ready(function () {\n";
1292
				print " 	jQuery('.inputhour, .inputminute').bind('keyup', function(e) { updateTotal(0, '".$modeinput."') });";
1293
				print "})\n";
1294
				print '</script>';
1295
1296
				print '</td>';
1297
1298
				// Note
1299
				print '<td class="center">';
1300
				print '<textarea name="'.$lines[$i]->id.'note" rows="'.ROWS_2.'" id="'.$lines[$i]->id.'note"'.($disabledtask ? ' disabled="disabled"' : '').'>';
1301
				print '</textarea>';
1302
				print '</td>';
1303
1304
				// Warning
1305
				print '<td class="right">';
1306
   				if ((!$lines[$i]->public) && $disabledproject) print $form->textwithpicto('', $langs->trans("UserIsNotContactOfProject"));
1307
   				elseif ($disabledtask)
1308
   				{
1309
   					$titleassigntask = $langs->trans("AssignTaskToMe");
1310
   					if ($fuser->id != $user->id) $titleassigntask = $langs->trans("AssignTaskToUser", '...');
1311
1312
   					print $form->textwithpicto('', $langs->trans("TaskIsNotAssignedToUser", $titleassigntask));
1313
   				}
1314
				print '</td>';
1315
1316
				print "</tr>\n";
1317
			}
1318
1319
			$inc++;
1320
			$level++;
1321
			if ($lines[$i]->id > 0)
1322
			{
1323
				//var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level);
1324
				//var_dump($totalforeachday);
1325
				$ret = projectLinesPerDay($inc, $lines[$i]->id, $fuser, ($parent == 0 ? $lineswithoutlevel0 : $lines), $level, $projectsrole, $tasksrole, $mine, $restricteditformytask, $preselectedday, $isavailable, $oldprojectforbreak, $arrayfields, $extrafields);
1326
				//var_dump('ret with parent='.$lines[$i]->id.' level='.$level);
1327
				//var_dump($ret);
1328
				foreach ($ret as $key => $val)
1329
				{
1330
					$totalforeachday[$key] += $val;
1331
				}
1332
				//var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level.' + subtasks');
1333
				//var_dump($totalforeachday);
1334
			}
1335
			$level--;
1336
		}
1337
		else
1338
		{
1339
			//$level--;
1340
		}
1341
	}
1342
1343
	return $totalforeachday;
1344
}
1345
1346
1347
/**
1348
 * Output a task line into a perday intput mode
1349
 *
1350
 * @param	string	   	$inc					Line output identificator (start to 0, then increased by recursive call)
1351
 * @param	int			$firstdaytoshow			First day to show
1352
 * @param	User|null	$fuser					Restrict list to user if defined
1353
 * @param   string		$parent					Id of parent task to show (0 to show all)
1354
 * @param   Task[]		$lines					Array of lines (list of tasks but we will show only if we have a specific role on task)
1355
 * @param   int			$level					Level (start to 0, then increased/decrease by recursive call)
1356
 * @param   string		$projectsrole			Array of roles user has on project
1357
 * @param   string		$tasksrole				Array of roles user has on task
1358
 * @param	string		$mine					Show only task lines I am assigned to
1359
 * @param   int			$restricteditformytask	0=No restriction, 1=Enable add time only if task is assigned to me, 2=Enable add time only if tasks is assigned to me and hide others
1360
 * @param   array       $isavailable			Array with data that say if user is available for several days for morning and afternoon
1361
 * @param	int			$oldprojectforbreak		Old project id of last project break
1362
 * @param	array		$arrayfields		    Array of additional column
1363
 * @param	Extrafields	$extrafields		    Object extrafields
1364
 * @return  array								Array with time spent for $fuser for each day of week on tasks in $lines and substasks
1365
 */
1366
function projectLinesPerWeek(&$inc, $firstdaytoshow, $fuser, $parent, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, &$isavailable, $oldprojectforbreak = 0, $arrayfields = array(), $extrafields = null)
1367
{
1368
	global $conf, $db, $user, $bc, $langs;
1369
	global $form, $formother, $projectstatic, $taskstatic, $thirdpartystatic;
1370
1371
	$numlines = count($lines);
1372
1373
	$lastprojectid = 0;
1374
	$workloadforid = array();
1375
	$totalforeachday = array();
1376
	$lineswithoutlevel0 = array();
1377
1378
	// Create a smaller array with sublevels only to be used later. This increase dramatically performances.
1379
	if ($parent == 0) // Always and only if at first level
1380
	{
1381
		for ($i = 0; $i < $numlines; $i++)
1382
		{
1383
		    if ($lines[$i]->fk_task_parent) $lineswithoutlevel0[] = $lines[$i];
1384
		}
1385
	}
1386
1387
	//dol_syslog('projectLinesPerWeek inc='.$inc.' firstdaytoshow='.$firstdaytoshow.' task parent id='.$parent.' level='.$level." count(lines)=".$numlines." count(lineswithoutlevel0)=".count($lineswithoutlevel0));
1388
1389
	if (empty($oldprojectforbreak))
1390
	{
1391
		$oldprojectforbreak = (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT) ? 0 : -1); // 0 = start break, -1 = never break
1392
	}
1393
1394
	for ($i = 0; $i < $numlines; $i++)
1395
	{
1396
		if ($parent == 0) $level = 0;
1397
1398
		if ($lines[$i]->fk_task_parent == $parent)
1399
		{
1400
            $obj = &$lines[$i]; // To display extrafields
1401
1402
			// If we want all or we have a role on task, we show it
1403
			if (empty($mine) || !empty($tasksrole[$lines[$i]->id]))
1404
			{
1405
				//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);
1406
1407
				if ($restricteditformytask == 2 && empty($tasksrole[$lines[$i]->id]))	// we have no role on task and we request to hide such cases
1408
				{
1409
					continue;
1410
				}
1411
1412
				// Break on a new project
1413
				if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid)
1414
				{
1415
					$lastprojectid = $lines[$i]->fk_project;
1416
					$projectstatic->id = $lines[$i]->fk_project;
1417
				}
1418
1419
				//var_dump('--- '.$level.' '.$firstdaytoshow.' '.$fuser->id.' '.$projectstatic->id.' '.$workloadforid[$projectstatic->id]);
1420
				//var_dump($projectstatic->weekWorkLoadPerTask);
1421
				if (empty($workloadforid[$projectstatic->id]))
1422
				{
1423
					$projectstatic->loadTimeSpent($firstdaytoshow, 0, $fuser->id); // Load time spent from table projet_task_time for the project into this->weekWorkLoad and this->weekWorkLoadPerTask for all days of a week
1424
					$workloadforid[$projectstatic->id] = 1;
1425
				}
1426
				//var_dump($projectstatic->weekWorkLoadPerTask);
1427
				//var_dump('--- '.$projectstatic->id.' '.$workloadforid[$projectstatic->id]);
1428
1429
				$projectstatic->id = $lines[$i]->fk_project;
1430
				$projectstatic->ref = $lines[$i]->projectref;
1431
				$projectstatic->title = $lines[$i]->projectlabel;
1432
				$projectstatic->public = $lines[$i]->public;
1433
				$projectstatic->thirdparty_name = $lines[$i]->thirdparty_name;
1434
1435
				$taskstatic->id = $lines[$i]->id;
1436
				$taskstatic->ref = ($lines[$i]->ref ? $lines[$i]->ref : $lines[$i]->id);
1437
				$taskstatic->label = $lines[$i]->label;
1438
				$taskstatic->date_start = $lines[$i]->date_start;
1439
				$taskstatic->date_end = $lines[$i]->date_end;
1440
1441
				$thirdpartystatic->id = $lines[$i]->thirdparty_id;
1442
				$thirdpartystatic->name = $lines[$i]->thirdparty_name;
1443
				$thirdpartystatic->email = $lines[$i]->thirdparty_email;
1444
1445
				if (empty($oldprojectforbreak) || ($oldprojectforbreak != -1 && $oldprojectforbreak != $projectstatic->id))
1446
				{
1447
                    $addcolspan = 0;
1448
                    if (!empty($arrayfields['t.planned_workload']['checked'])) $addcolspan++;
1449
                    if (!empty($arrayfields['t.progress']['checked'])) $addcolspan++;
1450
                    foreach ($arrayfields as $key => $val)
1451
                    {
1452
                        if ($val['checked'] && substr($key, 0, 5) == 'efpt.') $addcolspan++;
1453
                    }
1454
1455
					print '<tr class="oddeven trforbreak">'."\n";
1456
					print '<td colspan="'.(11 + $addcolspan).'">';
1457
					print $projectstatic->getNomUrl(1, '', 0, '<strong>'.$langs->transnoentitiesnoconv("YourRole").':</strong> '.$projectsrole[$lines[$i]->fk_project]);
1458
					if ($thirdpartystatic->id > 0) print ' - '.$thirdpartystatic->getNomUrl(1);
1459
					if ($projectstatic->title)
1460
					{
1461
						print ' - ';
1462
						print '<span class="secondary">'.$projectstatic->title.'</span>';
1463
					}
1464
1465
                    /*$colspan=5+(empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)?0:2);
1466
					print '<table class="">';
1467
1468
					print '<tr class="liste_titre">';
1469
1470
					// PROJECT fields
1471
                    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 ');
1472
                    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 ');
1473
                    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 ');
1474
                    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 ');
1475
                    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 ');
1476
1477
                    $extrafieldsobjectkey='projet';
1478
                    $extrafieldsobjectprefix='efp.';
1479
                    include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
1480
1481
                    print '</tr>';
1482
                    print '<tr>';
1483
1484
                    // PROJECT fields
1485
                    if (! empty($arrayfields['p.fk_opp_status']['checked']))
1486
                    {
1487
                        print '<td class="nowrap">';
1488
                        $code = dol_getIdFromCode($db, $lines[$i]->fk_opp_status, 'c_lead_status', 'rowid', 'code');
1489
                        if ($code) print $langs->trans("OppStatus".$code);
1490
                        print "</td>\n";
1491
                    }
1492
                    if (! empty($arrayfields['p.opp_amount']['checked']))
1493
                    {
1494
                        print '<td class="nowrap">';
1495
                        print price($lines[$i]->opp_amount, 0, $langs, 1, 0, -1, $conf->currency);
1496
                        print "</td>\n";
1497
                    }
1498
                    if (! empty($arrayfields['p.opp_percent']['checked']))
1499
                    {
1500
                        print '<td class="nowrap">';
1501
                        print price($lines[$i]->opp_percent, 0, $langs, 1, 0).' %';
1502
                        print "</td>\n";
1503
                    }
1504
                    if (! empty($arrayfields['p.budget_amount']['checked']))
1505
                    {
1506
                        print '<td class="nowrap">';
1507
                        print price($lines[$i]->budget_amount, 0, $langs, 1, 0, 0, $conf->currency);
1508
                        print "</td>\n";
1509
                    }
1510
                    if (! empty($arrayfields['p.usage_bill_time']['checked']))
1511
                    {
1512
                        print '<td class="nowrap">';
1513
                        print yn($lines[$i]->usage_bill_time);
1514
                        print "</td>\n";
1515
                    }
1516
1517
                    $extrafieldsobjectkey='projet';
1518
                    $extrafieldsobjectprefix='efp.';
1519
                    include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
1520
1521
                    print '</tr>';
1522
                    print '</table>';
1523
					*/
1524
1525
					print '</td>';
1526
					print '</tr>';
1527
				}
1528
1529
				if ($oldprojectforbreak != -1) $oldprojectforbreak = $projectstatic->id;
1530
1531
				print '<tr class="oddeven" data-taskid="'.$lines[$i]->id.'">'."\n";
1532
1533
				// User
1534
				/*
1535
				print '<td class="nowrap">';
1536
				print $fuser->getNomUrl(1, 'withproject', 'time');
1537
				print '</td>';
1538
				*/
1539
1540
				// Project
1541
				if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT))
1542
				{
1543
    				print '<td class="nowrap">';
1544
    				if ($oldprojectforbreak == -1) print $projectstatic->getNomUrl(1, '', 0, $langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]);
1545
    				print "</td>";
1546
				}
1547
1548
				// Thirdparty
1549
				if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT))
1550
				{
1551
				    print '<td class="tdoverflowmax100">';
1552
				    if ($thirdpartystatic->id > 0) print $thirdpartystatic->getNomUrl(1, 'project');
1553
				    print '</td>';
1554
				}
1555
1556
				// Ref
1557
				print '<td class="nowrap">';
1558
				print '<!-- Task id = '.$lines[$i]->id.' -->';
1559
				for ($k = 0; $k < $level; $k++) print "&nbsp;&nbsp;&nbsp;";
1560
				print $taskstatic->getNomUrl(1, 'withproject', 'time');
1561
				// Label task
1562
				print '<br>';
1563
				for ($k = 0; $k < $level; $k++) print "&nbsp;&nbsp;&nbsp;";
1564
				//print $taskstatic->getNomUrl(0, 'withproject', 'time');
1565
				print $taskstatic->label;
1566
				//print "<br>";
1567
				//for ($k = 0 ; $k < $level ; $k++) print "&nbsp;&nbsp;&nbsp;";
1568
				//print get_date_range($lines[$i]->date_start,$lines[$i]->date_end,'',$langs,0);
1569
				print "</td>\n";
1570
1571
				// TASK extrafields
1572
                $extrafieldsobjectkey = 'projet_task';
1573
                $extrafieldsobjectprefix = 'efpt.';
1574
                include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
1575
1576
                // Planned Workload
1577
                if (!empty($arrayfields['t.planned_workload']['checked']))
1578
                {
1579
    				print '<td class="leftborder plannedworkload right">';
1580
    				if ($lines[$i]->planned_workload) print convertSecondToTime($lines[$i]->planned_workload, 'allhourmin');
1581
    				else print '--:--';
1582
    				print '</td>';
1583
                }
1584
1585
                if (!empty($arrayfields['t.progress']['checked']))
1586
                {
1587
                    // Progress declared %
1588
    				print '<td class="right">';
1589
    				print $formother->select_percent($lines[$i]->progress, $lines[$i]->id.'progress');
1590
    				print '</td>';
1591
                }
1592
1593
				// Time spent by everybody
1594
				print '<td class="right">';
1595
				// $lines[$i]->duration is a denormalised field = summ of time spent by everybody for task. What we need is time consummed by user
1596
				if ($lines[$i]->duration)
1597
				{
1598
					print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$lines[$i]->id.'">';
1599
					print convertSecondToTime($lines[$i]->duration, 'allhourmin');
1600
					print '</a>';
1601
				}
1602
				else print '--:--';
1603
				print "</td>\n";
1604
1605
				// Time spent by user
1606
				print '<td class="right">';
1607
				$tmptimespent = $taskstatic->getSummaryOfTimeSpent($fuser->id);
1608
				if ($tmptimespent['total_duration']) print convertSecondToTime($tmptimespent['total_duration'], 'allhourmin');
1609
				else print '--:--';
1610
				print "</td>\n";
1611
1612
				$disabledproject = 1; $disabledtask = 1;
1613
				//print "x".$lines[$i]->fk_project;
1614
				//var_dump($lines[$i]);
1615
				//var_dump($projectsrole[$lines[$i]->fk_project]);
1616
				// If at least one role for project
1617
				if ($lines[$i]->public || !empty($projectsrole[$lines[$i]->fk_project]) || $user->rights->projet->all->creer)
1618
				{
1619
					$disabledproject = 0;
1620
					$disabledtask = 0;
1621
				}
1622
				// If $restricteditformytask is on and I have no role on task, i disable edit
1623
				if ($restricteditformytask && empty($tasksrole[$lines[$i]->id]))
1624
				{
1625
					$disabledtask = 1;
1626
				}
1627
1628
				//var_dump($projectstatic->weekWorkLoadPerTask);
1629
1630
				// Fields to show current time
1631
				$tableCell = ''; $modeinput = 'hours';
1632
				for ($idw = 0; $idw < 7; $idw++)
1633
				{
1634
					$tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd');
1635
1636
					$cssonholiday = '';
1637
					if (!$isavailable[$tmpday]['morning'] && !$isavailable[$tmpday]['afternoon'])   $cssonholiday .= 'onholidayallday ';
1638
					elseif (!$isavailable[$tmpday]['morning'])   $cssonholiday .= 'onholidaymorning ';
1639
					elseif (!$isavailable[$tmpday]['afternoon']) $cssonholiday .= 'onholidayafternoon ';
1640
1641
					$tmparray = dol_getdate($tmpday);
1642
					$dayWorkLoad = $projectstatic->weekWorkLoadPerTask[$tmpday][$lines[$i]->id];
1643
					$totalforeachday[$tmpday] += $dayWorkLoad;
1644
1645
					$alreadyspent = '';
1646
					if ($dayWorkLoad > 0) $alreadyspent = convertSecondToTime($dayWorkLoad, 'allhourmin');
1647
					$alttitle = $langs->trans("AddHereTimeSpentForDay", $tmparray['day'], $tmparray['mon']);
1648
1649
					global $numstartworkingday, $numendworkingday;
1650
					$cssweekend = '';
1651
					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.
1652
					{
1653
						$cssweekend = 'weekend';
1654
					}
1655
1656
					$tableCell = '<td class="center hide'.$idw.($cssonholiday ? ' '.$cssonholiday : '').($cssweekend ? ' '.$cssweekend : '').'">';
1657
					$placeholder = '';
1658
					if ($alreadyspent)
1659
					{
1660
						$tableCell .= '<span class="timesheetalreadyrecorded" title="texttoreplace"><input type="text" class="center smallpadd" size="2" disabled id="timespent['.$inc.']['.$idw.']" name="task['.$lines[$i]->id.']['.$idw.']" value="'.$alreadyspent.'"></span>';
1661
						//$placeholder=' placeholder="00:00"';
1662
					 	//$tableCell.='+';
1663
					}
1664
				  	$tableCell .= '<input type="text" alt="'.($disabledtask ? '' : $alttitle).'" title="'.($disabledtask ? '' : $alttitle).'" '.($disabledtask ? 'disabled' : $placeholder).' class="center smallpadd" size="2" id="timeadded['.$inc.']['.$idw.']" name="task['.$lines[$i]->id.']['.$idw.']" value="" cols="2"  maxlength="5"';
1665
					$tableCell .= ' onkeypress="return regexEvent(this,event,\'timeChar\')"';
1666
				   	$tableCell .= ' onkeyup="updateTotal('.$idw.',\''.$modeinput.'\')"';
1667
				   	$tableCell .= ' onblur="regexEvent(this,event,\''.$modeinput.'\'); updateTotal('.$idw.',\''.$modeinput.'\')" />';
1668
				   	$tableCell .= '</td>';
1669
					print $tableCell;
1670
				}
1671
1672
				// Warning
1673
				print '<td class="right">';
1674
   				if ((!$lines[$i]->public) && $disabledproject) print $form->textwithpicto('', $langs->trans("UserIsNotContactOfProject"));
1675
   				elseif ($disabledtask)
1676
   				{
1677
   					$titleassigntask = $langs->trans("AssignTaskToMe");
1678
   					if ($fuser->id != $user->id) $titleassigntask = $langs->trans("AssignTaskToUser", '...');
1679
1680
   					print $form->textwithpicto('', $langs->trans("TaskIsNotAssignedToUser", $titleassigntask));
1681
   				}
1682
				print '</td>';
1683
1684
				print "</tr>\n";
1685
			}
1686
1687
			// Call to show task with a lower level (task under the current task)
1688
			$inc++;
1689
			$level++;
1690
			if ($lines[$i]->id > 0)
1691
			{
1692
				//var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level);
1693
				//var_dump($totalforeachday);
1694
				$ret = projectLinesPerWeek($inc, $firstdaytoshow, $fuser, $lines[$i]->id, ($parent == 0 ? $lineswithoutlevel0 : $lines), $level, $projectsrole, $tasksrole, $mine, $restricteditformytask, $isavailable, $oldprojectforbreak, $arrayfields, $extrafields);
1695
				//var_dump('ret with parent='.$lines[$i]->id.' level='.$level);
1696
				//var_dump($ret);
1697
				foreach ($ret as $key => $val)
1698
				{
1699
					$totalforeachday[$key] += $val;
1700
				}
1701
				//var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level.' + subtasks');
1702
				//var_dump($totalforeachday);
1703
			}
1704
			$level--;
1705
		}
1706
		else
1707
		{
1708
			//$level--;
1709
		}
1710
	}
1711
1712
	return $totalforeachday;
1713
}
1714
1715
/**
1716
 * Output a task line into a perday intput mode
1717
 *
1718
 * @param	string	   	$inc					Line output identificator (start to 0, then increased by recursive call)
1719
 * @param	int			$firstdaytoshow			First day to show
1720
 * @param	User|null	$fuser					Restrict list to user if defined
1721
 * @param   string		$parent					Id of parent task to show (0 to show all)
1722
 * @param   Task[]		$lines					Array of lines (list of tasks but we will show only if we have a specific role on task)
1723
 * @param   int			$level					Level (start to 0, then increased/decrease by recursive call)
1724
 * @param   string		$projectsrole			Array of roles user has on project
1725
 * @param   string		$tasksrole				Array of roles user has on task
1726
 * @param	string		$mine					Show only task lines I am assigned to
1727
 * @param   int			$restricteditformytask	0=No restriction, 1=Enable add time only if task is a task i am affected to
1728
 * @param   array       $isavailable			Array with data that say if user is available for several days for morning and afternoon
1729
 * @param	int			$oldprojectforbreak		Old project id of last project break
1730
 * @param	array		$TWeek					Array of week numbers
1731
 * @return  array								Array with time spent for $fuser for each day of week on tasks in $lines and substasks
1732
 */
1733
function projectLinesPerMonth(&$inc, $firstdaytoshow, $fuser, $parent, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, &$isavailable, $oldprojectforbreak = 0, $TWeek = array())
1734
{
1735
	global $conf, $db, $user, $bc, $langs;
1736
	global $form, $formother, $projectstatic, $taskstatic, $thirdpartystatic;
1737
1738
	$numlines = count($lines);
1739
1740
	$lastprojectid = 0;
1741
	$workloadforid = array();
1742
	$totalforeachweek = array();
1743
	$lineswithoutlevel0 = array();
1744
1745
	// Create a smaller array with sublevels only to be used later. This increase dramatically performances.
1746
	if ($parent == 0) // Always and only if at first level
1747
	{
1748
		for ($i = 0; $i < $numlines; $i++)
1749
		{
1750
			if ($lines[$i]->fk_task_parent) $lineswithoutlevel0[] = $lines[$i];
1751
		}
1752
	}
1753
1754
	//dol_syslog('projectLinesPerWeek inc='.$inc.' firstdaytoshow='.$firstdaytoshow.' task parent id='.$parent.' level='.$level." count(lines)=".$numlines." count(lineswithoutlevel0)=".count($lineswithoutlevel0));
1755
1756
	if (empty($oldprojectforbreak))
1757
	{
1758
		$oldprojectforbreak = (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT) ? 0 : -1); // 0 = start break, -1 = never break
1759
	}
1760
1761
	for ($i = 0; $i < $numlines; $i++)
1762
	{
1763
		if ($parent == 0) $level = 0;
1764
1765
		if ($lines[$i]->fk_task_parent == $parent)
1766
		{
1767
			// If we want all or we have a role on task, we show it
1768
			if (empty($mine) || !empty($tasksrole[$lines[$i]->id]))
1769
			{
1770
				//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);
1771
1772
				// Break on a new project
1773
				if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid)
1774
				{
1775
					$lastprojectid = $lines[$i]->fk_project;
1776
					$projectstatic->id = $lines[$i]->fk_project;
1777
				}
1778
1779
				//var_dump('--- '.$level.' '.$firstdaytoshow.' '.$fuser->id.' '.$projectstatic->id.' '.$workloadforid[$projectstatic->id]);
1780
				//var_dump($projectstatic->weekWorkLoadPerTask);
1781
				if (empty($workloadforid[$projectstatic->id]))
1782
				{
1783
					$projectstatic->loadTimeSpentMonth($firstdaytoshow, 0, $fuser->id); // Load time spent from table projet_task_time for the project into this->weekWorkLoad and this->weekWorkLoadPerTask for all days of a week
1784
					$workloadforid[$projectstatic->id] = 1;
1785
				}
1786
				//var_dump($projectstatic->weekWorkLoadPerTask);
1787
				//var_dump('--- '.$projectstatic->id.' '.$workloadforid[$projectstatic->id]);
1788
1789
				$projectstatic->id = $lines[$i]->fk_project;
1790
				$projectstatic->ref = $lines[$i]->projectref;
1791
				$projectstatic->title = $lines[$i]->projectlabel;
1792
				$projectstatic->public = $lines[$i]->public;
1793
				$projectstatic->thirdparty_name = $lines[$i]->thirdparty_name;
1794
1795
				$taskstatic->id = $lines[$i]->id;
1796
				$taskstatic->ref = ($lines[$i]->ref ? $lines[$i]->ref : $lines[$i]->id);
1797
				$taskstatic->label = $lines[$i]->label;
1798
				$taskstatic->date_start = $lines[$i]->date_start;
1799
				$taskstatic->date_end = $lines[$i]->date_end;
1800
1801
				$thirdpartystatic->id = $lines[$i]->thirdparty_id;
1802
				$thirdpartystatic->name = $lines[$i]->thirdparty_name;
1803
				$thirdpartystatic->email = $lines[$i]->thirdparty_email;
1804
1805
				if (empty($oldprojectforbreak) || ($oldprojectforbreak != -1 && $oldprojectforbreak != $projectstatic->id))
1806
				{
1807
					print '<tr class="oddeven trforbreak">'."\n";
1808
					print '<td colspan="'.(6 + count($TWeek)).'">';
1809
					print $projectstatic->getNomUrl(1, '', 0, '<strong>'.$langs->transnoentitiesnoconv("YourRole").':</strong> '.$projectsrole[$lines[$i]->fk_project]);
1810
					if ($thirdpartystatic->id > 0) print ' - '.$thirdpartystatic->getNomUrl(1);
1811
					if ($projectstatic->title)
1812
					{
1813
						print ' - ';
1814
						print '<span class="secondary">'.$projectstatic->title.'</span>';
1815
					}
1816
					print '</td>';
1817
					print '</tr>';
1818
				}
1819
1820
				if ($oldprojectforbreak != -1) $oldprojectforbreak = $projectstatic->id;
1821
				print '<tr class="oddeven" data-taskid="'.$lines[$i]->id.'">'."\n";
1822
1823
				// User
1824
				/*
1825
				print '<td class="nowrap">';
1826
				print $fuser->getNomUrl(1, 'withproject', 'time');
1827
				print '</td>';
1828
				*/
1829
1830
				// Project
1831
				/*print '<td class="nowrap">';
1832
				if ($oldprojectforbreak == -1) print $projectstatic->getNomUrl(1,'',0,$langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]);
1833
				print "</td>";*/
1834
1835
				// Thirdparty
1836
				/*print '<td class="tdoverflowmax100">';
1837
				if ($thirdpartystatic->id > 0) print $thirdpartystatic->getNomUrl(1, 'project');
1838
				print '</td>';*/
1839
1840
				// Ref
1841
				print '<td class="nowrap">';
1842
				print '<!-- Task id = '.$lines[$i]->id.' -->';
1843
				for ($k = 0; $k < $level; $k++) print "&nbsp;&nbsp;&nbsp;";
1844
				print $taskstatic->getNomUrl(1, 'withproject', 'time');
1845
				// Label task
1846
				print '<br>';
1847
				for ($k = 0; $k < $level; $k++) print "&nbsp;&nbsp;&nbsp;";
1848
				//print $taskstatic->getNomUrl(0, 'withproject', 'time');
1849
				print $taskstatic->label;
1850
				//print "<br>";
1851
				//for ($k = 0 ; $k < $level ; $k++) print "&nbsp;&nbsp;&nbsp;";
1852
				//print get_date_range($lines[$i]->date_start,$lines[$i]->date_end,'',$langs,0);
1853
				print "</td>\n";
1854
1855
				// Planned Workload
1856
				print '<td class="leftborder plannedworkload right">';
1857
				if ($lines[$i]->planned_workload) print convertSecondToTime($lines[$i]->planned_workload, 'allhourmin');
1858
				else print '--:--';
1859
				print '</td>';
1860
1861
				// Progress declared %
1862
				print '<td class="right">';
1863
				print $formother->select_percent($lines[$i]->progress, $lines[$i]->id.'progress');
1864
				print '</td>';
1865
1866
				// Time spent by everybody
1867
				print '<td class="right">';
1868
				// $lines[$i]->duration is a denormalised field = summ of time spent by everybody for task. What we need is time consummed by user
1869
				if ($lines[$i]->duration)
1870
				{
1871
					print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$lines[$i]->id.'">';
1872
					print convertSecondToTime($lines[$i]->duration, 'allhourmin');
1873
					print '</a>';
1874
				}
1875
				else print '--:--';
1876
				print "</td>\n";
1877
1878
				// Time spent by user
1879
				print '<td class="right">';
1880
				$tmptimespent = $taskstatic->getSummaryOfTimeSpent($fuser->id);
1881
				if ($tmptimespent['total_duration']) print convertSecondToTime($tmptimespent['total_duration'], 'allhourmin');
1882
				else print '--:--';
1883
				print "</td>\n";
1884
1885
				$disabledproject = 1; $disabledtask = 1;
1886
				//print "x".$lines[$i]->fk_project;
1887
				//var_dump($lines[$i]);
1888
				//var_dump($projectsrole[$lines[$i]->fk_project]);
1889
				// If at least one role for project
1890
				if ($lines[$i]->public || !empty($projectsrole[$lines[$i]->fk_project]) || $user->rights->projet->all->creer)
1891
				{
1892
					$disabledproject = 0;
1893
					$disabledtask = 0;
1894
				}
1895
				// If $restricteditformytask is on and I have no role on task, i disable edit
1896
				if ($restricteditformytask && empty($tasksrole[$lines[$i]->id]))
1897
				{
1898
					$disabledtask = 1;
1899
				}
1900
1901
				//var_dump($projectstatic->weekWorkLoadPerTask);
1902
				//TODO
1903
				// Fields to show current time
1904
				$tableCell = ''; $modeinput = 'hours';
1905
				$TFirstDay = getFirstDayOfEachWeek($TWeek, date('Y', $firstdaytoshow));
1906
				$TFirstDay[reset($TWeek)] = 1;
1907
				foreach ($TFirstDay as &$fday) {
1908
					$fday--;
1909
				}
1910
				foreach ($TWeek as $weekNb)
1911
				{
1912
					$weekWorkLoad = $projectstatic->monthWorkLoadPerTask[$weekNb][$lines[$i]->id];
1913
					$totalforeachweek[$weekNb] += $weekWorkLoad;
1914
1915
					$alreadyspent = '';
1916
					if ($weekWorkLoad > 0) $alreadyspent = convertSecondToTime($weekWorkLoad, 'allhourmin');
1917
					$alttitle = $langs->trans("AddHereTimeSpentForWeek", $weekNb);
1918
1919
1920
					$tableCell = '<td align="center" class="hide">';
1921
					$placeholder = '';
1922
					if ($alreadyspent)
1923
					{
1924
						$tableCell .= '<span class="timesheetalreadyrecorded" title="texttoreplace"><input type="text" class="center smallpadd" size="2" disabled id="timespent['.$inc.']['.$weekNb.']" name="task['.$lines[$i]->id.']['.$weekNb.']" value="'.$alreadyspent.'"></span>';
1925
						//$placeholder=' placeholder="00:00"';
1926
						//$tableCell.='+';
1927
					}
1928
1929
					$tableCell .= '<input type="text" alt="'.($disabledtask ? '' : $alttitle).'" title="'.($disabledtask ? '' : $alttitle).'" '.($disabledtask ? 'disabled' : $placeholder).' class="center smallpadd" size="2" id="timeadded['.$inc.']['.$TFirstDay[$weekNb].']" name="task['.$lines[$i]->id.']['.$TFirstDay[$weekNb].']" value="" cols="2"  maxlength="5"';
1930
					$tableCell .= ' onkeypress="return regexEvent(this,event,\'timeChar\')"';
1931
					$tableCell .= ' onkeyup="updateTotal('.$weekNb.',\''.$modeinput.'\')"';
1932
					$tableCell .= ' onblur="regexEvent(this,event,\''.$modeinput.'\'); updateTotal('.$weekNb.',\''.$modeinput.'\')" />';
1933
					$tableCell .= '</td>';
1934
					print $tableCell;
1935
				}
1936
1937
				// Warning
1938
				print '<td class="right">';
1939
				if ((!$lines[$i]->public) && $disabledproject) print $form->textwithpicto('', $langs->trans("UserIsNotContactOfProject"));
1940
				elseif ($disabledtask)
1941
				{
1942
					$titleassigntask = $langs->trans("AssignTaskToMe");
1943
					if ($fuser->id != $user->id) $titleassigntask = $langs->trans("AssignTaskToUser", '...');
1944
1945
					print $form->textwithpicto('', $langs->trans("TaskIsNotAssignedToUser", $titleassigntask));
1946
				}
1947
				print '</td>';
1948
1949
				print "</tr>\n";
1950
			}
1951
1952
			// Call to show task with a lower level (task under the current task)
1953
			$inc++;
1954
			$level++;
1955
			if ($lines[$i]->id > 0)
1956
			{
1957
				//var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level);
1958
				//var_dump($totalforeachday);
1959
				$ret = projectLinesPerMonth($inc, $firstdaytoshow, $fuser, $lines[$i]->id, ($parent == 0 ? $lineswithoutlevel0 : $lines), $level, $projectsrole, $tasksrole, $mine, $restricteditformytask, $isavailable, $oldprojectforbreak, $TWeek);
1960
				//var_dump('ret with parent='.$lines[$i]->id.' level='.$level);
1961
				//var_dump($ret);
1962
				foreach ($ret as $key => $val)
1963
				{
1964
					$totalforeachweek[$key] += $val;
1965
				}
1966
				//var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level.' + subtasks');
1967
				//var_dump($totalforeachday);
1968
			}
1969
			$level--;
1970
		}
1971
		else
1972
		{
1973
			//$level--;
1974
		}
1975
	}
1976
1977
	return $totalforeachweek;
1978
}
1979
1980
1981
/**
1982
 * Search in task lines with a particular parent if there is a task for a particular user (in taskrole)
1983
 *
1984
 * @param 	string	$inc				Counter that count number of lines legitimate to show (for return)
1985
 * @param 	int		$parent				Id of parent task to start
1986
 * @param 	array	$lines				Array of all tasks
1987
 * @param	string	$taskrole			Array of task filtered on a particular user
1988
 * @return	int							1 if there is
1989
 */
1990
function searchTaskInChild(&$inc, $parent, &$lines, &$taskrole)
1991
{
1992
	//print 'Search in line with parent id = '.$parent.'<br>';
1993
	$numlines = count($lines);
1994
	for ($i = 0; $i < $numlines; $i++)
1995
	{
1996
		// Process line $lines[$i]
1997
		if ($lines[$i]->fk_parent == $parent && $lines[$i]->id != $lines[$i]->fk_parent)
1998
		{
1999
			// If task is legitimate to show, no more need to search deeper
2000
			if (isset($taskrole[$lines[$i]->id]))
2001
			{
2002
				//print 'Found a legitimate task id='.$lines[$i]->id.'<br>';
2003
				$inc++;
2004
				return $inc;
2005
			}
2006
2007
			searchTaskInChild($inc, $lines[$i]->id, $lines, $taskrole);
2008
			//print 'Found inc='.$inc.'<br>';
2009
2010
			if ($inc > 0) return $inc;
2011
		}
2012
	}
2013
2014
	return $inc;
2015
}
2016
2017
/**
2018
 * Return HTML table with list of projects and number of opened tasks
2019
 *
2020
 * @param	DoliDB	$db					Database handler
2021
 * @param	Form	$form				Object form
2022
 * @param   int		$socid				Id thirdparty
2023
 * @param   int		$projectsListId     Id of project I have permission on
2024
 * @param   int		$mytasks            Limited to task I am contact to
2025
 * @param	int		$status				-1=No filter on statut, 0 or 1 = Filter on status
2026
 * @param	array	$listofoppstatus	List of opportunity status
2027
 * @param   array   $hiddenfields       List of info to not show ('projectlabel', 'declaredprogress', '...', )
2028
 * @return	void
2029
 */
2030
function print_projecttasks_array($db, $form, $socid, $projectsListId, $mytasks = 0, $status = -1, $listofoppstatus = array(), $hiddenfields = array())
2031
{
2032
	global $langs, $conf, $user, $bc;
2033
	global $theme_datacolor;
2034
2035
	require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
2036
2037
	$listofstatus = array_keys($listofoppstatus);
2038
2039
	if (is_array($listofstatus) && ! empty($conf->global->USE_COLOR_FOR_PROSPECTION_STATUS)) {
2040
		// Define $themeColorId and array $statusOppList for each $listofstatus
2041
		$themeColorId = 0;
2042
		$statusOppList = array();
2043
		foreach ($listofstatus as $oppStatus) {
2044
			$oppStatusCode = dol_getIdFromCode($db, $oppStatus, 'c_lead_status', 'rowid', 'code');
2045
			if ($oppStatusCode) {
2046
				$statusOppList[$oppStatus]['code'] = $oppStatusCode;
2047
				$statusOppList[$oppStatus]['color'] = isset($theme_datacolor[$themeColorId]) ? implode(', ', $theme_datacolor[$themeColorId]) : '';
2048
			}
2049
			$themeColorId++;
2050
		}
2051
	}
2052
2053
	$projectstatic = new Project($db);
2054
	$thirdpartystatic = new Societe($db);
2055
2056
	$sortfield = '';
2057
	$sortorder = '';
2058
	$project_year_filter = 0;
2059
2060
	$title = $langs->trans("Projects");
2061
	if (strcmp($status, '') && $status >= 0) $title = $langs->trans("Projects").' '.$langs->trans($projectstatic->statuts_long[$status]);
2062
2063
	$arrayidtypeofcontact = array();
2064
2065
	print '<div class="div-table-responsive-no-min">';
2066
	print '<table class="noborder centpercent">';
2067
2068
	$sql = " FROM ".MAIN_DB_PREFIX."projet as p";
2069
	if ($mytasks)
2070
	{
2071
		$sql .= ", ".MAIN_DB_PREFIX."projet_task as t";
2072
		$sql .= ", ".MAIN_DB_PREFIX."element_contact as ec";
2073
		$sql .= ", ".MAIN_DB_PREFIX."c_type_contact as ctc";
2074
	}
2075
	else
2076
	{
2077
		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task as t ON p.rowid = t.fk_projet";
2078
	}
2079
	$sql .= " WHERE p.entity IN (".getEntity('project').")";
2080
	$sql .= " AND p.rowid IN (".$projectsListId.")";
2081
	if ($socid) $sql .= "  AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".$socid.")";
2082
	if ($mytasks)
2083
	{
2084
		$sql .= " AND p.rowid = t.fk_projet";
2085
		$sql .= " AND ec.element_id = t.rowid";
2086
		$sql .= " AND ec.fk_socpeople = ".$user->id;
2087
		$sql .= " AND ec.fk_c_type_contact = ctc.rowid"; // Replace the 2 lines with ec.fk_c_type_contact in $arrayidtypeofcontact
2088
		$sql .= " AND ctc.element = 'project_task'";
2089
	}
2090
	if ($status >= 0)
2091
	{
2092
		$sql .= " AND p.fk_statut = ".(int) $status;
2093
	}
2094
	if (!empty($conf->global->PROJECT_LIMIT_YEAR_RANGE))
2095
	{
2096
		$project_year_filter = GETPOST("project_year_filter");
2097
		//Check if empty or invalid year. Wildcard ignores the sql check
2098
		if ($project_year_filter != "*")
2099
		{
2100
			if (empty($project_year_filter) || !ctype_digit($project_year_filter))
2101
			{
2102
				$project_year_filter = date("Y");
2103
			}
2104
			$sql .= " AND (p.dateo IS NULL OR p.dateo <= ".$db->idate(dol_get_last_day($project_year_filter, 12, false)).")";
2105
			$sql .= " AND (p.datee IS NULL OR p.datee >= ".$db->idate(dol_get_first_day($project_year_filter, 1, false)).")";
2106
		}
2107
	}
2108
2109
	// Get id of project we must show tasks
2110
	$arrayidofprojects = array();
2111
	$sql1 = "SELECT p.rowid as projectid";
2112
	$sql1 .= $sql;
2113
	$resql = $db->query($sql1);
2114
	if ($resql)
2115
	{
2116
		$i = 0;
2117
		$num = $db->num_rows($resql);
2118
		while ($i < $num)
2119
		{
2120
			$objp = $db->fetch_object($resql);
2121
			$arrayidofprojects[$objp->projectid] = $objp->projectid;
2122
			$i++;
2123
		}
2124
	}
2125
	else dol_print_error($db);
2126
	if (empty($arrayidofprojects)) $arrayidofprojects[0] = -1;
2127
2128
	// Get list of project with calculation on tasks
2129
	$sql2 = "SELECT p.rowid as projectid, p.ref, p.title, p.fk_soc, s.nom as socname, p.fk_user_creat, p.public, p.fk_statut as status, p.fk_opp_status as opp_status, p.opp_percent, p.opp_amount,";
2130
	$sql2 .= " p.dateo, p.datee,";
2131
	$sql2 .= " COUNT(t.rowid) as nb, SUM(t.planned_workload) as planned_workload, SUM(t.planned_workload * t.progress / 100) as declared_progess_workload";
2132
	$sql2 .= " FROM ".MAIN_DB_PREFIX."projet as p";
2133
	$sql2 .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = p.fk_soc";
2134
	$sql2 .= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task as t ON p.rowid = t.fk_projet";
2135
	$sql2 .= " WHERE p.rowid IN (".join(',', $arrayidofprojects).")";
2136
	$sql2 .= " GROUP BY p.rowid, p.ref, p.title, p.fk_soc, s.nom, p.fk_user_creat, p.public, p.fk_statut, p.fk_opp_status, p.opp_percent, p.opp_amount, p.dateo, p.datee";
2137
	$sql2 .= " ORDER BY p.title, p.ref";
2138
2139
	$resql = $db->query($sql2);
2140
	if ($resql)
2141
	{
2142
	    $total_task = 0;
2143
		$total_opp_amount = 0;
2144
		$ponderated_opp_amount = 0;
2145
2146
		$num = $db->num_rows($resql);
2147
		$i = 0;
2148
2149
		print '<tr class="liste_titre">';
2150
		print_liste_field_titre($title.'<span class="badge marginleftonlyshort">'.$num.'</span>', $_SERVER["PHP_SELF"], "", "", "", "", $sortfield, $sortorder);
2151
		print_liste_field_titre("ThirdParty", $_SERVER["PHP_SELF"], "", "", "", "", $sortfield, $sortorder);
2152
		if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES))
2153
		{
2154
			if (!in_array('prospectionstatus', $hiddenfields)) print_liste_field_titre("OpportunityStatus", "", "", "", "", '', $sortfield, $sortorder, 'right ');
2155
			print_liste_field_titre("OpportunityAmount", "", "", "", "", 'align="right"', $sortfield, $sortorder);
2156
			print_liste_field_titre('OpportunityWeightedAmount', '', '', '', '', 'align="right"', $sortfield, $sortorder);
2157
		}
2158
		if (empty($conf->global->PROJECT_HIDE_TASKS))
2159
		{
2160
			print_liste_field_titre("Tasks", "", "", "", "", 'align="right"', $sortfield, $sortorder);
2161
			if (!in_array('plannedworkload', $hiddenfields))  print_liste_field_titre("PlannedWorkload", "", "", "", "", '', $sortfield, $sortorder, 'right ');
2162
			if (!in_array('declaredprogress', $hiddenfields)) print_liste_field_titre("ProgressDeclared", "", "", "", "", '', $sortfield, $sortorder, 'right ');
2163
		}
2164
		if (!in_array('projectstatus', $hiddenfields)) print_liste_field_titre("Status", "", "", "", "", '', $sortfield, $sortorder, 'right ');
2165
		print "</tr>\n";
2166
2167
		$total_plannedworkload = 0;
2168
		$total_declaredprogressworkload = 0;
2169
		while ($i < $num)
2170
		{
2171
			$objp = $db->fetch_object($resql);
2172
2173
			$projectstatic->id = $objp->projectid;
2174
			$projectstatic->user_author_id = $objp->fk_user_creat;
2175
			$projectstatic->public = $objp->public;
2176
2177
			// Check is user has read permission on project
2178
			$userAccess = $projectstatic->restrictedProjectArea($user);
2179
			if ($userAccess >= 0)
2180
			{
2181
				$projectstatic->ref = $objp->ref;
2182
				$projectstatic->statut = $objp->status;		// deprecated
2183
				$projectstatic->status = $objp->status;
2184
				$projectstatic->title = $objp->title;
2185
				$projectstatic->datee = $db->jdate($objp->datee);
2186
				$projectstatic->dateo = $db->jdate($objp->dateo);
2187
2188
				print '<tr class="oddeven">';
2189
2190
				print '<td>';
2191
				print $projectstatic->getNomUrl(1);
2192
				if (!in_array('projectlabel', $hiddenfields)) print '<br>'.dol_trunc($objp->title, 24);
2193
				print '</td>';
2194
				print '<td>';
2195
				if ($objp->fk_soc > 0)
2196
				{
2197
					$thirdpartystatic->id = $objp->fk_soc;
2198
					$thirdpartystatic->ref = $objp->socname;
2199
					$thirdpartystatic->name = $objp->socname;
2200
					print $thirdpartystatic->getNomUrl(1);
2201
				}
2202
				print '</td>';
2203
2204
				if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES))
2205
				{
2206
					if (!in_array('prospectionstatus', $hiddenfields)) {
2207
						print '<td class="right">';
2208
						// Because color of prospection status has no meaning yet, it is used if hidden constant is set
2209
						if (empty($conf->global->USE_COLOR_FOR_PROSPECTION_STATUS)) {
2210
							$oppStatusCode = dol_getIdFromCode($db, $objp->opp_status, 'c_lead_status', 'rowid', 'code');
2211
							if ($langs->trans("OppStatus".$oppStatusCode) != "OppStatus".$oppStatusCode) {
2212
								print $langs->trans("OppStatus".$oppStatusCode);
2213
							}
2214
						} else {
2215
							if (isset($statusOppList[$objp->opp_status])) {
2216
								$oppStatusCode = $statusOppList[$objp->opp_status]['code'];
2217
								$oppStatusColor = $statusOppList[$objp->opp_status]['color'];
2218
							} else {
2219
								$oppStatusCode = dol_getIdFromCode($db, $objp->opp_status, 'c_lead_status', 'rowid', 'code');
2220
								$oppStatusColor = '';
2221
							}
2222
							if ($oppStatusCode) {
2223
								if (!empty($oppStatusColor)) {
2224
									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>';
2225
								} else {
2226
									print '<a href="'.dol_buildpath('/projet/list.php?search_opp_status='.$objp->opp_status, 1).'" title="'.$langs->trans("OppStatus".$oppStatusCode).'">'.$oppStatusCode.'</a>';
2227
								}
2228
							}
2229
						}
2230
						print '</td>';
2231
					}
2232
2233
					print '<td class="right">';
2234
					if ($objp->opp_amount) print price($objp->opp_amount, 0, '', 1, -1, -1, $conf->currency);
2235
					print '</td>';
2236
					print '<td class="right">';
2237
                    if ($objp->opp_percent && $objp->opp_amount) {
2238
                        $opp_weighted_amount = $objp->opp_percent * $objp->opp_amount / 100;
2239
                        print price($opp_weighted_amount, 0, '', 1, -1, -1, $conf->currency);
2240
                        $ponderated_opp_amount += price2num($opp_weighted_amount);
2241
                    }
2242
					print '</td>';
2243
				}
2244
2245
				if (empty($conf->global->PROJECT_HIDE_TASKS))
2246
				{
2247
					print '<td class="right">'.$objp->nb.'</td>';
2248
2249
					$plannedworkload = $objp->planned_workload;
2250
					$total_plannedworkload += $plannedworkload;
2251
					if (!in_array('plannedworkload', $hiddenfields))
2252
					{
2253
						print '<td class="right">'.($plannedworkload ?convertSecondToTime($plannedworkload) : '').'</td>';
2254
					}
2255
					if (!in_array('declaredprogress', $hiddenfields))
2256
					{
2257
						$declaredprogressworkload = $objp->declared_progess_workload;
2258
						$total_declaredprogressworkload += $declaredprogressworkload;
2259
						print '<td class="right">';
2260
						//print $objp->planned_workload.'-'.$objp->declared_progess_workload."<br>";
2261
						print ($plannedworkload ?round(100 * $declaredprogressworkload / $plannedworkload, 0).'%' : '');
2262
						print '</td>';
2263
					}
2264
				}
2265
2266
				if (!in_array('projectstatus', $hiddenfields)) {
2267
					print '<td class="right">';
2268
					print $projectstatic->getLibStatut(3);
2269
					print '</td>';
2270
				}
2271
2272
				print "</tr>\n";
2273
2274
				$total_task = $total_task + $objp->nb;
2275
				$total_opp_amount = $total_opp_amount + $objp->opp_amount;
2276
			}
2277
2278
			$i++;
2279
		}
2280
2281
		print '<tr class="liste_total">';
2282
		print '<td colspan="2">'.$langs->trans("Total")."</td>";
2283
		if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES))
2284
		{
2285
			if (!in_array('prospectionstatus', $hiddenfields)) {
2286
				print '<td class="liste_total"></td>';
2287
			}
2288
			print '<td class="liste_total right">'.price($total_opp_amount, 0, '', 1, -1, -1, $conf->currency).'</td>';
2289
			print '<td class="liste_total right">'.$form->textwithpicto(price($ponderated_opp_amount, 0, '', 1, -1, -1, $conf->currency), $langs->trans("OpportunityPonderatedAmountDesc"), 1).'</td>';
2290
		}
2291
		if (empty($conf->global->PROJECT_HIDE_TASKS))
2292
		{
2293
			print '<td class="liste_total right">'.$total_task.'</td>';
2294
			if (!in_array('plannedworkload', $hiddenfields))  print '<td class="liste_total right">'.($total_plannedworkload ?convertSecondToTime($total_plannedworkload) : '').'</td>';
2295
			if (!in_array('declaredprogress', $hiddenfields)) print '<td class="liste_total right">'.($total_plannedworkload ?round(100 * $total_declaredprogressworkload / $total_plannedworkload, 0).'%' : '').'</td>';
2296
		}
2297
		if (!in_array('projectstatus', $hiddenfields)) {
2298
			print '<td class="liste_total"></td>';
2299
		}
2300
		print '</tr>';
2301
2302
		$db->free($resql);
2303
	}
2304
	else
2305
	{
2306
		dol_print_error($db);
2307
	}
2308
2309
	print "</table>";
2310
	print '</div>';
2311
2312
	if (!empty($conf->global->PROJECT_LIMIT_YEAR_RANGE))
2313
	{
2314
		//Add the year filter input
2315
		print '<form method="get" action="'.$_SERVER["PHP_SELF"].'">';
2316
		print '<table width="100%">';
2317
		print '<tr>';
2318
		print '<td>'.$langs->trans("Year").'</td>';
2319
		print '<td class="right"><input type="text" size="4" class="flat" name="project_year_filter" value="'.$project_year_filter.'"/>';
2320
		print "</tr>\n";
2321
		print '</table></form>';
2322
	}
2323
}
2324
2325
/**
2326
 * @param   Task        $task               the task object
2327
 * @param   bool|string $label              true = auto, false = dont display, string = replace output
2328
 * @param   bool|string $progressNumber     true = auto, false = dont display, string = replace output
2329
 * @param   bool        $hideOnProgressNull hide if progress is null
2330
 * @param   bool        $spaced             used to add space at bottom (made by css)
2331
 * @return string
2332
 * @see getTaskProgressBadge()
2333
 */
2334
function getTaskProgressView($task, $label = true, $progressNumber = true, $hideOnProgressNull = false, $spaced = false)
2335
{
2336
    global $langs, $conf;
2337
2338
    $out = '';
2339
2340
    $plannedworkloadoutputformat = 'allhourmin';
2341
    $timespentoutputformat = 'allhourmin';
2342
    if (!empty($conf->global->PROJECT_PLANNED_WORKLOAD_FORMAT)) $plannedworkloadoutputformat = $conf->global->PROJECT_PLANNED_WORKLOAD_FORMAT;
2343
    if (!empty($conf->global->PROJECT_TIMES_SPENT_FORMAT)) $timespentoutputformat = $conf->global->PROJECT_TIME_SPENT_FORMAT;
2344
2345
    if (empty($task->progress) && !empty($hideOnProgressNull)) {
2346
        return '';
2347
    }
2348
2349
    $spaced = !empty($spaced) ? 'spaced' : '';
2350
2351
    $diff = '';
2352
2353
    // define progress color according to time spend vs workload
2354
    $progressBarClass = 'progress-bar-info';
2355
    if ($task->planned_workload) {
2356
        $progressCalculated = round(100 * doubleval($task->duration_effective) / doubleval($task->planned_workload), 2);
2357
2358
        // this conf is actually hidden, by default we use 10% for "be carefull or warning"
2359
        $warningRatio = !empty($conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT) ? (1 + $conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT / 100) : 1.10;
2360
2361
        $diffTitle = '<br/>'.$langs->trans('ProgressDeclared').' : '.$task->progress.($task->progress ? '%' : '');
2362
        $diffTitle .= '<br/>'.$langs->trans('ProgressCalculated').' : '.$progressCalculated.($progressCalculated ? '%' : '');
2363
2364
        //var_dump($progressCalculated.' '.$warningRatio.' '.$task->progress.' '.doubleval($task->progress * $warningRatio));
2365
        if (doubleval($progressCalculated) > doubleval($task->progress * $warningRatio)) {
2366
            $progressBarClass = 'progress-bar-danger';
2367
            $title = $langs->trans('TheReportedProgressIsLessThanTheCalculatedProgressionByX', abs($task->progress - $progressCalculated).' '.$langs->trans("point"));
2368
            $diff = '<span class="text-danger classfortooltip paddingrightonly" title="'.dol_htmlentities($title.$diffTitle).'" ><i class="fa fa-caret-down"></i> '.($task->progress - $progressCalculated).'%</span>';
2369
        }
2370
        elseif (doubleval($progressCalculated) > doubleval($task->progress)) { // warning if close at 10%
2371
            $progressBarClass = 'progress-bar-warning';
2372
            $title = $langs->trans('TheReportedProgressIsLessThanTheCalculatedProgressionByX', abs($task->progress - $progressCalculated).' '.$langs->trans("point"));
2373
            $diff = '<span class="text-warning classfortooltip paddingrightonly" title="'.dol_htmlentities($title.$diffTitle).'" ><i class="fa fa-caret-left"></i> '.($task->progress - $progressCalculated).'%</span>';
2374
        }
2375
        else {
2376
            $progressBarClass = 'progress-bar-success';
2377
            $title = $langs->trans('TheReportedProgressIsMoreThanTheCalculatedProgressionByX', ($task->progress - $progressCalculated).' '.$langs->trans("point"));
2378
            $diff = '<span class="text-success classfortooltip paddingrightonly" title="'.dol_htmlentities($title.$diffTitle).'" ><i class="fa fa-caret-up"></i> '.($task->progress - $progressCalculated).'%</span>';
2379
        }
2380
    }
2381
2382
    $out .= '<div class="progress-group">';
2383
2384
    if ($label !== false)
2385
    {
2386
        $out .= '    <span class="progress-text">';
2387
2388
        if ($label !== true) {
2389
            $out .= $label; // replace label by param
2390
        }
2391
        else {
2392
            $out .= $task->getNomUrl(1).' '.dol_htmlentities($task->label);
2393
        }
2394
        $out .= '    </span>';
2395
    }
2396
2397
2398
    if ($progressNumber !== false)
2399
    {
2400
        $out .= '    <span class="progress-number">';
2401
        if ($progressNumber !== true) {
2402
            $out .= $progressNumber; // replace label by param
2403
        }
2404
        else {
2405
            if ($task->hasDelay()) $out .= img_warning($langs->trans("Late")).' ';
2406
2407
			$url = DOL_URL_ROOT.'/projet/tasks/time.php?id='.$task->id;
2408
2409
            $out .= !empty($diff) ? $diff.' ' : '';
2410
			$out .= '<a href="'.$url.'" >';
2411
            $out .= '<b title="'.$langs->trans('TimeSpent').'" >';
2412
            if ($task->duration_effective) $out .= convertSecondToTime($task->duration_effective, $timespentoutputformat);
2413
            else $out .= '--:--';
2414
            $out .= '</b>';
2415
			$out .= '</a>';
2416
2417
            $out .= '/';
2418
2419
			$out .= '<a href="'.$url.'" >';
2420
            $out .= '<span title="'.$langs->trans('PlannedWorkload').'" >';
2421
            if ($task->planned_workload) $out .= convertSecondToTime($task->planned_workload, $plannedworkloadoutputformat);
2422
            else $out .= '--:--';
2423
			$out .= '</a>';
2424
        }
2425
        $out .= '    </span>';
2426
    }
2427
2428
2429
    $out .= '</span>';
2430
    $out .= '    <div class="progress sm '.$spaced.'">';
2431
    $diffval = doubleval($task->progress) - doubleval($progressCalculated);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $progressCalculated does not seem to be defined for all execution paths leading up to this point.
Loading history...
2432
    if ($diffval >= 0) {
2433
    	// good
2434
    	$out .= '        <div class="progress-bar '.$progressBarClass.'" style="width: '.doubleval($task->progress).'%" title="'.doubleval($task->progress).'%">';
2435
    	if (!empty($task->progress)) {
2436
			$out .= '        <div class="progress-bar progress-bar-consumed" style="width: '.doubleval($progressCalculated / $task->progress * 100).'%" title="'.doubleval($progressCalculated).'%"></div>';
2437
		}
2438
    	$out .= '        </div>';
2439
    }
2440
    else
2441
    {
2442
    	// bad
2443
    	$out .= '        <div class="progress-bar progress-bar-consumed" style="width: '.doubleval($progressCalculated).'%" title="'.doubleval($progressCalculated).'%">';
2444
    	$out .= '        <div class="progress-bar '.$progressBarClass.'" style="width: '.($task->progress ? doubleval($task->progress / $progressCalculated * 100).'%' : '1px').'" title="'.doubleval($task->progress).'%"></div>';
2445
    	$out .= '        </div>';
2446
    }
2447
    $out .= '    </div>';
2448
    $out .= '</div>';
2449
2450
2451
2452
    return $out;
2453
}
2454
/**
2455
 * @param   Task    $task       the task object
2456
 * @param   string  $label      empty = auto (progress), string = replace output
2457
 * @param   string  $tooltip    empty = auto , string = replace output
2458
 * @return  string
2459
 * @see getTaskProgressView()
2460
 */
2461
function getTaskProgressBadge($task, $label = '', $tooltip = '')
2462
{
2463
    global $conf, $langs;
2464
2465
    $out = '';
2466
    $badgeClass = '';
2467
    if ($task->progress != '')
2468
    {
2469
        // TODO : manage 100%
2470
2471
        // define color according to time spend vs workload
2472
        $badgeClass = 'badge ';
2473
        if ($task->planned_workload) {
2474
            $progressCalculated = round(100 * doubleval($task->duration_effective) / doubleval($task->planned_workload), 2);
2475
2476
            // this conf is actually hidden, by default we use 10% for "be carefull or warning"
2477
            $warningRatio = !empty($conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT) ? (1 + $conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT / 100) : 1.10;
2478
2479
            if (doubleval($progressCalculated) > doubleval($task->progress * $warningRatio)) {
2480
                $badgeClass .= 'badge-danger';
2481
                if (empty($tooltip)) $tooltip = $task->progress.'% < '.$langs->trans("Expected").' '.$progressCalculated.'%';
2482
            }
2483
            elseif (doubleval($progressCalculated) > doubleval($task->progress)) { // warning if close at 10%
2484
                $badgeClass .= 'badge-warning';
2485
                if (empty($tooltip)) $tooltip = $task->progress.'% < '.$langs->trans("Expected").' '.$progressCalculated.'%';
2486
            }
2487
            else {
2488
                $badgeClass .= 'badge-success';
2489
                if (empty($tooltip)) $tooltip = $task->progress.'% >= '.$langs->trans("Expected").' '.$progressCalculated.'%';
2490
            }
2491
        }
2492
    }
2493
2494
    $title = '';
2495
    if (!empty($tooltip)) {
2496
        $badgeClass .= ' classfortooltip';
2497
        $title = 'title="'.dol_htmlentities($tooltip).'"';
2498
    }
2499
2500
    if (empty($label)) {
2501
        $label = $task->progress.' %';
2502
    }
2503
2504
    if (!empty($label)) {
2505
        $out = '<span class="'.$badgeClass.'" '.$title.' >'.$label.'</span>';
2506
    }
2507
2508
    return $out;
2509
}
2510