Added Worklog model

This commit is contained in:
Igor Scheller 2020-09-12 19:45:25 +02:00 committed by msquare
parent acf84f222d
commit f732a4af6f
13 changed files with 456 additions and 227 deletions

View File

@ -0,0 +1,106 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Carbon\Carbon;
use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\Worklog;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreateWorklogsTable extends Migration
{
use ChangesReferences;
use Reference;
/**
* Run the migration
*/
public function up(): void
{
$this->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');
}
}

View File

@ -1,6 +1,7 @@
<?php <?php
use Engelsystem\Models\User\User; use Engelsystem\Models\User\User;
use Engelsystem\Models\Worklog;
/** /**
* Delete a work log entry. * Delete a work log entry.
@ -10,11 +11,11 @@ use Engelsystem\Models\User\User;
function user_worklog_delete_controller() function user_worklog_delete_controller()
{ {
$request = request(); $request = request();
$userWorkLog = UserWorkLog($request->input('user_worklog_id')); $userWorkLog = Worklog::find($request->input('user_worklog_id'));
if (empty($userWorkLog)) { if (empty($userWorkLog)) {
throw_redirect(user_link(auth()->user()->id)); throw_redirect(user_link(auth()->user()->id));
} }
$user_source = User::find($userWorkLog['user_id']); $user_source = $userWorkLog->user;
if ($request->hasPostData('submit')) { if ($request->hasPostData('submit')) {
UserWorkLog_delete($userWorkLog); UserWorkLog_delete($userWorkLog);
@ -37,17 +38,24 @@ function user_worklog_delete_controller()
function user_worklog_edit_controller() function user_worklog_edit_controller()
{ {
$request = request(); $request = request();
$userWorkLog = UserWorkLog($request->input('user_worklog_id')); $userWorkLog = Worklog::find($request->input('user_worklog_id'));
if (empty($userWorkLog)) { if (empty($userWorkLog)) {
throw_redirect(user_link(auth()->user()->id)); throw_redirect(user_link(auth()->user()->id));
} }
$user_source = User::find($userWorkLog['user_id']); $user_source = $userWorkLog->user;
if ($request->hasPostData('submit')) { if ($request->hasPostData('submit')) {
list ($valid, $userWorkLog) = user_worklog_from_request($userWorkLog); list ($valid, $userWorkLog) = user_worklog_from_request($userWorkLog);
if ($valid) { 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.')); success(__('Work log entry updated.'));
throw_redirect(user_link($user_source->id)); throw_redirect(user_link($user_source->id));
@ -63,44 +71,41 @@ function user_worklog_edit_controller()
/** /**
* Handle form * Handle form
* *
* @param array $userWorkLog * @param Worklog $worklog
* @return array [bool $valid, UserWorkLog $userWorkLog] * @return bool[]|Worklog[] [bool $valid, Worklog $userWorkLog]
*/ */
function user_worklog_from_request($userWorkLog) function user_worklog_from_request(Worklog $worklog)
{ {
$request = request(); $request = request();
$valid = true; $valid = true;
$userWorkLog['work_timestamp'] = parse_date( $worklog->worked_at = DateTime::createFromFormat('Y-m-d H:i', $request->input('work_timestamp') . ' 00:00');
'Y-m-d H:i', if (!$worklog->worked_at) {
$request->input('work_timestamp') . ' 00:00'
);
if (is_null($userWorkLog['work_timestamp'])) {
$valid = false; $valid = false;
error(__('Please enter work date.')); error(__('Please enter work date.'));
} }
$userWorkLog['work_hours'] = $request->input('work_hours'); $worklog->hours = $request->input('work_hours');
if (!preg_match("/^[0-9]+(\.[0-9]+)?$/", $userWorkLog['work_hours'])) { if (!preg_match("/^[0-9]+(\.[0-9]{0,2})?$/", $worklog->hours)) {
$valid = false; $valid = false;
error(__('Please enter work hours in format ##[.##].')); error(__('Please enter work hours in format ##[.##].'));
} }
$userWorkLog['comment'] = $request->input('comment'); $worklog->comment = $request->input('comment');
if (empty($userWorkLog['comment'])) { if (empty($worklog->comment)) {
$valid = false; $valid = false;
error(__('Please enter a comment.')); error(__('Please enter a comment.'));
} }
if (mb_strlen($userWorkLog['comment']) > 200) { if (mb_strlen($worklog->comment) > 200) {
$valid = false; $valid = false;
error(__('Comment too long.')); error(__('Comment too long.'));
} }
return [ return [
$valid, $valid,
$userWorkLog $worklog
]; ];
} }
@ -143,7 +148,7 @@ function user_worklog_add_controller()
* *
* @return string * @return string
*/ */
function user_worklog_add_link($user) function user_worklog_add_link(User $user)
{ {
return page_link_to('user_worklog', [ return page_link_to('user_worklog', [
'action' => 'add', 'action' => 'add',
@ -154,29 +159,29 @@ function user_worklog_add_link($user)
/** /**
* Link to work log entry edit. * Link to work log entry edit.
* *
* @param array $userWorkLog * @param Worklog $userWorkLog
* @return string * @return string
*/ */
function user_worklog_edit_link($userWorkLog) function user_worklog_edit_link(Worklog $userWorkLog)
{ {
return page_link_to('user_worklog', [ return page_link_to('user_worklog', [
'action' => 'edit', 'action' => 'edit',
'user_worklog_id' => $userWorkLog['id'] 'user_worklog_id' => $userWorkLog->id
]); ]);
} }
/** /**
* Link to work log entry delete. * Link to work log entry delete.
* *
* @param array $userWorkLog * @param Worklog $userWorkLog
* @param array[] $parameters * @param array[] $parameters
* @return string * @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([ return page_link_to('user_worklog', array_merge([
'action' => 'delete', 'action' => 'delete',
'user_worklog_id' => $userWorkLog['id'] 'user_worklog_id' => $userWorkLog->id
], $parameters)); ], $parameters));
} }
@ -207,4 +212,6 @@ function user_worklog_controller()
case 'delete': case 'delete':
return user_worklog_delete_controller(); return user_worklog_delete_controller();
} }
return ['', ''];
} }

View File

@ -1,133 +1,67 @@
<?php <?php
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Database\Db;
use Engelsystem\Models\Room; use Engelsystem\Models\Room;
use Engelsystem\Models\User\User; use Engelsystem\Models\User\User;
use Engelsystem\Models\Worklog;
/** use Illuminate\Support\Collection;
* Load a single work log entry.
*
* @param int $user_worklog_id
* @return array|null
*/
function UserWorkLog($user_worklog_id)
{
$workLog = Db::selectOne("SELECT * FROM `UserWorkLog` WHERE `id`=?", [
$user_worklog_id
]);
return empty($workLog) ? null : $workLog;
}
/** /**
* Returns all work log entries for a user. * Returns all work log entries for a user.
* *
* @param int $userId * @param int $userId
* @param Carbon|null $sinceTime * @param Carbon|null $sinceTime
* @return array[] *
* @return Worklog[]|Collection
*/ */
function UserWorkLogsForUser($userId, Carbon $sinceTime = null) function UserWorkLogsForUser($userId, Carbon $sinceTime = null)
{ {
return Db::select( $worklogs = Worklog::whereUserId($userId);
' if ($sinceTime) {
SELECT * $worklogs = $worklogs->whereDate('worked_at', '>=', $sinceTime);
FROM `UserWorkLog` }
WHERE `user_id`=?
' . ($sinceTime ? 'AND work_timestamp >= ' . $sinceTime->getTimestamp() : '') . ' return $worklogs->get();
ORDER BY `created_timestamp`
',
[
$userId
]
);
} }
/** /**
* Delete a work log entry. * Delete a work log entry.
* *
* @param $userWorkLog * @param Worklog $userWorkLog
* @return int * @return int
*/ */
function UserWorkLog_delete($userWorkLog) function UserWorkLog_delete(Worklog $userWorkLog)
{ {
$user_source = User::find($userWorkLog['user_id']); $result = $userWorkLog->delete();
$result = Db::delete("DELETE FROM `UserWorkLog` WHERE `id`=?", [
$userWorkLog['id']
]);
engelsystem_log(sprintf( engelsystem_log(sprintf(
'Delete work log for %s, %s hours, %s', 'Delete work log for %s, %s hours, %s',
User_Nick_render($user_source, true), User_Nick_render($userWorkLog->user, true),
$userWorkLog['work_hours'], $userWorkLog->hours,
$userWorkLog['comment'] $userWorkLog->comment
)); ));
return $result; 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 * Create a new work log entry
* *
* @param $userWorkLog * @param Worklog $userWorkLog
* @return bool * @return bool
*/ */
function UserWorkLog_create($userWorkLog) function UserWorkLog_create(Worklog $userWorkLog)
{ {
$user = auth()->user(); $user = auth()->user();
$userWorkLog->creator()->associate($user);
$result = $userWorkLog->save();
$user_source = User::find($userWorkLog['user_id']); engelsystem_log(sprintf(
'Added work log entry for %s, %s hours, %s',
$result = Db::insert("INSERT INTO `UserWorkLog` ( User_Nick_render($userWorkLog->user, true),
`user_id`, $userWorkLog->hours,
`work_timestamp`, $userWorkLog->comment
`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']));
return $result; return $result;
} }
@ -165,11 +99,9 @@ function UserWorkLog_from_shift($shift)
$nightShiftMultiplier = $nightShifts['multiplier']; $nightShiftMultiplier = $nightShifts['multiplier'];
} }
UserWorkLog_create([ $worklog = UserWorkLog_new($entry['UID']);
'user_id' => $entry['UID'], $worklog->hours = (($shift['end'] - $shift['start']) / 60 / 60) * $nightShiftMultiplier;
'work_timestamp' => $shift['start'], $worklog->comment = sprintf(
'work_hours' => (($shift['end'] - $shift['start']) / 60 / 60) * $nightShiftMultiplier,
'comment' => sprintf(
'%s (%s as %s) in %s, %s-%s', '%s (%s as %s) in %s, %s-%s',
$shift['name'], $shift['name'],
$shift['title'], $shift['title'],
@ -177,8 +109,10 @@ function UserWorkLog_from_shift($shift)
$room->name, $room->name,
Carbon::createFromTimestamp($shift['start'])->format(__('m/d/Y h:i a')), Carbon::createFromTimestamp($shift['start'])->format(__('m/d/Y h:i a')),
Carbon::createFromTimestamp($shift['end'])->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 * New user work log entry
* *
* @param int $userId * @param int $userId
* @return array * @return Worklog
*/ */
function UserWorkLog_new($userId) function UserWorkLog_new($userId)
{ {
$work_date = parse_date('Y-m-d H:i', date('Y-m-d 00:00', time()));
/** @var Carbon $buildup */ /** @var Carbon $buildup */
$buildup = config('buildup_start'); $buildup = config('buildup_start');
$work_date = Carbon::today();
if (!empty($buildup)) { if (!empty($buildup)) {
$work_date = $buildup->format('Y-m-d H:i'); $work_date = $buildup;
} }
return [ $work_date
'user_id' => $userId, ->setHour(0)
'work_timestamp' => $work_date, ->setMinute(0)
'work_hours' => 0, ->setSecond(0);
'comment' => ''
]; $worklog = new Worklog();
$worklog->user_id = $userId;
$worklog->worked_at = $work_date;
return $worklog;
} }

View File

@ -3,8 +3,10 @@
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Database\DB; use Engelsystem\Database\DB;
use Engelsystem\Models\User\User; use Engelsystem\Models\User\User;
use Engelsystem\Models\Worklog;
use Engelsystem\ValidationResult; use Engelsystem\ValidationResult;
use Illuminate\Database\Query\JoinClause; use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;
/** /**
* User model * User model
@ -35,21 +37,12 @@ function User_tshirt_score($userId)
$result_shifts = ['tshirt_score' => 0]; $result_shifts = ['tshirt_score' => 0];
} }
$result_worklog = DB::selectOne(' $worklogHours = Worklog::query()
SELECT SUM(`work_hours`) AS `tshirt_score` ->where('user_id', $userId)
FROM `users` ->where('worked_at', '<=', Carbon::Now())
LEFT JOIN `UserWorkLog` ON `users`.`id` = `UserWorkLog`.`user_id` ->sum('hours');
WHERE `users`.`id` = ?
AND `UserWorkLog`.`work_timestamp` < ?
', [
$userId,
time()
]);
if (!isset($result_worklog['tshirt_score'])) {
$result_worklog = ['tshirt_score' => 0];
}
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. * Returns all users that are not member of given angeltype.
* *
* @param array $angeltype Angeltype * @param array $angeltype Angeltype
* @return User[] *
* @return User[]|Collection
*/ */
function Users_by_angeltype_inverted($angeltype) function Users_by_angeltype_inverted($angeltype)
{ {
@ -88,7 +82,7 @@ function Users_by_angeltype_inverted($angeltype)
* Returns all members of given angeltype. * Returns all members of given angeltype.
* *
* @param array $angeltype * @param array $angeltype
* @return User[] * @return User[]|Collection
*/ */
function Users_by_angeltype($angeltype) function Users_by_angeltype($angeltype)
{ {
@ -241,14 +235,14 @@ function User_get_eligable_voucher_count($user)
$worklog = UserWorkLogsForUser($user->id, $start); $worklog = UserWorkLogsForUser($user->id, $start);
$shifts_done = $shifts_done =
count($shifts) count($shifts)
+ count($worklog); + $worklog->count();
$shiftsTime = 0; $shiftsTime = 0;
foreach ($shifts as $shift){ foreach ($shifts as $shift){
$shiftsTime += ($shift['end'] - $shift['start']) / 60 / 60; $shiftsTime += ($shift['end'] - $shift['start']) / 60 / 60;
} }
foreach ($worklog as $entry){ foreach ($worklog as $entry){
$shiftsTime += $entry['work_hours']; $shiftsTime += $entry->hours;
} }
$vouchers = $voucher_settings['initial_vouchers']; $vouchers = $voucher_settings['initial_vouchers'];

View File

@ -62,13 +62,13 @@ function admin_active()
users.*, users.*,
COUNT(ShiftEntry.id) AS shift_count, COUNT(ShiftEntry.id) AS shift_count,
(%s + ( (%s + (
SELECT COALESCE(SUM(`work_hours`) * 3600, 0) FROM `UserWorkLog` WHERE `user_id`=`users`.`id` SELECT COALESCE(SUM(`hours`) * 3600, 0)
AND `work_timestamp` < ? FROM `worklogs` WHERE `user_id`=`users`.`id`
AND `worked_at` <= NOW()
)) AS `shift_length` )) AS `shift_length`
', ',
$shift_sum_formula $shift_sum_formula
), )
[time()]
) )
->leftJoin('ShiftEntry', 'users.id', '=', 'ShiftEntry.UID') ->leftJoin('ShiftEntry', 'users.id', '=', 'ShiftEntry.UID')
->leftJoin('Shifts', 'ShiftEntry.SID', '=', 'Shifts.SID') ->leftJoin('Shifts', 'ShiftEntry.SID', '=', 'Shifts.SID')
@ -156,13 +156,13 @@ function admin_active()
users.*, users.*,
COUNT(ShiftEntry.id) AS shift_count, COUNT(ShiftEntry.id) AS shift_count,
(%s + ( (%s + (
SELECT COALESCE(SUM(`work_hours`) * 3600, 0) FROM `UserWorkLog` WHERE `user_id`=`users`.`id` SELECT COALESCE(SUM(`hours`) * 3600, 0)
AND `work_timestamp` < ? FROM `worklogs` WHERE `user_id`=`users`.`id`
AND `worked_at` <= NOW()
)) AS `shift_length` )) AS `shift_length`
', ',
$shift_sum_formula $shift_sum_formula
), )
[time()]
) )
->leftJoin('ShiftEntry', 'users.id', '=', 'ShiftEntry.UID') ->leftJoin('ShiftEntry', 'users.id', '=', 'ShiftEntry.UID')
->leftJoin('Shifts', function ($join) use ($show_all_shifts) { ->leftJoin('Shifts', function ($join) use ($show_all_shifts) {

View File

@ -1,6 +1,7 @@
<?php <?php
use Engelsystem\Models\User\User; use Engelsystem\Models\User\User;
use Engelsystem\Models\Worklog;
/** /**
* Delete work log entry. * Delete work log entry.
@ -36,16 +37,16 @@ function UserWorkLog_delete_title()
* Render edit table. * Render edit table.
* *
* @param User $user_source * @param User $user_source
* @param array $userWorkLog * @param Worklog $userWorkLog
* @return string * @return string
*/ */
function UserWorkLog_edit_form($user_source, $userWorkLog) function UserWorkLog_edit_form($user_source, Worklog $userWorkLog)
{ {
return form([ return form([
form_info(__('User'), User_Nick_render($user_source)), form_info(__('User'), User_Nick_render($user_source)),
form_date('work_timestamp', __('Work date'), $userWorkLog['work_timestamp'], null, time()), form_date('work_timestamp', __('Work date'), $userWorkLog->worked_at->timestamp, null, time()),
form_text('work_hours', __('Work hours'), $userWorkLog['work_hours']), form_text('work_hours', __('Work hours'), $userWorkLog->hours),
form_text('comment', __('Comment'), $userWorkLog['comment'], false, 200), form_text('comment', __('Comment'), $userWorkLog->comment, false, 200),
form_submit('submit', __('Save')) form_submit('submit', __('Save'))
]); ]);
} }
@ -54,10 +55,10 @@ function UserWorkLog_edit_form($user_source, $userWorkLog)
* Form for edit a user work log entry. * Form for edit a user work log entry.
* *
* @param User $user_source * @param User $user_source
* @param array $userWorkLog * @param Worklog $userWorkLog
* @return string * @return string
*/ */
function UserWorkLog_edit_view($user_source, $userWorkLog) function UserWorkLog_edit_view($user_source, Worklog $userWorkLog)
{ {
return page_with_title(UserWorkLog_edit_title(), [ return page_with_title(UserWorkLog_edit_title(), [
buttons([ buttons([
@ -72,10 +73,10 @@ function UserWorkLog_edit_view($user_source, $userWorkLog)
* Form for adding a user work log entry. * Form for adding a user work log entry.
* *
* @param User $user_source * @param User $user_source
* @param array $userWorkLog * @param Worklog $userWorkLog
* @return string * @return string
*/ */
function UserWorkLog_add_view($user_source, $userWorkLog) function UserWorkLog_add_view($user_source, Worklog $userWorkLog)
{ {
return page_with_title(UserWorkLog_add_title(), [ return page_with_title(UserWorkLog_add_title(), [
buttons([ buttons([

View File

@ -3,6 +3,8 @@
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Models\Room; use Engelsystem\Models\Room;
use Engelsystem\Models\User\User; use Engelsystem\Models\User\User;
use Engelsystem\Models\Worklog;
use Illuminate\Support\Collection;
/** /**
* Renders user settings page * Renders user settings page
@ -429,8 +431,9 @@ function User_view_myshift($shift, $user_source, $its_me)
* @param bool $its_me * @param bool $its_me
* @param int $tshirt_score * @param int $tshirt_score
* @param bool $tshirt_admin * @param bool $tshirt_admin
* @param array[] $user_worklogs * @param Worklog[]|Collection $user_worklogs
* @param bool $admin_user_worklog_privilege * @param bool $admin_user_worklog_privilege
*
* @return array * @return array
*/ */
function User_view_myshifts( function User_view_myshifts(
@ -455,9 +458,9 @@ function User_view_myshifts(
if ($its_me || $admin_user_worklog_privilege) { if ($its_me || $admin_user_worklog_privilege) {
foreach ($user_worklogs as $worklog) { 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); $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 * Renders table entry for user work log
* *
* @param array $worklog * @param Worklog $worklog
* @param bool $admin_user_worklog_privilege * @param bool $admin_user_worklog_privilege
* @return array * @return array
*/ */
function User_view_worklog($worklog, $admin_user_worklog_privilege) function User_view_worklog(Worklog $worklog, $admin_user_worklog_privilege)
{ {
$actions = ''; $actions = '';
if ($admin_user_worklog_privilege) { if ($admin_user_worklog_privilege) {
@ -511,15 +514,15 @@ function User_view_worklog($worklog, $admin_user_worklog_privilege)
} }
return [ return [
'date' => glyph('calendar') . date('Y-m-d', $worklog['work_timestamp']), 'date' => glyph('calendar') . date('Y-m-d', $worklog->worked_at->timestamp),
'duration' => sprintf('%.2f', $worklog['work_hours']) . ' h', 'duration' => sprintf('%.2f', $worklog->hours) . ' h',
'room' => '', 'room' => '',
'shift_info' => __('Work log entry'), 'shift_info' => __('Work log entry'),
'comment' => $worklog['comment'] . '<br>' 'comment' => $worklog->comment . '<br>'
. sprintf( . sprintf(
__('Added by %s at %s'), __('Added by %s at %s'),
User_Nick_render(User::find($worklog['created_user_id'])), User_Nick_render($worklog->creator),
date('Y-m-d H:i', $worklog['created_timestamp']) $worklog->created_at->format('Y-m-d H:i')
), ),
'actions' => $actions 'actions' => $actions
]; ];
@ -538,7 +541,8 @@ function User_view_worklog($worklog, $admin_user_worklog_privilege)
* @param int $tshirt_score * @param int $tshirt_score
* @param bool $tshirt_admin * @param bool $tshirt_admin
* @param bool $admin_user_worklog_privilege * @param bool $admin_user_worklog_privilege
* @param array[] $user_worklogs * @param Worklog[]|Collection $user_worklogs
*
* @return string * @return string
*/ */
function User_view( function User_view(

View File

@ -18,6 +18,7 @@ use Engelsystem\Models\User\PersonalData;
use Engelsystem\Models\User\Settings; use Engelsystem\Models\User\Settings;
use Engelsystem\Models\User\State; use Engelsystem\Models\User\State;
use Engelsystem\Models\User\User; use Engelsystem\Models\User\User;
use Engelsystem\Models\Worklog;
use Illuminate\Database\Query\Builder as QueryBuilder; use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Database\Query\Expression as QueryExpression; use Illuminate\Database\Query\Expression as QueryExpression;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -48,7 +49,7 @@ class Stats
if (!is_null($working)) { if (!is_null($working)) {
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
$query $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') ->leftJoin('ShiftEntry', 'ShiftEntry.UID', '=', 'users_state.user_id')
->distinct(); ->distinct();
@ -57,14 +58,14 @@ class Stats
if ($working) { if ($working) {
$query $query
->whereNotNull('ShiftEntry.SID') ->whereNotNull('ShiftEntry.SID')
->orWhereNotNull('UserWorkLog.work_hours'); ->orWhereNotNull('worklogs.hours');
return; return;
} }
$query $query
->whereNull('ShiftEntry.SID') ->whereNull('ShiftEntry.SID')
->whereNull('UserWorkLog.work_hours'); ->whereNull('worklogs.hours');
}); });
// @codeCoverageIgnoreEnd // @codeCoverageIgnoreEnd
} }
@ -213,7 +214,7 @@ class Stats
} }
/** /**
* @param string $vehicle * @param string|null $vehicle
* @return int * @return int
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
@ -238,8 +239,6 @@ class Stats
} }
/** /**
* The number of worked shifts
*
* @param bool|null $done * @param bool|null $done
* @param bool|null $freeloaded * @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 $done
* @param bool|null $freeloaded * @param bool|null $freeloaded
@ -328,24 +327,14 @@ class Stats
return $return; return $return;
} }
/**
* @return QueryBuilder
* @codeCoverageIgnore
*/
protected function worklogSecondsQuery()
{
return $this
->getQuery('UserWorkLog');
}
/** /**
* @return int * @return int
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
public function worklogSeconds(): int public function worklogSeconds(): int
{ {
return (int)$this->worklogSecondsQuery() return (int)Worklog::query()
->sum($this->raw('work_hours * 60 * 60')); ->sum($this->raw('hours * 60 * 60'));
} }
/** /**
@ -358,10 +347,10 @@ class Stats
{ {
return $this->getBuckets( return $this->getBuckets(
$buckets, $buckets,
$this->worklogSecondsQuery(), Worklog::query(),
'user_id', 'user_id',
'SUM(work_hours * 60 * 60)', 'SUM(hours * 60 * 60)',
'work_hours * 60 * 60' 'hours * 60 * 60'
); );
} }

View File

@ -8,6 +8,7 @@ use Engelsystem\Models\Message;
use Engelsystem\Models\News; use Engelsystem\Models\News;
use Engelsystem\Models\NewsComment; use Engelsystem\Models\NewsComment;
use Engelsystem\Models\Question; use Engelsystem\Models\Question;
use Engelsystem\Models\Worklog;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\Relations\HasOne;
@ -29,8 +30,12 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
* @property-read QueryBuilder|State $state * @property-read QueryBuilder|State $state
* @property-read Collection|News[] $news * @property-read Collection|News[] $news
* @property-read Collection|NewsComment[] $newsComments * @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_count
* @property-read int|null $news_comments_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[] whereId($value)
* @method static QueryBuilder|User[] whereName($value) * @method static QueryBuilder|User[] whereName($value)
@ -128,6 +133,22 @@ class User extends BaseModel
return $this->hasMany(NewsComment::class); 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 * @return HasMany
*/ */

62
src/Models/Worklog.php Normal file
View File

@ -0,0 +1,62 @@
<?php
namespace Engelsystem\Models;
use Carbon\Carbon;
use Engelsystem\Models\User\User;
use Engelsystem\Models\User\UsesUserModel;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Query\Builder as QueryBuilder;
/**
* @property int $id
* @property int $creator_id
* @property float $hours
* @property string $comment
* @property Carbon $worked_at
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
*
* @property-read User $creator
*
* @method static QueryBuilder|Worklog[] whereId($value)
* @method static QueryBuilder|Worklog[] whereCreatorId($value)
* @method static QueryBuilder|Worklog[] whereWorkedAt($value)
* @method static QueryBuilder|Worklog[] whereHours($value)
* @method static QueryBuilder|Worklog[] whereComment($value)
*/
class Worklog extends BaseModel
{
use UsesUserModel;
/** @var bool Enable timestamps */
public $timestamps = true;
/** @var array The attributes that should be mutated to dates */
protected $dates = [
'worked_at',
];
/** @var string[] */
protected $casts = [
'user_id' => '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');
}
}

View File

@ -15,6 +15,7 @@ use Engelsystem\Models\User\PersonalData;
use Engelsystem\Models\User\Settings; use Engelsystem\Models\User\Settings;
use Engelsystem\Models\User\State; use Engelsystem\Models\User\State;
use Engelsystem\Models\User\User; use Engelsystem\Models\User\User;
use Engelsystem\Models\Worklog;
use Engelsystem\Test\Unit\HasDatabase; use Engelsystem\Test\Unit\HasDatabase;
use Engelsystem\Test\Unit\TestCase; use Engelsystem\Test\Unit\TestCase;
use Illuminate\Support\Str; use Illuminate\Support\Str;
@ -120,6 +121,28 @@ class StatsTest extends TestCase
], $themes->toArray()); ], $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 * @covers \Engelsystem\Controllers\Metrics\Stats::rooms
*/ */

View File

@ -2,6 +2,7 @@
namespace Engelsystem\Test\Unit\Models\User; namespace Engelsystem\Test\Unit\Models\User;
use Carbon\Carbon;
use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts; use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
use Engelsystem\Models\BaseModel; use Engelsystem\Models\BaseModel;
use Engelsystem\Models\News; use Engelsystem\Models\News;
@ -13,6 +14,7 @@ use Engelsystem\Models\User\PersonalData;
use Engelsystem\Models\User\Settings; use Engelsystem\Models\User\Settings;
use Engelsystem\Models\User\State; use Engelsystem\Models\User\State;
use Engelsystem\Models\User\User; use Engelsystem\Models\User\User;
use Engelsystem\Models\Worklog;
use Engelsystem\Test\Unit\Models\ModelTest; use Engelsystem\Test\Unit\Models\ModelTest;
use Exception; use Exception;
use Illuminate\Support\Str; use Illuminate\Support\Str;
@ -163,6 +165,46 @@ class UserTest extends ModelTest
$this->assertSame($newsComment->id, $comment->id); $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 * @covers \Engelsystem\Models\User\User::questionsAsked
*/ */

View File

@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Test\Unit\Models;
use Carbon\Carbon;
use Engelsystem\Models\Worklog;
use Engelsystem\Models\User\User;
class WorklogTest extends ModelTest
{
/**
* @covers \Engelsystem\Models\Worklog::creator
*/
public function testCreator(): void
{
$user1 = User::create([
'name' => '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);
}
}