dolibarr 23.0.3
perday.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2016 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005-2010 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2010 François Legastelois <flegastelois@teclib.com>
6 * Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
7 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
29require "../../main.inc.php";
38require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
39require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
40require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
41require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
42require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
43require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
44require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
45require_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php';
46
47// Load translation files required by the page
48$langs->loadLangs(array('projects', 'users', 'companies'));
49
50$action = GETPOST('action', 'aZ09');
51$mode = GETPOST("mode", 'alpha');
52$id = GETPOSTINT('id');
53$taskid = GETPOSTINT('taskid');
54
55$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'timespent';
56
57$mine = 0;
58if ($mode == 'mine') {
59 $mine = 1;
60}
61
62$projectid = GETPOSTISSET("id") ? GETPOSTINT("id", 1) : GETPOSTINT("projectid");
63
64$hookmanager->initHooks(array('timesheetperdaycard'));
65
66// Security check
67$socid = 0;
68// For external user, no check is done on company because readability is managed by public status of project and assignment.
69//if ($user->socid > 0) $socid=$user->socid;
70$result = restrictedArea($user, 'projet', $projectid);
71
72$now = dol_now();
73
74$year = GETPOSTINT('reyear') ? GETPOSTINT('reyear') : (GETPOSTINT("year") ? GETPOSTINT("year") : (GETPOSTINT("addtimeyear") ? GETPOSTINT("addtimeyear") : date("Y")));
75$month = GETPOSTINT('remonth') ? GETPOSTINT('remonth') : (GETPOSTINT("month") ? GETPOSTINT("month") : (GETPOSTINT("addtimemonth") ? GETPOSTINT("addtimemonth") : date("m")));
76$day = GETPOSTINT('reday') ? GETPOSTINT('reday') : (GETPOSTINT("day") ? GETPOSTINT("day") : (GETPOSTINT("addtimeday") ? GETPOSTINT("addtimeday") : date("d")));
77$week = GETPOSTINT("week") ? GETPOSTINT("week") : date("W");
78
79$day = (int) $day;
80
81//$search_categ = GETPOST("search_categ", 'alpha');
82$search_usertoprocessid = GETPOSTINT('search_usertoprocessid');
83$search_task_ref = GETPOST('search_task_ref', 'alpha');
84$search_task_label = GETPOST('search_task_label', 'alpha');
85$search_project_ref = GETPOST('search_project_ref', 'alpha');
86$search_thirdparty = GETPOST('search_thirdparty', 'alpha');
87$search_declared_progress = GETPOST('search_declared_progress', 'alpha');
88
89$sortfield = GETPOST('sortfield', 'aZ09comma');
90$sortorder = GETPOST('sortorder', 'aZ09comma');
91
92$monthofday = GETPOSTINT('addtimemonth');
93$dayofday = GETPOSTINT('addtimeday');
94$yearofday = GETPOSTINT('addtimeyear');
95
96//var_dump(GETPOST('remonth'));
97//var_dump(GETPOST('button_search_x'));
98//var_dump(GETPOST('button_addtime'));
99
100$daytoparse = $now;
101if ($year && $month && $day) {
102 $daytoparse = dol_mktime(0, 0, 0, $month, $day, $year); // this are value submitted after submit of action 'submitdateselect'
103} elseif ($yearofday && $monthofday && $dayofday) {
104 $daytoparse = dol_mktime(0, 0, 0, $monthofday, $dayofday, $yearofday); // xxxofday is value of day after submit action 'addtime'
105}
106
107$daytoparsegmt = dol_now('gmt');
108if ($yearofday && $monthofday && $dayofday) {
109 $daytoparsegmt = dol_mktime(0, 0, 0, $monthofday, $dayofday, $yearofday, 'gmt');
110} elseif ($year && $month && $day) { // xxxofday is value of day after submit action 'addtime'
111 $daytoparsegmt = dol_mktime(0, 0, 0, $month, $day, $year, 'gmt');
112} // this are value submitted after submit of action 'submitdateselect'
113
114if (empty($search_usertoprocessid) || $search_usertoprocessid == $user->id) {
115 $usertoprocess = $user;
116 $search_usertoprocessid = $usertoprocess->id;
117} elseif ($search_usertoprocessid > 0) {
118 $usertoprocess = new User($db);
119 $usertoprocess->fetch($search_usertoprocessid);
120 $search_usertoprocessid = $usertoprocess->id;
121} else {
122 $usertoprocess = new User($db);
123}
124
125$object = new Task($db);
126$project = new Project($db);
127
128// Extra fields
129$extrafields = new ExtraFields($db);
130
131// fetch optionals attributes and labels
132$extrafields->fetch_name_optionals_label($object->table_element);
133
134// Definition of fields for list
135$arrayfields = array();
136$arrayfields['t.planned_workload'] = array('label' => 'PlannedWorkload', 'checked' => '1', 'enabled' => '1', 'position' => 0);
137$arrayfields['t.progress'] = array('label' => 'ProgressDeclared', 'checked' => '1', 'enabled' => '1', 'position' => 0);
138$arrayfields['timeconsumed'] = array('label' => 'TimeConsumed', 'checked' => '1', 'enabled' => '1', 'position' => 15);
139/*$arrayfields=array(
140 // Project
141 'p.opp_amount'=>array('label'=>$langs->trans("OpportunityAmountShort"), 'checked'=>0, 'enabled'=>($conf->global->PROJECT_USE_OPPORTUNITIES?1:0), 'position'=>103),
142 'p.fk_opp_status'=>array('label'=>$langs->trans("OpportunityStatusShort"), 'checked'=>0, 'enabled'=>($conf->global->PROJECT_USE_OPPORTUNITIES?1:0), 'position'=>104),
143 'p.opp_percent'=>array('label'=>$langs->trans("OpportunityProbabilityShort"), 'checked'=>0, 'enabled'=>($conf->global->PROJECT_USE_OPPORTUNITIES?1:0), 'position'=>105),
144 'p.budget_amount'=>array('label'=>$langs->trans("Budget"), 'checked'=>0, 'position'=>110),
145 'p.usage_bill_time'=>array('label'=>$langs->trans("BillTimeShort"), 'checked'=>0, 'position'=>115),
146 );
147 */
148// Extra fields
149$extrafieldsobjectkey = $object->table_element;
150$extrafieldsobjectprefix = 'efpt.';
151include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php';
152
153$arrayfields = dol_sort_array($arrayfields, 'position');
154
155
156$search_array_options_project = $extrafields->getOptionalsFromPost($project->table_element, '', 'search_');
157$search_array_options_task = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_task_');
158
159
160/*
161 * Actions
162 */
163
164$error = 0;
165$parameters = array('id' => $id, 'taskid' => $taskid, 'projectid' => $projectid);
166$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
167if ($reshook < 0) {
168 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
169}
170// Purge criteria
171if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
172 $action = '';
173 //$search_categ = '';
174 $search_usertoprocessid = $user->id;
175 $search_task_ref = '';
176 $search_task_label = '';
177 $search_project_ref = '';
178 $search_thirdparty = '';
179 $search_declared_progress = '';
180
181 $search_array_options_project = array();
182 $search_array_options_task = array();
183
184 // We redefine $usertoprocess
185 $usertoprocess = $user;
186}
187if (GETPOST("button_search_x", 'alpha') || GETPOST("button_search.x", 'alpha') || GETPOST("button_search", 'alpha')) {
188 $action = '';
189}
190
191if (GETPOST('submitdateselect')) {
192 if (GETPOSTINT('remonth') && GETPOSTINT('reday') && GETPOSTINT('reyear')) {
193 $daytoparse = dol_mktime(0, 0, 0, GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'));
194 }
195
196 $action = '';
197}
198
199include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
200
201if ($action == 'addtime' && $user->hasRight('projet', 'lire') && GETPOST('assigntask') && GETPOST('formfilteraction') != 'listafterchangingselectedfields') {
202 $action = 'assigntask';
203
204 if ($taskid > 0) {
205 $result = $object->fetch($taskid);
206 if ($result < 0) {
207 $error++;
208 }
209 } else {
210 setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Task")), null, 'errors');
211 $error++;
212 }
213 if (!GETPOST('type')) {
214 setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
215 $error++;
216 }
217 if (!$error) {
218 $idfortaskuser = $usertoprocess->id;
219 $result = $object->add_contact($idfortaskuser, GETPOST("type"), 'internal');
220
221 if ($result >= 0 || $result == -2) { // Contact add ok or already contact of task
222 // 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)
223 $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';
224 $sql .= ' AND ec.fk_socpeople = '.((int) $idfortaskuser)." AND ec.element_id = ".((int) $object->fk_project)." AND tc.element = 'project' AND source = 'internal'";
225 $resql = $db->query($sql);
226 if ($resql) {
227 $obj = $db->fetch_object($resql);
228 if (!$obj) { // User is not already linked to project, so we will create link to first type
229 $project = new Project($db);
230 $project->fetch($object->fk_project);
231 // Get type
232 $listofprojcontact = $project->liste_type_contact('internal');
233
234 if (count($listofprojcontact)) {
235 $tmparray = array_keys($listofprojcontact);
236 $typeforprojectcontact = reset($tmparray);
237 $result = $project->add_contact($idfortaskuser, $typeforprojectcontact, 'internal');
238 }
239 }
240 } else {
241 dol_print_error($db);
242 }
243 }
244 }
245
246 if ($result < 0) {
247 $error++;
248 if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
249 $langs->load("errors");
250 setEventMessages($langs->trans("ErrorTaskAlreadyAssigned"), null, 'warnings');
251 } else {
252 setEventMessages($object->error, $object->errors, 'errors');
253 }
254 }
255
256 if (!$error) {
257 setEventMessages("TaskAssignedToEnterTime", null);
258 $taskid = 0;
259 }
260
261 $action = '';
262}
263
264if ($action == 'addtime' && $user->hasRight('projet', 'lire') && GETPOST('formfilteraction') != 'listafterchangingselectedfields') {
265 $timespent_duration = array();
266
267 if (is_array($_POST)) {
268 foreach ($_POST as $key => $time) {
269 if (intval($time) > 0) {
270 $matches = array();
271 // Hours or minutes of duration
272 if (preg_match("/([0-9]+)duration(hour|min)/", $key, $matches)) {
273 $id = $matches[1];
274 if ($id > 0) {
275 // We store HOURS in seconds
276 if ($matches[2] == 'hour') {
277 $timespent_duration[$id] += (int) $time * 60 * 60;
278 }
279
280 // We store MINUTES in seconds
281 if ($matches[2] == 'min') {
282 $timespent_duration[$id] += (int) $time * 60;
283 }
284 }
285 }
286 }
287 }
288 }
289
290 if (count($timespent_duration) > 0) {
291 foreach ($timespent_duration as $key => $val) {
292 $object->fetch($key);
293 $taskid = $object->id;
294
295 if (GETPOSTISSET($taskid.'progress')) {
296 $object->progress = GETPOSTINT($taskid.'progress');
297 } else {
298 unset($object->progress);
299 }
300
301 $object->timespent_duration = $val;
302 $object->timespent_fk_user = $usertoprocess->id;
303 $object->timespent_note = GETPOST($key.'note');
304 if (GETPOSTINT($key."hour") != '' && GETPOSTINT($key."hour") >= 0) { // If hour was entered
305 $object->timespent_datehour = dol_mktime(GETPOSTINT($key."hour"), GETPOSTINT($key."min"), 0, $monthofday, $dayofday, $yearofday);
306 $object->timespent_withhour = 1;
307 } else {
308 $object->timespent_datehour = dol_mktime(12, 0, 0, $monthofday, $dayofday, $yearofday);
309 }
310 $object->timespent_date = $object->timespent_datehour;
311
312 if ($object->timespent_date > 0) {
313 $result = $object->addTimeSpent($user);
314 } else {
315 setEventMessages("ErrorBadDate", null, 'errors');
316 $error++;
317 break;
318 }
319
320 if ($result < 0) {
321 setEventMessages($object->error, $object->errors, 'errors');
322 $error++;
323 break;
324 }
325 }
326
327 if (!$error) {
328 setEventMessages($langs->trans("RecordSaved"), null, 'mesgs');
329
330 // Redirect to avoid submit twice on back
331 header('Location: '.$_SERVER["PHP_SELF"].'?'.($projectid ? 'id='.$projectid : '').($search_usertoprocessid ? '&search_usertoprocessid='.urlencode((string) $search_usertoprocessid) : '').($mode ? '&mode='.$mode : '').'&year='.$yearofday.'&month='.$monthofday.'&day='.$dayofday);
332 exit;
333 }
334 } else {
335 setEventMessages($langs->trans("ErrorTimeSpentIsEmpty"), null, 'errors');
336 }
337}
338
339
340
341/*
342 * View
343 */
344
345$form = new Form($db);
346$formother = new FormOther($db);
347$formcompany = new FormCompany($db);
348$formproject = new FormProjets($db);
349$projectstatic = new Project($db);
350$project = new Project($db);
351$taskstatic = new Task($db);
352$thirdpartystatic = new Societe($db);
353$holiday = new Holiday($db);
354
355$prev = dol_getdate($daytoparse - (24 * 3600));
356$prev_year = $prev['year'];
357$prev_month = $prev['mon'];
358$prev_day = $prev['mday'];
359
360$next = dol_getdate($daytoparse + (24 * 3600));
361$next_year = $next['year'];
362$next_month = $next['mon'];
363$next_day = $next['mday'];
364
365$title = $langs->trans("TimeSpent");
366
367$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
368
369if ($id) {
370 $project->fetch($id);
371 $project->fetch_thirdparty();
372}
373
374$onlyopenedproject = 1; // or -1
375$morewherefilter = '';
376
377if ($search_project_ref) {
378 $morewherefilter .= natural_search(array("p.ref", "p.title"), $search_project_ref);
379}
380if ($search_task_ref) {
381 $morewherefilter .= natural_search("t.ref", $search_task_ref);
382}
383if ($search_task_label) {
384 $morewherefilter .= natural_search(array("t.ref", "t.label"), $search_task_label);
385}
386if ($search_thirdparty) {
387 $morewherefilter .= natural_search("s.nom", $search_thirdparty);
388}
389if ($search_declared_progress) {
390 $morewherefilter .= natural_search("t.progress", $search_declared_progress, 1);
391}
392
393$sql = &$morewherefilter;
394
395/*$search_array_options = $search_array_options_project;
396$extrafieldsobjectprefix='efp.';
397$search_options_pattern='search_options_';
398$extrafieldsobjectkey='projet';
399include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
400*/
401$search_array_options = $search_array_options_task;
402$extrafieldsobjectprefix = 'efpt.';
403$search_options_pattern = 'search_task_options_';
404$extrafieldsobjectkey = 'projet_task';
405include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
406
407$tasksarray = $taskstatic->getTasksArray(null, null, ($project->id ? $project->id : 0), $socid, 0, $search_project_ref, (string) $onlyopenedproject, $morewherefilter, ($search_usertoprocessid ? $search_usertoprocessid : 0), 0, $extrafields); // We want to see all task of opened project i am allowed to see and that match filter, not only my tasks. Later only mine will be editable later.
408
409$tasksarraywithoutfilter = array();
410if ($morewherefilter) { // Get all task without any filter, so we can show total of time spent for not visible tasks
411 $tasksarraywithoutfilter = $taskstatic->getTasksArray(null, null, ($project->id ? $project->id : 0), $socid, 0, '', (string) $onlyopenedproject, '', ($search_usertoprocessid ? $search_usertoprocessid : 0)); // We want to see all task of opened project i am allowed to see and that match filter, not only my tasks. Later only mine will be editable later.
412}
413$projectsrole = $taskstatic->getUserRolesForProjectsOrTasks($usertoprocess, null, ($project->id ? (string) $project->id : '0'), 0, $onlyopenedproject);
414$tasksrole = $taskstatic->getUserRolesForProjectsOrTasks(null, $usertoprocess, ($project->id ? (string) $project->id : '0'), 0, $onlyopenedproject);
415
416llxHeader('', $title, '', '', 0, 0, array('/core/js/timesheet.js'), '', '', 'mod-project project-activity page-activity_perday');
417
418//print_barre_liste($title, $page, $_SERVER["PHP_SELF"], "", $sortfield, $sortorder, "", $num, '', 'project');
419
420$param = '';
421$param .= ($mode ? '&mode='.urlencode($mode) : '');
422$param .= ($search_project_ref ? '&search_project_ref='.urlencode($search_project_ref) : '');
423$param .= ($search_usertoprocessid > 0 ? '&search_usertoprocessid='.urlencode((string) $search_usertoprocessid) : '');
424$param .= ($search_thirdparty ? '&search_thirdparty='.urlencode($search_thirdparty) : '');
425$param .= ($search_task_ref ? '&search_task_ref='.urlencode($search_task_ref) : '');
426$param .= ($search_task_label ? '&search_task_label='.urlencode($search_task_label) : '');
427
428/*
429$search_array_options = $search_array_options_project;
430$search_options_pattern='search_options_';
431include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
432*/
433
434$search_array_options = $search_array_options_task;
435$search_options_pattern = 'search_task_options_';
436include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
437
438// Show navigation bar
439$nav = '<a class="inline-block valignmiddle" href="?year='.$prev_year."&month=".$prev_month."&day=".$prev_day.$param.'">'.img_previous($langs->trans("Previous"))."</a>\n";
440$nav .= dol_print_date(dol_mktime(0, 0, 0, $month, $day, $year), "%a").' ';
441$nav .= ' <span id="month_name">'.dol_print_date(dol_mktime(0, 0, 0, $month, $day, $year), "day")." </span>\n";
442$nav .= '<a class="inline-block valignmiddle" href="?year='.$next_year."&month=".$next_month."&day=".$next_day.$param.'">'.img_next($langs->trans("Next"))."</a>\n";
443$nav .= ' '.$form->selectDate(-1, '', 0, 0, 2, "addtime", 1, ($conf->dol_optimize_smallscreen ? 0 : 1)).' ';
444$nav .= ' <button type="submit" name="button_search_x" value="x" class="bordertransp nobordertransp button_search"><span class="fa fa-search"></span></button>';
445
446$picto = 'clock';
447
448print '<form name="addtime" method="POST" action="'.$_SERVER["PHP_SELF"].($project->id > 0 ? '?id='.$project->id : '').'">';
449print '<input type="hidden" name="token" value="'.newToken().'">';
450print '<input type="hidden" name="action" value="addtime">';
451print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
452print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
453print '<input type="hidden" name="mode" value="'.$mode.'">';
454$tmp = dol_getdate($daytoparse);
455print '<input type="hidden" name="addtimeyear" value="'.$tmp['year'].'">';
456print '<input type="hidden" name="addtimemonth" value="'.$tmp['mon'].'">';
457print '<input type="hidden" name="addtimeday" value="'.$tmp['mday'].'">';
458
459$head = project_timesheet_prepare_head($mode, $usertoprocess);
460print dol_get_fiche_head($head, 'inputperday', $langs->trans('TimeSpent'), -1, $picto);
461
462// Show description of content
463$s = '';
464if ($mine || ($usertoprocess->id == $user->id)) {
465 $s .= $langs->trans("MyTasksDesc").'.'.($onlyopenedproject ? ' '.$langs->trans("OnlyOpenedProject") : '').'<br>';
466} else {
467 if (empty($usertoprocess->id) || $usertoprocess->id < 0) {
468 if ($user->hasRight('projet', 'all', 'lire') && !$socid) {
469 $s .= $langs->trans("ProjectsDesc").'.'.($onlyopenedproject ? ' '.$langs->trans("OnlyOpenedProject") : '').'<br>';
470 } else {
471 $s .= $langs->trans("ProjectsPublicTaskDesc").'.'.($onlyopenedproject ? ' '.$langs->trans("OnlyOpenedProject") : '').'<br>';
472 }
473 }
474}
475if ($mine || ($usertoprocess->id == $user->id)) {
476 $s .= $langs->trans("OnlyYourTaskAreVisible").'<br>';
477} else {
478 $s .= $langs->trans("AllTaskVisibleButEditIfYouAreAssigned").'<br>';
479}
480print info_admin($s, 0, 0, 'info', 'nomargintop hideonsmartphone');
481
482print dol_get_fiche_end();
483
484
485print '<div class="'.($conf->dol_optimize_smallscreen ? 'center centpercent' : 'floatright right').'">'.$nav.'</div>'; // We move this before the assign to components so, the default submit button is not the assign to.
486
487print '<div class="colorbacktimesheet valignmiddle'.($conf->dol_optimize_smallscreen ? ' center' : ' float').'">';
488$titleassigntask = $langs->transnoentities("AssignTaskToMe");
489if ($usertoprocess->id != $user->id) {
490 $titleassigntask = $langs->transnoentities("AssignTaskToUser", $usertoprocess->getFullName($langs));
491}
492print '<div class="taskiddiv inline-block">';
493print img_picto('', 'projecttask', 'class="pictofixedwidth"');
494$formproject->selectTasks($socid ? $socid : -1, $taskid, 'taskid', 32, 0, '-- '.$langs->trans("ChooseANotYetAssignedTask").' --', 1, 0, 0, 'widthcentpercentminusx maxwidth500', '', 'all', $usertoprocess);
495print '</div>';
496print ' ';
497print $formcompany->selectTypeContact($object, '', 'type', 'internal', 'position', 0, 'maxwidth150onsmartphone');
498print '<input type="submit" class="button valignmiddle smallonsmartphone small" name="assigntask" value="'.dol_escape_htmltag($titleassigntask).'">';
499print '</div>';
500
501print '<div class="clearboth" style="padding-bottom: 20px;"></div>';
502
503
504$moreforfilter = '';
505
506// Filter on categories
507/*if (isModEnabled("categorie")) {
508 require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
509 $moreforfilter.='<div class="divsearchfield">';
510 $moreforfilter.=$langs->trans('ProjectCategories'). ': ';
511 $moreforfilter.=$formother->select_categories('project', $search_categ, 'search_categ', 1, 1, 'maxwidth300');
512 $moreforfilter.='</div>';
513}*/
514
515// If the user can view user other than himself
516$includeonly = 'hierarchyme';
517if (!$user->hasRight('user', 'user', 'lire')) {
518 $includeonly = array($user->id);
519}
520$selecteduser = $search_usertoprocessid ? $search_usertoprocessid : $usertoprocess->id;
521$moreforfiltertmp = $form->select_dolusers($selecteduser, 'search_usertoprocessid', 0, null, 0, $includeonly, '', '0', 0, 0, '', 0, '', 'maxwidth200');
522if ($form->num > 1 || empty($conf->dol_optimize_smallscreen)) {
523 $moreforfilter .= '<div class="divsearchfield">';
524 $moreforfilter .= '<div class="inline-block hideonsmartphone"></div>';
525 $moreforfilter .= img_picto($langs->trans('Filter').' '.$langs->trans('User'), 'user', 'class="paddingright pictofixedwidth"');
526 $moreforfilter .= $moreforfiltertmp;
527 $moreforfilter .= '</div>';
528} else {
529 $moreforfilter .= '<input type="hidden" name="search_usertoprocessid" value="'.$selecteduser.'">';
530}
531
532if (!getDolGlobalString('PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT')) {
533 $moreforfilter .= '<div class="divsearchfield">';
534 $moreforfilter .= '<div class="inline-block"></div>';
535 $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).'">';
536 $moreforfilter .= '</div>';
537
538 $moreforfilter .= '<div class="divsearchfield">';
539 $moreforfilter .= '<div class="inline-block"></div>';
540 $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).'">';
541 $moreforfilter .= '</div>';
542}
543
544if (!empty($moreforfilter)) {
545 print '<div class="liste_titre liste_titre_bydiv centpercent">';
546 print $moreforfilter;
547 $parameters = array();
548 $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
549 print $hookmanager->resPrint;
550 print '</div>';
551}
552
553$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
554$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields
555
556// This must be after the $selectedfields
557$addcolspan = 0;
558if (!empty($arrayfields['t.planned_workload']['checked'])) {
559 $addcolspan++;
560}
561if (!empty($arrayfields['t.progress']['checked'])) {
562 $addcolspan++;
563}
564foreach ($arrayfields as $key => $val) {
565 if ($val['checked'] && substr($key, 0, 5) == 'efpt.') {
566 $addcolspan++;
567 }
568}
569
570print '<div class="div-table-responsive">';
571print '<table class="tagtable liste'.($moreforfilter ? " listwithfilterbefore" : "").'" id="tablelines3">'."\n";
572
573print '<tr class="liste_titre_filter">';
574if (getDolGlobalString('PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT')) {
575 print '<td class="liste_titre"><input type="text" size="4" name="search_project_ref" value="'.dol_escape_htmltag($search_project_ref).'"></td>';
576}
577if (getDolGlobalString('PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT')) {
578 print '<td class="liste_titre"><input type="text" size="4" name="search_thirdparty" value="'.dol_escape_htmltag($search_thirdparty).'"></td>';
579}
580print '<td class="liste_titre"><input type="text" size="4" name="search_task_label" value="'.dol_escape_htmltag($search_task_label).'"></td>';
581// TASK fields
582$search_options_pattern = 'search_task_options_';
583$extrafieldsobjectkey = 'projet_task';
584$extrafieldsobjectprefix = 'efpt.';
585include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
586if (!empty($arrayfields['t.planned_workload']['checked'])) {
587 print '<td class="liste_titre"></td>';
588}
589if (!empty($arrayfields['t.progress']['checked'])) {
590 print '<td class="liste_titre right"><input type="text" size="4" name="search_declared_progress" value="'.dol_escape_htmltag($search_declared_progress).'"></td>';
591}
592if (!empty($arrayfields['timeconsumed']['checked'])) {
593 print '<td class="liste_titre"></td>';
594 print '<td class="liste_titre"></td>';
595}
596print '<td class="liste_titre"></td>';
597print '<td class="liste_titre"></td>';
598print '<td class="liste_titre"></td>';
599// Action column
600print '<td class="liste_titre nowrap right">';
601$searchpicto = $form->showFilterAndCheckAddButtons(0);
602print $searchpicto;
603print '</td>';
604print "</tr>\n";
605
606print '<tr class="liste_titre">';
607if (getDolGlobalString('PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT')) {
608 print '<th>'.$langs->trans("Project").'</th>';
609}
610if (getDolGlobalString('PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT')) {
611 print '<th>'.$langs->trans("ThirdParty").'</th>';
612}
613print '<th>'.$langs->trans("Task").'</th>';
614// TASK fields
615$extrafieldsobjectkey = 'projet_task';
616$extrafieldsobjectprefix = 'efpt.';
617include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
618if (!empty($arrayfields['t.planned_workload']['checked'])) {
619 print '<th class="leftborder plannedworkload minwidth75 maxwidth100 right" title="'.dol_escape_htmltag($langs->trans("PlannedWorkload")).'">'.$form->textwithpicto($langs->trans("PlannedWorkloadShort"), $langs->trans("PlannedWorkload")).'</th>';
620}
621if (!empty($arrayfields['t.progress']['checked'])) {
622 print '<th class="right minwidth75 maxwidth100 title="'.dol_escape_htmltag($langs->trans("ProgressDeclared")).'">'.$langs->trans("ProgressDeclared").'</th>';
623}
624if (!empty($arrayfields['timeconsumed']['checked'])) {
625 print '<th class="right maxwidth100">'.$langs->trans("TimeSpentSmall").'<br>';
626 print '<span class="nowraponall">';
627 print '<span class="opacitymedium nopadding userimg"><img alt="Photo" class="photouserphoto userphotosmall" src="'.DOL_URL_ROOT.'/theme/common/everybody.png"></span>';
628 print '<span class="opacitymedium paddingleft">'.$langs->trans("EverybodySmall").'</span>';
629 print '</span>';
630 print '</th>';
631 print '<th class="right maxwidth75 maxwidth100">'.$langs->trans("TimeSpentSmall").($usertoprocess->firstname ? '<br><span class="nowraponall">'.$usertoprocess->getNomUrl(-3).'<span class="opacitymedium paddingleft">'.dol_trunc($usertoprocess->firstname, 10).'</span></span>' : '').'</th>';
632}
633print '<th class="center leftborder">'.$langs->trans("HourStart").'</td>';
634
635// By default, we can edit only tasks we are assigned to
636$restrictviewformytask = getDolGlobalInt('PROJECT_TIME_SHOW_TASK_NOT_ASSIGNED', 2);
637
638$numendworkingday = 0;
639$numstartworkingday = 0;
640// Get if user is available or not for each day
641$isavailable = array();
642
643// Assume from Monday to Friday if conf empty or badly formed
644$numstartworkingday = 1;
645$numendworkingday = 5;
646
647if (getDolGlobalString('MAIN_DEFAULT_WORKING_DAYS')) {
648 $tmparray = explode('-', getDolGlobalString('MAIN_DEFAULT_WORKING_DAYS'));
649 if (count($tmparray) >= 2) {
650 $numstartworkingday = $tmparray[0];
651 $numendworkingday = $tmparray[1];
652 }
653}
654
655$statusofholidaytocheck = Holiday::STATUS_APPROVED;
656$isavailablefordayanduser = $holiday->verifDateHolidayForTimestamp($usertoprocess->id, $daytoparse, (string) $statusofholidaytocheck); // $daytoparse is a date with hours = 0
657$isavailable[$daytoparse] = $isavailablefordayanduser; // in projectLinesPerWeek later, we are using $firstdaytoshow and dol_time_plus_duree to loop on each day
658
659$test = num_public_holiday($daytoparsegmt, $daytoparsegmt + 86400, $mysoc->country_code);
660if ($test) {
661 $isavailable[$daytoparse] = array('morning' => false, 'afternoon' => false, 'morning_reason' => 'public_holiday', 'afternoon_reason' => 'public_holiday');
662}
663
664$tmparray = dol_getdate($daytoparse, true); // detail of current day
665// For monday, must be 0 for monday if MAIN_START_WEEK = 1, must be 1 for monday if MAIN_START_WEEK = 0
666$idw = ($tmparray['wday'] - (!getDolGlobalString('MAIN_START_WEEK') ? 0 : 1));
667// numstartworkingday and numendworkingday are default start and end date of working days (1 means sunday if MAIN_START_WEEK is 0, 1 means monday if MAIN_START_WEEK is 1)
668$cssweekend = '';
669if ((($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.
670 $cssweekend = 'weekend';
671}
672
673$tmpday = dol_time_plus_duree($daytoparse, $idw, 'd');
674
675$cssonholiday = '';
676if (!$isavailable[$daytoparse]['morning'] && !$isavailable[$daytoparse]['afternoon']) {
677 $cssonholiday .= 'onholidayallday ';
678} elseif (!$isavailable[$daytoparse]['morning']) {
679 $cssonholiday .= 'onholidaymorning ';
680} elseif (!$isavailable[$daytoparse]['afternoon']) {
681 $cssonholiday .= 'onholidayafternoon ';
682}
683
684print '<th class="center'.($cssonholiday ? ' '.$cssonholiday : '').($cssweekend ? ' '.$cssweekend : '').'">'.$langs->trans("Duration").'</th>';
685print '<th class="center">'.$langs->trans("Note").'</th>';
686//print '<td class="center"></td>';
687print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
688
689print "</tr>\n";
690
691$colspan = 2 + (!getDolGlobalString('PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT') ? 0 : 2);
692
693if ($conf->use_javascript_ajax && count($tasksarray) >= getDolGlobalInt('NBLINES_TO_DUPLICATE_TOTAL_TIMESPENT_ON_TOP', 10)) {
694 print '<tr class="liste_total hideonsmartphone">';
695 print '<td class="liste_total" colspan="'.($colspan - 1 + $addcolspan).'">';
696 print $langs->trans("Total");
697 print '</td>';
698 if (!empty($arrayfields['timeconsumed']['checked'])) {
699 print '<td class="liste_total"></td>';
700 print '<td class="liste_total"></td>';
701 }
702 print '<td class="liste_total leftborder">';
703 print '</td>';
704
705 print '<td class="liste_total center'.($cssonholiday ? ' '.$cssonholiday : '').($cssweekend ? ' '.$cssweekend : '').'"><div class="totalDay0">&nbsp;</div></td>';
706
707 print '<td class="liste_total"></td>';
708 print '<td class="liste_total"></td>';
709 print '</tr>';
710}
711
712
713if (count($tasksarray) > 0) {
714 //var_dump($tasksarray); // contains only selected tasks
715 //var_dump($tasksarraywithoutfilter); // contains all tasks (if there is a filter, not defined if no filter)
716 //var_dump($tasksrole);
717
718 $j = 0;
719 $level = 0;
720 $totalforvisibletasks = projectLinesPerDay($j, 0, $usertoprocess, $tasksarray, $level, $projectsrole, $tasksrole, $mine, $restrictviewformytask, $daytoparse, $isavailable, 0, $arrayfields, $extrafields);
721 //var_dump($totalforvisibletasks);
722
723 // Show total for all other tasks
724
725 // Calculate total for all tasks
726 $listofdistinctprojectid = array(); // List of all distinct projects
727 if (!empty($tasksarraywithoutfilter) && is_array($tasksarraywithoutfilter) && count($tasksarraywithoutfilter)) {
728 foreach ($tasksarraywithoutfilter as $tmptask) {
729 $listofdistinctprojectid[$tmptask->fk_project] = $tmptask->fk_project;
730 }
731 }
732 //var_dump($listofdistinctprojectid);
733 $totalforeachday = array();
734 foreach ($listofdistinctprojectid as $tmpprojectid) {
735 $projectstatic->id = $tmpprojectid;
736 $projectstatic->loadTimeSpent($daytoparse, 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
737 for ($idw = 0; $idw < 7; $idw++) {
738 $tmpday = dol_time_plus_duree($daytoparse, $idw, 'd');
739 $totalforeachday[$tmpday] += $projectstatic->weekWorkLoad[$tmpday];
740 }
741 }
742 //var_dump($totalforeachday);
743
744 // Is there a diff between selected/filtered tasks and all tasks ?
745 $isdiff = 0;
746 if (count($totalforeachday)) {
747 $timeonothertasks = ($totalforeachday[$daytoparse] - $totalforvisibletasks[$daytoparse]);
748 if ($timeonothertasks) {
749 $isdiff = 1;
750 }
751 }
752
753 // 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
754 if ($isdiff) {
755 print '<tr class="oddeven othertaskwithtime">';
756 print '<td colspan="'.($colspan - 1).'" class="opacitymedium">';
757 print $langs->trans("OtherFilteredTasks");
758 print '</td>';
759 if (!empty($arrayfields['timeconsumed']['checked'])) {
760 print '<td class="liste_total"></td>';
761 print '<td class="liste_total"></td>';
762 }
763 print '<td class="leftborder"></td>';
764 print '<td class="right">';
765 $timeonothertasks = ($totalforeachday[$daytoparse] - $totalforvisibletasks[$daytoparse]);
766 print '<span class="timesheetalreadyrecorded" title="texttoreplace"><input type="text" class="center width50" disabled="" id="timespent[-1][0]" name="task[-1][0]" value="';
767 if ($timeonothertasks) {
768 print convertSecondToTime($timeonothertasks, 'allhourmin');
769 }
770 print '"></span>';
771 print '</td>';
772 print ' <td class="liste_total borderleft"></td>';
773 print ' <td class="liste_total"></td>';
774 print '</tr>';
775 }
776
777 if ($conf->use_javascript_ajax) {
778 print '<tr class="liste_total">';
779 print '<td class="liste_total" colspan="'.($colspan - 1 + $addcolspan).'">';
780 print $langs->trans("Total");
781 print '</td>';
782 if (!empty($arrayfields['timeconsumed']['checked'])) {
783 print '<td class="liste_total"></td>';
784 print '<td class="liste_total"></td>';
785 }
786 print '<td class="liste_total leftborder borderleft">';
787 //print ' - '.$langs->trans("ExpectedWorkedHours").': <strong>'.price($usertoprocess->weeklyhours, 1, $langs, 0, 0).'</strong>';
788 print '</td>';
789
790 print '<td class="liste_total center'.($cssonholiday ? ' '.$cssonholiday : '').($cssweekend ? ' '.$cssweekend : '').'"><div class="totalDay0">&nbsp;</div></td>';
791
792 print '<td class="liste_total"></td>';
793 print '<td class="liste_total"></td>';
794 print '</tr>';
795 }
796} else {
797 print '<tr><td colspan="14"><span class="opacitymedium">'.$langs->trans("NoAssignedTasks").'</span></td></tr>';
798}
799print "</table>";
800print '</div>';
801
802print '<input type="hidden" id="numberOfLines" name="numberOfLines" value="'.count($tasksarray).'"/>'."\n";
803
804print '<div class="center">';
805print '<input type="submit" name="button_addtime" class="button button-save"'.(!empty($disabledtask) ? ' disabled' : '').' value="'.$langs->trans("Save").'">';
806print '</div>';
807
808print '</form>';
809
810if (!empty($conf->use_javascript_ajax)) {
811 $modeinput = 'hours';
812 print "\n<!-- JS CODE TO ENABLE Tooltips on all object with class classfortooltip -->\n";
813 print '<script type="text/javascript">'."\n";
814 print "jQuery(document).ready(function () {\n";
815 print " updateTotal(0, '".dol_escape_js($modeinput)."');\n";
816 print ' jQuery(".timesheetalreadyrecorded").tooltip({
817 show: { collision: "flipfit", effect:\'toggle\', delay:50 },
818 hide: { effect:\'toggle\', delay: 50 },
819 tooltipClass: "mytooltip",
820 content: function () {
821 return \''.dol_escape_js($langs->trans("TimeAlreadyRecorded", $usertoprocess->getFullName($langs))).'\';
822 }
823 });'."\n";
824 print " jQuery('.inputhour, .inputminute').bind('keyup', function(e) { updateTotal(0, '".dol_escape_js($modeinput)."') });";
825 print "\n});\n";
826 print '</script>';
827}
828
829// End of page
830llxFooter();
831$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class to manage standard extra fields.
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.
Class 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.
const STATUS_APPROVED
Approved.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage tasks.
Class to manage Dolibarr users.
global $mysoc
num_public_holiday($timestampStart, $timestampEnd, $countryCodeOrId='', $lastday=0, $includesaturday=-1, $includesunday=-1, $includefriday=-1, $includemonday=-1)
Return the number of non working days including Friday, Saturday and Sunday (or not) between 2 dates ...
Definition date.lib.php:770
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition date.lib.php:125
convertSecondToTime($iSecond, $format='all', $lengthOfDay=86400, $lengthOfWeek=7)
Return, in clear text, value of a number of seconds in days, hours and minutes.
Definition date.lib.php:247
dol_now($mode='gmt')
Return date for now.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
print_liste_field_titre($name, $file="", $field="", $begin="", $param="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
natural_search($fields, $value, $mode=0, $nofirstand=0, $sqltoadd='')
Generate natural SQL search string for a criteria (this criteria can be tested on one or several fiel...
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by the value of a given key, which produces ascending (default) or descending out...
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.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='')
Show information in HTML for admin users or standard users.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
projectLinesPerDay(&$inc, $parent, $fuser, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, $preselectedday, &$isavailable, $oldprojectforbreak=0, $arrayfields=array(), $extrafields=null)
Output a task line into a pertime input mode.
project_timesheet_prepare_head($mode, $fuser=null)
Prepare array with list of tabs.
if(getDolGlobalString( 'TAKEPOS_SHOW_CUSTOMER')) print $langs trans('Date')." left Label right Qty right Price right TotalHT right TotalTTC right right right right right right right right right centpercent right TotalHT right n right VAT right n right TotalVAT right n No sujeto a RE IRPF right TotalLT1 right n right TotalLT2 right n right TotalTTC right n takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency right TotalTTC takeposcustomercurrency right takeposcustomercurrency n right PaymentTypeShortLIQ right SELECT p pos_change as p datep as date
Definition receipt.php:464
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.