diff --git a/db/update.sql b/db/update.sql
index 212cd97e..351cf8b4 100644
--- a/db/update.sql
+++ b/db/update.sql
@@ -49,3 +49,10 @@ ALTER TABLE `Room` ADD `description` TEXT NULL AFTER `map_url`;
-- Dashboard
ALTER TABLE `AngelTypes` ADD `show_on_dashboard` BOOLEAN NOT NULL AFTER `contact_email`;
UPDATE `AngelTypes` SET `show_on_dashboard` = TRUE;
+
+-- Work Log
+CREATE TABLE `engelsystem`.`UserWorkLog` ( `id` INT NOT NULL AUTO_INCREMENT , `user_id` INT NOT NULL , `work_hours` DECIMAL NOT NULL , `comment` VARCHAR(200) NOT NULL , `created_user_id` INT NOT NULL , `created_timestamp` INT NOT NULL , PRIMARY KEY (`id`), INDEX (`user_id`), INDEX (`created_user_id`)) ENGINE = InnoDB;
+ALTER TABLE `UserWorkLog` ADD FOREIGN KEY (`created_user_id`) REFERENCES `User`(`UID`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `UserWorkLog` ADD FOREIGN KEY (`user_id`) REFERENCES `User`(`UID`) ON DELETE CASCADE ON UPDATE CASCADE;
+ALTER TABLE `UserWorkLog` ADD INDEX(`created_timestamp`);
+INSERT INTO `Privileges` (`id`, `name`, `desc`) VALUES (NULL, 'admin_user_worklog', 'Manage user work log entries.');
+ALTER TABLE `UserWorkLog` CHANGE `work_hours` `work_hours` DECIMAL(10,2) NOT NULL;
diff --git a/includes/controller/user_worklog_controller.php b/includes/controller/user_worklog_controller.php
new file mode 100644
index 00000000..ba91534b
--- /dev/null
+++ b/includes/controller/user_worklog_controller.php
@@ -0,0 +1,189 @@
+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_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..d9628e1d
--- /dev/null
+++ b/includes/model/UserWorkLog_model.php
@@ -0,0 +1,111 @@
+ $user['UID'],
+ '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..b398cefe 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,16 @@ 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` = ?
+ ',[
+ $user['UID']
+ ]);
- 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..18553159 100644
--- a/includes/pages/admin_active.php
+++ b/includes/pages/admin_active.php
@@ -58,7 +58,9 @@ function admin_active()
SELECT
`User`.*,
COUNT(`ShiftEntry`.`id`) AS `shift_count`,
- %s AS `shift_length`
+ (%s + (
+ SELECT SUM(`work_hours`) * 3600 FROM `UserWorkLog` WHERE `user_id`=`User`.`UID`
+ )) AS `shift_length`
FROM `User`
LEFT JOIN `ShiftEntry` ON `User`.`UID` = `ShiftEntry`.`UID`
LEFT JOIN `Shifts` ON `ShiftEntry`.`SID` = `Shifts`.`SID`
@@ -140,7 +142,9 @@ function admin_active()
SELECT
`User`.*,
COUNT(`ShiftEntry`.`id`) AS `shift_count`,
- %s AS `shift_length`
+ (%s + (
+ SELECT SUM(`work_hours`) * 3600 FROM `UserWorkLog` WHERE `user_id`=`User`.`UID`
+ )) 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)") . '
diff --git a/includes/view/UserWorkLog_view.php b/includes/view/UserWorkLog_view.php
new file mode 100644
index 00000000..86a367ae
--- /dev/null
+++ b/includes/view/UserWorkLog_view.php
@@ -0,0 +1,95 @@
+ 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_text('work_hours', _('Work hours'), $userWorkLog['work_hours']),
+ form_text('comment', _('Comment'), $userWorkLog['comment']),
+ form_submit('submit', _('Add'))
+ ]);
+}
+
+/**
+ * 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..b1521ff8 100644
--- a/includes/view/User_view.php
+++ b/includes/view/User_view.php
@@ -408,7 +408,7 @@ 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;
@@ -420,6 +420,13 @@ function User_view_myshifts($shifts, $user_source, $its_me, $tshirt_score, $tshi
}
}
+ if($its_me || $admin_user_worklog_privilege) {
+ foreach($user_worklogs as $worklog) {
+ $myshifts_table[] = User_view_worklog($worklog, $admin_user_worklog_privilege);
+ $timesum += $worklog['work_hours'] * 3600;
+ }
+ }
+
if (count($myshifts_table) > 0) {
$myshifts_table[] = [
'date' => '' . _('Sum:') . '',
@@ -443,6 +450,38 @@ function User_view_myshifts($shifts, $user_source, $its_me, $tshirt_score, $tshi
return $myshifts_table;
}
+/**
+ * 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' => '',
+ 'duration' => '' . $worklog['work_hours'] . ' h',
+ 'room' => '',
+ 'shift_info' => _('Work log entry'),
+ 'comment' => $worklog['comment'],
+ 'actions' => $actions
+ ];
+}
+
/**
* Renders view for a single user
*
@@ -466,12 +505,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 +555,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')
diff --git a/public/index.php b/public/index.php
index af7318b1..adf22e71 100644
--- a/public/index.php
+++ b/public/index.php
@@ -22,6 +22,7 @@ $free_pages = [
'users',
'user_driver_licenses',
'user_password_recovery',
+ 'user_worklog'
];
// Gewünschte Seite/Funktion
@@ -130,6 +131,9 @@ if (
$title = shifts_title();
$content = user_shifts();
break;
+ case 'user_worklog':
+ list($title, $content) = user_worklogs_controller();
+ break;
case 'user_messages':
$title = messages_title();
$content = user_messages();