dolibarr 18.0.6
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
27require "../../main.inc.php";
28require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
29require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
30require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
31require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
32require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
33require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
34require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
35require_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;
47if ($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
92if (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
113if ($reshook < 0) {
114 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
115}
116
117// Purge criteria
118if (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}
128if (GETPOST("button_search_x", 'alpha') || GETPOST("button_search.x", 'alpha') || GETPOST("button_search", 'alpha')) {
129 $action = '';
130}
131
132if (GETPOST('submitdateselect')) {
133 $daytoparse = dol_mktime(0, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear'));
134
135 $action = '';
136}
137if ($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
201if ($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);
301if ($id) {
302 $project->fetch($id);
303 $project->fetch_thirdparty();
304}
305
306$onlyopenedproject = 1; // or -1
307$morewherefilter = '';
308
309if ($search_project_ref) {
310 $morewherefilter .= natural_search(array("p.ref", "p.title"), $search_project_ref);
311}
312if ($search_task_ref) {
313 $morewherefilter .= natural_search("t.ref", $search_task_ref);
314}
315if ($search_task_label) {
316 $morewherefilter .= natural_search(array("t.ref", "t.label"), $search_task_label);
317}
318if ($search_thirdparty) {
319 $morewherefilter .= natural_search("s.nom", $search_thirdparty);
320}
321if ($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.
326if ($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
336llxHeader("", $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
357print '<form name="addtime" method="POST" action="'.$_SERVER["PHP_SELF"].'">';
358print '<input type="hidden" name="token" value="'.newToken().'">';
359print '<input type="hidden" name="action" value="addtime">';
360print '<input type="hidden" name="mode" value="'.$mode.'">';
361print '<input type="hidden" name="day" value="'.$day.'">';
362print '<input type="hidden" name="month" value="'.$month.'">';
363print '<input type="hidden" name="year" value="'.$year.'">';
364
365$head = project_timesheet_prepare_head($mode, $usertoprocess);
366print dol_get_fiche_head($head, 'inputpermonth', $langs->trans('TimeSpent'), -1, $picto);
367
368// Show description of content
369print '<div class="hideonsmartphone opacitymedium">';
370if ($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}
381if ($mine || ($usertoprocess->id == $user->id)) {
382 print $langs->trans("OnlyYourTaskAreVisible").'<br>';
383} else {
384 print $langs->trans("AllTaskVisibleButEditIfYouAreAssigned").'<br>';
385}
386print '</div>';
387
388print dol_get_fiche_end();
389
390print '<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
392print '<div class="colorbacktimesheet float valignmiddle">';
393$titleassigntask = $langs->transnoentities("AssignTaskToMe");
394if ($usertoprocess->id != $user->id) {
395 $titleassigntask = $langs->transnoentities("AssignTaskToUser", $usertoprocess->getFullName($langs));
396}
397print '<div class="taskiddiv inline-block">';
398print img_picto('', 'projecttask', 'class="pictofixedwidth"');
399$formproject->selectTasks($socid ? $socid : -1, $taskid, 'taskid', 32, 0, '-- '.$langs->trans("ChooseANotYetAssignedTask").' --', 1);
400print '</div>';
401print ' ';
402print $formcompany->selectTypeContact($object, '', 'type', 'internal', 'position', 0, 'maxwidth150onsmartphone');
403print '<input type="submit" class="button valignmiddle smallonsmartphone small" name="assigntask" value="'.dol_escape_htmltag($titleassigntask).'">';
404print '</div>';
405
406print '<div class="clearboth" style="padding-bottom: 20px;"></div>';
407
408
409$moreforfilter = '';
410
411// Filter on categories
412/*
413if (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';
425if (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
431if (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
443if (!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
452print '<div class="div-table-responsive">';
453
454print '<table class="tagtable liste'.($moreforfilter ? " listwithfilterbefore" : "").'" id="tablelines3">'."\n";
455
456print '<tr class="liste_titre_filter">';
457if (!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}
460if (!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}
463print '<td class="liste_titre"><input type="text" size="4" name="search_task_label" value="'.dol_escape_htmltag($search_task_label).'"></td>';
464print '<td class="liste_titre"></td>';
465print '<td class="liste_titre right"><input type="text" size="4" name="search_declared_progress" value="'.dol_escape_htmltag($search_declared_progress).'"></td>';
466print '<td class="liste_titre"></td>';
467print '<td class="liste_titre"></td>';
468foreach ($TWeek as $week_number) {
469 print '<td class="liste_titre"></td>';
470}
471// Action column
472print '<td class="liste_titre nowrap" align="right">';
473$searchpicto = $form->showFilterAndCheckAddButtons(0);
474print $searchpicto;
475print '</td>';
476print "</tr>\n";
477
478print '<tr class="liste_titre">';
479if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) {
480 print '<td>'.$langs->trans("Project").'</td>';
481}
482if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) {
483 print '<td>'.$langs->trans("ThirdParty").'</td>';
484}
485print '<td>'.$langs->trans("Task").'</td>';
486print '<td align="right" class="leftborder plannedworkload maxwidth75">'.$langs->trans("PlannedWorkload").'</td>';
487print '<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>';*/
491print '<td class="right maxwidth100">'.$langs->trans("TimeSpent").'<br>';
492print '<span class="nowraponall">';
493print '<span class="opacitymedium nopadding userimg"><img alt="Photo" class="photouserphoto userphoto" src="'.DOL_URL_ROOT.'/theme/common/everybody.png"></span>';
494print '<span class="opacitymedium paddingleft">'.$langs->trans("Everybody").'</span>';
495print '</span>';
496print '</td>';
497print '<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
499foreach ($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}
502print '<td></td>';
503print "</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
515if (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}
596print "</table>";
597print '</div>';
598
599print '<input type="hidden" id="numberOfLines" name="numberOfLines" value="'.count($tasksarray).'"/>'."\n";
600print '<input type="hidden" id="numberOfFirstLine" name="numberOfFirstLine" value="'.(reset($TWeek)).'"/>'."\n";
601
602print $form->buttonsSaveCancel("Save", '');
603
604print '</form>'."\n\n";
605
606$modeinput = 'hours';
607
608if ($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
629llxFooter();
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.
Class to manage Dolibarr users.
dol_get_prev_month($month, $year)
Return previous month.
Definition date.lib.php:496
getLastDayOfEachWeek($TWeek, $year)
Return array of last day of weeks.
getWeekNumbersOfMonth($month, $year)
Return array of week numbers.
getFirstDayOfEachWeek($TWeek, $year)
Return array of first day of weeks.
dol_get_next_month($month, $year)
Return next month.
Definition date.lib.php:515
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:240
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.
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.
$conf db user
Definition repair.php:124
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.