dolibarr  19.0.0-dev
permonth.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2004-2015 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2005-2010 Regis Houssin <regis.houssin@capnetworks.com>
5  * Copyright (C) 2010 François Legastelois <flegastelois@teclib.com>
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  */
20 
27 require "../../main.inc.php";
28 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
29 require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
30 require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
31 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
32 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
33 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
34 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
35 require_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php';
36 
37 // Load translation files required by the page
38 $langs->loadLangs(array('projects', 'users', 'companies'));
39 $hookmanager->initHooks(array('timesheetpermonthcard'));
40 
41 $action = GETPOST('action', 'aZ09');
42 $mode = GETPOST("mode", 'alpha');
43 $id = GETPOST('id', 'int');
44 $taskid = GETPOST('taskid', 'int');
45 
46 $mine = 0;
47 if ($mode == 'mine') {
48  $mine = 1;
49 }
50 
51 $projectid = GETPOSTISSET("id") ? GETPOST("id", "int", 1) : GETPOST("projectid", "int");
52 
53 // Security check
54 $socid = 0;
55 // For external user, no check is done on company because readability is managed by public status of project and assignement.
56 // if ($user->societe_id > 0) $socid=$user->societe_id;
57 $result = restrictedArea($user, 'projet', $projectid);
58 
59 $now = dol_now();
60 
61 $year = GETPOST('reyear') ?GETPOST('reyear', 'int') : (GETPOST("year") ?GETPOST("year", "int") : date("Y"));
62 $month = GETPOST('remonth') ?GETPOST('remonth', 'int') : (GETPOST("month") ?GETPOST("month", "int") : date("m"));
63 $day = GETPOST('reday') ?GETPOST('reday', 'int') : (GETPOST("day") ?GETPOST("day", "int") : date("d"));
64 $day = (int) $day;
65 $week = GETPOST("week", "int") ?GETPOST("week", "int") : date("W");
66 
67 //$search_categ = GETPOST("search_categ", 'alpha');
68 $search_usertoprocessid = GETPOST('search_usertoprocessid', 'int');
69 $search_task_ref = GETPOST('search_task_ref', 'alpha');
70 $search_task_label = GETPOST('search_task_label', 'alpha');
71 $search_project_ref = GETPOST('search_project_ref', 'alpha');
72 $search_thirdparty = GETPOST('search_thirdparty', 'alpha');
73 $search_declared_progress = GETPOST('search_declared_progress', 'alpha');
74 
75 $startdayarray = dol_get_prev_month($month, $year);
76 
77 $prev = $startdayarray;
78 $prev_year = $prev['year'];
79 $prev_month = $prev['month'];
80 $prev_day = 1;
81 
82 $next = dol_get_next_month($month, $year);
83 $next_year = $next['year'];
84 $next_month = $next['month'];
85 $next_day = 1;
86 $TWeek = getWeekNumbersOfMonth($month, $year);
87 $firstdaytoshow = dol_mktime(0, 0, 0, $month, 1, $year);
88 $TFirstDays = getFirstDayOfEachWeek($TWeek, $year);
89 $TFirstDays[reset($TWeek)] = '01'; //first day of month
90 $TLastDays = getLastDayOfEachWeek($TWeek, $year);
91 $TLastDays[end($TWeek)] = date("t", strtotime($year.'-'.$month.'-'.$day)); //last day of month
92 if (empty($search_usertoprocessid) || $search_usertoprocessid == $user->id) {
93  $usertoprocess = $user;
94  $search_usertoprocessid = $usertoprocess->id;
95 } elseif ($search_usertoprocessid > 0) {
96  $usertoprocess = new User($db);
97  $usertoprocess->fetch($search_usertoprocessid);
98  $search_usertoprocessid = $usertoprocess->id;
99 } else {
100  $usertoprocess = new User($db);
101 }
102 
103 $object = new Task($db);
104 
105 $error = 0;
106 
107 
108 /*
109  * Actions
110  */
111 $parameters = array('id' => $id, 'taskid' => $taskid, 'projectid' => $projectid, 'TWeek' => $TWeek, 'TFirstDays' => $TFirstDays, 'TLastDays' => $TLastDays);
112 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
113 if ($reshook < 0) {
114  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
115 }
116 
117 // Purge criteria
118 if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
119  $action = '';
120  //$search_categ = '';
121  $search_usertoprocessid = $user->id;
122  $search_task_ref = '';
123  $search_task_label = '';
124  $search_project_ref = '';
125  $search_thirdparty = '';
126  $search_declared_progress = '';
127 }
128 if (GETPOST("button_search_x", 'alpha') || GETPOST("button_search.x", 'alpha') || GETPOST("button_search", 'alpha')) {
129  $action = '';
130 }
131 
132 if (GETPOST('submitdateselect')) {
133  $daytoparse = dol_mktime(0, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear'));
134 
135  $action = '';
136 }
137 if ($action == 'addtime' && $user->rights->projet->lire && GETPOST('assigntask')) {
138  $action = 'assigntask';
139 
140  if ($taskid > 0) {
141  $result = $object->fetch($taskid, $ref);
142  if ($result < 0) {
143  $error++;
144  }
145  } else {
146  setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Task")), null, 'errors');
147  $error++;
148  }
149  if (!GETPOST('type')) {
150  setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
151  $error++;
152  }
153 
154  if (!$error) {
155  $idfortaskuser = $usertoprocess->id;
156  $result = $object->add_contact($idfortaskuser, GETPOST("type"), 'internal');
157 
158  if ($result >= 0 || $result == -2) { // Contact add ok or already contact of task
159  // Test if we are already contact of the project (should be rare but sometimes we can add as task contact without being contact of project, like when admin user has been removed from contact of project)
160  $sql = 'SELECT ec.rowid FROM '.MAIN_DB_PREFIX.'element_contact as ec, '.MAIN_DB_PREFIX.'c_type_contact as tc WHERE tc.rowid = ec.fk_c_type_contact';
161  $sql .= ' AND ec.fk_socpeople = '.((int) $idfortaskuser)." AND ec.element_id = ".((int) $object->fk_project)." AND tc.element = 'project' AND source = 'internal'";
162  $resql = $db->query($sql);
163  if ($resql) {
164  $obj = $db->fetch_object($resql);
165  if (!$obj) { // User is not already linked to project, so we will create link to first type
166  $project = new Project($db);
167  $project->fetch($object->fk_project);
168  // Get type
169  $listofprojcontact = $project->liste_type_contact('internal');
170 
171  if (count($listofprojcontact)) {
172  $tmparray = array_keys($listofprojcontact);
173  $typeforprojectcontact = reset($tmparray);
174  $result = $project->add_contact($idfortaskuser, $typeforprojectcontact, 'internal');
175  }
176  }
177  } else {
178  dol_print_error($db);
179  }
180  }
181  }
182 
183  if ($result < 0) {
184  $error++;
185  if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
186  $langs->load("errors");
187  setEventMessages($langs->trans("ErrorTaskAlreadyAssigned"), null, 'warnings');
188  } else {
189  setEventMessages($object->error, $object->errors, 'errors');
190  }
191  }
192 
193  if (!$error) {
194  setEventMessages("TaskAssignedToEnterTime", null);
195  $taskid = 0;
196  }
197 
198  $action = '';
199 }
200 
201 if ($action == 'addtime' && $user->rights->projet->lire) {
202  $timetoadd = GETPOST('task');
203  if (empty($timetoadd)) {
204  setEventMessages($langs->trans("ErrorTimeSpentIsEmpty"), null, 'errors');
205  } else {
206  foreach ($timetoadd as $tmptaskid => $tmpvalue) { // Loop on each task
207  $updateoftaskdone = 0;
208  foreach ($tmpvalue as $key => $val) { // Loop on each day
209  $amountoadd = $timetoadd[$tmptaskid][$key];
210  if (!empty($amountoadd)) {
211  $tmpduration = explode(':', $amountoadd);
212  $newduration = 0;
213  if (!empty($tmpduration[0])) {
214  $newduration += ($tmpduration[0] * 3600);
215  }
216  if (!empty($tmpduration[1])) {
217  $newduration += ($tmpduration[1] * 60);
218  }
219  if (!empty($tmpduration[2])) {
220  $newduration += ($tmpduration[2]);
221  }
222 
223  if ($newduration > 0) {
224  $object->fetch($tmptaskid);
225  $object->progress = GETPOST($tmptaskid.'progress', 'int');
226  $object->timespent_duration = $newduration;
227  $object->timespent_fk_user = $usertoprocess->id;
228  $object->timespent_date = dol_time_plus_duree($firstdaytoshow, $key, 'd');
229  $object->timespent_datehour = $object->timespent_date;
230 
231  $result = $object->addTimeSpent($user);
232  if ($result < 0) {
233  setEventMessages($object->error, $object->errors, 'errors');
234  $error++;
235  break;
236  }
237 
238  $updateoftaskdone++;
239  }
240  }
241  }
242 
243  if (!$updateoftaskdone) { // Check to update progress if no update were done on task.
244  $object->fetch($tmptaskid);
245  //var_dump($object->progress);
246  //var_dump(GETPOST($tmptaskid . 'progress', 'int')); exit;
247  if ($object->progress != GETPOST($tmptaskid.'progress', 'int')) {
248  $object->progress = GETPOST($tmptaskid.'progress', 'int');
249  $result = $object->update($user);
250  if ($result < 0) {
251  setEventMessages($object->error, $object->errors, 'errors');
252  $error++;
253  break;
254  }
255  }
256  }
257  }
258 
259  if (!$error) {
260  setEventMessages($langs->trans("RecordSaved"), null, 'mesgs');
261 
262  $param = '';
263  $param .= ($mode ? '&mode='.$mode : '');
264  $param .= ($projectid ? 'id='.$projectid : '');
265  $param .= ($search_usertoprocessid ? '&search_usertoprocessid='.$search_usertoprocessid : '');
266  $param .= ($day ? '&day='.$day : '').($month ? '&month='.$month : '').($year ? '&year='.$year : '');
267  $param .= ($search_project_ref ? '&search_project_ref='.$search_project_ref : '');
268  $param .= ($search_usertoprocessid > 0 ? '&search_usertoprocessid='.$search_usertoprocessid : '');
269  $param .= ($search_thirdparty ? '&search_thirdparty='.$search_thirdparty : '');
270  $param .= ($search_declared_progress ? '&search_declared_progress='.$search_declared_progress : '');
271  $param .= ($search_task_ref ? '&search_task_ref='.$search_task_ref : '');
272  $param .= ($search_task_label ? '&search_task_label='.$search_task_label : '');
273 
274  // Redirect to avoid submit twice on back
275  header('Location: '.$_SERVER["PHP_SELF"].'?'.$param);
276  exit;
277  }
278  }
279 }
280 
281 
282 
283 /*
284  * View
285  */
286 
287 $form = new Form($db);
288 $formother = new FormOther($db);
289 $formcompany = new FormCompany($db);
290 $formproject = new FormProjets($db);
291 $projectstatic = new Project($db);
292 $project = new Project($db);
293 $taskstatic = new Task($db);
294 $thirdpartystatic = new Societe($db);
295 $holiday = new Holiday($db);
296 
297 $title = $langs->trans("TimeSpent");
298 
299 $projectsListId = $projectstatic->getProjectsAuthorizedForUser($usertoprocess, (empty($usertoprocess->id) ? 2 : 0), 1); // Return all project i have permission on (assigned to me+public). I want my tasks and some of my task may be on a public projet that is not my project
300 //var_dump($projectsListId);
301 if ($id) {
302  $project->fetch($id);
303  $project->fetch_thirdparty();
304 }
305 
306 $onlyopenedproject = 1; // or -1
307 $morewherefilter = '';
308 
309 if ($search_project_ref) {
310  $morewherefilter .= natural_search(array("p.ref", "p.title"), $search_project_ref);
311 }
312 if ($search_task_ref) {
313  $morewherefilter .= natural_search("t.ref", $search_task_ref);
314 }
315 if ($search_task_label) {
316  $morewherefilter .= natural_search(array("t.ref", "t.label"), $search_task_label);
317 }
318 if ($search_thirdparty) {
319  $morewherefilter .= natural_search("s.nom", $search_thirdparty);
320 }
321 if ($search_declared_progress) {
322  $morewherefilter .= natural_search("t.progress", $search_declared_progress, 1);
323 }
324 
325 $tasksarray = $taskstatic->getTasksArray(0, 0, ($project->id ? $project->id : 0), $socid, 0, $search_project_ref, $onlyopenedproject, $morewherefilter, ($search_usertoprocessid ? $search_usertoprocessid : 0)); // We want to see all tasks of open project i am allowed to see and that match filter, not only my tasks. Later only mine will be editable later.
326 if ($morewherefilter) { // Get all task without any filter, so we can show total of time spent for not visible tasks
327  $tasksarraywithoutfilter = $taskstatic->getTasksArray(0, 0, ($project->id ? $project->id : 0), $socid, 0, '', $onlyopenedproject, '', ($search_usertoprocessid ? $search_usertoprocessid : 0)); // We want to see all tasks of open project i am allowed to see and that match filter, not only my tasks. Later only mine will be editable later.
328 }
329 $projectsrole = $taskstatic->getUserRolesForProjectsOrTasks($usertoprocess, null, ($project->id ? $project->id : 0), 0, $onlyopenedproject);
330 $tasksrole = $taskstatic->getUserRolesForProjectsOrTasks(null, $usertoprocess, ($project->id ? $project->id : 0), 0, $onlyopenedproject);
331 //var_dump($tasksarray);
332 //var_dump($projectsrole);
333 //var_dump($taskrole);
334 
335 
336 llxHeader("", $title, "", '', '', '', array('/core/js/timesheet.js'));
337 
338 //print_barre_liste($title, $page, $_SERVER["PHP_SELF"], "", $sortfield, $sortorder, "", $num, '', 'title_project');
339 
340 $param = '';
341 $param .= ($mode ? '&mode='.urlencode($mode) : '');
342 $param .= ($search_project_ref ? '&search_project_ref='.urlencode($search_project_ref) : '');
343 $param .= ($search_usertoprocessid > 0 ? '&search_usertoprocessid='.urlencode($search_usertoprocessid) : '');
344 $param .= ($search_thirdparty ? '&search_thirdparty='.urlencode($search_thirdparty) : '');
345 $param .= ($search_task_ref ? '&search_task_ref='.urlencode($search_task_ref) : '');
346 $param .= ($search_task_label ? '&search_task_label='.urlencode($search_task_label) : '');
347 
348 // Show navigation bar
349 $nav = '<a class="inline-block valignmiddle" href="?year='.$prev_year."&month=".$prev_month."&day=".$prev_day.$param.'">'.img_previous($langs->trans("Previous"))."</a>\n";
350 $nav .= " <span id=\"month_name\">".dol_print_date(dol_mktime(0, 0, 0, $month, 1, $year), "%Y").", ".$langs->trans(date('F', mktime(0, 0, 0, $month, 10)))." </span>\n";
351 $nav .= '<a class="inline-block valignmiddle" href="?year='.$next_year."&month=".$next_month."&day=".$next_day.$param.'">'.img_next($langs->trans("Next"))."</a>\n";
352 $nav .= ' '.$form->selectDate(-1, '', 0, 0, 2, "addtime", 1, 1).' ';
353 $nav .= ' <button type="submit" name="button_search_x" value="x" class="bordertransp nobordertransp button_search_x"><span class="fa fa-search"></span></button>';
354 
355 $picto = 'clock';
356 
357 print '<form name="addtime" method="POST" action="'.$_SERVER["PHP_SELF"].'">';
358 print '<input type="hidden" name="token" value="'.newToken().'">';
359 print '<input type="hidden" name="action" value="addtime">';
360 print '<input type="hidden" name="mode" value="'.$mode.'">';
361 print '<input type="hidden" name="day" value="'.$day.'">';
362 print '<input type="hidden" name="month" value="'.$month.'">';
363 print '<input type="hidden" name="year" value="'.$year.'">';
364 
365 $head = project_timesheet_prepare_head($mode, $usertoprocess);
366 print dol_get_fiche_head($head, 'inputpermonth', $langs->trans('TimeSpent'), -1, $picto);
367 
368 // Show description of content
369 print '<div class="hideonsmartphone opacitymedium">';
370 if ($mine || ($usertoprocess->id == $user->id)) {
371  print $langs->trans("MyTasksDesc").'.'.($onlyopenedproject ? ' '.$langs->trans("OnlyOpenedProject") : '').'<br>';
372 } else {
373  if (empty($usertoprocess->id) || $usertoprocess->id < 0) {
374  if ($user->rights->projet->all->lire && !$socid) {
375  print $langs->trans("ProjectsDesc").'.'.($onlyopenedproject ? ' '.$langs->trans("OnlyOpenedProject") : '').'<br>';
376  } else {
377  print $langs->trans("ProjectsPublicTaskDesc").'.'.($onlyopenedproject ? ' '.$langs->trans("OnlyOpenedProject") : '').'<br>';
378  }
379  }
380 }
381 if ($mine || ($usertoprocess->id == $user->id)) {
382  print $langs->trans("OnlyYourTaskAreVisible").'<br>';
383 } else {
384  print $langs->trans("AllTaskVisibleButEditIfYouAreAssigned").'<br>';
385 }
386 print '</div>';
387 
388 print dol_get_fiche_end();
389 
390 print '<div class="floatright right'.($conf->dol_optimize_smallscreen ? ' centpercent' : '').'">'.$nav.'</div>'; // We move this before the assign to components so, the default submit button is not the assign to.
391 
392 print '<div class="colorbacktimesheet float valignmiddle">';
393 $titleassigntask = $langs->transnoentities("AssignTaskToMe");
394 if ($usertoprocess->id != $user->id) {
395  $titleassigntask = $langs->transnoentities("AssignTaskToUser", $usertoprocess->getFullName($langs));
396 }
397 print '<div class="taskiddiv inline-block">';
398 print img_picto('', 'projecttask', 'class="pictofixedwidth"');
399 $formproject->selectTasks($socid ? $socid : -1, $taskid, 'taskid', 32, 0, '-- '.$langs->trans("ChooseANotYetAssignedTask").' --', 1);
400 print '</div>';
401 print ' ';
402 print $formcompany->selectTypeContact($object, '', 'type', 'internal', 'position', 0, 'maxwidth150onsmartphone');
403 print '<input type="submit" class="button valignmiddle smallonsmartphone small" name="assigntask" value="'.dol_escape_htmltag($titleassigntask).'">';
404 print '</div>';
405 
406 print '<div class="clearboth" style="padding-bottom: 20px;"></div>';
407 
408 
409 $moreforfilter = '';
410 
411 // Filter on categories
412 /*
413 if (isModEnabled("categorie")) {
414  require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
415  $moreforfilter.='<div class="divsearchfield">';
416  $moreforfilter.=$langs->trans('ProjectCategories'). ': ';
417  $moreforfilter.=$formother->select_categories('project', $search_categ, 'search_categ', 1, 1, 'maxwidth300');
418  $moreforfilter.='</div>';
419 }*/
420 
421 // If the user can view user other than himself
422 $moreforfilter .= '<div class="divsearchfield">';
423 $moreforfilter .= '<div class="inline-block hideonsmartphone"></div>';
424 $includeonly = 'hierarchyme';
425 if (empty($user->rights->user->user->lire)) {
426  $includeonly = array($user->id);
427 }
428 $moreforfilter .= img_picto($langs->trans('Filter').' '.$langs->trans('User'), 'user', 'class="paddingright pictofixedwidth"').$form->select_dolusers($search_usertoprocessid ? $search_usertoprocessid : $usertoprocess->id, 'search_usertoprocessid', $user->rights->user->user->lire ? 0 : 0, null, 0, $includeonly, null, 0, 0, 0, '', 0, '', 'maxwidth200');
429 $moreforfilter .= '</div>';
430 
431 if (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) {
432  $moreforfilter .= '<div class="divsearchfield">';
433  $moreforfilter .= '<div class="inline-block"></div>';
434  $moreforfilter .= img_picto($langs->trans('Filter').' '.$langs->trans('Project'), 'project', 'class="paddingright pictofixedwidth"').'<input type="text" name="search_project_ref" class="maxwidth100" value="'.dol_escape_htmltag($search_project_ref).'">';
435  $moreforfilter .= '</div>';
436 
437  $moreforfilter .= '<div class="divsearchfield">';
438  $moreforfilter .= '<div class="inline-block"></div>';
439  $moreforfilter .= img_picto($langs->trans('Filter').' '.$langs->trans('ThirdParty'), 'company', 'class="paddingright pictofixedwidth"').'<input type="text" name="search_thirdparty" class="maxwidth100" value="'.dol_escape_htmltag($search_thirdparty).'">';
440  $moreforfilter .= '</div>';
441 }
442 
443 if (!empty($moreforfilter)) {
444  print '<div class="liste_titre liste_titre_bydiv centpercent">';
445  print $moreforfilter;
446  $parameters = array();
447  $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook
448  print $hookmanager->resPrint;
449  print '</div>';
450 }
451 
452 print '<div class="div-table-responsive">';
453 
454 print '<table class="tagtable liste'.($moreforfilter ? " listwithfilterbefore" : "").'" id="tablelines3">'."\n";
455 
456 print '<tr class="liste_titre_filter">';
457 if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) {
458  print '<td class="liste_titre"><input type="text" size="4" name="search_project_ref" value="'.dol_escape_htmltag($search_project_ref).'"></td>';
459 }
460 if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) {
461  print '<td class="liste_titre"><input type="text" size="4" name="search_thirdparty" value="'.dol_escape_htmltag($search_thirdparty).'"></td>';
462 }
463 print '<td class="liste_titre"><input type="text" size="4" name="search_task_label" value="'.dol_escape_htmltag($search_task_label).'"></td>';
464 print '<td class="liste_titre"></td>';
465 print '<td class="liste_titre right"><input type="text" size="4" name="search_declared_progress" value="'.dol_escape_htmltag($search_declared_progress).'"></td>';
466 print '<td class="liste_titre"></td>';
467 print '<td class="liste_titre"></td>';
468 foreach ($TWeek as $week_number) {
469  print '<td class="liste_titre"></td>';
470 }
471 // Action column
472 print '<td class="liste_titre nowrap" align="right">';
473 $searchpicto = $form->showFilterAndCheckAddButtons(0);
474 print $searchpicto;
475 print '</td>';
476 print "</tr>\n";
477 
478 print '<tr class="liste_titre">';
479 if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) {
480  print '<td>'.$langs->trans("Project").'</td>';
481 }
482 if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) {
483  print '<td>'.$langs->trans("ThirdParty").'</td>';
484 }
485 print '<td>'.$langs->trans("Task").'</td>';
486 print '<td align="right" class="leftborder plannedworkload maxwidth75">'.$langs->trans("PlannedWorkload").'</td>';
487 print '<td align="right" class="maxwidth75">'.$langs->trans("ProgressDeclared").'</td>';
488 /*print '<td align="right" class="maxwidth75">'.$langs->trans("TimeSpent").'</td>';
489  if ($usertoprocess->id == $user->id) print '<td align="right" class="maxwidth75">'.$langs->trans("TimeSpentByYou").'</td>';
490  else print '<td align="right" class="maxwidth75">'.$langs->trans("TimeSpentByUser").'</td>';*/
491 print '<td class="right maxwidth100">'.$langs->trans("TimeSpent").'<br>';
492 print '<span class="nowraponall">';
493 print '<span class="opacitymedium nopadding userimg"><img alt="Photo" class="photouserphoto userphoto" src="'.DOL_URL_ROOT.'/theme/common/everybody.png"></span>';
494 print '<span class="opacitymedium paddingleft">'.$langs->trans("Everybody").'</span>';
495 print '</span>';
496 print '</td>';
497 print '<td align="right" class="maxwidth75">'.$langs->trans("TimeSpent").($usertoprocess->firstname ? '<br><span class="nowraponall">'.$usertoprocess->getNomUrl(-2).'<span class="opacitymedium paddingleft">'.dol_trunc($usertoprocess->firstname, 10).'</span></span>' : '').'</td>';
498 
499 foreach ($TWeek as $week_number) {
500  print '<td width="6%" align="center" class="bold hide">'.$langs->trans("Week").' '.$week_number.'<br>('.$TFirstDays[$week_number].'...'.$TLastDays[$week_number].')</td>';
501 }
502 print '<td></td>';
503 print "</tr>\n";
504 
505 $colspan = 5;
506 
507 // By default, we can edit only tasks we are assigned to
508 $restrictviewformytask = (empty($conf->global->PROJECT_TIME_SHOW_TASK_NOT_ASSIGNED) ? 1 : 0);
509 
510 // Get if user is available or not for each day
511 $isavailable = array();
512 // TODO See code into perweek.php to initialize isavailable array
513 
514 
515 if (count($tasksarray) > 0) {
516  //var_dump($tasksarray); // contains only selected tasks
517  //var_dump($tasksarraywithoutfilter); // contains all tasks (if there is a filter, not defined if no filter)
518  //var_dump($tasksrole);
519 
520  $j = 0;
521  $level = 0;
522  $totalforvisibletasks = projectLinesPerMonth($j, $firstdaytoshow, $usertoprocess, 0, $tasksarray, $level, $projectsrole, $tasksrole, $mine, $restrictviewformytask, $isavailable, 0, $TWeek);
523  //var_dump($totalforvisibletasks);
524 
525  // Show total for all other tasks
526 
527  // Calculate total for all tasks
528  $listofdistinctprojectid = array(); // List of all distinct projects
529  if (!empty($tasksarraywithoutfilter) && is_array($tasksarraywithoutfilter) && count($tasksarraywithoutfilter)) {
530  foreach ($tasksarraywithoutfilter as $tmptask) {
531  $listofdistinctprojectid[$tmptask->fk_project] = $tmptask->fk_project;
532  }
533  }
534  //var_dump($listofdistinctprojectid);
535  $totalforeachweek = array();
536  foreach ($listofdistinctprojectid as $tmpprojectid) {
537  $projectstatic->id = $tmpprojectid;
538  $projectstatic->loadTimeSpentMonth($firstdaytoshow, 0, $usertoprocess->id); // Load time spent from table element_time for the project into this->weekWorkLoad and this->weekWorkLoadPerTask for all days of a week
539  foreach ($TWeek as $weekNb) {
540  $totalforeachweek[$weekNb] += $projectstatic->monthWorkLoad[$weekNb];
541  }
542  }
543 
544  //var_dump($totalforeachday);
545  //var_dump($totalforvisibletasks);
546 
547  // Is there a diff between selected/filtered tasks and all tasks ?
548  $isdiff = 0;
549  if (count($totalforeachweek)) {
550  foreach ($TWeek as $weekNb) {
551  $timeonothertasks = ($totalforeachweek[$weekNb] - $totalforvisibletasks[$weekNb]);
552  if ($timeonothertasks) {
553  $isdiff = 1;
554  break;
555  }
556  }
557  }
558 
559  // There is a diff between total shown on screen and total spent by user, so we add a line with all other cumulated time of user
560  if ($isdiff) {
561  print '<tr class="oddeven othertaskwithtime">';
562  print '<td colspan="'.$colspan.'" class="opacitymedium">';
563  print $langs->trans("OtherFilteredTasks");
564  print '</td>';
565  foreach ($TWeek as $weekNb) {
566  print '<td class="center hide">';
567 
568  $timeonothertasks = ($totalforeachweek[$weekNb] - $totalforvisibletasks[$weekNb]);
569  if ($timeonothertasks) {
570  print '<span class="timesheetalreadyrecorded" title="texttoreplace"><input type="text" class="center smallpadd" size="2" disabled="" id="timespent[-1]['.$weekNb.']" name="task[-1]['.$weekNb.']" value="';
571  print convertSecondToTime($timeonothertasks, 'allhourmin');
572  print '"></span>';
573  }
574  print '</td>';
575  }
576  print ' <td class="liste_total"></td>';
577  print '</tr>';
578  }
579 
580  if ($conf->use_javascript_ajax) {
581  print '<tr class="liste_total">
582  <td class="liste_total" colspan="'.$colspan.'">';
583  print $langs->trans("Total");
584  print '<span class="opacitymediumbycolor"> - '.$langs->trans("ExpectedWorkedHours").': <strong>'.price($usertoprocess->weeklyhours, 1, $langs, 0, 0).'</strong></span>';
585  print '</td>';
586 
587  foreach ($TWeek as $weekNb) {
588  print '<td class="liste_total hide'.$weekNb.'" align="center"><div class="totalDay'.$weekNb.'">'.convertSecondToTime($totalforvisibletasks[$weekNb], 'allhourmin').'</div></td>';
589  }
590  print '<td class="liste_total center"><div class="totalDayAll">&nbsp;</div></td>
591  </tr>';
592  }
593 } else {
594  print '<tr><td colspan="15"><span class="opacitymedium">'.$langs->trans("NoAssignedTasks").'</span></td></tr>';
595 }
596 print "</table>";
597 print '</div>';
598 
599 print '<input type="hidden" id="numberOfLines" name="numberOfLines" value="'.count($tasksarray).'"/>'."\n";
600 print '<input type="hidden" id="numberOfFirstLine" name="numberOfFirstLine" value="'.(reset($TWeek)).'"/>'."\n";
601 
602 print $form->buttonsSaveCancel("Save", '');
603 
604 print '</form>'."\n\n";
605 
606 $modeinput = 'hours';
607 
608 if ($conf->use_javascript_ajax) {
609  print "\n<!-- JS CODE TO ENABLE Tooltips on all object with class classfortooltip -->\n";
610  print '<script type="text/javascript">'."\n";
611  print "jQuery(document).ready(function () {\n";
612  print ' jQuery(".timesheetalreadyrecorded").tooltip({
613  show: { collision: "flipfit", effect:\'toggle\', delay:50 },
614  hide: { effect:\'toggle\', delay: 50 },
615  tooltipClass: "mytooltip",
616  content: function () {
617  return \''.dol_escape_js($langs->trans("TimeAlreadyRecorded", $usertoprocess->getFullName($langs))).'\';
618  }
619  });'."\n";
620 
621  foreach ($TWeek as $week_number) {
622  print ' updateTotal('.$week_number.',\''.$modeinput.'\');';
623  }
624  print "\n});\n";
625  print '</script>';
626 }
627 
628 
629 llxFooter();
630 
631 $db->close();
if(!defined('NOREQUIRESOC')) if(!defined('NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) llxHeader()
Empty header.
Definition: wrapper.php:56
Class to build HTML component for third parties management Only common components are here.
Class to manage generation of HTML components Only common components must be here.
Classe permettant la generation de composants html autre Only common components are here.
Class to manage building of HTML components.
Class of the module paid holiday.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage tasks.
Definition: task.class.php:40
Class to manage Dolibarr users.
Definition: user.class.php:48
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
dol_get_prev_month($month, $year)
Return previous month.
Definition: date.lib.php:495
getLastDayOfEachWeek($TWeek, $year)
Return array of last day of weeks.
Definition: date.lib.php:1151
getWeekNumbersOfMonth($month, $year)
Return array of week numbers.
Definition: date.lib.php:1116
getFirstDayOfEachWeek($TWeek, $year)
Return array of first day of weeks.
Definition: date.lib.php:1133
dol_get_next_month($month, $year)
Return next month.
Definition: date.lib.php:514
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition: date.lib.php:122
convertSecondToTime($iSecond, $format='all', $lengthOfDay=86400, $lengthOfWeek=7)
Return, in clear text, value of a number of seconds in days, hours and minutes.
Definition: date.lib.php:239
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_get_fiche_end($notab=0)
Return tab footer of a card.
natural_search($fields, $value, $mode=0, $nofirstand=0)
Generate natural SQL search string for a criteria (this criteria can be tested on one or several fiel...
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_now($mode='auto')
Return date for now.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
img_previous($titlealt='default', $moreatt='')
Show previous logo.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
img_next($titlealt='default', $moreatt='')
Show next logo.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
projectLinesPerMonth(&$inc, $firstdaytoshow, $fuser, $parent, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, &$isavailable, $oldprojectforbreak=0, $TWeek=array())
Output a task line into a perday intput mode.
project_timesheet_prepare_head($mode, $fuser=null)
Prepare array with list of tabs.
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.