diff options
Diffstat (limited to 'includes')
-rw-r--r-- | includes/controller/user_worklog_controller.php | 195 | ||||
-rw-r--r-- | includes/controller/users_controller.php | 4 | ||||
-rw-r--r-- | includes/includes.php | 3 | ||||
-rw-r--r-- | includes/model/UserWorkLog_model.php | 123 | ||||
-rw-r--r-- | includes/model/User_model.php | 14 | ||||
-rw-r--r-- | includes/pages/admin_active.php | 12 | ||||
-rw-r--r-- | includes/pages/user_shifts.php | 16 | ||||
-rw-r--r-- | includes/view/UserWorkLog_view.php | 96 | ||||
-rw-r--r-- | includes/view/User_view.php | 65 |
9 files changed, 510 insertions, 18 deletions
diff --git a/includes/controller/user_worklog_controller.php b/includes/controller/user_worklog_controller.php new file mode 100644 index 00000000..bd62c83c --- /dev/null +++ b/includes/controller/user_worklog_controller.php @@ -0,0 +1,195 @@ +<?php + +/** + * Delete a work log entry. + */ +function user_worklog_delete_controller() +{ + global $user; + + $request = request(); + $userWorkLog = UserWorkLog($request->input('user_worklog_id')); + if (empty($userWorkLog)) { + redirect(user_link($user)); + } + $user_source = User($userWorkLog['user_id']); + + if ($request->has('confirmed')) { + UserWorkLog_delete($userWorkLog); + + success(_('Work log entry deleted.')); + redirect(user_link($user_source)); + } + + return [ + UserWorkLog_delete_title(), + UserWorkLog_delete_view($user_source, $userWorkLog) + ]; +} + +/** + * Edit work log for user. + */ +function user_worklog_edit_controller() +{ + global $user; + + $request = request(); + $userWorkLog = UserWorkLog($request->input('user_worklog_id')); + if (empty($userWorkLog)) { + redirect(user_link($user)); + } + $user_source = User($userWorkLog['user_id']); + + if ($request->has('submit')) { + list ($valid, $userWorkLog) = user_worklog_from_request($userWorkLog); + + if ($valid) { + UserWorkLog_update($userWorkLog); + + success(_('Work log entry updated.')); + redirect(user_link($user_source)); + } + } + + return [ + UserWorkLog_edit_title(), + UserWorkLog_edit_view($user_source, $userWorkLog) + ]; +} + +/** + * + * @param UserWorkLog $userWorkLog + * @return [bool $valid, UserWorkLog $userWorkLog] + */ +function user_worklog_from_request($userWorkLog) +{ + $request = request(); + + $valid = true; + + $userWorkLog['work_timestamp'] = parse_date('Y-m-d H:i', $request->input('work_timestamp') . ' 00:00'); + if ($userWorkLog['work_timestamp'] == null) { + $valid = false; + error(_('Please enter work date.')); + } + + $userWorkLog['work_hours'] = $request->input('work_hours'); + if (! preg_match("/[0-9]+(\.[0-9]+)?/", $userWorkLog['work_hours'])) { + $valid = false; + error(_('Please enter work hours in format ##[.##].')); + } + + $userWorkLog['comment'] = $request->input('comment'); + if (empty($userWorkLog['comment'])) { + $valid = false; + error(_('Please enter a comment.')); + } + + return [ + $valid, + $userWorkLog + ]; +} + +/** + * Add work log entry to user. + */ +function user_worklog_add_controller() +{ + global $user; + + $request = request(); + $user_source = User($request->input('user_id')); + if (empty($user_source)) { + redirect(user_link($user)); + } + + $userWorkLog = UserWorkLog_new($user_source); + + if ($request->has('submit')) { + list ($valid, $userWorkLog) = user_worklog_from_request($userWorkLog); + + if ($valid) { + UserWorkLog_create($userWorkLog); + + success(_('Work log entry created.')); + redirect(user_link($user_source)); + } + } + + return [ + UserWorkLog_add_title(), + UserWorkLog_add_view($user_source, $userWorkLog) + ]; +} + +/** + * Link to work log entry add for given user. + * + * @param User $user + */ +function user_worklog_add_link($user) +{ + return page_link_to('user_worklog', [ + 'action' => 'add', + 'user_id' => $user['UID'] + ]); +} + +/** + * Link to work log entry edit. + * + * @param UserWorkLog $userWorkLog + */ +function user_worklog_edit_link($userWorkLog) +{ + return page_link_to('user_worklog', [ + 'action' => 'edit', + 'user_worklog_id' => $userWorkLog['id'] + ]); +} + +/** + * Link to work log entry delete. + * + * @param UserWorkLog $userWorkLog + * @param array[] $parameters + */ +function user_worklog_delete_link($userWorkLog, $parameters = []) +{ + return page_link_to('user_worklog', array_merge([ + 'action' => 'delete', + 'user_worklog_id' => $userWorkLog['id'] + ], $parameters)); +} + +/** + * Work log entry actions + */ +function user_worklogs_controller() +{ + global $user, $privileges; + + if (! in_array('admin_user_worklog', $privileges)) { + redirect(user_link($user)); + } + + $request = request(); + $action = $request->input('action'); + if (! $request->has('action')) { + redirect(user_link($user)); + } + + switch ($action) { + case 'add': + return user_worklog_add_controller(); + case 'edit': + return user_worklog_edit_controller(); + case 'delete': + return user_worklog_delete_controller(); + } +} + +?>
\ No newline at end of file diff --git a/includes/controller/users_controller.php b/includes/controller/users_controller.php index a2a28410..c763cd48 100644 --- a/includes/controller/users_controller.php +++ b/includes/controller/users_controller.php @@ -242,7 +242,9 @@ function user_controller() $shifts, $user['UID'] == $user_source['UID'], $tshirt_score, - in_array('admin_active', $privileges) + in_array('admin_active', $privileges), + in_array('admin_user_worklog', $privileges), + UserWorkLogsForUser($user_source) ) ]; } diff --git a/includes/includes.php b/includes/includes.php index e8e5ce29..e316e550 100644 --- a/includes/includes.php +++ b/includes/includes.php @@ -27,6 +27,7 @@ $includeFiles = [ __DIR__ . '/../includes/model/UserDriverLicenses_model.php', __DIR__ . '/../includes/model/UserGroups_model.php', __DIR__ . '/../includes/model/User_model.php', + __DIR__ . '/../includes/model/UserWorkLog_model.php', __DIR__ . '/../includes/model/ValidationResult.php', __DIR__ . '/../includes/view/AngelTypes_view.php', @@ -45,6 +46,7 @@ $includeFiles = [ __DIR__ . '/../includes/view/UserDriverLicenses_view.php', __DIR__ . '/../includes/view/UserHintsRenderer.php', __DIR__ . '/../includes/view/User_view.php', + __DIR__ . '/../includes/view/UserWorkLog_view.php', __DIR__ . '/../includes/controller/angeltypes_controller.php', __DIR__ . '/../includes/controller/event_config_controller.php', @@ -56,6 +58,7 @@ $includeFiles = [ __DIR__ . '/../includes/controller/users_controller.php', __DIR__ . '/../includes/controller/user_angeltypes_controller.php', __DIR__ . '/../includes/controller/user_driver_licenses_controller.php', + __DIR__ . '/../includes/controller/user_worklog_controller.php', __DIR__ . '/../includes/helper/graph_helper.php', __DIR__ . '/../includes/helper/internationalization_helper.php', diff --git a/includes/model/UserWorkLog_model.php b/includes/model/UserWorkLog_model.php new file mode 100644 index 00000000..36442943 --- /dev/null +++ b/includes/model/UserWorkLog_model.php @@ -0,0 +1,123 @@ +<?php +use Engelsystem\Database\Db; + +/** + * Load a single work log entry. + * + * @param int $user_worklog_id + */ +function UserWorkLog($user_worklog_id) +{ + return Db::selectOne("SELECT * FROM `UserWorkLog` WHERE `id`=?", [ + $user_worklog_id + ]); +} + +/** + * Returns all work log entries for a user. + * + * @param User $user + */ +function UserWorkLogsForUser($user) +{ + return Db::select("SELECT * FROM `UserWorkLog` WHERE `user_id`=? ORDER BY `created_timestamp`", [ + $user['UID'] + ]); +} + +/** + * Delete a work log entry. + * + * @param UserWorkLog $userWorkLog + */ +function UserWorkLog_delete($userWorkLog) +{ + $user_source = User($userWorkLog['user_id']); + $result = Db::delete("DELETE FROM `UserWorkLog` WHERE `id`=?", [ + $userWorkLog['id'] + ]); + + engelsystem_log(sprintf('Delete work log for %s, %s hours, %s', User_Nick_render($user_source), $userWorkLog['work_hours'], $userWorkLog['comment'])); + + return $result; +} + +/** + * Update work log entry (only work hours and comment) + * + * @param UserWorkLog $userWorkLog + */ +function UserWorkLog_update($userWorkLog) +{ + $user_source = User($userWorkLog['user_id']); + + $result = Db::update("UPDATE `UserWorkLog` SET + `work_timestamp`=?, + `work_hours`=?, + `comment`=? + WHERE `id`=?", [ + $userWorkLog['work_timestamp'], + $userWorkLog['work_hours'], + $userWorkLog['comment'], + $userWorkLog['id'] + ]); + + engelsystem_log(sprintf('Updated work log for %s, %s hours, %s', User_Nick_render($user_source), $userWorkLog['work_hours'], $userWorkLog['comment'])); + + return $result; +} + +/** + * Create a new work log entry + * + * @param UserWorkLog $userWorkLog + */ +function UserWorkLog_create($userWorkLog) +{ + global $user; + + $user_source = User($userWorkLog['user_id']); + + $result = Db::insert("INSERT INTO `UserWorkLog` ( + `user_id`, + `work_timestamp`, + `work_hours`, + `comment`, + `created_user_id`, + `created_timestamp` + ) + VALUES (?, ?, ?, ?, ?, ?)", [ + $userWorkLog['user_id'], + $userWorkLog['work_timestamp'], + $userWorkLog['work_hours'], + $userWorkLog['comment'], + $user['UID'], + time() + ]); + + engelsystem_log(sprintf('Added work log entry for %s, %s hours, %s', User_Nick_render($user_source), $userWorkLog['work_hours'], $userWorkLog['comment'])); + + return $result; +} + +/** + * New user work log entry + * + * @param array[] $user + */ +function UserWorkLog_new($user) +{ + $work_date = parse_date('Y-m-d H:i', date('Y-m-d 00:00', time())); + $event_config = EventConfig(); + if (! empty($event_config['buildup_start_date'])) { + $work_date = parse_date('Y-m-d H:i', date('Y-m-d 00:00', $event_config['buildup_start_date'])); + } + return [ + 'user_id' => $user['UID'], + 'work_timestamp' => $work_date, + 'work_hours' => 0, + 'comment' => '' + ]; +} + +?>
\ No newline at end of file diff --git a/includes/model/User_model.php b/includes/model/User_model.php index fa24aac1..5a31e7b8 100644 --- a/includes/model/User_model.php +++ b/includes/model/User_model.php @@ -26,7 +26,7 @@ function User_delete($user_id) function User_tshirt_score($user) { $shift_sum_formula = config('shift_sum_formula'); - $result = DB::selectOne(' + $result_shifts = DB::selectOne(' SELECT ROUND((' . $shift_sum_formula . ') / 3600, 2) AS `tshirt_score` FROM `User` LEFT JOIN `ShiftEntry` ON `User`.`UID` = `ShiftEntry`.`UID` LEFT JOIN `Shifts` ON `ShiftEntry`.`SID` = `Shifts`.`SID` @@ -37,8 +37,18 @@ function User_tshirt_score($user) { $user['UID'], time() ]); + $result_worklog = DB::selectOne(' + SELECT SUM(`work_hours`) AS `tshirt_score` + FROM `User` + LEFT JOIN `UserWorkLog` ON `User`.`UID` = `UserWorkLog`.`user_id` + WHERE `User`.`UID` = ? + AND `UserWorkLog`.`work_timestamp` < ? + ',[ + $user['UID'], + time() + ]); - return $result['tshirt_score']; + return $result_shifts['tshirt_score'] + $result_worklog['tshirt_score']; } /** diff --git a/includes/pages/admin_active.php b/includes/pages/admin_active.php index 576cdc49..f3a28061 100644 --- a/includes/pages/admin_active.php +++ b/includes/pages/admin_active.php @@ -58,7 +58,10 @@ function admin_active() SELECT `User`.*, COUNT(`ShiftEntry`.`id`) AS `shift_count`, - %s AS `shift_length` + (%s + ( + SELECT COALESCE(SUM(`work_hours`) * 3600, 0) FROM `UserWorkLog` WHERE `user_id`=`User`.`UID` + AND `work_timestamp` < %s + )) AS `shift_length` FROM `User` LEFT JOIN `ShiftEntry` ON `User`.`UID` = `ShiftEntry`.`UID` LEFT JOIN `Shifts` ON `ShiftEntry`.`SID` = `Shifts`.`SID` @@ -69,6 +72,7 @@ function admin_active() %s ', $shift_sum_formula, + time(), $limit )); $user_nicks = []; @@ -140,7 +144,10 @@ function admin_active() SELECT `User`.*, COUNT(`ShiftEntry`.`id`) AS `shift_count`, - %s AS `shift_length` + (%s + ( + SELECT COALESCE(SUM(`work_hours`) * 3600, 0) FROM `UserWorkLog` WHERE `user_id`=`User`.`UID` + AND `work_timestamp` < %s + )) AS `shift_length` FROM `User` LEFT JOIN `ShiftEntry` ON `User`.`UID` = `ShiftEntry`.`UID` LEFT JOIN `Shifts` ON `ShiftEntry`.`SID` = `Shifts`.`SID` ' . ($show_all_shifts ? '' : 'AND (`Shifts`.`end` < ' . time() . " OR `Shifts`.`end` IS NULL)") . ' @@ -150,6 +157,7 @@ function admin_active() %s ', $shift_sum_formula, + time(), $limit )); $matched_users = []; diff --git a/includes/pages/user_shifts.php b/includes/pages/user_shifts.php index 0be4aa67..81b405b1 100644 --- a/includes/pages/user_shifts.php +++ b/includes/pages/user_shifts.php @@ -313,11 +313,19 @@ function get_ids_from_array($array) */ function make_select($items, $selected, $name, $title = null, $additionalButtons = []) { + $html = ''; $htmlItems = []; if (isset($title)) { - $htmlItems[] = '<h4>' . $title . '</h4>' . "\n"; + $html .= '<h4>' . $title . '</h4>' . "\n"; } + $buttons = []; + $buttons[] = button('javascript: checkAll(\'selection_' . $name . '\', true)', _('All')); + $buttons[] = button('javascript: checkAll(\'selection_' . $name . '\', false)', _('None')); + $buttons = array_merge($buttons, $additionalButtons); + + $html .= buttons($buttons); + foreach ($items as $i) { $htmlItems[] = '<div class="checkbox">' . '<label><input type="checkbox" name="' . $name . '[]" value="' . $i['id'] . '" ' @@ -326,13 +334,9 @@ function make_select($items, $selected, $name, $title = null, $additionalButtons . (!isset($i['enabled']) || $i['enabled'] ? '' : glyph('lock')) . '</div><br />'; } - $html = '<div id="selection_' . $name . '" class="selection ' . $name . '">' . "\n"; + $html .= '<div id="selection_' . $name . '" class="selection ' . $name . '">' . "\n"; $html .= implode("\n", $htmlItems); - $buttons = []; - $buttons[] = button('javascript: checkAll(\'selection_' . $name . '\', true)', _('All')); - $buttons[] = button('javascript: checkAll(\'selection_' . $name . '\', false)', _('None')); - $buttons = array_merge($buttons, $additionalButtons); $html .= buttons($buttons); $html .= '</div>' . "\n"; diff --git a/includes/view/UserWorkLog_view.php b/includes/view/UserWorkLog_view.php new file mode 100644 index 00000000..79c049b3 --- /dev/null +++ b/includes/view/UserWorkLog_view.php @@ -0,0 +1,96 @@ +<?php + +/** + * Delete work log entry. + * @param User $user_source + * @param UserWorkLog $userWorkLog + */ +function UserWorkLog_delete_view($user_source, $userWorkLog) +{ + return page_with_title(UserWorkLog_delete_title(), [ + info(sprintf(_('Do you want to delete the worklog entry for %s?'), User_Nick_render($user_source)), true), + buttons([ + button(user_link($user_source), glyph('remove') . _('cancel')), + button(user_worklog_delete_link($userWorkLog, [ + 'confirmed' => 1 + ]), glyph('ok') . _('delete'), 'btn-danger') + ]) + ]); +} + +/** + * Title for work log delete. + */ +function UserWorkLog_delete_title() +{ + return _('Delete work log entry'); +} + +/** + * Render edit table. + * + * @param User $user_source + * @param UserWorkLog $userWorkLog + */ +function UserWorkLog_edit_form($user_source, $userWorkLog) +{ + return form([ + form_info(_('User'), User_Nick_render($user_source)), + form_date('work_timestamp', _('Work date'), $userWorkLog['work_timestamp'], null, time()), + form_text('work_hours', _('Work hours'), $userWorkLog['work_hours']), + form_text('comment', _('Comment'), $userWorkLog['comment']), + form_submit('submit', _('Save')) + ]); +} + +/** + * Form for edit a user work log entry. + * + * @param User $user_source + * @param UserWorkLog $userWorkLog + */ +function UserWorkLog_edit_view($user_source, $userWorkLog) +{ + return page_with_title(UserWorkLog_edit_title(), [ + buttons([ + button(user_link($user_source), _('back')) + ]), + msg(), + UserWorkLog_edit_form($user_source, $userWorkLog) + ]); +} + +/** + * Form for adding a user work log entry. + * + * @param User $user_source + * @param UserWorkLog $userWorkLog + */ +function UserWorkLog_add_view($user_source, $userWorkLog) +{ + return page_with_title(UserWorkLog_add_title(), [ + buttons([ + button(user_link($user_source), _('back')) + ]), + msg(), + UserWorkLog_edit_form($user_source, $userWorkLog) + ]); +} + +/** + * Title text for editing work log entry. + */ +function UserWorkLog_edit_title() +{ + return _('Edit work log entry'); +} + +/** + * Title text for adding work log entry. + */ +function UserWorkLog_add_title() +{ + return _('Add work log entry'); +} + +?>
\ No newline at end of file diff --git a/includes/view/User_view.php b/includes/view/User_view.php index fff2952e..36ac36c3 100644 --- a/includes/view/User_view.php +++ b/includes/view/User_view.php @@ -356,7 +356,7 @@ function User_view_myshift($shift, $user_source, $its_me) . glyph('time') . date('H:i', $shift['start']) . ' - ' . date('H:i', $shift['end']), - 'duration' => round(($shift['end'] - $shift['start']) / 3600, 2) . ' h', + 'duration' => sprintf('%.2f', round(($shift['end'] - $shift['start']) / 3600, 2)) . ' h', 'room' => Room_name_render($shift), 'shift_info' => $shift_info, 'comment' => '' @@ -408,22 +408,30 @@ function User_view_myshift($shift, $user_source, $its_me) * @param bool $its_me * @return array */ -function User_view_myshifts($shifts, $user_source, $its_me, $tshirt_score, $tshirt_admin) +function User_view_myshifts($shifts, $user_source, $its_me, $tshirt_score, $tshirt_admin, $user_worklogs, $admin_user_worklog_privilege) { $myshifts_table = []; $timesum = 0; foreach ($shifts as $shift) { - $myshifts_table[] = User_view_myshift($shift, $user_source, $its_me); + $myshifts_table[$shift['start']] = User_view_myshift($shift, $user_source, $its_me); if (!$shift['freeloaded']) { $timesum += ($shift['end'] - $shift['start']); } } + if($its_me || $admin_user_worklog_privilege) { + foreach($user_worklogs as $worklog) { + $myshifts_table[$worklog['work_timestamp']] = User_view_worklog($worklog, $admin_user_worklog_privilege); + $timesum += $worklog['work_hours'] * 3600; + } + } + if (count($myshifts_table) > 0) { + ksort($myshifts_table); $myshifts_table[] = [ 'date' => '<b>' . _('Sum:') . '</b>', - 'duration' => '<b>' . round($timesum / 3600, 2) . ' h</b>', + 'duration' => '<b>' . sprintf('%.2f', round($timesum / 3600, 2)) . ' h</b>', 'room' => '', 'shift_info' => '', 'comment' => '', @@ -432,7 +440,7 @@ function User_view_myshifts($shifts, $user_source, $its_me, $tshirt_score, $tshi if (config('enable_tshirt_size', false) && ($its_me || $tshirt_admin)) { $myshifts_table[] = [ 'date' => '<b>' . _('Your t-shirt score') . '™:</b>', - 'duration' => '<b>' . $tshirt_score . '</b>', + 'duration' => '<b>' . sprintf('%.2f', $tshirt_score) . ' h</b>', 'room' => '', 'shift_info' => '', 'comment' => '', @@ -444,6 +452,43 @@ function User_view_myshifts($shifts, $user_source, $its_me, $tshirt_score, $tshi } /** + * Renders table entry for user work log + * @param UserWorkLog $worklog + * @param bool $admin_user_worklog_privilege + */ +function User_view_worklog($worklog, $admin_user_worklog_privilege) { + $actions = ''; + if($admin_user_worklog_privilege) { + $actions = table_buttons([ + button( + user_worklog_edit_link($worklog), + glyph('edit') . _('edit'), + 'btn-xs' + ), + button( + user_worklog_delete_link($worklog), + glyph('trash') . _('delete'), + 'btn-xs' + ) + ]); + } + + return [ + 'date' => glyph('calendar') . date('Y-m-d', $worklog['work_timestamp']), + 'duration' => '<b>' . sprintf('%.2f', $worklog['work_hours']) . ' h</b>', + 'room' => '', + 'shift_info' => _('Work log entry'), + 'comment' => $worklog['comment'] . '<br>' + . sprintf( + _('Added by %s at %s'), + User_Nick_render(User($worklog['user_id'])), + date('Y-m-d H:i', $worklog['created_timestamp']) + ), + 'actions' => $actions + ]; +} + +/** * Renders view for a single user * * @param array $user_source @@ -466,12 +511,14 @@ function User_view( $shifts, $its_me, $tshirt_score, - $tshirt_admin + $tshirt_admin, + $admin_user_worklog_privilege, + $user_worklogs ) { $user_name = htmlspecialchars($user_source['Vorname']) . ' ' . htmlspecialchars($user_source['Name']); $myshifts_table = ''; if($its_me || $admin_user_privilege) { - $my_shifts = User_view_myshifts($shifts, $user_source, $its_me, $tshirt_score, $tshirt_admin); + $my_shifts = User_view_myshifts($shifts, $user_source, $its_me, $tshirt_score, $tshirt_admin, $user_worklogs, $admin_user_worklog_privilege); if(count($my_shifts) > 0) { $myshifts_table = table([ 'date' => _('Day & time'), @@ -514,6 +561,10 @@ function User_view( ), glyph('cutlery') . _('Edit vouchers') ) : '', + $admin_user_worklog_privilege ? button( + user_worklog_add_link($user_source), + glyph('list') . _('Add work log') + ) : '', $its_me ? button( page_link_to('user_settings'), glyph('list-alt') . _('Settings') |