From f732a4af6f1c60d87b6b367d7ba5011b93ad3283 Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Sat, 12 Sep 2020 19:45:25 +0200 Subject: [PATCH] Added Worklog model --- ...020_09_07_000000_create_worklogs_table.php | 106 +++++++++++ .../controller/user_worklog_controller.php | 59 +++--- includes/model/UserWorkLog_model.php | 170 ++++++------------ includes/model/User_model.php | 30 ++-- includes/pages/admin_active.php | 16 +- includes/view/UserWorkLog_view.php | 19 +- includes/view/User_view.php | 60 ++++--- src/Controllers/Metrics/Stats.php | 33 ++-- src/Models/User/User.php | 21 +++ src/Models/Worklog.php | 62 +++++++ tests/Unit/Controllers/Metrics/StatsTest.php | 23 +++ tests/Unit/Models/User/UserTest.php | 42 +++++ tests/Unit/Models/WorklogTest.php | 42 +++++ 13 files changed, 456 insertions(+), 227 deletions(-) create mode 100644 db/migrations/2020_09_07_000000_create_worklogs_table.php create mode 100644 src/Models/Worklog.php create mode 100644 tests/Unit/Models/WorklogTest.php diff --git a/db/migrations/2020_09_07_000000_create_worklogs_table.php b/db/migrations/2020_09_07_000000_create_worklogs_table.php new file mode 100644 index 00000000..3c21a39c --- /dev/null +++ b/db/migrations/2020_09_07_000000_create_worklogs_table.php @@ -0,0 +1,106 @@ +schema->create('worklogs', function (Blueprint $table) { + $table->increments('id'); + $this->referencesUser($table); + $this->references($table, 'users', 'creator_id'); + $table->decimal('hours'); + $table->string('comment', 200); + $table->date('worked_at'); + $table->timestamps(); + }); + + if ($this->schema->hasTable('UserWorkLog')) { + $connection = $this->schema->getConnection(); + /** @var stdClass[] $previousRecords */ + $previousRecords = $connection + ->table('UserWorkLog') + ->get(); + + foreach ($previousRecords as $previousRecord) { + $room = new Worklog([ + 'user_id' => $previousRecord->user_id, + 'creator_id' => $previousRecord->created_user_id, + 'worked_at' => $previousRecord->work_timestamp, + 'hours' => $previousRecord->work_hours, + 'comment' => $previousRecord->comment, + ]); + $created_at = Carbon::createFromTimestamp($previousRecord->created_timestamp); + $room->setAttribute('id', $previousRecord->id); + $room->setAttribute('created_at', $created_at); + $room->setAttribute('updated_at', $created_at); + $room->save(); + } + + $this->changeReferences( + 'UserWorkLog', + 'id', + 'worklogs', + 'id' + ); + + $this->schema->drop('UserWorkLog'); + } + } + + /** + * Reverse the migration + */ + public function down(): void + { + $this->schema->create('UserWorkLog', function (Blueprint $table) { + $table->increments('id'); + $this->referencesUser($table); + $table->integer('work_timestamp'); + $table->decimal('work_hours'); + $table->string('comment', 200); + $this->references($table, 'users', 'created_user_id'); + $table->integer('created_timestamp')->index(); + }); + + foreach (Worklog::all() as $record) { + /** @var Worklog $record */ + $this->schema + ->getConnection() + ->table('UserWorkLog') + ->insert([ + 'id' => $record->id, + 'user_id' => $record->user_id, + 'work_timestamp' => $record->worked_at->timestamp, + 'work_hours' => $record->hours, + 'comment' => $record->comment, + 'created_user_id' => $record->creator_id, + 'created_timestamp' => $record->created_at->timestamp, + ]); + } + + $this->changeReferences( + 'worklogs', + 'id', + 'UserWorkLog', + 'id' + ); + + $this->schema->drop('worklogs'); + } +} diff --git a/includes/controller/user_worklog_controller.php b/includes/controller/user_worklog_controller.php index 5bb07f33..8ca955bc 100644 --- a/includes/controller/user_worklog_controller.php +++ b/includes/controller/user_worklog_controller.php @@ -1,6 +1,7 @@ input('user_worklog_id')); + $userWorkLog = Worklog::find($request->input('user_worklog_id')); if (empty($userWorkLog)) { throw_redirect(user_link(auth()->user()->id)); } - $user_source = User::find($userWorkLog['user_id']); + $user_source = $userWorkLog->user; if ($request->hasPostData('submit')) { UserWorkLog_delete($userWorkLog); @@ -37,17 +38,24 @@ function user_worklog_delete_controller() function user_worklog_edit_controller() { $request = request(); - $userWorkLog = UserWorkLog($request->input('user_worklog_id')); + $userWorkLog = Worklog::find($request->input('user_worklog_id')); if (empty($userWorkLog)) { throw_redirect(user_link(auth()->user()->id)); } - $user_source = User::find($userWorkLog['user_id']); + $user_source = $userWorkLog->user; if ($request->hasPostData('submit')) { list ($valid, $userWorkLog) = user_worklog_from_request($userWorkLog); if ($valid) { - UserWorkLog_update($userWorkLog); + $userWorkLog->save(); + + engelsystem_log(sprintf( + 'Updated work log for %s, %s hours, %s', + User_Nick_render($userWorkLog->user, true), + $userWorkLog->hours, + $userWorkLog->comment + )); success(__('Work log entry updated.')); throw_redirect(user_link($user_source->id)); @@ -63,44 +71,41 @@ function user_worklog_edit_controller() /** * Handle form * - * @param array $userWorkLog - * @return array [bool $valid, UserWorkLog $userWorkLog] + * @param Worklog $worklog + * @return bool[]|Worklog[] [bool $valid, Worklog $userWorkLog] */ -function user_worklog_from_request($userWorkLog) +function user_worklog_from_request(Worklog $worklog) { $request = request(); $valid = true; - $userWorkLog['work_timestamp'] = parse_date( - 'Y-m-d H:i', - $request->input('work_timestamp') . ' 00:00' - ); - if (is_null($userWorkLog['work_timestamp'])) { + $worklog->worked_at = DateTime::createFromFormat('Y-m-d H:i', $request->input('work_timestamp') . ' 00:00'); + if (!$worklog->worked_at) { $valid = false; error(__('Please enter work date.')); } - $userWorkLog['work_hours'] = $request->input('work_hours'); - if (!preg_match("/^[0-9]+(\.[0-9]+)?$/", $userWorkLog['work_hours'])) { + $worklog->hours = $request->input('work_hours'); + if (!preg_match("/^[0-9]+(\.[0-9]{0,2})?$/", $worklog->hours)) { $valid = false; error(__('Please enter work hours in format ##[.##].')); } - $userWorkLog['comment'] = $request->input('comment'); - if (empty($userWorkLog['comment'])) { + $worklog->comment = $request->input('comment'); + if (empty($worklog->comment)) { $valid = false; error(__('Please enter a comment.')); } - if (mb_strlen($userWorkLog['comment']) > 200) { + if (mb_strlen($worklog->comment) > 200) { $valid = false; error(__('Comment too long.')); } return [ $valid, - $userWorkLog + $worklog ]; } @@ -143,7 +148,7 @@ function user_worklog_add_controller() * * @return string */ -function user_worklog_add_link($user) +function user_worklog_add_link(User $user) { return page_link_to('user_worklog', [ 'action' => 'add', @@ -154,29 +159,29 @@ function user_worklog_add_link($user) /** * Link to work log entry edit. * - * @param array $userWorkLog + * @param Worklog $userWorkLog * @return string */ -function user_worklog_edit_link($userWorkLog) +function user_worklog_edit_link(Worklog $userWorkLog) { return page_link_to('user_worklog', [ 'action' => 'edit', - 'user_worklog_id' => $userWorkLog['id'] + 'user_worklog_id' => $userWorkLog->id ]); } /** * Link to work log entry delete. * - * @param array $userWorkLog + * @param Worklog $userWorkLog * @param array[] $parameters * @return string */ -function user_worklog_delete_link($userWorkLog, $parameters = []) +function user_worklog_delete_link(Worklog $userWorkLog, $parameters = []) { return page_link_to('user_worklog', array_merge([ 'action' => 'delete', - 'user_worklog_id' => $userWorkLog['id'] + 'user_worklog_id' => $userWorkLog->id ], $parameters)); } @@ -207,4 +212,6 @@ function user_worklog_controller() case 'delete': return user_worklog_delete_controller(); } + + return ['', '']; } diff --git a/includes/model/UserWorkLog_model.php b/includes/model/UserWorkLog_model.php index 4ac0af31..df32576c 100644 --- a/includes/model/UserWorkLog_model.php +++ b/includes/model/UserWorkLog_model.php @@ -1,133 +1,67 @@ = ' . $sinceTime->getTimestamp() : '') . ' - ORDER BY `created_timestamp` - ', - [ - $userId - ] - ); + $worklogs = Worklog::whereUserId($userId); + if ($sinceTime) { + $worklogs = $worklogs->whereDate('worked_at', '>=', $sinceTime); + } + + return $worklogs->get(); } /** * Delete a work log entry. * - * @param $userWorkLog + * @param Worklog $userWorkLog * @return int */ -function UserWorkLog_delete($userWorkLog) +function UserWorkLog_delete(Worklog $userWorkLog) { - $user_source = User::find($userWorkLog['user_id']); - $result = Db::delete("DELETE FROM `UserWorkLog` WHERE `id`=?", [ - $userWorkLog['id'] - ]); + $result = $userWorkLog->delete(); engelsystem_log(sprintf( 'Delete work log for %s, %s hours, %s', - User_Nick_render($user_source, true), - $userWorkLog['work_hours'], - $userWorkLog['comment'] + User_Nick_render($userWorkLog->user, true), + $userWorkLog->hours, + $userWorkLog->comment )); return $result; } -/** - * Update work log entry (only work hours and comment) - * - * @param $userWorkLog - * @return int - */ -function UserWorkLog_update($userWorkLog) -{ - $user_source = User::find($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, true), - $userWorkLog['work_hours'], - $userWorkLog['comment']) - ); - - return $result; -} - /** * Create a new work log entry * - * @param $userWorkLog + * @param Worklog $userWorkLog * @return bool */ -function UserWorkLog_create($userWorkLog) +function UserWorkLog_create(Worklog $userWorkLog) { $user = auth()->user(); + $userWorkLog->creator()->associate($user); + $result = $userWorkLog->save(); - $user_source = User::find($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->id, - time() - ]); - - engelsystem_log(sprintf('Added work log entry for %s, %s hours, %s', User_Nick_render($user_source, true), - $userWorkLog['work_hours'], $userWorkLog['comment'])); + engelsystem_log(sprintf( + 'Added work log entry for %s, %s hours, %s', + User_Nick_render($userWorkLog->user, true), + $userWorkLog->hours, + $userWorkLog->comment + )); return $result; } @@ -165,20 +99,20 @@ function UserWorkLog_from_shift($shift) $nightShiftMultiplier = $nightShifts['multiplier']; } - UserWorkLog_create([ - 'user_id' => $entry['UID'], - 'work_timestamp' => $shift['start'], - 'work_hours' => (($shift['end'] - $shift['start']) / 60 / 60) * $nightShiftMultiplier, - 'comment' => sprintf( - '%s (%s as %s) in %s, %s-%s', - $shift['name'], - $shift['title'], - $type['name'], - $room->name, - Carbon::createFromTimestamp($shift['start'])->format(__('m/d/Y h:i a')), - Carbon::createFromTimestamp($shift['end'])->format(__('m/d/Y h:i a')) - ), - ]); + $worklog = UserWorkLog_new($entry['UID']); + $worklog->hours = (($shift['end'] - $shift['start']) / 60 / 60) * $nightShiftMultiplier; + $worklog->comment = sprintf( + '%s (%s as %s) in %s, %s-%s', + $shift['name'], + $shift['title'], + $type['name'], + $room->name, + Carbon::createFromTimestamp($shift['start'])->format(__('m/d/Y h:i a')), + Carbon::createFromTimestamp($shift['end'])->format(__('m/d/Y h:i a')) + ); + $worklog->worked_at = Carbon::createFromTimestamp($shift['start']); + + UserWorkLog_create($worklog); } } @@ -186,22 +120,26 @@ function UserWorkLog_from_shift($shift) * New user work log entry * * @param int $userId - * @return array + * @return Worklog */ function UserWorkLog_new($userId) { - $work_date = parse_date('Y-m-d H:i', date('Y-m-d 00:00', time())); - /** @var Carbon $buildup */ $buildup = config('buildup_start'); + + $work_date = Carbon::today(); if (!empty($buildup)) { - $work_date = $buildup->format('Y-m-d H:i'); + $work_date = $buildup; } - return [ - 'user_id' => $userId, - 'work_timestamp' => $work_date, - 'work_hours' => 0, - 'comment' => '' - ]; + $work_date + ->setHour(0) + ->setMinute(0) + ->setSecond(0); + + $worklog = new Worklog(); + $worklog->user_id = $userId; + $worklog->worked_at = $work_date; + + return $worklog; } diff --git a/includes/model/User_model.php b/includes/model/User_model.php index 1402afe8..968dfa21 100644 --- a/includes/model/User_model.php +++ b/includes/model/User_model.php @@ -3,8 +3,10 @@ use Carbon\Carbon; use Engelsystem\Database\DB; use Engelsystem\Models\User\User; +use Engelsystem\Models\Worklog; use Engelsystem\ValidationResult; use Illuminate\Database\Query\JoinClause; +use Illuminate\Support\Collection; /** * User model @@ -35,21 +37,12 @@ function User_tshirt_score($userId) $result_shifts = ['tshirt_score' => 0]; } - $result_worklog = DB::selectOne(' - SELECT SUM(`work_hours`) AS `tshirt_score` - FROM `users` - LEFT JOIN `UserWorkLog` ON `users`.`id` = `UserWorkLog`.`user_id` - WHERE `users`.`id` = ? - AND `UserWorkLog`.`work_timestamp` < ? - ', [ - $userId, - time() - ]); - if (!isset($result_worklog['tshirt_score'])) { - $result_worklog = ['tshirt_score' => 0]; - } + $worklogHours = Worklog::query() + ->where('user_id', $userId) + ->where('worked_at', '<=', Carbon::Now()) + ->sum('hours'); - return $result_shifts['tshirt_score'] + $result_worklog['tshirt_score']; + return $result_shifts['tshirt_score'] + $worklogHours; } /** @@ -67,7 +60,8 @@ function User_is_freeloader($user) * Returns all users that are not member of given angeltype. * * @param array $angeltype Angeltype - * @return User[] + * + * @return User[]|Collection */ function Users_by_angeltype_inverted($angeltype) { @@ -88,7 +82,7 @@ function Users_by_angeltype_inverted($angeltype) * Returns all members of given angeltype. * * @param array $angeltype - * @return User[] + * @return User[]|Collection */ function Users_by_angeltype($angeltype) { @@ -241,14 +235,14 @@ function User_get_eligable_voucher_count($user) $worklog = UserWorkLogsForUser($user->id, $start); $shifts_done = count($shifts) - + count($worklog); + + $worklog->count(); $shiftsTime = 0; foreach ($shifts as $shift){ $shiftsTime += ($shift['end'] - $shift['start']) / 60 / 60; } foreach ($worklog as $entry){ - $shiftsTime += $entry['work_hours']; + $shiftsTime += $entry->hours; } $vouchers = $voucher_settings['initial_vouchers']; diff --git a/includes/pages/admin_active.php b/includes/pages/admin_active.php index d9024e7c..a19d5712 100644 --- a/includes/pages/admin_active.php +++ b/includes/pages/admin_active.php @@ -62,13 +62,13 @@ function admin_active() users.*, COUNT(ShiftEntry.id) AS shift_count, (%s + ( - SELECT COALESCE(SUM(`work_hours`) * 3600, 0) FROM `UserWorkLog` WHERE `user_id`=`users`.`id` - AND `work_timestamp` < ? + SELECT COALESCE(SUM(`hours`) * 3600, 0) + FROM `worklogs` WHERE `user_id`=`users`.`id` + AND `worked_at` <= NOW() )) AS `shift_length` ', $shift_sum_formula - ), - [time()] + ) ) ->leftJoin('ShiftEntry', 'users.id', '=', 'ShiftEntry.UID') ->leftJoin('Shifts', 'ShiftEntry.SID', '=', 'Shifts.SID') @@ -156,13 +156,13 @@ function admin_active() users.*, COUNT(ShiftEntry.id) AS shift_count, (%s + ( - SELECT COALESCE(SUM(`work_hours`) * 3600, 0) FROM `UserWorkLog` WHERE `user_id`=`users`.`id` - AND `work_timestamp` < ? + SELECT COALESCE(SUM(`hours`) * 3600, 0) + FROM `worklogs` WHERE `user_id`=`users`.`id` + AND `worked_at` <= NOW() )) AS `shift_length` ', $shift_sum_formula - ), - [time()] + ) ) ->leftJoin('ShiftEntry', 'users.id', '=', 'ShiftEntry.UID') ->leftJoin('Shifts', function ($join) use ($show_all_shifts) { diff --git a/includes/view/UserWorkLog_view.php b/includes/view/UserWorkLog_view.php index 879979ba..c0a841b8 100644 --- a/includes/view/UserWorkLog_view.php +++ b/includes/view/UserWorkLog_view.php @@ -1,6 +1,7 @@ worked_at->timestamp, null, time()), + form_text('work_hours', __('Work hours'), $userWorkLog->hours), + form_text('comment', __('Comment'), $userWorkLog->comment, false, 200), form_submit('submit', __('Save')) ]); } @@ -54,10 +55,10 @@ function UserWorkLog_edit_form($user_source, $userWorkLog) * Form for edit a user work log entry. * * @param User $user_source - * @param array $userWorkLog + * @param Worklog $userWorkLog * @return string */ -function UserWorkLog_edit_view($user_source, $userWorkLog) +function UserWorkLog_edit_view($user_source, Worklog $userWorkLog) { return page_with_title(UserWorkLog_edit_title(), [ buttons([ @@ -72,10 +73,10 @@ function UserWorkLog_edit_view($user_source, $userWorkLog) * Form for adding a user work log entry. * * @param User $user_source - * @param array $userWorkLog + * @param Worklog $userWorkLog * @return string */ -function UserWorkLog_add_view($user_source, $userWorkLog) +function UserWorkLog_add_view($user_source, Worklog $userWorkLog) { return page_with_title(UserWorkLog_add_title(), [ buttons([ diff --git a/includes/view/User_view.php b/includes/view/User_view.php index 6ca1e332..ce25749a 100644 --- a/includes/view/User_view.php +++ b/includes/view/User_view.php @@ -3,6 +3,8 @@ use Carbon\Carbon; use Engelsystem\Models\Room; use Engelsystem\Models\User\User; +use Engelsystem\Models\Worklog; +use Illuminate\Support\Collection; /** * Renders user settings page @@ -424,13 +426,14 @@ function User_view_myshift($shift, $user_source, $its_me) /** * Helper that prepares the shift table for user view * - * @param array[] $shifts - * @param User $user_source - * @param bool $its_me - * @param int $tshirt_score - * @param bool $tshirt_admin - * @param array[] $user_worklogs - * @param bool $admin_user_worklog_privilege + * @param array[] $shifts + * @param User $user_source + * @param bool $its_me + * @param int $tshirt_score + * @param bool $tshirt_admin + * @param Worklog[]|Collection $user_worklogs + * @param bool $admin_user_worklog_privilege + * * @return array */ function User_view_myshifts( @@ -455,9 +458,9 @@ function User_view_myshifts( if ($its_me || $admin_user_worklog_privilege) { foreach ($user_worklogs as $worklog) { - $key = $worklog['work_timestamp'] . '-worklog-' . $worklog['id']; + $key = $worklog->worked_at->timestamp . '-worklog-' . $worklog->id; $myshifts_table[$key] = User_view_worklog($worklog, $admin_user_worklog_privilege); - $timeSum += $worklog['work_hours'] * 3600; + $timeSum += $worklog->hours * 3600; } } @@ -488,11 +491,11 @@ function User_view_myshifts( /** * Renders table entry for user work log * - * @param array $worklog - * @param bool $admin_user_worklog_privilege + * @param Worklog $worklog + * @param bool $admin_user_worklog_privilege * @return array */ -function User_view_worklog($worklog, $admin_user_worklog_privilege) +function User_view_worklog(Worklog $worklog, $admin_user_worklog_privilege) { $actions = ''; if ($admin_user_worklog_privilege) { @@ -511,15 +514,15 @@ function User_view_worklog($worklog, $admin_user_worklog_privilege) } return [ - 'date' => glyph('calendar') . date('Y-m-d', $worklog['work_timestamp']), - 'duration' => sprintf('%.2f', $worklog['work_hours']) . ' h', + 'date' => glyph('calendar') . date('Y-m-d', $worklog->worked_at->timestamp), + 'duration' => sprintf('%.2f', $worklog->hours) . ' h', 'room' => '', 'shift_info' => __('Work log entry'), - 'comment' => $worklog['comment'] . '
' + 'comment' => $worklog->comment . '
' . sprintf( __('Added by %s at %s'), - User_Nick_render(User::find($worklog['created_user_id'])), - date('Y-m-d H:i', $worklog['created_timestamp']) + User_Nick_render($worklog->creator), + $worklog->created_at->format('Y-m-d H:i') ), 'actions' => $actions ]; @@ -528,17 +531,18 @@ function User_view_worklog($worklog, $admin_user_worklog_privilege) /** * Renders view for a single user * - * @param User $user_source - * @param bool $admin_user_privilege - * @param bool $freeloader - * @param array[] $user_angeltypes - * @param array[] $user_groups - * @param array[] $shifts - * @param bool $its_me - * @param int $tshirt_score - * @param bool $tshirt_admin - * @param bool $admin_user_worklog_privilege - * @param array[] $user_worklogs + * @param User $user_source + * @param bool $admin_user_privilege + * @param bool $freeloader + * @param array[] $user_angeltypes + * @param array[] $user_groups + * @param array[] $shifts + * @param bool $its_me + * @param int $tshirt_score + * @param bool $tshirt_admin + * @param bool $admin_user_worklog_privilege + * @param Worklog[]|Collection $user_worklogs + * * @return string */ function User_view( diff --git a/src/Controllers/Metrics/Stats.php b/src/Controllers/Metrics/Stats.php index bcaa234d..3c05457f 100644 --- a/src/Controllers/Metrics/Stats.php +++ b/src/Controllers/Metrics/Stats.php @@ -18,6 +18,7 @@ use Engelsystem\Models\User\PersonalData; use Engelsystem\Models\User\Settings; use Engelsystem\Models\User\State; use Engelsystem\Models\User\User; +use Engelsystem\Models\Worklog; use Illuminate\Database\Query\Builder as QueryBuilder; use Illuminate\Database\Query\Expression as QueryExpression; use Illuminate\Support\Collection; @@ -48,7 +49,7 @@ class Stats if (!is_null($working)) { // @codeCoverageIgnoreStart $query - ->leftJoin('UserWorkLog', 'UserWorkLog.user_id', '=', 'users_state.user_id') + ->leftJoin('worklogs', 'worklogs.user_id', '=', 'users_state.user_id') ->leftJoin('ShiftEntry', 'ShiftEntry.UID', '=', 'users_state.user_id') ->distinct(); @@ -57,14 +58,14 @@ class Stats if ($working) { $query ->whereNotNull('ShiftEntry.SID') - ->orWhereNotNull('UserWorkLog.work_hours'); + ->orWhereNotNull('worklogs.hours'); return; } $query ->whereNull('ShiftEntry.SID') - ->whereNull('UserWorkLog.work_hours'); + ->whereNull('worklogs.hours'); }); // @codeCoverageIgnoreEnd } @@ -213,7 +214,7 @@ class Stats } /** - * @param string $vehicle + * @param string|null $vehicle * @return int * @codeCoverageIgnore */ @@ -238,8 +239,6 @@ class Stats } /** - * The number of worked shifts - * * @param bool|null $done * @param bool|null $freeloaded * @@ -264,7 +263,7 @@ class Stats } /** - * The number of worked shifts + * The amount of worked seconds * * @param bool|null $done * @param bool|null $freeloaded @@ -328,24 +327,14 @@ class Stats return $return; } - /** - * @return QueryBuilder - * @codeCoverageIgnore - */ - protected function worklogSecondsQuery() - { - return $this - ->getQuery('UserWorkLog'); - } - /** * @return int * @codeCoverageIgnore */ public function worklogSeconds(): int { - return (int)$this->worklogSecondsQuery() - ->sum($this->raw('work_hours * 60 * 60')); + return (int)Worklog::query() + ->sum($this->raw('hours * 60 * 60')); } /** @@ -358,10 +347,10 @@ class Stats { return $this->getBuckets( $buckets, - $this->worklogSecondsQuery(), + Worklog::query(), 'user_id', - 'SUM(work_hours * 60 * 60)', - 'work_hours * 60 * 60' + 'SUM(hours * 60 * 60)', + 'hours * 60 * 60' ); } diff --git a/src/Models/User/User.php b/src/Models/User/User.php index 30d57c83..88283451 100644 --- a/src/Models/User/User.php +++ b/src/Models/User/User.php @@ -8,6 +8,7 @@ use Engelsystem\Models\Message; use Engelsystem\Models\News; use Engelsystem\Models\NewsComment; use Engelsystem\Models\Question; +use Engelsystem\Models\Worklog; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; @@ -29,8 +30,12 @@ use Illuminate\Database\Query\Builder as QueryBuilder; * @property-read QueryBuilder|State $state * @property-read Collection|News[] $news * @property-read Collection|NewsComment[] $newsComments + * @property-read Collection|Worklog[] $worklogs + * @property-read Collection|Worklog[] $worklogsCreated * @property-read int|null $news_count * @property-read int|null $news_comments_count + * @property-read int|null $worklogs_count + * @property-read int|null $worklogs_created_count * * @method static QueryBuilder|User[] whereId($value) * @method static QueryBuilder|User[] whereName($value) @@ -128,6 +133,22 @@ class User extends BaseModel return $this->hasMany(NewsComment::class); } + /** + * @return HasMany + */ + public function worklogs(): HasMany + { + return $this->hasMany(Worklog::class); + } + + /** + * @return HasMany + */ + public function worklogsCreated(): HasMany + { + return $this->hasMany(Worklog::class, 'creator_id'); + } + /** * @return HasMany */ diff --git a/src/Models/Worklog.php b/src/Models/Worklog.php new file mode 100644 index 00000000..cc290a09 --- /dev/null +++ b/src/Models/Worklog.php @@ -0,0 +1,62 @@ + 'integer', + 'creator_id' => 'integer', + ]; + + /** The attributes that are mass assignable. */ + protected $fillable = [ + 'user_id', + 'creator_id', + 'hours', + 'comment', + 'worked_at', + ]; + + /** + * @return BelongsTo + */ + public function creator(): BelongsTo + { + return $this->belongsTo(User::class, 'creator_id'); + } +} diff --git a/tests/Unit/Controllers/Metrics/StatsTest.php b/tests/Unit/Controllers/Metrics/StatsTest.php index f3f0058b..d8be170b 100644 --- a/tests/Unit/Controllers/Metrics/StatsTest.php +++ b/tests/Unit/Controllers/Metrics/StatsTest.php @@ -15,6 +15,7 @@ use Engelsystem\Models\User\PersonalData; use Engelsystem\Models\User\Settings; use Engelsystem\Models\User\State; use Engelsystem\Models\User\User; +use Engelsystem\Models\Worklog; use Engelsystem\Test\Unit\HasDatabase; use Engelsystem\Test\Unit\TestCase; use Illuminate\Support\Str; @@ -120,6 +121,28 @@ class StatsTest extends TestCase ], $themes->toArray()); } + /** + * @covers \Engelsystem\Controllers\Metrics\Stats::worklogSeconds + */ + public function testWorklogSeconds() + { + $this->addUsers(); + $worklogData = [ + 'user_id' => 1, + 'creator_id' => 1, + 'hours' => 2.4, + 'comment' => '', + 'worked_at' => new Carbon() + ]; + (new Worklog($worklogData))->save(); + (new Worklog(['hours' => 1.2, 'user_id' => 3] + $worklogData))->save(); + + $stats = new Stats($this->database); + $seconds = $stats->worklogSeconds(); + + $this->assertEquals(2.4 * 60 * 60 + 1.2 * 60 * 60, $seconds); + } + /** * @covers \Engelsystem\Controllers\Metrics\Stats::rooms */ diff --git a/tests/Unit/Models/User/UserTest.php b/tests/Unit/Models/User/UserTest.php index aa5d0369..dbb0f58d 100644 --- a/tests/Unit/Models/User/UserTest.php +++ b/tests/Unit/Models/User/UserTest.php @@ -2,6 +2,7 @@ namespace Engelsystem\Test\Unit\Models\User; +use Carbon\Carbon; use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts; use Engelsystem\Models\BaseModel; use Engelsystem\Models\News; @@ -13,6 +14,7 @@ use Engelsystem\Models\User\PersonalData; use Engelsystem\Models\User\Settings; use Engelsystem\Models\User\State; use Engelsystem\Models\User\User; +use Engelsystem\Models\Worklog; use Engelsystem\Test\Unit\Models\ModelTest; use Exception; use Illuminate\Support\Str; @@ -163,6 +165,46 @@ class UserTest extends ModelTest $this->assertSame($newsComment->id, $comment->id); } + /** + * @covers \Engelsystem\Models\User\User::worklogs + */ + public function testWorklogs(): void + { + ($user = new User($this->data))->save(); + $worklogEntry = Worklog::create([ + 'user_id' => $user->id, + 'creator_id' => $user->id, + 'hours' => 1, + 'comment' => '', + 'worked_at' => Carbon::now(), + ]); + + $worklogs = $user->worklogs; + $this->assertCount(1, $worklogs); + $worklog = $worklogs->first(); + $this->assertSame($worklogEntry->id, $worklog->id); + } + + /** + * @covers \Engelsystem\Models\User\User::worklogsCreated + */ + public function testWorklogsCreated(): void + { + ($user = new User($this->data))->save(); + $worklogEntry = Worklog::create([ + 'user_id' => $user->id, + 'creator_id' => $user->id, + 'hours' => 1, + 'comment' => '', + 'worked_at' => Carbon::now(), + ]); + + $worklogs = $user->worklogsCreated; + $this->assertCount(1, $worklogs); + $worklog = $worklogs->first(); + $this->assertSame($worklogEntry->id, $worklog->id); + } + /** * @covers \Engelsystem\Models\User\User::questionsAsked */ diff --git a/tests/Unit/Models/WorklogTest.php b/tests/Unit/Models/WorklogTest.php new file mode 100644 index 00000000..a062bf00 --- /dev/null +++ b/tests/Unit/Models/WorklogTest.php @@ -0,0 +1,42 @@ + 'user1', + 'password' => '', + 'email' => 'user1@example.com', + 'api_key' => '', + ]); + $user2 = User::create([ + 'name' => 'user2', + 'password' => '', + 'email' => 'user2@example.com', + 'api_key' => '', + ]); + + $worklog = new Worklog(); + $worklog->user()->associate($user1); + $worklog->creator()->associate($user2); + $worklog->hours = 4.2; + $worklog->comment = 'Lorem ipsum'; + $worklog->worked_at = new Carbon(); + $worklog->save(); + + $savedWorklog = Worklog::first(); + $this->assertEquals($user2->name, $savedWorklog->creator->name); + } +}