Add ShiftEntry model
This commit is contained in:
parent
89f9b423b1
commit
89dc85c3d5
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories\Engelsystem\Models\Shifts;
|
||||||
|
|
||||||
|
use Engelsystem\Models\AngelType;
|
||||||
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
|
use Engelsystem\Models\User\User;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
class ShiftEntryFactory extends Factory
|
||||||
|
{
|
||||||
|
/** @var string */
|
||||||
|
protected $model = ShiftEntry::class; // phpcs:ignore
|
||||||
|
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
$freeloaded = $this->faker->optional(.01, false)->boolean();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'shift_id' => Shift::factory(),
|
||||||
|
'angel_type_id' => AngelType::factory(),
|
||||||
|
'user_id' => User::factory(),
|
||||||
|
'user_comment' => $this->faker->optional(.05, '')->text(),
|
||||||
|
'freeloaded' => $freeloaded,
|
||||||
|
'freeloaded_comment' => $freeloaded ? $this->faker->text() : '',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use stdClass;
|
||||||
|
|
||||||
|
class CreateShiftEntriesTable extends Migration
|
||||||
|
{
|
||||||
|
use ChangesReferences;
|
||||||
|
use Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the new table, copies the data and drops the old one
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$connection = $this->schema->getConnection();
|
||||||
|
$previous = $this->schema->hasTable('ShiftEntry');
|
||||||
|
|
||||||
|
$this->schema->create('shift_entries', function (Blueprint $table): void {
|
||||||
|
$table->increments('id');
|
||||||
|
$this->references($table, 'shifts');
|
||||||
|
$this->references($table, 'angel_types');
|
||||||
|
$this->referencesUser($table);
|
||||||
|
|
||||||
|
$table->mediumText('user_comment')->default('');
|
||||||
|
|
||||||
|
$table->boolean('freeloaded')->default(false)->index();
|
||||||
|
$table->mediumText('freeloaded_comment')->default('');
|
||||||
|
|
||||||
|
$table->index(['angel_type_id', 'shift_id']);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!$previous) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var stdClass[] $records */
|
||||||
|
$records = $connection
|
||||||
|
->table('ShiftEntry')
|
||||||
|
->get();
|
||||||
|
foreach ($records as $record) {
|
||||||
|
$connection->table('shift_entries')->insert([
|
||||||
|
'id' => $record->id,
|
||||||
|
'shift_id' => $record->SID,
|
||||||
|
'angel_type_id' => $record->TID,
|
||||||
|
'user_id' => $record->UID,
|
||||||
|
'user_comment' => $record->Comment,
|
||||||
|
'freeloaded' => (bool) $record->freeloaded,
|
||||||
|
'freeloaded_comment' => $record->freeload_comment,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->changeReferences(
|
||||||
|
'ShiftEntry',
|
||||||
|
'id',
|
||||||
|
'shift_entries',
|
||||||
|
'id'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->schema->drop('ShiftEntry');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recreates the previous table, copies the data and drops the new one
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$connection = $this->schema->getConnection();
|
||||||
|
|
||||||
|
$this->schema->create('ShiftEntry', function (Blueprint $table): void {
|
||||||
|
$table->increments('id');
|
||||||
|
$this->references($table, 'shifts', 'SID')->default(0);
|
||||||
|
$this->references($table, 'angel_types', 'TID')->default(0);
|
||||||
|
$this->references($table, 'users', 'UID')->default(0);
|
||||||
|
|
||||||
|
$table->mediumText('Comment')->nullable();
|
||||||
|
|
||||||
|
$table->mediumText('freeload_comment')->nullable()->default(null);
|
||||||
|
$table->boolean('freeloaded')->index();
|
||||||
|
|
||||||
|
$table->index(['SID', 'TID']);
|
||||||
|
});
|
||||||
|
|
||||||
|
/** @var stdClass[] $records */
|
||||||
|
$records = $connection
|
||||||
|
->table('shift_entries')
|
||||||
|
->get();
|
||||||
|
foreach ($records as $record) {
|
||||||
|
$connection->table('ShiftEntry')->insert([
|
||||||
|
'id' => $record->id,
|
||||||
|
'SID' => $record->shift_id,
|
||||||
|
'TID' => $record->angel_type_id,
|
||||||
|
'UID' => $record->user_id,
|
||||||
|
'Comment' => $record->user_comment,
|
||||||
|
'freeloaded' => (bool) $record->freeloaded,
|
||||||
|
'freeload_comment' => $record->freeloaded_comment,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->changeReferences(
|
||||||
|
'shift_entries',
|
||||||
|
'id',
|
||||||
|
'ShiftEntry',
|
||||||
|
'id'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->schema->drop('shift_entries');
|
||||||
|
}
|
||||||
|
}
|
|
@ -107,8 +107,8 @@ function public_dashboard_needed_angels($needed_angels, ShiftsFilter $filter = n
|
||||||
$result = [];
|
$result = [];
|
||||||
foreach ($needed_angels as $needed_angel) {
|
foreach ($needed_angels as $needed_angel) {
|
||||||
$need = $needed_angel['count'] - $needed_angel['taken'];
|
$need = $needed_angel['count'] - $needed_angel['taken'];
|
||||||
if ($need > 0 && (!$filter || in_array($needed_angel['TID'], $filter->getTypes()))) {
|
if ($need > 0 && (!$filter || in_array($needed_angel['angel_type_id'], $filter->getTypes()))) {
|
||||||
$angeltype = AngelType::find($needed_angel['TID']);
|
$angeltype = AngelType::find($needed_angel['angel_type_id']);
|
||||||
if ($angeltype->show_on_dashboard) {
|
if ($angeltype->show_on_dashboard) {
|
||||||
$result[] = [
|
$result[] = [
|
||||||
'need' => $need,
|
'need' => $need,
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use Engelsystem\Models\AngelType;
|
use Engelsystem\Models\AngelType;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Engelsystem\Models\User\User;
|
use Engelsystem\Models\User\User;
|
||||||
use Engelsystem\Models\UserAngelType;
|
use Engelsystem\Models\UserAngelType;
|
||||||
use Engelsystem\ShiftSignupState;
|
use Engelsystem\ShiftSignupState;
|
||||||
|
@ -27,7 +28,7 @@ function shift_entries_controller(): array
|
||||||
return match ($action) {
|
return match ($action) {
|
||||||
'create' => shift_entry_create_controller(),
|
'create' => shift_entry_create_controller(),
|
||||||
'delete' => shift_entry_delete_controller(),
|
'delete' => shift_entry_delete_controller(),
|
||||||
default => ['', ''],
|
default => ['', ''],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ function shift_entry_create_controller(): array
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$request = request();
|
$request = request();
|
||||||
|
|
||||||
if (User_is_freeloader($user)) {
|
if ($user->isFreeloader()) {
|
||||||
throw_redirect(page_link_to('user_myshifts'));
|
throw_redirect(page_link_to('user_myshifts'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,14 +100,12 @@ function shift_entry_create_controller_admin(Shift $shift, ?AngelType $angeltype
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->hasPostData('submit')) {
|
if ($request->hasPostData('submit')) {
|
||||||
ShiftEntry_create([
|
$shiftEntry = new ShiftEntry();
|
||||||
'SID' => $shift->id,
|
$shiftEntry->shift()->associate($shift);
|
||||||
'TID' => $angeltype->id,
|
$shiftEntry->angelType()->associate($angeltype);
|
||||||
'UID' => $signup_user->id,
|
$shiftEntry->user()->associate($signup_user);
|
||||||
'Comment' => '',
|
$shiftEntry->save();
|
||||||
'freeloaded' => false,
|
ShiftEntry_onCreate($shiftEntry);
|
||||||
'freeload_comment' => ''
|
|
||||||
]);
|
|
||||||
|
|
||||||
success(sprintf(__('%s has been subscribed to the shift.'), User_Nick_render($signup_user)));
|
success(sprintf(__('%s has been subscribed to the shift.'), User_Nick_render($signup_user)));
|
||||||
throw_redirect(shift_link($shift));
|
throw_redirect(shift_link($shift));
|
||||||
|
@ -150,14 +149,12 @@ function shift_entry_create_controller_supporter(Shift $shift, AngelType $angelt
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->hasPostData('submit')) {
|
if ($request->hasPostData('submit')) {
|
||||||
ShiftEntry_create([
|
$shiftEntry = new ShiftEntry();
|
||||||
'SID' => $shift->id,
|
$shiftEntry->shift()->associate($shift);
|
||||||
'TID' => $angeltype->id,
|
$shiftEntry->angelType()->associate($angeltype);
|
||||||
'UID' => $signup_user->id,
|
$shiftEntry->user()->associate($signup_user);
|
||||||
'Comment' => '',
|
$shiftEntry->save();
|
||||||
'freeloaded' => false,
|
ShiftEntry_onCreate($shiftEntry);
|
||||||
'freeload_comment' => ''
|
|
||||||
]);
|
|
||||||
|
|
||||||
success(sprintf(__('%s has been subscribed to the shift.'), User_Nick_render($signup_user)));
|
success(sprintf(__('%s has been subscribed to the shift.'), User_Nick_render($signup_user)));
|
||||||
throw_redirect(shift_link($shift));
|
throw_redirect(shift_link($shift));
|
||||||
|
@ -214,7 +211,9 @@ function shift_entry_create_controller_user(Shift $shift, AngelType $angeltype):
|
||||||
|
|
||||||
$signup_user = auth()->user();
|
$signup_user = auth()->user();
|
||||||
$needed_angeltype = (new AngelType())->forceFill(NeededAngeltype_by_Shift_and_Angeltype($shift, $angeltype));
|
$needed_angeltype = (new AngelType())->forceFill(NeededAngeltype_by_Shift_and_Angeltype($shift, $angeltype));
|
||||||
$shift_entries = ShiftEntries_by_shift_and_angeltype($shift->id, $angeltype->id);
|
$shift_entries = $shift->shiftEntries()
|
||||||
|
->where('angel_type_id', $angeltype->id)
|
||||||
|
->get();
|
||||||
$shift_signup_state = Shift_signup_allowed(
|
$shift_signup_state = Shift_signup_allowed(
|
||||||
$signup_user,
|
$signup_user,
|
||||||
$shift,
|
$shift,
|
||||||
|
@ -232,14 +231,14 @@ function shift_entry_create_controller_user(Shift $shift, AngelType $angeltype):
|
||||||
$comment = '';
|
$comment = '';
|
||||||
if ($request->hasPostData('submit')) {
|
if ($request->hasPostData('submit')) {
|
||||||
$comment = strip_request_item_nl('comment');
|
$comment = strip_request_item_nl('comment');
|
||||||
ShiftEntry_create([
|
|
||||||
'SID' => $shift->id,
|
$shiftEntry = new ShiftEntry();
|
||||||
'TID' => $angeltype->id,
|
$shiftEntry->shift()->associate($shift);
|
||||||
'UID' => $signup_user->id,
|
$shiftEntry->angelType()->associate($angeltype);
|
||||||
'Comment' => $comment,
|
$shiftEntry->user()->associate($signup_user);
|
||||||
'freeloaded' => false,
|
$shiftEntry->user_comment = $comment;
|
||||||
'freeload_comment' => ''
|
$shiftEntry->save();
|
||||||
]);
|
ShiftEntry_onCreate($shiftEntry);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!$angeltype->restricted
|
!$angeltype->restricted
|
||||||
|
@ -299,7 +298,7 @@ function shift_entry_create_link_admin(Shift $shift, $params = [])
|
||||||
/**
|
/**
|
||||||
* Load a shift entry from get parameter shift_entry_id.
|
* Load a shift entry from get parameter shift_entry_id.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return ShiftEntry
|
||||||
*/
|
*/
|
||||||
function shift_entry_load()
|
function shift_entry_load()
|
||||||
{
|
{
|
||||||
|
@ -308,11 +307,7 @@ function shift_entry_load()
|
||||||
if (!$request->has('shift_entry_id') || !test_request_int('shift_entry_id')) {
|
if (!$request->has('shift_entry_id') || !test_request_int('shift_entry_id')) {
|
||||||
throw_redirect(page_link_to('user_shifts'));
|
throw_redirect(page_link_to('user_shifts'));
|
||||||
}
|
}
|
||||||
$shiftEntry = ShiftEntry($request->input('shift_entry_id'));
|
$shiftEntry = ShiftEntry::findOrFail($request->input('shift_entry_id'));
|
||||||
if (empty($shiftEntry)) {
|
|
||||||
error(__('Shift entry not found.'));
|
|
||||||
throw_redirect(page_link_to('user_shifts'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $shiftEntry;
|
return $shiftEntry;
|
||||||
}
|
}
|
||||||
|
@ -328,9 +323,9 @@ function shift_entry_delete_controller()
|
||||||
$request = request();
|
$request = request();
|
||||||
$shiftEntry = shift_entry_load();
|
$shiftEntry = shift_entry_load();
|
||||||
|
|
||||||
$shift = Shift($shiftEntry['SID']);
|
$shift = Shift($shiftEntry->shift);
|
||||||
$angeltype = AngelType::find($shiftEntry['TID']);
|
$angeltype = $shiftEntry->angelType;
|
||||||
$signout_user = User::find($shiftEntry['UID']);
|
$signout_user = $shiftEntry->user;
|
||||||
if (!Shift_signout_allowed($shift, $angeltype, $signout_user->id)) {
|
if (!Shift_signout_allowed($shift, $angeltype, $signout_user->id)) {
|
||||||
error(__(
|
error(__(
|
||||||
'You are not allowed to remove this shift entry. If necessary, ask your supporter or heaven to do so.'
|
'You are not allowed to remove this shift entry. If necessary, ask your supporter or heaven to do so.'
|
||||||
|
@ -339,7 +334,8 @@ function shift_entry_delete_controller()
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->hasPostData('delete')) {
|
if ($request->hasPostData('delete')) {
|
||||||
ShiftEntry_delete($shiftEntry);
|
$shiftEntry->delete();
|
||||||
|
ShiftEntry_onDelete($shiftEntry);
|
||||||
success(__('Shift entry removed.'));
|
success(__('Shift entry removed.'));
|
||||||
throw_redirect(shift_link($shift));
|
throw_redirect(shift_link($shift));
|
||||||
}
|
}
|
||||||
|
@ -347,7 +343,7 @@ function shift_entry_delete_controller()
|
||||||
if ($user->id == $signout_user->id) {
|
if ($user->id == $signout_user->id) {
|
||||||
return [
|
return [
|
||||||
ShiftEntry_delete_title(),
|
ShiftEntry_delete_title(),
|
||||||
ShiftEntry_delete_view($shift, $angeltype, $signout_user->id)
|
ShiftEntry_delete_view($shift, $angeltype, $signout_user)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,8 +356,8 @@ function shift_entry_delete_controller()
|
||||||
/**
|
/**
|
||||||
* Link to delete a shift entry.
|
* Link to delete a shift entry.
|
||||||
*
|
*
|
||||||
* @param array|Shift $shiftEntry
|
* @param Shift|ShiftEntry $shiftEntry
|
||||||
* @param array $params
|
* @param array $params
|
||||||
* @return string URL
|
* @return string URL
|
||||||
*/
|
*/
|
||||||
function shift_entry_delete_link($shiftEntry, $params = [])
|
function shift_entry_delete_link($shiftEntry, $params = [])
|
||||||
|
|
|
@ -6,7 +6,6 @@ use Engelsystem\Models\AngelType;
|
||||||
use Engelsystem\Models\Shifts\ScheduleShift;
|
use Engelsystem\Models\Shifts\ScheduleShift;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
use Engelsystem\Models\Shifts\ShiftType;
|
use Engelsystem\Models\Shifts\ShiftType;
|
||||||
use Engelsystem\Models\User\User;
|
|
||||||
use Engelsystem\ShiftSignupState;
|
use Engelsystem\ShiftSignupState;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
@ -159,7 +158,6 @@ function shift_edit_controller()
|
||||||
$shift->updatedBy()->associate(auth()->user());
|
$shift->updatedBy()->associate(auth()->user());
|
||||||
|
|
||||||
// Remove merged data as it is not really part of the model and thus can't be saved
|
// Remove merged data as it is not really part of the model and thus can't be saved
|
||||||
unset($shift->shiftEntry);
|
|
||||||
unset($shift->neededAngels);
|
unset($shift->neededAngels);
|
||||||
|
|
||||||
$shift->save();
|
$shift->save();
|
||||||
|
@ -244,24 +242,23 @@ function shift_delete_controller()
|
||||||
|
|
||||||
// Schicht löschen bestätigt
|
// Schicht löschen bestätigt
|
||||||
if ($request->hasPostData('delete')) {
|
if ($request->hasPostData('delete')) {
|
||||||
foreach ($shift->shiftEntry as $entry) {
|
foreach ($shift->shiftEntries as $entry) {
|
||||||
$type = AngelType::find($entry['TID']);
|
|
||||||
event('shift.entry.deleting', [
|
event('shift.entry.deleting', [
|
||||||
'user' => User::find($entry['user_id']),
|
'user' => $entry->user,
|
||||||
'start' => $shift->start,
|
'start' => $shift->start,
|
||||||
'end' => $shift->end,
|
'end' => $shift->end,
|
||||||
'name' => $shift->shiftType->name,
|
'name' => $shift->shiftType->name,
|
||||||
'title' => $shift->title,
|
'title' => $shift->title,
|
||||||
'type' => $type->name,
|
'type' => $entry->angelType->name,
|
||||||
'room' => $shift->room,
|
'room' => $shift->room,
|
||||||
'freeloaded' => (bool) $entry['freeloaded'],
|
'freeloaded' => $entry->freeloaded,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$shift->delete();
|
$shift->delete();
|
||||||
|
|
||||||
engelsystem_log(
|
engelsystem_log(
|
||||||
'Deleted shift ' . $shift->title . ': ' . $shift->shiftType->name
|
'Deleted shift ' . $shift->title . ': ' . $shift->shiftType->name
|
||||||
. ' from ' . $shift->start->format('Y-m-d H:i')
|
. ' from ' . $shift->start->format('Y-m-d H:i')
|
||||||
. ' to ' . $shift->end->format('Y-m-d H:i')
|
. ' to ' . $shift->end->format('Y-m-d H:i')
|
||||||
);
|
);
|
||||||
|
@ -318,7 +315,9 @@ function shift_controller()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$shift_entries = ShiftEntries_by_shift_and_angeltype($shift->id, $angeltype->id);
|
$shift_entries = $shift->shiftEntries()
|
||||||
|
->where('angel_type_id', $angeltype->id)
|
||||||
|
->get();
|
||||||
$needed_angeltype = (new AngelType())->forceFill($needed_angeltype);
|
$needed_angeltype = (new AngelType())->forceFill($needed_angeltype);
|
||||||
|
|
||||||
$angeltype_signup_state = Shift_signup_allowed(
|
$angeltype_signup_state = Shift_signup_allowed(
|
||||||
|
@ -351,8 +350,8 @@ function shifts_controller()
|
||||||
}
|
}
|
||||||
|
|
||||||
return match ($request->input('action')) {
|
return match ($request->input('action')) {
|
||||||
'view' => shift_controller(),
|
'view' => shift_controller(),
|
||||||
'next' => shift_next_controller(), // throws redirect
|
'next' => shift_next_controller(), // throws redirect
|
||||||
default => throw_redirect(page_link_to('/')),
|
default => throw_redirect(page_link_to('/')),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -368,8 +367,8 @@ function shift_next_controller()
|
||||||
|
|
||||||
$upcoming_shifts = ShiftEntries_upcoming_for_user(auth()->user());
|
$upcoming_shifts = ShiftEntries_upcoming_for_user(auth()->user());
|
||||||
|
|
||||||
if (!empty($upcoming_shifts)) {
|
if (!$upcoming_shifts->isEmpty()) {
|
||||||
throw_redirect(shift_link($upcoming_shifts[0]));
|
throw_redirect(shift_link($upcoming_shifts[0]->shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
throw_redirect(page_link_to('user_shifts'));
|
throw_redirect(page_link_to('user_shifts'));
|
||||||
|
@ -406,41 +405,41 @@ function shifts_json_export_controller()
|
||||||
// See engelsystem-base/src/main/kotlin/info/metadude/kotlin/library/engelsystem/models/Shift.kt
|
// See engelsystem-base/src/main/kotlin/info/metadude/kotlin/library/engelsystem/models/Shift.kt
|
||||||
$data = [
|
$data = [
|
||||||
// Name of the shift (type)
|
// Name of the shift (type)
|
||||||
'name' => $shift->shiftType->name,
|
'name' => $shift->shiftType->name,
|
||||||
// Shift / Talk title
|
// Shift / Talk title
|
||||||
'title' => $shift->title,
|
'title' => $shift->title,
|
||||||
// Shift description
|
// Shift description
|
||||||
'description' => $shift->description,
|
'description' => $shift->description,
|
||||||
|
|
||||||
// Users comment
|
// Users comment
|
||||||
'Comment' => $shift->Comment,
|
'Comment' => $shift->user_comment,
|
||||||
|
|
||||||
// Shift id
|
// Shift id
|
||||||
'SID' => $shift->id,
|
'SID' => $shift->id,
|
||||||
// Shift type id
|
// Shift type id
|
||||||
'shifttype_id' => $shift->shift_type_id,
|
'shifttype_id' => $shift->shift_type_id,
|
||||||
// Talk URL
|
// Talk URL
|
||||||
'URL' => $shift->url,
|
'URL' => $shift->url,
|
||||||
|
|
||||||
// Room name
|
// Room name
|
||||||
'Name' => $shift->room->name,
|
'Name' => $shift->room->name,
|
||||||
// Location map url
|
// Location map url
|
||||||
'map_url' => $shift->room->map_url,
|
'map_url' => $shift->room->map_url,
|
||||||
|
|
||||||
// Start timestamp
|
// Start timestamp
|
||||||
/** @deprecated start_date should be used */
|
/** @deprecated start_date should be used */
|
||||||
'start' => $shift->start->timestamp,
|
'start' => $shift->start->timestamp,
|
||||||
// Start date
|
// Start date
|
||||||
'start_date' => $shift->start->toRfc3339String(),
|
'start_date' => $shift->start->toRfc3339String(),
|
||||||
// End timestamp
|
// End timestamp
|
||||||
/** @deprecated end_date should be used */
|
/** @deprecated end_date should be used */
|
||||||
'end' => $shift->end->timestamp,
|
'end' => $shift->end->timestamp,
|
||||||
// End date
|
// End date
|
||||||
'end_date' => $shift->end->toRfc3339String(),
|
'end_date' => $shift->end->toRfc3339String(),
|
||||||
|
|
||||||
// Timezone offset like "+01:00"
|
// Timezone offset like "+01:00"
|
||||||
/** @deprecated should be retrieved from start_date or end_date */
|
/** @deprecated should be retrieved from start_date or end_date */
|
||||||
'timezone' => $timeZone->toOffsetName(),
|
'timezone' => $timeZone->toOffsetName(),
|
||||||
// The events timezone like "Europe/Berlin"
|
// The events timezone like "Europe/Berlin"
|
||||||
'event_timezone' => $timeZone->getName(),
|
'event_timezone' => $timeZone->getName(),
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Engelsystem\Database\Db;
|
use Engelsystem\Database\Db;
|
||||||
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Engelsystem\Models\User\State;
|
use Engelsystem\Models\User\State;
|
||||||
use Engelsystem\Models\User\User;
|
use Engelsystem\Models\User\User;
|
||||||
use Engelsystem\ShiftCalendarRenderer;
|
use Engelsystem\ShiftCalendarRenderer;
|
||||||
|
@ -209,9 +210,9 @@ function user_controller()
|
||||||
$shift->needed_angeltypes = Db::select(
|
$shift->needed_angeltypes = Db::select(
|
||||||
'
|
'
|
||||||
SELECT DISTINCT `angel_types`.*
|
SELECT DISTINCT `angel_types`.*
|
||||||
FROM `ShiftEntry`
|
FROM `shift_entries`
|
||||||
JOIN `angel_types` ON `ShiftEntry`.`TID`=`angel_types`.`id`
|
JOIN `angel_types` ON `shift_entries`.`angel_type_id`=`angel_types`.`id`
|
||||||
WHERE `ShiftEntry`.`SID` = ?
|
WHERE `shift_entries`.`shift_id` = ?
|
||||||
ORDER BY `angel_types`.`name`
|
ORDER BY `angel_types`.`name`
|
||||||
',
|
',
|
||||||
[$shift->id]
|
[$shift->id]
|
||||||
|
@ -220,11 +221,11 @@ function user_controller()
|
||||||
foreach ($neededAngeltypes as &$needed_angeltype) {
|
foreach ($neededAngeltypes as &$needed_angeltype) {
|
||||||
$needed_angeltype['users'] = Db::select(
|
$needed_angeltype['users'] = Db::select(
|
||||||
'
|
'
|
||||||
SELECT `ShiftEntry`.`freeloaded`, `users`.*
|
SELECT `shift_entries`.`freeloaded`, `users`.*
|
||||||
FROM `ShiftEntry`
|
FROM `shift_entries`
|
||||||
JOIN `users` ON `ShiftEntry`.`UID`=`users`.`id`
|
JOIN `users` ON `shift_entries`.`user_id`=`users`.`id`
|
||||||
WHERE `ShiftEntry`.`SID` = ?
|
WHERE `shift_entries`.`shift_id` = ?
|
||||||
AND `ShiftEntry`.`TID` = ?
|
AND `shift_entries`.`angel_type_id` = ?
|
||||||
',
|
',
|
||||||
[$shift->id, $needed_angeltype['id']]
|
[$shift->id, $needed_angeltype['id']]
|
||||||
);
|
);
|
||||||
|
@ -247,7 +248,7 @@ function user_controller()
|
||||||
User_view(
|
User_view(
|
||||||
$user_source,
|
$user_source,
|
||||||
auth()->can('admin_user'),
|
auth()->can('admin_user'),
|
||||||
User_is_freeloader($user_source),
|
$user_source->isFreeloader(),
|
||||||
$user_source->userAngelTypes,
|
$user_source->userAngelTypes,
|
||||||
$user_source->groups,
|
$user_source->groups,
|
||||||
$shifts,
|
$shifts,
|
||||||
|
@ -300,7 +301,12 @@ function users_list_controller()
|
||||||
->orderBy('name')
|
->orderBy('name')
|
||||||
->get();
|
->get();
|
||||||
foreach ($users as $user) {
|
foreach ($users as $user) {
|
||||||
$user->setAttribute('freeloads', count(ShiftEntries_freeloaded_by_user($user->id)));
|
$user->setAttribute(
|
||||||
|
'freeloads',
|
||||||
|
$user->shiftEntries()
|
||||||
|
->where('freeloaded', true)
|
||||||
|
->count()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$users = $users->sortBy(function (User $user) use ($order_by) {
|
$users = $users->sortBy(function (User $user) use ($order_by) {
|
||||||
|
@ -321,7 +327,7 @@ function users_list_controller()
|
||||||
State::whereArrived(true)->count(),
|
State::whereArrived(true)->count(),
|
||||||
State::whereActive(true)->count(),
|
State::whereActive(true)->count(),
|
||||||
State::whereForceActive(true)->count(),
|
State::whereForceActive(true)->count(),
|
||||||
ShiftEntries_freeloaded_count(),
|
ShiftEntry::whereFreeloaded(true)->count(),
|
||||||
State::whereGotShirt(true)->count(),
|
State::whereGotShirt(true)->count(),
|
||||||
State::query()->sum('got_voucher')
|
State::query()->sum('got_voucher')
|
||||||
)
|
)
|
||||||
|
@ -360,6 +366,7 @@ function shiftCalendarRendererByShiftFilter(ShiftsFilter $shiftsFilter)
|
||||||
$shift_entries_source = ShiftEntries_by_ShiftsFilter($shiftsFilter);
|
$shift_entries_source = ShiftEntries_by_ShiftsFilter($shiftsFilter);
|
||||||
|
|
||||||
$needed_angeltypes = [];
|
$needed_angeltypes = [];
|
||||||
|
/** @var ShiftEntry[][] $shift_entries */
|
||||||
$shift_entries = [];
|
$shift_entries = [];
|
||||||
foreach ($shifts as $shift) {
|
foreach ($shifts as $shift) {
|
||||||
$needed_angeltypes[$shift->id] = [];
|
$needed_angeltypes[$shift->id] = [];
|
||||||
|
@ -367,8 +374,8 @@ function shiftCalendarRendererByShiftFilter(ShiftsFilter $shiftsFilter)
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($shift_entries_source as $shift_entry) {
|
foreach ($shift_entries_source as $shift_entry) {
|
||||||
if (isset($shift_entries[$shift_entry['SID']])) {
|
if (isset($shift_entries[$shift_entry->shift_id])) {
|
||||||
$shift_entries[$shift_entry['SID']][] = $shift_entry;
|
$shift_entries[$shift_entry->shift_id][] = $shift_entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,8 +410,8 @@ function shiftCalendarRendererByShiftFilter(ShiftsFilter $shiftsFilter)
|
||||||
|
|
||||||
foreach ($shift_entries[$shift->id] as $shift_entry) {
|
foreach ($shift_entries[$shift->id] as $shift_entry) {
|
||||||
if (
|
if (
|
||||||
$needed_angeltype['angel_type_id'] == $shift_entry['TID']
|
$needed_angeltype['angel_type_id'] == $shift_entry->angel_type_id
|
||||||
&& $shift_entry['freeloaded'] == 0
|
&& !$shift_entry->freeloaded
|
||||||
) {
|
) {
|
||||||
$taken++;
|
$taken++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Engelsystem\Models\User\User;
|
use Engelsystem\Models\User\User;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
function mail_shift_change(Shift $old_shift, Shift $new_shift)
|
function mail_shift_change(Shift $old_shift, Shift $new_shift)
|
||||||
{
|
{
|
||||||
$users = ShiftEntries_by_shift($old_shift->id);
|
/** @var ShiftEntry[]|Collection $shiftEntries */
|
||||||
|
$shiftEntries = $old_shift->shiftEntries()
|
||||||
|
->with(['user', 'user.settings'])
|
||||||
|
->get();
|
||||||
$old_room = $old_shift->room;
|
$old_room = $old_shift->room;
|
||||||
$new_room = $new_shift->room;
|
$new_room = $new_shift->room;
|
||||||
|
|
||||||
|
@ -65,8 +70,8 @@ function mail_shift_change(Shift $old_shift, Shift $new_shift)
|
||||||
$message .= $new_room->name . "\n\n";
|
$message .= $new_room->name . "\n\n";
|
||||||
$message .= url('/shifts', ['action' => 'view', 'shift_id' => $new_shift->id]) . "\n";
|
$message .= url('/shifts', ['action' => 'view', 'shift_id' => $new_shift->id]) . "\n";
|
||||||
|
|
||||||
foreach ($users as $user) {
|
foreach ($shiftEntries as $shiftEntry) {
|
||||||
$user = (new User())->forceFill($user);
|
$user = $shiftEntry->user;
|
||||||
if ($user->settings->email_shiftinfo) {
|
if ($user->settings->email_shiftinfo) {
|
||||||
engelsystem_email_to_user(
|
engelsystem_email_to_user(
|
||||||
$user,
|
$user,
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Engelsystem\Database\Db;
|
use Engelsystem\Database\Db;
|
||||||
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entity needed angeltypes describes how many angels of given type are needed for a shift or in a room.
|
* Entity needed angeltypes describes how many angels of given type are needed for a shift or in a room.
|
||||||
|
@ -108,13 +110,16 @@ function NeededAngelTypes_by_shift($shiftId)
|
||||||
', [$shiftId]);
|
', [$shiftId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$shift_entries = ShiftEntries_by_shift($shiftId);
|
/** @var ShiftEntry[]|Collection $shift_entries */
|
||||||
|
$shift_entries = ShiftEntry::with('user', 'angelType')
|
||||||
|
->where('shift_id', $shiftId)
|
||||||
|
->get();
|
||||||
$needed_angeltypes = [];
|
$needed_angeltypes = [];
|
||||||
foreach ($needed_angeltypes_source as $angeltype) {
|
foreach ($needed_angeltypes_source as $angeltype) {
|
||||||
$angeltype['shift_entries'] = [];
|
$angeltype['shift_entries'] = [];
|
||||||
$angeltype['taken'] = 0;
|
$angeltype['taken'] = 0;
|
||||||
foreach ($shift_entries as $shift_entry) {
|
foreach ($shift_entries as $shift_entry) {
|
||||||
if ($shift_entry['TID'] == $angeltype['angel_type_id'] && $shift_entry['freeloaded'] == 0) {
|
if ($shift_entry->angel_type_id == $angeltype['angel_type_id'] && !$shift_entry->freeloaded) {
|
||||||
$angeltype['taken']++;
|
$angeltype['taken']++;
|
||||||
$angeltype['shift_entries'][] = $shift_entry;
|
$angeltype['shift_entries'][] = $shift_entry;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,153 +1,40 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Engelsystem\Database\Db;
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Engelsystem\Models\AngelType;
|
|
||||||
use Engelsystem\Models\User\User;
|
use Engelsystem\Models\User\User;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
/**
|
|
||||||
* Counts all freeloaded shifts.
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
function ShiftEntries_freeloaded_count()
|
|
||||||
{
|
|
||||||
$result = Db::selectOne('SELECT COUNT(*) FROM `ShiftEntry` WHERE `freeloaded` = 1');
|
|
||||||
|
|
||||||
if (empty($result)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (int) array_shift($result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List users subscribed to a given shift.
|
|
||||||
*
|
|
||||||
* @param int $shift_id
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
function ShiftEntries_by_shift($shift_id)
|
|
||||||
{
|
|
||||||
return Db::select(
|
|
||||||
'
|
|
||||||
SELECT
|
|
||||||
`users`.*,
|
|
||||||
`ShiftEntry`.`UID`,
|
|
||||||
`ShiftEntry`.`TID`,
|
|
||||||
`ShiftEntry`.`SID`,
|
|
||||||
`angel_types`.`name` AS `angel_type_name`,
|
|
||||||
`ShiftEntry`.`Comment`,
|
|
||||||
`ShiftEntry`.`freeloaded`
|
|
||||||
FROM `ShiftEntry`
|
|
||||||
JOIN `users` ON `ShiftEntry`.`UID`=`users`.`id`
|
|
||||||
JOIN `angel_types` ON `ShiftEntry`.`TID`=`angel_types`.`id`
|
|
||||||
WHERE `ShiftEntry`.`SID` = ?
|
|
||||||
',
|
|
||||||
[$shift_id]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new shift entry.
|
* Create a new shift entry.
|
||||||
*
|
|
||||||
* @param array $shift_entry
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
function ShiftEntry_create($shift_entry)
|
function ShiftEntry_onCreate(ShiftEntry $shiftEntry): void
|
||||||
{
|
{
|
||||||
$user = User::find($shift_entry['UID']);
|
$shift = $shiftEntry->shift;
|
||||||
$shift = Shift($shift_entry['SID']);
|
|
||||||
$shifttype = $shift->shiftType;
|
|
||||||
$room = $shift->room;
|
|
||||||
$angeltype = AngelType::find($shift_entry['TID']);
|
|
||||||
$result = Db::insert(
|
|
||||||
'
|
|
||||||
INSERT INTO `ShiftEntry` (
|
|
||||||
`SID`,
|
|
||||||
`TID`,
|
|
||||||
`UID`,
|
|
||||||
`Comment`,
|
|
||||||
`freeload_comment`,
|
|
||||||
`freeloaded`
|
|
||||||
)
|
|
||||||
VALUES(?, ?, ?, ?, ?, ?)
|
|
||||||
',
|
|
||||||
[
|
|
||||||
$shift_entry['SID'],
|
|
||||||
$shift_entry['TID'],
|
|
||||||
$shift_entry['UID'],
|
|
||||||
$shift_entry['Comment'],
|
|
||||||
$shift_entry['freeload_comment'],
|
|
||||||
(int) $shift_entry['freeloaded'],
|
|
||||||
]
|
|
||||||
);
|
|
||||||
engelsystem_log(
|
engelsystem_log(
|
||||||
'User ' . User_Nick_render($user, true)
|
'User ' . User_Nick_render($shiftEntry->user, true)
|
||||||
. ' signed up for shift ' . $shift->title
|
. ' signed up for shift ' . $shiftEntry->shift->title
|
||||||
. ' (' . $shifttype->name . ')'
|
. ' (' . $shift->shiftType->name . ')'
|
||||||
. ' at ' . $room->name
|
. ' at ' . $shift->room->name
|
||||||
. ' from ' . $shift->start->format('Y-m-d H:i')
|
. ' from ' . $shift->start->format('Y-m-d H:i')
|
||||||
. ' to ' . $shift->end->format('Y-m-d H:i')
|
. ' to ' . $shift->end->format('Y-m-d H:i')
|
||||||
. ' as ' . $angeltype->name
|
. ' as ' . $shiftEntry->angelType->name
|
||||||
);
|
);
|
||||||
mail_shift_assign($user, $shift);
|
mail_shift_assign($shiftEntry->user, $shift);
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update a shift entry.
|
|
||||||
*
|
|
||||||
* @param array $shift_entry
|
|
||||||
*/
|
|
||||||
function ShiftEntry_update($shift_entry)
|
|
||||||
{
|
|
||||||
Db::update(
|
|
||||||
'
|
|
||||||
UPDATE `ShiftEntry`
|
|
||||||
SET
|
|
||||||
`Comment` = ?,
|
|
||||||
`freeload_comment` = ?,
|
|
||||||
`freeloaded` = ?
|
|
||||||
WHERE `id` = ?
|
|
||||||
',
|
|
||||||
[
|
|
||||||
$shift_entry['Comment'],
|
|
||||||
$shift_entry['freeload_comment'],
|
|
||||||
(int) $shift_entry['freeloaded'],
|
|
||||||
$shift_entry['id']
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a shift entry.
|
|
||||||
*
|
|
||||||
* @param int $shift_entry_id
|
|
||||||
* @return array|null
|
|
||||||
*/
|
|
||||||
function ShiftEntry($shift_entry_id)
|
|
||||||
{
|
|
||||||
$shiftEntry = Db::selectOne('SELECT * FROM `ShiftEntry` WHERE `id` = ?', [$shift_entry_id]);
|
|
||||||
|
|
||||||
return empty($shiftEntry) ? null : $shiftEntry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a shift entry.
|
* Delete a shift entry.
|
||||||
*
|
*
|
||||||
* @param array $shiftEntry
|
* @param ShiftEntry $shiftEntry
|
||||||
*/
|
*/
|
||||||
function ShiftEntry_delete($shiftEntry)
|
function ShiftEntry_onDelete(ShiftEntry $shiftEntry)
|
||||||
{
|
{
|
||||||
Db::delete('DELETE FROM `ShiftEntry` WHERE `id` = ?', [$shiftEntry['id']]);
|
$signout_user = $shiftEntry->user;
|
||||||
|
$shift = Shift($shiftEntry->shift);
|
||||||
$signout_user = User::find($shiftEntry['UID']);
|
|
||||||
$shift = Shift($shiftEntry['SID']);
|
|
||||||
$shifttype = $shift->shiftType;
|
$shifttype = $shift->shiftType;
|
||||||
$room = $shift->room;
|
$room = $shift->room;
|
||||||
$angeltype = AngelType::find($shiftEntry['TID']);
|
$angeltype = $shiftEntry->angelType;
|
||||||
|
|
||||||
engelsystem_log(
|
engelsystem_log(
|
||||||
'Shift signout: ' . User_Nick_render($signout_user, true)
|
'Shift signout: ' . User_Nick_render($signout_user, true)
|
||||||
|
@ -159,100 +46,44 @@ function ShiftEntry_delete($shiftEntry)
|
||||||
. ' as ' . $angeltype->name
|
. ' as ' . $angeltype->name
|
||||||
);
|
);
|
||||||
|
|
||||||
mail_shift_removed(User::find($shiftEntry['UID']), $shift);
|
mail_shift_removed($signout_user, $shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns next (or current) shifts of given user.
|
* Returns next (or current) shifts of given user.
|
||||||
*
|
*
|
||||||
* @param User $user
|
* @param User $user
|
||||||
* @return array
|
* @return ShiftEntry[]|Collection
|
||||||
*/
|
*/
|
||||||
function ShiftEntries_upcoming_for_user(User $user)
|
function ShiftEntries_upcoming_for_user(User $user)
|
||||||
{
|
{
|
||||||
return Db::select(
|
return $user->shiftEntries()
|
||||||
'
|
->with(['shift', 'shift.shiftType'])
|
||||||
SELECT *, shifts.id as shift_id
|
->join('shifts', 'shift_entries.shift_id', 'shifts.id')
|
||||||
FROM `ShiftEntry`
|
->where('shifts.end', '>', Carbon::now())
|
||||||
JOIN `shifts` ON (`shifts`.`id` = `ShiftEntry`.`SID`)
|
->orderBy('shifts.end')
|
||||||
JOIN `shift_types` ON `shift_types`.`id` = `shifts`.`shift_type_id`
|
->get();
|
||||||
WHERE `ShiftEntry`.`UID` = ?
|
|
||||||
AND `shifts`.`end` > NOW()
|
|
||||||
ORDER BY `shifts`.`end`
|
|
||||||
',
|
|
||||||
[
|
|
||||||
$user->id
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns shifts completed by the given user.
|
* Returns shifts completed by the given user.
|
||||||
*
|
*
|
||||||
* @param User $user
|
* @param User $user
|
||||||
* @param Carbon|null $sinceTime
|
* @param Carbon|null $sinceTime
|
||||||
* @return array
|
* @return ShiftEntry[]|Collection
|
||||||
*/
|
*/
|
||||||
function ShiftEntries_finished_by_user(User $user, Carbon $sinceTime = null)
|
function ShiftEntries_finished_by_user(User $user, Carbon $sinceTime = null)
|
||||||
{
|
{
|
||||||
return Db::select(
|
$query = $user->shiftEntries()
|
||||||
'
|
->with(['shift', 'shift.shiftType'])
|
||||||
SELECT *
|
->join('shifts', 'shift_entries.shift_id', 'shifts.id')
|
||||||
FROM `ShiftEntry`
|
->where('shifts.end', '<', Carbon::now())
|
||||||
JOIN `shifts` ON (`shifts`.`id` = `ShiftEntry`.`SID`)
|
->where('freeloaded', false)
|
||||||
JOIN `shift_types` ON `shift_types`.`id` = `shifts`.`shift_type_id`
|
->orderByDesc('shifts.end');
|
||||||
WHERE `ShiftEntry`.`UID` = ?
|
|
||||||
AND `shifts`.`end` < NOW()
|
|
||||||
AND `ShiftEntry`.`freeloaded` = 0
|
|
||||||
' . ($sinceTime ? 'AND shifts.start >= "' . $sinceTime->toString() . '"' : '') . '
|
|
||||||
ORDER BY `shifts`.`end` desc
|
|
||||||
',
|
|
||||||
[
|
|
||||||
$user->id,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
if ($sinceTime) {
|
||||||
* Returns all shift entries in given shift for given angeltype.
|
$query = $query->where('shifts.start', '>=', $sinceTime);
|
||||||
*
|
}
|
||||||
* @param int $shift_id
|
|
||||||
* @param int $angeltype_id
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
function ShiftEntries_by_shift_and_angeltype($shift_id, $angeltype_id)
|
|
||||||
{
|
|
||||||
return Db::select(
|
|
||||||
'
|
|
||||||
SELECT *
|
|
||||||
FROM `ShiftEntry`
|
|
||||||
WHERE `SID` = ?
|
|
||||||
AND `TID` = ?
|
|
||||||
',
|
|
||||||
[
|
|
||||||
$shift_id,
|
|
||||||
$angeltype_id,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
return $query->get();
|
||||||
* Returns all freeloaded shifts for given user.
|
|
||||||
*
|
|
||||||
* @param int $userId
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
function ShiftEntries_freeloaded_by_user($userId)
|
|
||||||
{
|
|
||||||
return Db::select(
|
|
||||||
'
|
|
||||||
SELECT *
|
|
||||||
FROM `ShiftEntry`
|
|
||||||
WHERE `freeloaded` = 1
|
|
||||||
AND `UID` = ?
|
|
||||||
',
|
|
||||||
[
|
|
||||||
$userId
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,13 @@ use Engelsystem\Database\Db;
|
||||||
use Engelsystem\Helpers\Carbon;
|
use Engelsystem\Helpers\Carbon;
|
||||||
use Engelsystem\Models\AngelType;
|
use Engelsystem\Models\AngelType;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Engelsystem\Models\User\User;
|
use Engelsystem\Models\User\User;
|
||||||
use Engelsystem\Models\UserAngelType;
|
use Engelsystem\Models\UserAngelType;
|
||||||
use Engelsystem\ShiftsFilter;
|
use Engelsystem\ShiftsFilter;
|
||||||
use Engelsystem\ShiftSignupState;
|
use Engelsystem\ShiftSignupState;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
use Illuminate\Support\Collection as SupportCollection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param AngelType $angeltype
|
* @param AngelType $angeltype
|
||||||
|
@ -57,7 +59,7 @@ function Shifts_free($start, $end, ShiftsFilter $filter = null)
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
WHERE (`end` > ? AND `start` < ?)
|
WHERE (`end` > ? AND `start` < ?)
|
||||||
AND (SELECT SUM(`count`) FROM `NeededAngelTypes` WHERE `NeededAngelTypes`.`shift_id`=`shifts`.`id`' . ($filter ? ' AND NeededAngelTypes.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
AND (SELECT SUM(`count`) FROM `NeededAngelTypes` WHERE `NeededAngelTypes`.`shift_id`=`shifts`.`id`' . ($filter ? ' AND NeededAngelTypes.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
||||||
> (SELECT COUNT(*) FROM `ShiftEntry` WHERE `ShiftEntry`.`SID`=`shifts`.`id` AND `freeloaded`=0' . ($filter ? ' AND ShiftEntry.TID IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
> (SELECT COUNT(*) FROM `shift_entries` WHERE `shift_entries`.`shift_id`=`shifts`.`id` AND shift_entries.`freeloaded`=0' . ($filter ? ' AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
||||||
AND s.shift_id IS NULL
|
AND s.shift_id IS NULL
|
||||||
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
|
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
|
||||||
|
|
||||||
|
@ -68,7 +70,7 @@ function Shifts_free($start, $end, ShiftsFilter $filter = null)
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
WHERE (`end` > ? AND `start` < ?)
|
WHERE (`end` > ? AND `start` < ?)
|
||||||
AND (SELECT SUM(`count`) FROM `NeededAngelTypes` WHERE `NeededAngelTypes`.`room_id`=`shifts`.`room_id`' . ($filter ? ' AND NeededAngelTypes.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
AND (SELECT SUM(`count`) FROM `NeededAngelTypes` WHERE `NeededAngelTypes`.`room_id`=`shifts`.`room_id`' . ($filter ? ' AND NeededAngelTypes.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
||||||
> (SELECT COUNT(*) FROM `ShiftEntry` WHERE `ShiftEntry`.`SID`=`shifts`.`id` AND `freeloaded`=0' . ($filter ? ' AND ShiftEntry.TID IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
> (SELECT COUNT(*) FROM `shift_entries` WHERE `shift_entries`.`shift_id`=`shifts`.`id` AND `freeloaded`=0' . ($filter ? ' AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
||||||
AND NOT s.shift_id IS NULL
|
AND NOT s.shift_id IS NULL
|
||||||
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
|
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
|
||||||
) AS `tmp`
|
) AS `tmp`
|
||||||
|
@ -246,41 +248,21 @@ function NeededAngeltype_by_Shift_and_Angeltype(Shift $shift, AngelType $angelty
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ShiftsFilter $shiftsFilter
|
* @param ShiftsFilter $shiftsFilter
|
||||||
* @return array[]
|
* @return ShiftEntry[]|Collection
|
||||||
*/
|
*/
|
||||||
function ShiftEntries_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
|
function ShiftEntries_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
|
||||||
{
|
{
|
||||||
$sql = sprintf(
|
return ShiftEntry::with('user')
|
||||||
'
|
->join('shifts', 'shifts.id', 'shift_entries.shift_id')
|
||||||
SELECT
|
->whereIn('shifts.room_id', $shiftsFilter->getRooms())
|
||||||
users.*,
|
->whereBetween('start', [$shiftsFilter->getStart(), $shiftsFilter->getEnd()])
|
||||||
`ShiftEntry`.`UID`,
|
->get();
|
||||||
`ShiftEntry`.`TID`,
|
|
||||||
`ShiftEntry`.`SID`,
|
|
||||||
`ShiftEntry`.`Comment`,
|
|
||||||
`ShiftEntry`.`freeloaded`
|
|
||||||
FROM `shifts`
|
|
||||||
JOIN `ShiftEntry` ON `ShiftEntry`.`SID`=`shifts`.`id`
|
|
||||||
JOIN `users` ON `ShiftEntry`.`UID`=`users`.`id`
|
|
||||||
WHERE `shifts`.`room_id` IN (%s)
|
|
||||||
AND `start` BETWEEN ? AND ?
|
|
||||||
ORDER BY `shifts`.`start`
|
|
||||||
',
|
|
||||||
implode(',', $shiftsFilter->getRooms())
|
|
||||||
);
|
|
||||||
return Db::select(
|
|
||||||
$sql,
|
|
||||||
[
|
|
||||||
$shiftsFilter->getStart(),
|
|
||||||
$shiftsFilter->getEnd(),
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a shift collides with other shifts (in time).
|
* Check if a shift collides with other shifts (in time).
|
||||||
*
|
*
|
||||||
* @param Shift $shift
|
* @param Shift $shift
|
||||||
* @param Shift[]|Collection $shifts
|
* @param Shift[]|Collection $shifts
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
|
@ -290,8 +272,8 @@ function Shift_collides(Shift $shift, $shifts)
|
||||||
if ($shift->id != $other_shift->id) {
|
if ($shift->id != $other_shift->id) {
|
||||||
if (
|
if (
|
||||||
!(
|
!(
|
||||||
$shift->start->timestamp >= $other_shift->end->timestamp
|
$shift->start->timestamp >= $other_shift->end->timestamp
|
||||||
|| $shift->end->timestamp <= $other_shift->start->timestamp
|
|| $shift->end->timestamp <= $other_shift->start->timestamp
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -304,15 +286,15 @@ function Shift_collides(Shift $shift, $shifts)
|
||||||
/**
|
/**
|
||||||
* Returns the number of needed angels/free shift entries for an angeltype.
|
* Returns the number of needed angels/free shift entries for an angeltype.
|
||||||
*
|
*
|
||||||
* @param AngelType $needed_angeltype
|
* @param AngelType $needed_angeltype
|
||||||
* @param array[] $shift_entries
|
* @param ShiftEntry[]|Collection $shift_entries
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
function Shift_free_entries(AngelType $needed_angeltype, $shift_entries)
|
function Shift_free_entries(AngelType $needed_angeltype, $shift_entries)
|
||||||
{
|
{
|
||||||
$taken = 0;
|
$taken = 0;
|
||||||
foreach ($shift_entries as $shift_entry) {
|
foreach ($shift_entries as $shift_entry) {
|
||||||
if ($shift_entry['freeloaded'] == 0) {
|
if (!$shift_entry->freeloaded) {
|
||||||
$taken++;
|
$taken++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,7 +312,7 @@ function Shift_free_entries(AngelType $needed_angeltype, $shift_entries)
|
||||||
* @param array|null $user_angeltype
|
* @param array|null $user_angeltype
|
||||||
* @param SHift[]|Collection|null $user_shifts List of the users shifts
|
* @param SHift[]|Collection|null $user_shifts List of the users shifts
|
||||||
* @param AngelType $needed_angeltype
|
* @param AngelType $needed_angeltype
|
||||||
* @param array[] $shift_entries
|
* @param ShiftEntry[]|Collection $shift_entries
|
||||||
* @return ShiftSignupState
|
* @return ShiftSignupState
|
||||||
*/
|
*/
|
||||||
function Shift_signup_allowed_angel(
|
function Shift_signup_allowed_angel(
|
||||||
|
@ -410,8 +392,8 @@ function Shift_signup_allowed_angel(
|
||||||
/**
|
/**
|
||||||
* Check if an angeltype supporter can sign up a user to a shift.
|
* Check if an angeltype supporter can sign up a user to a shift.
|
||||||
*
|
*
|
||||||
* @param AngelType $needed_angeltype
|
* @param AngelType $needed_angeltype
|
||||||
* @param array[] $shift_entries
|
* @param ShiftEntry[]|Collection $shift_entries
|
||||||
* @return ShiftSignupState
|
* @return ShiftSignupState
|
||||||
*/
|
*/
|
||||||
function Shift_signup_allowed_angeltype_supporter(AngelType $needed_angeltype, $shift_entries)
|
function Shift_signup_allowed_angeltype_supporter(AngelType $needed_angeltype, $shift_entries)
|
||||||
|
@ -427,8 +409,8 @@ function Shift_signup_allowed_angeltype_supporter(AngelType $needed_angeltype, $
|
||||||
/**
|
/**
|
||||||
* Check if an admin can sign up a user to a shift.
|
* Check if an admin can sign up a user to a shift.
|
||||||
*
|
*
|
||||||
* @param AngelType $needed_angeltype
|
* @param AngelType $needed_angeltype
|
||||||
* @param array[] $shift_entries
|
* @param ShiftEntry[]|Collection $shift_entries
|
||||||
* @return ShiftSignupState
|
* @return ShiftSignupState
|
||||||
*/
|
*/
|
||||||
function Shift_signup_allowed_admin(AngelType $needed_angeltype, $shift_entries)
|
function Shift_signup_allowed_admin(AngelType $needed_angeltype, $shift_entries)
|
||||||
|
@ -484,7 +466,7 @@ function Shift_signout_allowed(Shift $shift, AngelType $angeltype, $signout_user
|
||||||
* @param array|null $user_angeltype
|
* @param array|null $user_angeltype
|
||||||
* @param Shift[]|Collection|null $user_shifts List of the users shifts
|
* @param Shift[]|Collection|null $user_shifts List of the users shifts
|
||||||
* @param AngelType $needed_angeltype
|
* @param AngelType $needed_angeltype
|
||||||
* @param array[] $shift_entries
|
* @param ShiftEntry[]|Collection $shift_entries
|
||||||
* @return ShiftSignupState
|
* @return ShiftSignupState
|
||||||
*/
|
*/
|
||||||
function Shift_signup_allowed(
|
function Shift_signup_allowed(
|
||||||
|
@ -522,10 +504,10 @@ function Shift_signup_allowed(
|
||||||
* Return users shifts.
|
* Return users shifts.
|
||||||
*
|
*
|
||||||
* @param int $userId
|
* @param int $userId
|
||||||
* @param bool $include_freeload_comments
|
* @param bool $include_freeloaded_comments
|
||||||
* @return Collection|Shift[]
|
* @return SupportCollection|Shift[]
|
||||||
*/
|
*/
|
||||||
function Shifts_by_user($userId, $include_freeload_comments = false)
|
function Shifts_by_user($userId, $include_freeloaded_comments = false)
|
||||||
{
|
{
|
||||||
$shiftsData = Db::select(
|
$shiftsData = Db::select(
|
||||||
'
|
'
|
||||||
|
@ -534,19 +516,19 @@ function Shifts_by_user($userId, $include_freeload_comments = false)
|
||||||
`rooms`.name AS Name,
|
`rooms`.name AS Name,
|
||||||
`shift_types`.`id` AS `shifttype_id`,
|
`shift_types`.`id` AS `shifttype_id`,
|
||||||
`shift_types`.`name`,
|
`shift_types`.`name`,
|
||||||
`ShiftEntry`.`id` as shift_entry_id,
|
`shift_entries`.`id` as shift_entry_id,
|
||||||
`ShiftEntry`.`SID`,
|
`shift_entries`.`shift_id`,
|
||||||
`ShiftEntry`.`TID`,
|
`shift_entries`.`angel_type_id`,
|
||||||
`ShiftEntry`.`UID`,
|
`shift_entries`.`user_id`,
|
||||||
`ShiftEntry`.`freeloaded`,
|
`shift_entries`.`freeloaded`,
|
||||||
`ShiftEntry`.`Comment`,
|
`shift_entries`.`user_comment`,
|
||||||
' . ($include_freeload_comments ? '`ShiftEntry`.`freeload_comment`, ' : '') . '
|
' . ($include_freeloaded_comments ? '`shift_entries`.`freeloaded_comment`, ' : '') . '
|
||||||
`shifts`.*
|
`shifts`.*
|
||||||
FROM `ShiftEntry`
|
FROM `shift_entries`
|
||||||
JOIN `shifts` ON (`ShiftEntry`.`SID` = `shifts`.`id`)
|
JOIN `shifts` ON (`shift_entries`.`shift_id` = `shifts`.`id`)
|
||||||
JOIN `shift_types` ON (`shift_types`.`id` = `shifts`.`shift_type_id`)
|
JOIN `shift_types` ON (`shift_types`.`id` = `shifts`.`shift_type_id`)
|
||||||
JOIN `rooms` ON (`shifts`.`room_id` = `rooms`.`id`)
|
JOIN `rooms` ON (`shifts`.`room_id` = `rooms`.`id`)
|
||||||
WHERE ShiftEntry.`UID` = ?
|
WHERE shift_entries.`user_id` = ?
|
||||||
ORDER BY `start`
|
ORDER BY `start`
|
||||||
',
|
',
|
||||||
[
|
[
|
||||||
|
@ -578,22 +560,14 @@ function Shift($shift)
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$shift->shiftEntry = Db::select('
|
|
||||||
SELECT
|
|
||||||
`ShiftEntry`.`id`, `ShiftEntry`.`TID` , `ShiftEntry`.`UID` , `ShiftEntry`.`freeloaded`,
|
|
||||||
`users`.`name` AS `username`, `users`.`id` AS `user_id`
|
|
||||||
FROM `ShiftEntry`
|
|
||||||
LEFT JOIN `users` ON (`users`.`id` = `ShiftEntry`.`UID`)
|
|
||||||
WHERE `SID`=?', [$shift->id]);
|
|
||||||
|
|
||||||
$neededAngels = [];
|
$neededAngels = [];
|
||||||
$angelTypes = NeededAngelTypes_by_shift($shift->id);
|
$angelTypes = NeededAngelTypes_by_shift($shift->id);
|
||||||
foreach ($angelTypes as $type) {
|
foreach ($angelTypes as $type) {
|
||||||
$neededAngels[] = [
|
$neededAngels[] = [
|
||||||
'TID' => $type['angel_type_id'],
|
'angel_type_id' => $type['angel_type_id'],
|
||||||
'count' => $type['count'],
|
'count' => $type['count'],
|
||||||
'restricted' => $type['restricted'],
|
'restricted' => $type['restricted'],
|
||||||
'taken' => $type['taken']
|
'taken' => $type['taken']
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
$shift->neededAngels = $neededAngels;
|
$shift->neededAngels = $neededAngels;
|
||||||
|
|
|
@ -16,10 +16,10 @@ function stats_currently_working(ShiftsFilter $filter = null)
|
||||||
'
|
'
|
||||||
SELECT SUM((
|
SELECT SUM((
|
||||||
SELECT COUNT(*)
|
SELECT COUNT(*)
|
||||||
FROM `ShiftEntry`
|
FROM `shift_entries`
|
||||||
WHERE `ShiftEntry`.`SID`=`shifts`.`id`
|
WHERE `shift_entries`.`shift_id`=`shifts`.`id`
|
||||||
AND `freeloaded`=0
|
AND `freeloaded`=0
|
||||||
' . ($filter ? 'AND ShiftEntry.TID IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
' . ($filter ? 'AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
)) AS `count`
|
)) AS `count`
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
WHERE (`end` >= NOW() AND `start` <= NOW())
|
WHERE (`end` >= NOW() AND `start` <= NOW())
|
||||||
|
@ -89,12 +89,12 @@ function stats_angels_needed_three_hours(ShiftsFilter $filter = null)
|
||||||
AND `NeededAngelTypes`.`shift_id`=`shifts`.`id`
|
AND `NeededAngelTypes`.`shift_id`=`shifts`.`id`
|
||||||
' . ($filter ? 'AND NeededAngelTypes.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
' . ($filter ? 'AND NeededAngelTypes.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
) - (
|
) - (
|
||||||
SELECT COUNT(*) FROM `ShiftEntry`
|
SELECT COUNT(*) FROM `shift_entries`
|
||||||
JOIN `angel_types` ON `angel_types`.`id`=`ShiftEntry`.`TID`
|
JOIN `angel_types` ON `angel_types`.`id`=`shift_entries`.`angel_type_id`
|
||||||
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
||||||
AND `ShiftEntry`.`SID`=`shifts`.`id`
|
AND `shift_entries`.`shift_id`=`shifts`.`id`
|
||||||
AND `freeloaded`=0
|
AND `freeloaded`=0
|
||||||
' . ($filter ? 'AND ShiftEntry.TID IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
' . ($filter ? 'AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
AS `count`
|
AS `count`
|
||||||
|
@ -116,12 +116,13 @@ function stats_angels_needed_three_hours(ShiftsFilter $filter = null)
|
||||||
AND `NeededAngelTypes`.`room_id`=`shifts`.`room_id`
|
AND `NeededAngelTypes`.`room_id`=`shifts`.`room_id`
|
||||||
' . ($filter ? 'AND NeededAngelTypes.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
' . ($filter ? 'AND NeededAngelTypes.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
) - (
|
) - (
|
||||||
SELECT COUNT(*) FROM `ShiftEntry`
|
SELECT COUNT(*)
|
||||||
JOIN `angel_types` ON `angel_types`.`id`=`ShiftEntry`.`TID`
|
FROM `shift_entries`
|
||||||
|
JOIN `angel_types` ON `angel_types`.`id`=`shift_entries`.`angel_type_id`
|
||||||
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
||||||
AND `ShiftEntry`.`SID`=`shifts`.`id`
|
AND `shift_entries`.`shift_id`=`shifts`.`id`
|
||||||
AND `freeloaded`=0
|
AND `freeloaded`=0
|
||||||
' . ($filter ? 'AND ShiftEntry.TID IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
' . ($filter ? 'AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
AS `count`
|
AS `count`
|
||||||
|
@ -168,12 +169,12 @@ function stats_angels_needed_for_nightshifts(ShiftsFilter $filter = null)
|
||||||
AND `NeededAngelTypes`.`shift_id`=`shifts`.`id`
|
AND `NeededAngelTypes`.`shift_id`=`shifts`.`id`
|
||||||
' . ($filter ? 'AND NeededAngelTypes.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
' . ($filter ? 'AND NeededAngelTypes.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
) - (
|
) - (
|
||||||
SELECT COUNT(*) FROM `ShiftEntry`
|
SELECT COUNT(*) FROM `shift_entries`
|
||||||
JOIN `angel_types` ON `angel_types`.`id`=`ShiftEntry`.`TID`
|
JOIN `angel_types` ON `angel_types`.`id`=`shift_entries`.`angel_type_id`
|
||||||
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
||||||
AND `ShiftEntry`.`SID`=`shifts`.`id`
|
AND `shift_entries`.`shift_id`=`shifts`.`id`
|
||||||
AND `freeloaded`=0
|
AND shift_entries.`freeloaded`=0
|
||||||
' . ($filter ? 'AND ShiftEntry.TID IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
' . ($filter ? 'AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
AS `count`
|
AS `count`
|
||||||
|
@ -195,12 +196,12 @@ function stats_angels_needed_for_nightshifts(ShiftsFilter $filter = null)
|
||||||
AND `NeededAngelTypes`.`room_id`=`shifts`.`room_id`
|
AND `NeededAngelTypes`.`room_id`=`shifts`.`room_id`
|
||||||
' . ($filter ? 'AND angel_types.id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
' . ($filter ? 'AND angel_types.id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
) - (
|
) - (
|
||||||
SELECT COUNT(*) FROM `ShiftEntry`
|
SELECT COUNT(*) FROM `shift_entries`
|
||||||
JOIN `angel_types` ON `angel_types`.`id`=`ShiftEntry`.`TID`
|
JOIN `angel_types` ON `angel_types`.`id`=`shift_entries`.`angel_type_id`
|
||||||
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
||||||
AND `ShiftEntry`.`SID`=`shifts`.`id`
|
AND `shift_entries`.`shift_id`=`shifts`.`id`
|
||||||
AND `freeloaded`=0
|
AND `freeloaded`=0
|
||||||
' . ($filter ? 'AND ShiftEntry.TID IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
' . ($filter ? 'AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
AS `count`
|
AS `count`
|
||||||
|
|
|
@ -25,8 +25,8 @@ function User_tshirt_score($userId)
|
||||||
$shift_sum_formula = User_get_shifts_sum_query();
|
$shift_sum_formula = User_get_shifts_sum_query();
|
||||||
$result_shifts = Db::selectOne(sprintf('
|
$result_shifts = Db::selectOne(sprintf('
|
||||||
SELECT ROUND((%s) / 3600, 2) AS `tshirt_score`
|
SELECT ROUND((%s) / 3600, 2) AS `tshirt_score`
|
||||||
FROM `users` LEFT JOIN `ShiftEntry` ON `users`.`id` = `ShiftEntry`.`UID`
|
FROM `users` LEFT JOIN `shift_entries` ON `users`.`id` = `shift_entries`.`user_id`
|
||||||
LEFT JOIN `shifts` ON `ShiftEntry`.`SID` = `shifts`.`id`
|
LEFT JOIN `shifts` ON `shift_entries`.`shift_id` = `shifts`.`id`
|
||||||
WHERE `users`.`id` = ?
|
WHERE `users`.`id` = ?
|
||||||
AND `shifts`.`end` < NOW()
|
AND `shifts`.`end` < NOW()
|
||||||
GROUP BY `users`.`id`
|
GROUP BY `users`.`id`
|
||||||
|
@ -45,17 +45,6 @@ function User_tshirt_score($userId)
|
||||||
return $result_shifts['tshirt_score'] + $worklogHours;
|
return $result_shifts['tshirt_score'] + $worklogHours;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if user is freeloader
|
|
||||||
*
|
|
||||||
* @param User $user
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
function User_is_freeloader($user)
|
|
||||||
{
|
|
||||||
return count(ShiftEntries_freeloaded_by_user($user->id)) >= config('max_freeloadable_shifts');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all users that are not member of given angeltype.
|
* Returns all users that are not member of given angeltype.
|
||||||
*
|
*
|
||||||
|
@ -196,15 +185,15 @@ function User_get_eligable_voucher_count($user)
|
||||||
? Carbon::createFromFormat('Y-m-d', $voucher_settings['voucher_start'])->setTime(0, 0)
|
? Carbon::createFromFormat('Y-m-d', $voucher_settings['voucher_start'])->setTime(0, 0)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
$shifts = ShiftEntries_finished_by_user($user, $start);
|
$shiftEntries = ShiftEntries_finished_by_user($user, $start);
|
||||||
$worklog = UserWorkLogsForUser($user->id, $start);
|
$worklog = UserWorkLogsForUser($user->id, $start);
|
||||||
$shifts_done =
|
$shifts_done =
|
||||||
count($shifts)
|
count($shiftEntries)
|
||||||
+ $worklog->count();
|
+ $worklog->count();
|
||||||
|
|
||||||
$shiftsTime = 0;
|
$shiftsTime = 0;
|
||||||
foreach ($shifts as $shift) {
|
foreach ($shiftEntries as $shiftEntry) {
|
||||||
$shiftsTime += (Carbon::make($shift['end'])->timestamp - Carbon::make($shift['start'])->timestamp) / 60 / 60;
|
$shiftsTime += ($shiftEntry->shift->end->timestamp - $shiftEntry->shift->start->timestamp) / 60 / 60;
|
||||||
}
|
}
|
||||||
foreach ($worklog as $entry) {
|
foreach ($worklog as $entry) {
|
||||||
$shiftsTime += $entry->hours;
|
$shiftsTime += $entry->hours;
|
||||||
|
@ -248,7 +237,7 @@ function User_get_shifts_sum_query()
|
||||||
OR (HOUR(shifts.start) <= %1$d AND HOUR(shifts.end) >= %2$d)
|
OR (HOUR(shifts.start) <= %1$d AND HOUR(shifts.end) >= %2$d)
|
||||||
))
|
))
|
||||||
* (UNIX_TIMESTAMP(shifts.end) - UNIX_TIMESTAMP(shifts.start))
|
* (UNIX_TIMESTAMP(shifts.end) - UNIX_TIMESTAMP(shifts.start))
|
||||||
* (1 - (%3$d + 1) * `ShiftEntry`.`freeloaded`)
|
* (1 - (%3$d + 1) * `shift_entries`.`freeloaded`)
|
||||||
), 0)
|
), 0)
|
||||||
',
|
',
|
||||||
$nightShifts['start'],
|
$nightShifts['start'],
|
||||||
|
|
|
@ -60,7 +60,7 @@ function admin_active()
|
||||||
sprintf(
|
sprintf(
|
||||||
'
|
'
|
||||||
users.*,
|
users.*,
|
||||||
COUNT(ShiftEntry.id) AS shift_count,
|
COUNT(shift_entries.id) AS shift_count,
|
||||||
(%s + (
|
(%s + (
|
||||||
SELECT COALESCE(SUM(`hours`) * 3600, 0)
|
SELECT COALESCE(SUM(`hours`) * 3600, 0)
|
||||||
FROM `worklogs` WHERE `user_id`=`users`.`id`
|
FROM `worklogs` WHERE `user_id`=`users`.`id`
|
||||||
|
@ -70,8 +70,8 @@ function admin_active()
|
||||||
$shift_sum_formula
|
$shift_sum_formula
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
->leftJoin('ShiftEntry', 'users.id', '=', 'ShiftEntry.UID')
|
->leftJoin('shift_entries', 'users.id', '=', 'shift_entries.user_id')
|
||||||
->leftJoin('shifts', 'ShiftEntry.SID', '=', 'shifts.id')
|
->leftJoin('shifts', 'shift_entries.shift_id', '=', 'shifts.id')
|
||||||
->leftJoin('users_state', 'users.id', '=', 'users_state.user_id')
|
->leftJoin('users_state', 'users.id', '=', 'users_state.user_id')
|
||||||
->where('users_state.arrived', '=', true)
|
->where('users_state.arrived', '=', true)
|
||||||
->groupBy('users.id')
|
->groupBy('users.id')
|
||||||
|
@ -152,7 +152,7 @@ function admin_active()
|
||||||
sprintf(
|
sprintf(
|
||||||
'
|
'
|
||||||
users.*,
|
users.*,
|
||||||
COUNT(ShiftEntry.id) AS shift_count,
|
COUNT(shift_entries.id) AS shift_count,
|
||||||
(%s + (
|
(%s + (
|
||||||
SELECT COALESCE(SUM(`hours`) * 3600, 0)
|
SELECT COALESCE(SUM(`hours`) * 3600, 0)
|
||||||
FROM `worklogs` WHERE `user_id`=`users`.`id`
|
FROM `worklogs` WHERE `user_id`=`users`.`id`
|
||||||
|
@ -162,10 +162,10 @@ function admin_active()
|
||||||
$shift_sum_formula
|
$shift_sum_formula
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
->leftJoin('ShiftEntry', 'users.id', '=', 'ShiftEntry.UID')
|
->leftJoin('shift_entries', 'users.id', '=', 'shift_entries.user_id')
|
||||||
->leftJoin('shifts', function ($join) use ($show_all_shifts) {
|
->leftJoin('shifts', function ($join) use ($show_all_shifts) {
|
||||||
/** @var JoinClause $join */
|
/** @var JoinClause $join */
|
||||||
$join->on('ShiftEntry.SID', '=', 'shifts.id');
|
$join->on('shift_entries.shift_id', '=', 'shifts.id');
|
||||||
if (!$show_all_shifts) {
|
if (!$show_all_shifts) {
|
||||||
$join->where(function ($query) {
|
$join->where(function ($query) {
|
||||||
/** @var Builder $query */
|
/** @var Builder $query */
|
||||||
|
|
|
@ -40,11 +40,11 @@ function admin_free()
|
||||||
if ($request->has('submit')) {
|
if ($request->has('submit')) {
|
||||||
$query = User::with('personalData')
|
$query = User::with('personalData')
|
||||||
->select('users.*')
|
->select('users.*')
|
||||||
->leftJoin('ShiftEntry', 'users.id', 'ShiftEntry.UID')
|
->leftJoin('shift_entries', 'users.id', 'shift_entries.user_id')
|
||||||
->leftJoin('users_state', 'users.id', 'users_state.user_id')
|
->leftJoin('users_state', 'users.id', 'users_state.user_id')
|
||||||
->leftJoin('shifts', function ($join) {
|
->leftJoin('shifts', function ($join) {
|
||||||
/** @var JoinClause $join */
|
/** @var JoinClause $join */
|
||||||
$join->on('ShiftEntry.SID', '=', 'shifts.id')
|
$join->on('shift_entries.shift_id', '=', 'shifts.id')
|
||||||
->where('shifts.start', '<', Carbon::now())
|
->where('shifts.start', '<', Carbon::now())
|
||||||
->where('shifts.end', '>', Carbon::now());
|
->where('shifts.end', '>', Carbon::now());
|
||||||
})
|
})
|
||||||
|
|
|
@ -189,15 +189,14 @@ function admin_rooms()
|
||||||
$shifts = $room->shifts;
|
$shifts = $room->shifts;
|
||||||
foreach ($shifts as $shift) {
|
foreach ($shifts as $shift) {
|
||||||
$shift = Shift($shift);
|
$shift = Shift($shift);
|
||||||
foreach ($shift->shiftEntry as $entry) {
|
foreach ($shift->shiftEntries as $entry) {
|
||||||
$type = AngelType::find($entry['TID']);
|
|
||||||
event('shift.entry.deleting', [
|
event('shift.entry.deleting', [
|
||||||
'user' => User::find($entry['user_id']),
|
'user' => User::find($entry['user_id']),
|
||||||
'start' => $shift->start,
|
'start' => $shift->start,
|
||||||
'end' => $shift->end,
|
'end' => $shift->end,
|
||||||
'name' => $shift->shiftType->name,
|
'name' => $shift->shiftType->name,
|
||||||
'title' => $shift->title,
|
'title' => $shift->title,
|
||||||
'type' => $type->name,
|
'type' => $entry->angelType->name,
|
||||||
'room' => $room,
|
'room' => $room,
|
||||||
'freeloaded' => (bool) $entry['freeloaded'],
|
'freeloaded' => (bool) $entry['freeloaded'],
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -563,17 +563,16 @@ function admin_shifts_history(): string
|
||||||
|
|
||||||
foreach ($shifts as $shift) {
|
foreach ($shifts as $shift) {
|
||||||
$shift = Shift($shift);
|
$shift = Shift($shift);
|
||||||
foreach ($shift->shiftEntry as $entry) {
|
foreach ($shift->shiftEntries as $entry) {
|
||||||
$type = AngelType::find($entry['TID']);
|
|
||||||
event('shift.entry.deleting', [
|
event('shift.entry.deleting', [
|
||||||
'user' => User::find($entry['user_id']),
|
'user' => $entry->user,
|
||||||
'start' => $shift->start,
|
'start' => $shift->start,
|
||||||
'end' => $shift->end,
|
'end' => $shift->end,
|
||||||
'name' => $shift->shiftType->name,
|
'name' => $shift->shiftType->name,
|
||||||
'title' => $shift->title,
|
'title' => $shift->title,
|
||||||
'type' => $type->name,
|
'type' => $entry->angelType->name,
|
||||||
'room' => $shift->room,
|
'room' => $shift->room,
|
||||||
'freeloaded' => (bool) $entry['freeloaded'],
|
'freeloaded' => $entry->freeloaded,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -266,15 +266,15 @@ class ImportSchedule extends BaseController
|
||||||
protected function fireDeleteShiftEntryEvents(Event $event): void
|
protected function fireDeleteShiftEntryEvents(Event $event): void
|
||||||
{
|
{
|
||||||
$shiftEntries = $this->db
|
$shiftEntries = $this->db
|
||||||
->table('ShiftEntry')
|
->table('shift_entries')
|
||||||
->select([
|
->select([
|
||||||
'shift_types.name', 'shifts.title', 'angel_types.name AS type', 'rooms.id AS room_id',
|
'shift_types.name', 'shifts.title', 'angel_types.name AS type', 'rooms.id AS room_id',
|
||||||
'shifts.start', 'shifts.end', 'ShiftEntry.UID as user_id', 'ShiftEntry.freeloaded'
|
'shifts.start', 'shifts.end', 'shift_entries.user_id', 'shift_entries.freeloaded'
|
||||||
])
|
])
|
||||||
->join('shifts', 'shifts.id', 'ShiftEntry.SID')
|
->join('shifts', 'shifts.id', 'shift_entries.shift_id')
|
||||||
->join('schedule_shift', 'shifts.id', 'schedule_shift.shift_id')
|
->join('schedule_shift', 'shifts.id', 'schedule_shift.shift_id')
|
||||||
->join('rooms', 'rooms.id', 'shifts.room_id')
|
->join('rooms', 'rooms.id', 'shifts.room_id')
|
||||||
->join('angel_types', 'angel_types.id', 'ShiftEntry.TID')
|
->join('angel_types', 'angel_types.id', 'shift_entries.angel_type_id')
|
||||||
->join('shift_types', 'shift_types.id', 'shifts.shift_type_id')
|
->join('shift_types', 'shift_types.id', 'shifts.shift_type_id')
|
||||||
->where('schedule_shift.guid', $event->getGuid())
|
->where('schedule_shift.guid', $event->getGuid())
|
||||||
->get();
|
->get();
|
||||||
|
|
|
@ -60,8 +60,8 @@ function make_ical_entry_from_shift(Shift $shift)
|
||||||
$output .= 'UID:' . md5($shift->start->timestamp . $shift->end->timestamp . $shift->shiftType->name) . "\r\n";
|
$output .= 'UID:' . md5($shift->start->timestamp . $shift->end->timestamp . $shift->shiftType->name) . "\r\n";
|
||||||
$output .= 'SUMMARY:' . str_replace("\n", "\\n", $shift->shiftType->name)
|
$output .= 'SUMMARY:' . str_replace("\n", "\\n", $shift->shiftType->name)
|
||||||
. ' (' . str_replace("\n", "\\n", $shift->title) . ")\r\n";
|
. ' (' . str_replace("\n", "\\n", $shift->title) . ")\r\n";
|
||||||
if (isset($shift->Comment)) {
|
if (isset($shift->user_comment)) {
|
||||||
$output .= 'DESCRIPTION:' . str_replace("\n", "\\n", $shift->Comment) . "\r\n";
|
$output .= 'DESCRIPTION:' . str_replace("\n", "\\n", $shift->user_comment) . "\r\n";
|
||||||
}
|
}
|
||||||
$output .= 'DTSTAMP:' . $shift->start->utc()->format('Ymd\THis\Z') . "\r\n";
|
$output .= 'DTSTAMP:' . $shift->start->utc()->format('Ymd\THis\Z') . "\r\n";
|
||||||
$output .= 'DTSTART:' . $shift->start->utc()->format('Ymd\THis\Z') . "\r\n";
|
$output .= 'DTSTART:' . $shift->start->utc()->format('Ymd\THis\Z') . "\r\n";
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Engelsystem\Database\Db;
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
|
||||||
use Engelsystem\Models\User\User;
|
use Engelsystem\Models\User\User;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -49,60 +48,38 @@ function user_myshifts()
|
||||||
]);
|
]);
|
||||||
} elseif ($request->has('edit') && preg_match('/^\d+$/', $request->input('edit'))) {
|
} elseif ($request->has('edit') && preg_match('/^\d+$/', $request->input('edit'))) {
|
||||||
$shift_entry_id = $request->input('edit');
|
$shift_entry_id = $request->input('edit');
|
||||||
$shift = Db::selectOne(
|
/** @var ShiftEntry $shiftEntry */
|
||||||
'
|
$shiftEntry = ShiftEntry::where('id', $shift_entry_id)
|
||||||
SELECT
|
->where('user_id', $shifts_user->id)
|
||||||
`ShiftEntry`.`freeloaded`,
|
->with(['shift', 'shift.shiftType', 'shift.room', 'user'])
|
||||||
`ShiftEntry`.`freeload_comment`,
|
->first();
|
||||||
`ShiftEntry`.`Comment`,
|
if (!empty($shiftEntry)) {
|
||||||
`ShiftEntry`.`UID`,
|
$shift = $shiftEntry->shift;
|
||||||
`shift_types`.`name`,
|
$freeloaded = $shiftEntry->freeloaded;
|
||||||
`shifts`.*,
|
$freeloaded_comment = $shiftEntry->freeloaded_comment;
|
||||||
`angel_types`.`name` AS `angel_type`
|
|
||||||
FROM `ShiftEntry`
|
|
||||||
JOIN `angel_types` ON (`ShiftEntry`.`TID` = `angel_types`.`id`)
|
|
||||||
JOIN `shifts` ON (`ShiftEntry`.`SID` = `shifts`.`id`)
|
|
||||||
JOIN `shift_types` ON (`shift_types`.`id` = `shifts`.`shift_type_id`)
|
|
||||||
WHERE `ShiftEntry`.`id`=?
|
|
||||||
AND `UID`=?
|
|
||||||
LIMIT 1
|
|
||||||
',
|
|
||||||
[
|
|
||||||
$shift_entry_id,
|
|
||||||
$shifts_user->id,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
if (!empty($shift)) {
|
|
||||||
/** @var Shift $shift */
|
|
||||||
$shift = (new Shift())->forceFill($shift);
|
|
||||||
|
|
||||||
$freeloaded = $shift->freeloaded;
|
|
||||||
$freeload_comment = $shift->freeloaded_comment;
|
|
||||||
|
|
||||||
if ($request->hasPostData('submit')) {
|
if ($request->hasPostData('submit')) {
|
||||||
$valid = true;
|
$valid = true;
|
||||||
if (auth()->can('user_shifts_admin')) {
|
if (auth()->can('user_shifts_admin')) {
|
||||||
$freeloaded = $request->has('freeloaded');
|
$freeloaded = $request->has('freeloaded');
|
||||||
$freeload_comment = strip_request_item_nl('freeload_comment');
|
$freeloaded_comment = strip_request_item_nl('freeloaded_comment');
|
||||||
if ($freeloaded && $freeload_comment == '') {
|
if ($freeloaded && $freeloaded_comment == '') {
|
||||||
$valid = false;
|
$valid = false;
|
||||||
error(__('Please enter a freeload comment!'));
|
error(__('Please enter a freeload comment!'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$comment = $shift->Comment;
|
$comment = $shiftEntry->user_comment;
|
||||||
$user_source = User::find($shift->UID);
|
$user_source = $shiftEntry->user;
|
||||||
if (auth()->user()->id == $user_source->id) {
|
if (auth()->user()->id == $user_source->id) {
|
||||||
$comment = strip_request_item_nl('comment');
|
$comment = strip_request_item_nl('comment');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
ShiftEntry_update([
|
$shiftEntry->user_comment = $comment;
|
||||||
'id' => $shift_entry_id,
|
$shiftEntry->freeloaded = $freeloaded;
|
||||||
'Comment' => $comment,
|
$shiftEntry->freeloaded_comment = $freeloaded_comment;
|
||||||
'freeloaded' => $freeloaded,
|
$shiftEntry->save();
|
||||||
'freeload_comment' => $freeload_comment
|
|
||||||
]);
|
|
||||||
|
|
||||||
engelsystem_log(
|
engelsystem_log(
|
||||||
'Updated ' . User_Nick_render($user_source, true) . '\'s shift '
|
'Updated ' . User_Nick_render($user_source, true) . '\'s shift '
|
||||||
|
@ -110,7 +87,7 @@ function user_myshifts()
|
||||||
. ' from ' . $shift->start->format('Y-m-d H:i')
|
. ' from ' . $shift->start->format('Y-m-d H:i')
|
||||||
. ' to ' . $shift->end->format('Y-m-d H:i')
|
. ' to ' . $shift->end->format('Y-m-d H:i')
|
||||||
. ' with comment ' . $comment
|
. ' with comment ' . $comment
|
||||||
. '. Freeloaded: ' . ($freeloaded ? 'YES Comment: ' . $freeload_comment : 'NO')
|
. '. Freeloaded: ' . ($freeloaded ? 'YES Comment: ' . $freeloaded_comment : 'NO')
|
||||||
);
|
);
|
||||||
success(__('Shift saved.'));
|
success(__('Shift saved.'));
|
||||||
throw_redirect(page_link_to('users', ['action' => 'view', 'user_id' => $shifts_user->id]));
|
throw_redirect(page_link_to('users', ['action' => 'view', 'user_id' => $shifts_user->id]));
|
||||||
|
@ -122,10 +99,10 @@ function user_myshifts()
|
||||||
$shift->start->format('Y-m-d H:i') . ', ' . shift_length($shift),
|
$shift->start->format('Y-m-d H:i') . ', ' . shift_length($shift),
|
||||||
$shift->room->name,
|
$shift->room->name,
|
||||||
$shift->shiftType->name,
|
$shift->shiftType->name,
|
||||||
$shift->angel_type,
|
$shiftEntry->angelType->name,
|
||||||
$shift->Comment,
|
$shiftEntry->user_comment,
|
||||||
$shift->freeloaded,
|
$shiftEntry->freeloaded,
|
||||||
$shift->freeload_comment,
|
$shiftEntry->freeloaded_comment,
|
||||||
auth()->can('user_shifts_admin')
|
auth()->can('user_shifts_admin')
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -31,7 +31,7 @@ function user_shifts()
|
||||||
{
|
{
|
||||||
$request = request();
|
$request = request();
|
||||||
|
|
||||||
if (User_is_freeloader(auth()->user())) {
|
if (auth()->user()->isFreeloader()) {
|
||||||
throw_redirect(page_link_to('user_myshifts'));
|
throw_redirect(page_link_to('user_myshifts'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
namespace Engelsystem;
|
namespace Engelsystem;
|
||||||
|
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
class ShiftCalendarRenderer
|
class ShiftCalendarRenderer
|
||||||
{
|
{
|
||||||
|
@ -45,10 +47,10 @@ class ShiftCalendarRenderer
|
||||||
/**
|
/**
|
||||||
* ShiftCalendarRenderer constructor.
|
* ShiftCalendarRenderer constructor.
|
||||||
*
|
*
|
||||||
* @param Shift[] $shifts
|
* @param Shift[] $shifts
|
||||||
* @param array[] $needed_angeltypes
|
* @param array[] $needed_angeltypes
|
||||||
* @param array[] $shift_entries
|
* @param ShiftEntry[][]|Collection $shift_entries
|
||||||
* @param ShiftsFilter $shiftsFilter
|
* @param ShiftsFilter $shiftsFilter
|
||||||
*/
|
*/
|
||||||
public function __construct($shifts, private $needed_angeltypes, private $shift_entries, ShiftsFilter $shiftsFilter)
|
public function __construct($shifts, private $needed_angeltypes, private $shift_entries, ShiftsFilter $shiftsFilter)
|
||||||
{
|
{
|
||||||
|
@ -204,7 +206,7 @@ class ShiftCalendarRenderer
|
||||||
/**
|
/**
|
||||||
* Renders a tick/block for given time
|
* Renders a tick/block for given time
|
||||||
*
|
*
|
||||||
* @param int $time unix timestamp
|
* @param int $time unix timestamp
|
||||||
* @param boolean $label Should time labels be generated?
|
* @param boolean $label Should time labels be generated?
|
||||||
* @return string rendered tick html
|
* @return string rendered tick html
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -4,7 +4,9 @@ namespace Engelsystem;
|
||||||
|
|
||||||
use Engelsystem\Models\AngelType;
|
use Engelsystem\Models\AngelType;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Engelsystem\Models\User\User;
|
use Engelsystem\Models\User\User;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
use function theme_type;
|
use function theme_type;
|
||||||
|
|
||||||
|
@ -16,10 +18,10 @@ class ShiftCalendarShiftRenderer
|
||||||
/**
|
/**
|
||||||
* Renders a shift
|
* Renders a shift
|
||||||
*
|
*
|
||||||
* @param Shift $shift The shift to render
|
* @param Shift $shift The shift to render
|
||||||
* @param array[] $needed_angeltypes
|
* @param array[] $needed_angeltypes
|
||||||
* @param array $shift_entries
|
* @param ShiftEntry[]|Collection $shift_entries
|
||||||
* @param User $user The user who is viewing the shift calendar
|
* @param User $user The user who is viewing the shift calendar
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function render(Shift $shift, $needed_angeltypes, $shift_entries, $user)
|
public function render(Shift $shift, $needed_angeltypes, $shift_entries, $user)
|
||||||
|
@ -80,10 +82,10 @@ class ShiftCalendarShiftRenderer
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Shift $shift
|
* @param Shift $shift
|
||||||
* @param array[] $needed_angeltypes
|
* @param array[] $needed_angeltypes
|
||||||
* @param array[] $shift_entries
|
* @param ShiftEntry[]|Collection $shift_entries
|
||||||
* @param User $user
|
* @param User $user
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function renderShiftNeededAngeltypes(Shift $shift, $needed_angeltypes, $shift_entries, $user)
|
private function renderShiftNeededAngeltypes(Shift $shift, $needed_angeltypes, $shift_entries, $user)
|
||||||
|
@ -93,7 +95,7 @@ class ShiftCalendarShiftRenderer
|
||||||
$shift_entries_filtered[$needed_angeltype['id']] = [];
|
$shift_entries_filtered[$needed_angeltype['id']] = [];
|
||||||
}
|
}
|
||||||
foreach ($shift_entries as $shift_entry) {
|
foreach ($shift_entries as $shift_entry) {
|
||||||
$shift_entries_filtered[$shift_entry['TID']][] = $shift_entry;
|
$shift_entries_filtered[$shift_entry->angel_type_id][] = $shift_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
$html = '';
|
$html = '';
|
||||||
|
@ -144,11 +146,11 @@ class ShiftCalendarShiftRenderer
|
||||||
/**
|
/**
|
||||||
* Renders a list entry containing the needed angels for an angeltype
|
* Renders a list entry containing the needed angels for an angeltype
|
||||||
*
|
*
|
||||||
* @param Shift $shift The shift which is rendered
|
* @param Shift $shift The shift which is rendered
|
||||||
* @param array[] $shift_entries
|
* @param ShiftEntry[]|Collection $shift_entries
|
||||||
* @param array $angeltype The angeltype, containing information about needed angeltypes
|
* @param array $angeltype The angeltype, containing information about needed angeltypes
|
||||||
* and already signed up angels
|
* and already signed up angels
|
||||||
* @param User $user The user who is viewing the shift calendar
|
* @param User $user The user who is viewing the shift calendar
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function renderShiftNeededAngeltype(Shift $shift, $shift_entries, $angeltype, $user)
|
private function renderShiftNeededAngeltype(Shift $shift, $shift_entries, $angeltype, $user)
|
||||||
|
@ -156,8 +158,8 @@ class ShiftCalendarShiftRenderer
|
||||||
$angeltype = (new AngelType())->forceFill($angeltype);
|
$angeltype = (new AngelType())->forceFill($angeltype);
|
||||||
$entry_list = [];
|
$entry_list = [];
|
||||||
foreach ($shift_entries as $entry) {
|
foreach ($shift_entries as $entry) {
|
||||||
$class = $entry['freeloaded'] ? 'text-decoration-line-through' : '';
|
$class = $entry->freeloaded ? 'text-decoration-line-through' : '';
|
||||||
$entry_list[] = '<span class="text-nowrap ' . $class . '">' . User_Nick_render($entry) . '</span>';
|
$entry_list[] = '<span class="text-nowrap ' . $class . '">' . User_Nick_render($entry->user) . '</span>';
|
||||||
}
|
}
|
||||||
$shift_signup_state = Shift_signup_allowed(
|
$shift_signup_state = Shift_signup_allowed(
|
||||||
$user,
|
$user,
|
||||||
|
|
|
@ -39,11 +39,11 @@ function ShiftEntry_delete_view_admin(Shift $shift, AngelType $angeltype, User $
|
||||||
*
|
*
|
||||||
* @param Shift $shift
|
* @param Shift $shift
|
||||||
* @param AngelType $angeltype
|
* @param AngelType $angeltype
|
||||||
* @param int $signoff_user_id
|
* @param User $signoff_user
|
||||||
*
|
*
|
||||||
* @return string HTML
|
* @return string HTML
|
||||||
*/
|
*/
|
||||||
function ShiftEntry_delete_view(Shift $shift, AngelType $angeltype, $signoff_user_id)
|
function ShiftEntry_delete_view(Shift $shift, AngelType $angeltype, User $signoff_user)
|
||||||
{
|
{
|
||||||
return page_with_title(ShiftEntry_delete_title(), [
|
return page_with_title(ShiftEntry_delete_title(), [
|
||||||
info(sprintf(
|
info(sprintf(
|
||||||
|
@ -56,7 +56,7 @@ function ShiftEntry_delete_view(Shift $shift, AngelType $angeltype, $signoff_use
|
||||||
|
|
||||||
form([
|
form([
|
||||||
buttons([
|
buttons([
|
||||||
button(user_link($signoff_user_id), icon('x-lg') . __('cancel')),
|
button(user_link($signoff_user->id), icon('x-lg') . __('cancel')),
|
||||||
form_submit('delete', icon('trash') . __('delete'), 'btn-danger', false),
|
form_submit('delete', icon('trash') . __('delete'), 'btn-danger', false),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
|
@ -180,7 +180,7 @@ function ShiftEntry_create_title()
|
||||||
* @param string $type
|
* @param string $type
|
||||||
* @param string $comment
|
* @param string $comment
|
||||||
* @param bool $freeloaded
|
* @param bool $freeloaded
|
||||||
* @param string $freeload_comment
|
* @param string $freeloaded_comment
|
||||||
* @param bool $user_admin_shifts
|
* @param bool $user_admin_shifts
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@ -192,7 +192,7 @@ function ShiftEntry_edit_view(
|
||||||
$type,
|
$type,
|
||||||
$comment,
|
$comment,
|
||||||
$freeloaded,
|
$freeloaded,
|
||||||
$freeload_comment,
|
$freeloaded_comment,
|
||||||
$user_admin_shifts = false
|
$user_admin_shifts = false
|
||||||
) {
|
) {
|
||||||
$freeload_form = [];
|
$freeload_form = [];
|
||||||
|
@ -200,9 +200,9 @@ function ShiftEntry_edit_view(
|
||||||
$freeload_form = [
|
$freeload_form = [
|
||||||
form_checkbox('freeloaded', __('Freeloaded'), $freeloaded),
|
form_checkbox('freeloaded', __('Freeloaded'), $freeloaded),
|
||||||
form_textarea(
|
form_textarea(
|
||||||
'freeload_comment',
|
'freeloaded_comment',
|
||||||
__('Freeload comment (Only for shift coordination):'),
|
__('Freeload comment (Only for shift coordination):'),
|
||||||
$freeload_comment
|
$freeloaded_comment
|
||||||
)
|
)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
use Engelsystem\Models\AngelType;
|
use Engelsystem\Models\AngelType;
|
||||||
use Engelsystem\Models\Room;
|
use Engelsystem\Models\Room;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Engelsystem\Models\Shifts\ShiftType;
|
use Engelsystem\Models\Shifts\ShiftType;
|
||||||
use Engelsystem\Models\User\User;
|
|
||||||
use Engelsystem\Models\UserAngelType;
|
use Engelsystem\Models\UserAngelType;
|
||||||
use Engelsystem\ShiftSignupState;
|
use Engelsystem\ShiftSignupState;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
@ -75,8 +75,8 @@ function Shift_editor_info_render(Shift $shift)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Shift $shift
|
* @param Shift $shift
|
||||||
* @param AngelType $angeltype
|
* @param AngelType $angeltype
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function Shift_signup_button_render(Shift $shift, AngelType $angeltype)
|
function Shift_signup_button_render(Shift $shift, AngelType $angeltype)
|
||||||
|
@ -136,16 +136,16 @@ function Shift_view(Shift $shift, ShiftType $shifttype, Room $room, $angeltypes_
|
||||||
$needed_angels .= Shift_view_render_needed_angeltype($needed_angeltype, $angeltypes, $shift, $user_shift_admin);
|
$needed_angels .= Shift_view_render_needed_angeltype($needed_angeltype, $angeltypes, $shift, $user_shift_admin);
|
||||||
}
|
}
|
||||||
|
|
||||||
$shiftEntry = new Collection($shift->shiftEntry);
|
$shiftEntry = $shift->shiftEntries;
|
||||||
foreach ($shiftEntry->groupBy('TID') as $angelTypes) {
|
foreach ($shiftEntry->groupBy('angel_type_id') as $angelTypes) {
|
||||||
/** @var Collection $angelTypes */
|
/** @var Collection $angelTypes */
|
||||||
$type = $angelTypes->first()['TID'];
|
$type = $angelTypes->first()['angel_type_id'];
|
||||||
if (!$neededAngels->where('TID', $type)->first()) {
|
if (!$neededAngels->where('angel_type_id', $type)->first()) {
|
||||||
$needed_angels .= Shift_view_render_needed_angeltype([
|
$needed_angels .= Shift_view_render_needed_angeltype([
|
||||||
'TID' => $type,
|
'angel_type_id' => $type,
|
||||||
'count' => 0,
|
'count' => 0,
|
||||||
'restricted' => true,
|
'restricted' => true,
|
||||||
'taken' => $angelTypes->count(),
|
'taken' => $angelTypes->count(),
|
||||||
], $angeltypes, $shift, $user_shift_admin);
|
], $angeltypes, $shift, $user_shift_admin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -213,7 +213,7 @@ function Shift_view(Shift $shift, ShiftType $shifttype, Room $room, $angeltypes_
|
||||||
*/
|
*/
|
||||||
function Shift_view_render_needed_angeltype($needed_angeltype, $angeltypes, Shift $shift, $user_shift_admin)
|
function Shift_view_render_needed_angeltype($needed_angeltype, $angeltypes, Shift $shift, $user_shift_admin)
|
||||||
{
|
{
|
||||||
$angeltype = $angeltypes[$needed_angeltype['TID']];
|
$angeltype = $angeltypes[$needed_angeltype['angel_type_id']];
|
||||||
$angeltype_supporter = auth()->user()->isAngelTypeSupporter($angeltype)
|
$angeltype_supporter = auth()->user()->isAngelTypeSupporter($angeltype)
|
||||||
|| auth()->can('admin_user_angeltypes');
|
|| auth()->can('admin_user_angeltypes');
|
||||||
|
|
||||||
|
@ -242,8 +242,8 @@ function Shift_view_render_needed_angeltype($needed_angeltype, $angeltypes, Shif
|
||||||
);
|
);
|
||||||
|
|
||||||
$angels = [];
|
$angels = [];
|
||||||
foreach ($shift->shiftEntry as $shift_entry) {
|
foreach ($shift->shiftEntries as $shift_entry) {
|
||||||
if ($shift_entry['TID'] == $needed_angeltype['TID']) {
|
if ($shift_entry->angel_type_id == $needed_angeltype['angel_type_id']) {
|
||||||
$angels[] = Shift_view_render_shift_entry($shift_entry, $user_shift_admin, $angeltype_supporter, $shift);
|
$angels[] = Shift_view_render_shift_entry($shift_entry, $user_shift_admin, $angeltype_supporter, $shift);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,30 +255,30 @@ function Shift_view_render_needed_angeltype($needed_angeltype, $angeltypes, Shif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $shift_entry
|
* @param ShiftEntry $shift_entry
|
||||||
* @param bool $user_shift_admin
|
* @param bool $user_shift_admin
|
||||||
* @param bool $angeltype_supporter
|
* @param bool $angeltype_supporter
|
||||||
* @param Shift $shift
|
* @param Shift $shift
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function Shift_view_render_shift_entry($shift_entry, $user_shift_admin, $angeltype_supporter, Shift $shift)
|
function Shift_view_render_shift_entry(ShiftEntry $shift_entry, $user_shift_admin, $angeltype_supporter, Shift $shift)
|
||||||
{
|
{
|
||||||
$entry = User_Nick_render(User::find($shift_entry['UID']));
|
$entry = User_Nick_render($shift_entry->user);
|
||||||
if ($shift_entry['freeloaded']) {
|
if ($shift_entry->freeloaded) {
|
||||||
$entry = '<del>' . $entry . '</del>';
|
$entry = '<del>' . $entry . '</del>';
|
||||||
}
|
}
|
||||||
$isUser = $shift_entry['UID'] == auth()->user()->id;
|
$isUser = $shift_entry->user_id == auth()->user()->id;
|
||||||
if ($user_shift_admin || $angeltype_supporter || $isUser) {
|
if ($user_shift_admin || $angeltype_supporter || $isUser) {
|
||||||
$entry .= ' <div class="btn-group m-1">';
|
$entry .= ' <div class="btn-group m-1">';
|
||||||
if ($user_shift_admin || $isUser) {
|
if ($user_shift_admin || $isUser) {
|
||||||
$entry .= button_icon(
|
$entry .= button_icon(
|
||||||
page_link_to('user_myshifts', ['edit' => $shift_entry['id'], 'id' => $shift_entry['UID']]),
|
page_link_to('user_myshifts', ['edit' => $shift_entry->id, 'id' => $shift_entry->user_id]),
|
||||||
'pencil',
|
'pencil',
|
||||||
'btn-sm'
|
'btn-sm'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$angeltype = AngelType::find($shift_entry['TID']);
|
$angeltype = $shift_entry->angelType;
|
||||||
$disabled = Shift_signout_allowed($shift, $angeltype, $shift_entry['UID']) ? '' : ' btn-disabled';
|
$disabled = Shift_signout_allowed($shift, $angeltype, $shift_entry->user_id) ? '' : ' btn-disabled';
|
||||||
$entry .= button_icon(shift_entry_delete_link($shift_entry), 'trash', 'btn-sm' . $disabled);
|
$entry .= button_icon(shift_entry_delete_link($shift_entry), 'trash', 'btn-sm' . $disabled);
|
||||||
$entry .= '</div>';
|
$entry .= '</div>';
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ use Carbon\Carbon;
|
||||||
use Engelsystem\Models\AngelType;
|
use Engelsystem\Models\AngelType;
|
||||||
use Engelsystem\Models\Group;
|
use Engelsystem\Models\Group;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Engelsystem\Models\User\User;
|
use Engelsystem\Models\User\User;
|
||||||
use Engelsystem\Models\Worklog;
|
use Engelsystem\Models\Worklog;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
@ -197,14 +198,15 @@ function User_shift_state_render($user)
|
||||||
}
|
}
|
||||||
|
|
||||||
$upcoming_shifts = ShiftEntries_upcoming_for_user($user);
|
$upcoming_shifts = ShiftEntries_upcoming_for_user($user);
|
||||||
if (empty($upcoming_shifts)) {
|
if ($upcoming_shifts->isEmpty()) {
|
||||||
return '<span class="text-success">' . __('Free') . '</span>';
|
return '<span class="text-success">' . __('Free') . '</span>';
|
||||||
}
|
}
|
||||||
|
|
||||||
$nextShift = array_shift($upcoming_shifts);
|
/** @var ShiftEntry $nextShiftEntry */
|
||||||
|
$nextShiftEntry = $upcoming_shifts->first();
|
||||||
|
|
||||||
$start = Carbon::make($nextShift['start']);
|
$start = $nextShiftEntry->shift->start;
|
||||||
$end = Carbon::make($nextShift['end']);
|
$end = $nextShiftEntry->shift->end;
|
||||||
$startFormat = $start->format(__('Y-m-d H:i'));
|
$startFormat = $start->format(__('Y-m-d H:i'));
|
||||||
$endFormat = $end->format(__('Y-m-d H:i'));
|
$endFormat = $end->format(__('Y-m-d H:i'));
|
||||||
$startTimestamp = $start->timestamp;
|
$startTimestamp = $start->timestamp;
|
||||||
|
@ -244,8 +246,9 @@ function User_last_shift_render($user)
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$lastShift = array_shift($last_shifts);
|
/** @var ShiftEntry $lastShiftEntry */
|
||||||
$end = Carbon::make($lastShift['end']);
|
$lastShiftEntry = $last_shifts->first();
|
||||||
|
$end = $lastShiftEntry->shift->end;
|
||||||
|
|
||||||
return '<span title="' . $end->format(__('Y-m-d H:i')) . '" data-countdown-ts="' . $end->timestamp . '">'
|
return '<span title="' . $end->format(__('Y-m-d H:i')) . '" data-countdown-ts="' . $end->timestamp . '">'
|
||||||
. __('Shift ended %c')
|
. __('Shift ended %c')
|
||||||
|
@ -307,7 +310,7 @@ function User_view_myshift(Shift $shift, $user_source, $its_me)
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($its_me) {
|
if ($its_me) {
|
||||||
$myshift['comment'] = $shift->Comment;
|
$myshift['comment'] = $shift->user_comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($shift->freeloaded) {
|
if ($shift->freeloaded) {
|
||||||
|
@ -316,7 +319,7 @@ function User_view_myshift(Shift $shift, $user_source, $its_me)
|
||||||
. '</p>';
|
. '</p>';
|
||||||
if (auth()->can('user_shifts_admin')) {
|
if (auth()->can('user_shifts_admin')) {
|
||||||
$myshift['comment'] .= '<br />'
|
$myshift['comment'] .= '<br />'
|
||||||
. '<p class="text-danger">' . __('Freeloaded') . ': ' . $shift->freeload_comment . '</p>';
|
. '<p class="text-danger">' . __('Freeloaded') . ': ' . $shift->freeloaded_comment . '</p>';
|
||||||
} else {
|
} else {
|
||||||
$myshift['comment'] .= '<br /><p class="text-danger">' . __('Freeloaded') . '</p>';
|
$myshift['comment'] .= '<br /><p class="text-danger">' . __('Freeloaded') . '</p>';
|
||||||
}
|
}
|
||||||
|
@ -332,7 +335,8 @@ function User_view_myshift(Shift $shift, $user_source, $its_me)
|
||||||
'btn-sm'
|
'btn-sm'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (Shift_signout_allowed($shift, (new AngelType())->forceFill(['id' => $shift->TID]), $user_source->id)) {
|
|
||||||
|
if (Shift_signout_allowed($shift, (new AngelType())->forceFill(['id' => $shift->angel_type_id]), $user_source->id)) {
|
||||||
$myshift['actions'][] = button(
|
$myshift['actions'][] = button(
|
||||||
shift_entry_delete_link($shift),
|
shift_entry_delete_link($shift),
|
||||||
icon('trash') . __('sign off'),
|
icon('trash') . __('sign off'),
|
||||||
|
@ -517,7 +521,7 @@ function User_view(
|
||||||
return page_with_title(
|
return page_with_title(
|
||||||
'<span class="icon-icon_angel"></span> '
|
'<span class="icon-icon_angel"></span> '
|
||||||
. (
|
. (
|
||||||
(config('enable_pronoun') && $user_source->personalData->pronoun)
|
(config('enable_pronoun') && $user_source->personalData->pronoun)
|
||||||
? '<small>' . htmlspecialchars($user_source->personalData->pronoun) . '</small> '
|
? '<small>' . htmlspecialchars($user_source->personalData->pronoun) . '</small> '
|
||||||
: ''
|
: ''
|
||||||
)
|
)
|
||||||
|
@ -554,7 +558,7 @@ function User_view(
|
||||||
),
|
),
|
||||||
icon('valentine') . __('Vouchers')
|
icon('valentine') . __('Vouchers')
|
||||||
)
|
)
|
||||||
: '',
|
: '',
|
||||||
$admin_user_worklog_privilege ? button(
|
$admin_user_worklog_privilege ? button(
|
||||||
url('/admin/user/' . $user_source->id . '/worklog'),
|
url('/admin/user/' . $user_source->id . '/worklog'),
|
||||||
icon('clock-history') . __('worklog.add')
|
icon('clock-history') . __('worklog.add')
|
||||||
|
@ -572,13 +576,13 @@ function User_view(
|
||||||
icon('braces') . __('JSON Export')
|
icon('braces') . __('JSON Export')
|
||||||
) : '',
|
) : '',
|
||||||
($its_me && (
|
($its_me && (
|
||||||
$auth->can('shifts_json_export')
|
$auth->can('shifts_json_export')
|
||||||
|| $auth->can('ical')
|
|| $auth->can('ical')
|
||||||
|| $auth->can('atom')
|
|| $auth->can('atom')
|
||||||
)) ? button(
|
)) ? button(
|
||||||
page_link_to('user_myshifts', ['reset' => 1]),
|
page_link_to('user_myshifts', ['reset' => 1]),
|
||||||
icon('arrow-repeat') . __('Reset API key')
|
icon('arrow-repeat') . __('Reset API key')
|
||||||
) : ''
|
) : ''
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
|
@ -591,7 +595,7 @@ function User_view(
|
||||||
. $user_source->contact->dect
|
. $user_source->contact->dect
|
||||||
. '</a>'
|
. '</a>'
|
||||||
)
|
)
|
||||||
: '' ,
|
: '',
|
||||||
config('enable_mobile_show') && $user_source->contact->mobile ?
|
config('enable_mobile_show') && $user_source->contact->mobile ?
|
||||||
$user_source->settings->mobile_show ?
|
$user_source->settings->mobile_show ?
|
||||||
heading(
|
heading(
|
||||||
|
@ -600,15 +604,15 @@ function User_view(
|
||||||
. $user_source->contact->mobile
|
. $user_source->contact->mobile
|
||||||
. '</a>'
|
. '</a>'
|
||||||
)
|
)
|
||||||
: ''
|
: ''
|
||||||
: '' ,
|
: '',
|
||||||
$auth->can('user_messages') ?
|
$auth->can('user_messages') ?
|
||||||
heading(
|
heading(
|
||||||
'<a href="' . page_link_to('/messages/' . $user_source->id) . '">'
|
'<a href="' . page_link_to('/messages/' . $user_source->id) . '">'
|
||||||
. icon('envelope')
|
. icon('envelope')
|
||||||
. '</a>'
|
. '</a>'
|
||||||
)
|
)
|
||||||
: '' ,
|
: '',
|
||||||
]),
|
]),
|
||||||
User_view_state($admin_user_privilege, $freeloader, $user_source),
|
User_view_state($admin_user_privilege, $freeloader, $user_source),
|
||||||
User_angeltypes_render($user_angeltypes),
|
User_angeltypes_render($user_angeltypes),
|
||||||
|
@ -794,8 +798,8 @@ function User_oauth_render(User $user)
|
||||||
foreach ($user->oauth as $oauth) {
|
foreach ($user->oauth as $oauth) {
|
||||||
$output[] = __(
|
$output[] = __(
|
||||||
isset($config[$oauth->provider]['name'])
|
isset($config[$oauth->provider]['name'])
|
||||||
? $config[$oauth->provider]['name']
|
? $config[$oauth->provider]['name']
|
||||||
: Str::ucfirst($oauth->provider)
|
: Str::ucfirst($oauth->provider)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -887,7 +891,7 @@ function render_user_departure_date_hint()
|
||||||
*/
|
*/
|
||||||
function render_user_freeloader_hint()
|
function render_user_freeloader_hint()
|
||||||
{
|
{
|
||||||
if (User_is_freeloader(auth()->user())) {
|
if (auth()->user()->isFreeloader()) {
|
||||||
return sprintf(
|
return sprintf(
|
||||||
__('You freeloaded at least %s shifts. Shift signup is locked. Please go to heavens desk to be unlocked again.'),
|
__('You freeloaded at least %s shifts. Shift signup is locked. Please go to heavens desk to be unlocked again.'),
|
||||||
config('max_freeloadable_shifts')
|
config('max_freeloadable_shifts')
|
||||||
|
|
|
@ -45,27 +45,25 @@ class Stats
|
||||||
$query = State::whereArrived(true);
|
$query = State::whereArrived(true);
|
||||||
|
|
||||||
if (!is_null($working)) {
|
if (!is_null($working)) {
|
||||||
// @codeCoverageIgnoreStart
|
|
||||||
$query
|
$query
|
||||||
->leftJoin('worklogs', 'worklogs.user_id', '=', 'users_state.user_id')
|
->leftJoin('worklogs', 'worklogs.user_id', '=', 'users_state.user_id')
|
||||||
->leftJoin('ShiftEntry', 'ShiftEntry.UID', '=', 'users_state.user_id')
|
->leftJoin('shift_entries', 'shift_entries.user_id', '=', 'users_state.user_id')
|
||||||
->distinct();
|
->distinct();
|
||||||
|
|
||||||
$query->where(function ($query) use ($working): void {
|
$query->where(function ($query) use ($working): void {
|
||||||
/** @var QueryBuilder $query */
|
/** @var QueryBuilder $query */
|
||||||
if ($working) {
|
if ($working) {
|
||||||
$query
|
$query
|
||||||
->whereNotNull('ShiftEntry.SID')
|
->whereNotNull('shift_entries.shift_id')
|
||||||
->orWhereNotNull('worklogs.hours');
|
->orWhereNotNull('worklogs.hours');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$query
|
$query
|
||||||
->whereNull('ShiftEntry.SID')
|
->whereNull('shift_entries.shift_id')
|
||||||
->whereNull('worklogs.hours');
|
->whereNull('worklogs.hours');
|
||||||
});
|
});
|
||||||
// @codeCoverageIgnoreEnd
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $query->count('users_state.user_id');
|
return $query->count('users_state.user_id');
|
||||||
|
@ -104,18 +102,17 @@ class Stats
|
||||||
* The number of currently working users
|
* The number of currently working users
|
||||||
*
|
*
|
||||||
* @param bool|null $freeloaded
|
* @param bool|null $freeloaded
|
||||||
* @codeCoverageIgnore
|
|
||||||
*/
|
*/
|
||||||
public function currentlyWorkingUsers(bool $freeloaded = null): int
|
public function currentlyWorkingUsers(bool $freeloaded = null): int
|
||||||
{
|
{
|
||||||
$query = User::query()
|
$query = User::query()
|
||||||
->join('ShiftEntry', 'ShiftEntry.UID', '=', 'users.id')
|
->join('shift_entries', 'shift_entries.user_id', '=', 'users.id')
|
||||||
->join('shifts', 'shifts.id', '=', 'ShiftEntry.SID')
|
->join('shifts', 'shifts.id', '=', 'shift_entries.shift_id')
|
||||||
->where('shifts.start', '<=', Carbon::now())
|
->where('shifts.start', '<=', Carbon::now())
|
||||||
->where('shifts.end', '>', Carbon::now());
|
->where('shifts.end', '>', Carbon::now());
|
||||||
|
|
||||||
if (!is_null($freeloaded)) {
|
if (!is_null($freeloaded)) {
|
||||||
$query->where('ShiftEntry.freeloaded', '=', $freeloaded);
|
$query->where('shift_entries.freeloaded', '=', $freeloaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $query->count();
|
return $query->count();
|
||||||
|
@ -202,13 +199,13 @@ class Stats
|
||||||
* @param bool|null $done
|
* @param bool|null $done
|
||||||
* @param bool|null $freeloaded
|
* @param bool|null $freeloaded
|
||||||
*
|
*
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore because it is only used in functions that use TIMESTAMPDIFF
|
||||||
*/
|
*/
|
||||||
protected function workSecondsQuery(bool $done = null, bool $freeloaded = null): QueryBuilder
|
protected function workSecondsQuery(bool $done = null, bool $freeloaded = null): QueryBuilder
|
||||||
{
|
{
|
||||||
$query = $this
|
$query = $this
|
||||||
->getQuery('ShiftEntry')
|
->getQuery('shift_entries')
|
||||||
->join('shifts', 'shifts.id', '=', 'ShiftEntry.SID');
|
->join('shifts', 'shifts.id', '=', 'shift_entries.shift_id');
|
||||||
|
|
||||||
if (!is_null($freeloaded)) {
|
if (!is_null($freeloaded)) {
|
||||||
$query->where('freeloaded', '=', $freeloaded);
|
$query->where('freeloaded', '=', $freeloaded);
|
||||||
|
@ -227,13 +224,13 @@ class Stats
|
||||||
* @param bool|null $done
|
* @param bool|null $done
|
||||||
* @param bool|null $freeloaded
|
* @param bool|null $freeloaded
|
||||||
*
|
*
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore as TIMESTAMPDIFF is not implemented in SQLite
|
||||||
*/
|
*/
|
||||||
public function workSeconds(bool $done = null, bool $freeloaded = null): int
|
public function workSeconds(bool $done = null, bool $freeloaded = null): int
|
||||||
{
|
{
|
||||||
$query = $this->workSecondsQuery($done, $freeloaded);
|
$query = $this->workSecondsQuery($done, $freeloaded);
|
||||||
|
|
||||||
return (int) $query->sum($this->raw('end - start'));
|
return (int) $query->sum($this->raw('TIMESTAMPDIFF(MINUTE, start, end) * 60'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -242,22 +239,19 @@ class Stats
|
||||||
* @param bool|null $done
|
* @param bool|null $done
|
||||||
* @param bool|null $freeloaded
|
* @param bool|null $freeloaded
|
||||||
*
|
*
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore as TIMESTAMPDIFF is not implemented in SQLite
|
||||||
*/
|
*/
|
||||||
public function workBuckets(array $buckets, bool $done = null, bool $freeloaded = null): array
|
public function workBuckets(array $buckets, bool $done = null, bool $freeloaded = null): array
|
||||||
{
|
{
|
||||||
return $this->getBuckets(
|
return $this->getBuckets(
|
||||||
$buckets,
|
$buckets,
|
||||||
$this->workSecondsQuery($done, $freeloaded),
|
$this->workSecondsQuery($done, $freeloaded),
|
||||||
'UID',
|
'user_id',
|
||||||
'SUM(end - start)',
|
'SUM(TIMESTAMPDIFF(MINUTE, start, end) * 60)',
|
||||||
'SUM(end - start)'
|
'SUM(TIMESTAMPDIFF(MINUTE, start, end) * 60)'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @codeCoverageIgnore As long as its only used for old tables
|
|
||||||
*/
|
|
||||||
protected function getBuckets(
|
protected function getBuckets(
|
||||||
array $buckets,
|
array $buckets,
|
||||||
BuilderContract $basicQuery,
|
BuilderContract $basicQuery,
|
||||||
|
@ -281,18 +275,12 @@ class Stats
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @codeCoverageIgnore
|
|
||||||
*/
|
|
||||||
public function worklogSeconds(): int
|
public function worklogSeconds(): int
|
||||||
{
|
{
|
||||||
return (int) Worklog::query()
|
return (int) Worklog::query()
|
||||||
->sum($this->raw('hours * 60 * 60'));
|
->sum($this->raw('hours * 60 * 60'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @codeCoverageIgnore
|
|
||||||
*/
|
|
||||||
public function worklogBuckets(array $buckets): array
|
public function worklogBuckets(array $buckets): array
|
||||||
{
|
{
|
||||||
return $this->getBuckets(
|
return $this->getBuckets(
|
||||||
|
|
|
@ -4,28 +4,31 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Engelsystem\Models;
|
namespace Engelsystem\Models;
|
||||||
|
|
||||||
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Engelsystem\Models\User\User;
|
use Engelsystem\Models\User\User;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Query\Builder as QueryBuilder;
|
use Illuminate\Database\Query\Builder as QueryBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property string $name
|
* @property string $name
|
||||||
* @property string $description
|
* @property string $description
|
||||||
* @property string $contact_name
|
* @property string $contact_name
|
||||||
* @property string $contact_dect
|
* @property string $contact_dect
|
||||||
* @property string $contact_email
|
* @property string $contact_email
|
||||||
* @property boolean $restricted # If users need an introduction
|
* @property boolean $restricted # If users need an introduction
|
||||||
* @property boolean $requires_driver_license # If users must have a driver license
|
* @property boolean $requires_driver_license # If users must have a driver license
|
||||||
* @property boolean $no_self_signup # Users can sign up for shifts
|
* @property boolean $no_self_signup # Users can sign up for shifts
|
||||||
* @property boolean $show_on_dashboard # Show on public dashboard
|
* @property boolean $show_on_dashboard # Show on public dashboard
|
||||||
* @property boolean $hide_register # Hide from registration page
|
* @property boolean $hide_register # Hide from registration page
|
||||||
*
|
*
|
||||||
* @property-read Collection|User[] $userAngelTypes
|
* @property-read UserAngelType $pivot
|
||||||
* @property-read UserAngelType $pivot
|
* @property-read Collection|ShiftEntry[] $shiftEntries
|
||||||
|
* @property-read Collection|User[] $userAngelTypes
|
||||||
*
|
*
|
||||||
* @method static QueryBuilder|AngelType[] whereId($value)
|
* @method static QueryBuilder|AngelType[] whereId($value)
|
||||||
* @method static QueryBuilder|AngelType[] whereName($value)
|
* @method static QueryBuilder|AngelType[] whereName($value)
|
||||||
|
@ -68,6 +71,11 @@ class AngelType extends BaseModel
|
||||||
'hide_register' => 'boolean',
|
'hide_register' => 'boolean',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public function shiftEntries(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(ShiftEntry::class);
|
||||||
|
}
|
||||||
|
|
||||||
public function userAngelTypes(): BelongsToMany
|
public function userAngelTypes(): BelongsToMany
|
||||||
{
|
{
|
||||||
return $this
|
return $this
|
||||||
|
|
|
@ -8,31 +8,34 @@ use Carbon\Carbon;
|
||||||
use Engelsystem\Models\BaseModel;
|
use Engelsystem\Models\BaseModel;
|
||||||
use Engelsystem\Models\Room;
|
use Engelsystem\Models\Room;
|
||||||
use Engelsystem\Models\User\User;
|
use Engelsystem\Models\User\User;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasOneThrough;
|
use Illuminate\Database\Eloquent\Relations\HasOneThrough;
|
||||||
use Illuminate\Database\Query\Builder as QueryBuilder;
|
use Illuminate\Database\Query\Builder as QueryBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property string $title
|
* @property string $title
|
||||||
* @property string $description
|
* @property string $description
|
||||||
* @property string $url
|
* @property string $url
|
||||||
* @property Carbon $start
|
* @property Carbon $start
|
||||||
* @property Carbon $end
|
* @property Carbon $end
|
||||||
* @property int $shift_type_id
|
* @property int $shift_type_id
|
||||||
* @property int $room_id
|
* @property int $room_id
|
||||||
* @property string $transaction_id
|
* @property string $transaction_id
|
||||||
* @property int $created_by
|
* @property int $created_by
|
||||||
* @property int|null $updated_by
|
* @property int|null $updated_by
|
||||||
* @property Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
*
|
*
|
||||||
* @property-read QueryBuilder|Schedule $schedule
|
* @property-read QueryBuilder|Schedule $schedule
|
||||||
* @property-read QueryBuilder|ShiftType $shiftType
|
* @property-read QueryBuilder|Collection|ShiftEntry[] $shiftEntries
|
||||||
* @property-read QueryBuilder|Room $room
|
* @property-read QueryBuilder|ShiftType $shiftType
|
||||||
* @property-read QueryBuilder|User $createdBy
|
* @property-read QueryBuilder|Room $room
|
||||||
* @property-read QueryBuilder|User|null $updatedBy
|
* @property-read QueryBuilder|User $createdBy
|
||||||
|
* @property-read QueryBuilder|User|null $updatedBy
|
||||||
*
|
*
|
||||||
* @method static QueryBuilder|Shift[] whereId($value)
|
* @method static QueryBuilder|Shift[] whereId($value)
|
||||||
* @method static QueryBuilder|Shift[] whereTitle($value)
|
* @method static QueryBuilder|Shift[] whereTitle($value)
|
||||||
|
@ -88,6 +91,11 @@ class Shift extends BaseModel
|
||||||
return $this->hasOneThrough(Schedule::class, ScheduleShift::class, null, 'id', null, 'schedule_id');
|
return $this->hasOneThrough(Schedule::class, ScheduleShift::class, null, 'id', null, 'schedule_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function shiftEntries(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(ShiftEntry::class);
|
||||||
|
}
|
||||||
|
|
||||||
public function shiftType(): BelongsTo
|
public function shiftType(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(ShiftType::class);
|
return $this->belongsTo(ShiftType::class);
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Models\Shifts;
|
||||||
|
|
||||||
|
use Engelsystem\Models\AngelType;
|
||||||
|
use Engelsystem\Models\BaseModel;
|
||||||
|
use Engelsystem\Models\User\UsesUserModel;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Database\Query\Builder as QueryBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property int $shift_id
|
||||||
|
* @property int $angel_type_id
|
||||||
|
* @property string $user_comment
|
||||||
|
* @property bool $freeloaded
|
||||||
|
* @property string $freeloaded_comment
|
||||||
|
*
|
||||||
|
* @property-read Shift $shift
|
||||||
|
* @property-read AngelType $angelType
|
||||||
|
*
|
||||||
|
* @method static QueryBuilder|ShiftEntry[] whereId($value)
|
||||||
|
* @method static QueryBuilder|ShiftEntry[] whereShiftId($value)
|
||||||
|
* @method static QueryBuilder|ShiftEntry[] whereAngelTypeId($value)
|
||||||
|
* @method static QueryBuilder|ShiftEntry[] whereUserComment($value)
|
||||||
|
* @method static QueryBuilder|ShiftEntry[] whereFreeloaded($value)
|
||||||
|
* @method static QueryBuilder|ShiftEntry[] whereFreeloadedComment($value)
|
||||||
|
*/
|
||||||
|
class ShiftEntry extends BaseModel
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
use UsesUserModel;
|
||||||
|
|
||||||
|
/** @var array<string> */
|
||||||
|
protected $fillable = [ // phpcs:ignore
|
||||||
|
'shift_id',
|
||||||
|
'angel_type_id',
|
||||||
|
'user_id',
|
||||||
|
'user_comment',
|
||||||
|
'freeloaded',
|
||||||
|
'freeloaded_comment',
|
||||||
|
];
|
||||||
|
|
||||||
|
/** @var array<string, string|bool> default attributes */
|
||||||
|
protected $attributes = [ // phpcs:ignore
|
||||||
|
'user_comment' => '',
|
||||||
|
'freeloaded' => false,
|
||||||
|
'freeloaded_comment' => '',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function shift(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Shift::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function angelType(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(AngelType::class);
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ use Engelsystem\Models\OAuth;
|
||||||
use Engelsystem\Models\Privilege;
|
use Engelsystem\Models\Privilege;
|
||||||
use Engelsystem\Models\Question;
|
use Engelsystem\Models\Question;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Engelsystem\Models\UserAngelType;
|
use Engelsystem\Models\UserAngelType;
|
||||||
use Engelsystem\Models\Worklog;
|
use Engelsystem\Models\Worklog;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
@ -47,6 +48,7 @@ use Illuminate\Support\Collection as SupportCollection;
|
||||||
* @property-read SupportCollection|Privilege[] $privileges
|
* @property-read SupportCollection|Privilege[] $privileges
|
||||||
* @property-read Collection|AngelType[] $userAngelTypes
|
* @property-read Collection|AngelType[] $userAngelTypes
|
||||||
* @property-read UserAngelType $pivot
|
* @property-read UserAngelType $pivot
|
||||||
|
* @property-read Collection|ShiftEntry[] $shiftEntries
|
||||||
* @property-read Collection|Worklog[] $worklogs
|
* @property-read Collection|Worklog[] $worklogs
|
||||||
* @property-read Collection|Worklog[] $worklogsCreated
|
* @property-read Collection|Worklog[] $worklogsCreated
|
||||||
* @property-read Collection|Question[] $questionsAsked
|
* @property-read Collection|Question[] $questionsAsked
|
||||||
|
@ -109,6 +111,14 @@ class User extends BaseModel
|
||||||
return $this->belongsToMany(Group::class, 'users_groups');
|
return $this->belongsToMany(Group::class, 'users_groups');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isFreeloader(): bool
|
||||||
|
{
|
||||||
|
return $this->shiftEntries()
|
||||||
|
->where('freeloaded', true)
|
||||||
|
->count()
|
||||||
|
>= config('max_freeloadable_shifts');
|
||||||
|
}
|
||||||
|
|
||||||
public function license(): HasOne
|
public function license(): HasOne
|
||||||
{
|
{
|
||||||
return $this
|
return $this
|
||||||
|
@ -189,6 +199,11 @@ class User extends BaseModel
|
||||||
return $this->hasMany(OAuth::class);
|
return $this->hasMany(OAuth::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function shiftEntries(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(ShiftEntry::class);
|
||||||
|
}
|
||||||
|
|
||||||
public function worklogs(): HasMany
|
public function worklogs(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(Worklog::class);
|
return $this->hasMany(Worklog::class);
|
||||||
|
|
|
@ -76,8 +76,10 @@ class TwigServiceProvider extends ServiceProvider
|
||||||
$this->app->instance('twig.loader', $twigLoader);
|
$this->app->instance('twig.loader', $twigLoader);
|
||||||
|
|
||||||
$cache = $this->app->get('path.cache.views');
|
$cache = $this->app->get('path.cache.views');
|
||||||
|
$twigDebug = false;
|
||||||
if ($config->get('environment') == 'development') {
|
if ($config->get('environment') == 'development') {
|
||||||
$cache = false;
|
$cache = false;
|
||||||
|
$twigDebug = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$twig = $this->app->make(
|
$twig = $this->app->make(
|
||||||
|
@ -86,7 +88,8 @@ class TwigServiceProvider extends ServiceProvider
|
||||||
'options' => [
|
'options' => [
|
||||||
'cache' => $cache,
|
'cache' => $cache,
|
||||||
'auto_reload' => true,
|
'auto_reload' => true,
|
||||||
'strict_variables' => ($config->get('environment') == 'development'),
|
'debug' => $twigDebug,
|
||||||
|
'strict_variables' => $twigDebug,
|
||||||
],
|
],
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
|
@ -13,6 +13,7 @@ use Engelsystem\Models\OAuth;
|
||||||
use Engelsystem\Models\Question;
|
use Engelsystem\Models\Question;
|
||||||
use Engelsystem\Models\Room;
|
use Engelsystem\Models\Room;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Engelsystem\Models\User\License;
|
use Engelsystem\Models\User\License;
|
||||||
use Engelsystem\Models\User\PasswordReset;
|
use Engelsystem\Models\User\PasswordReset;
|
||||||
use Engelsystem\Models\User\PersonalData;
|
use Engelsystem\Models\User\PersonalData;
|
||||||
|
@ -163,6 +164,35 @@ class StatsTest extends TestCase
|
||||||
$this->assertEquals(2.4 * 60 * 60 + 1.2 * 60 * 60, $seconds);
|
$this->assertEquals(2.4 * 60 * 60 + 1.2 * 60 * 60, $seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Controllers\Metrics\Stats::worklogBuckets
|
||||||
|
* @covers \Engelsystem\Controllers\Metrics\Stats::getBuckets
|
||||||
|
*/
|
||||||
|
public function testWorklogBuckets(): void
|
||||||
|
{
|
||||||
|
Worklog::factory()->create(['hours' => 1.2, 'worked_at' => Carbon::now()->subDay()]);
|
||||||
|
Worklog::factory()->create(['hours' => 1.9, 'worked_at' => Carbon::now()->subDay()]);
|
||||||
|
Worklog::factory()->create(['hours' => 3, 'worked_at' => Carbon::now()->subDay()]);
|
||||||
|
Worklog::factory()->create(['hours' => 10, 'worked_at' => Carbon::now()->subDay()]);
|
||||||
|
|
||||||
|
$stats = new Stats($this->database);
|
||||||
|
$buckets = $stats->worklogBuckets([
|
||||||
|
1 * 60 * 60,
|
||||||
|
2 * 60 * 60,
|
||||||
|
3 * 60 * 60,
|
||||||
|
4 * 60 * 60,
|
||||||
|
'+Inf'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertEquals([
|
||||||
|
3600 => 0,
|
||||||
|
7200 => 2,
|
||||||
|
10800 => 3,
|
||||||
|
14400 => 3,
|
||||||
|
'+Inf' => 4,
|
||||||
|
], $buckets);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \Engelsystem\Controllers\Metrics\Stats::rooms
|
* @covers \Engelsystem\Controllers\Metrics\Stats::rooms
|
||||||
*/
|
*/
|
||||||
|
@ -251,9 +281,13 @@ class StatsTest extends TestCase
|
||||||
public function testArrivedUsers(): void
|
public function testArrivedUsers(): void
|
||||||
{
|
{
|
||||||
$this->addUsers();
|
$this->addUsers();
|
||||||
|
ShiftEntry::factory()->create(['user_id' => 3]);
|
||||||
|
ShiftEntry::factory()->create(['user_id' => 4]);
|
||||||
|
|
||||||
$stats = new Stats($this->database);
|
$stats = new Stats($this->database);
|
||||||
$this->assertEquals(7, $stats->arrivedUsers());
|
$this->assertEquals(7, $stats->arrivedUsers());
|
||||||
|
$this->assertEquals(5, $stats->arrivedUsers(false));
|
||||||
|
$this->assertEquals(2, $stats->arrivedUsers(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -293,6 +327,25 @@ class StatsTest extends TestCase
|
||||||
$this->assertEquals(1, $stats->email('news'));
|
$this->assertEquals(1, $stats->email('news'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Controllers\Metrics\Stats::currentlyWorkingUsers
|
||||||
|
*/
|
||||||
|
public function testCurrentlyWorkingUsers(): void
|
||||||
|
{
|
||||||
|
$this->addUsers();
|
||||||
|
/** @var Shift $shift */
|
||||||
|
$shift = Shift::factory()->create(['start' => Carbon::now()->subHour(), 'end' => Carbon::now()->addHour()]);
|
||||||
|
|
||||||
|
ShiftEntry::factory()->create(['shift_id' => $shift->id]);
|
||||||
|
ShiftEntry::factory()->create(['shift_id' => $shift->id]);
|
||||||
|
ShiftEntry::factory()->create(['shift_id' => $shift->id, 'freeloaded' => true]);
|
||||||
|
|
||||||
|
$stats = new Stats($this->database);
|
||||||
|
$this->assertEquals(3, $stats->currentlyWorkingUsers());
|
||||||
|
$this->assertEquals(2, $stats->currentlyWorkingUsers(false));
|
||||||
|
$this->assertEquals(1, $stats->currentlyWorkingUsers(true));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \Engelsystem\Controllers\Metrics\Stats::faq
|
* @covers \Engelsystem\Controllers\Metrics\Stats::faq
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -10,6 +10,7 @@ use Engelsystem\Models\Question;
|
||||||
use Engelsystem\Models\Room;
|
use Engelsystem\Models\Room;
|
||||||
use Engelsystem\Models\Shifts\Schedule;
|
use Engelsystem\Models\Shifts\Schedule;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Engelsystem\Models\User\Contact;
|
use Engelsystem\Models\User\Contact;
|
||||||
use Engelsystem\Models\User\License;
|
use Engelsystem\Models\User\License;
|
||||||
use Engelsystem\Models\User\PasswordReset;
|
use Engelsystem\Models\User\PasswordReset;
|
||||||
|
@ -41,6 +42,7 @@ class FactoriesTest extends TestCase
|
||||||
[Question::class],
|
[Question::class],
|
||||||
[Room::class],
|
[Room::class],
|
||||||
[Schedule::class],
|
[Schedule::class],
|
||||||
|
[ShiftEntry::class],
|
||||||
[Settings::class],
|
[Settings::class],
|
||||||
[Shift::class],
|
[Shift::class],
|
||||||
[State::class],
|
[State::class],
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace Engelsystem\Test\Unit\Models;
|
namespace Engelsystem\Test\Unit\Models;
|
||||||
|
|
||||||
use Engelsystem\Models\AngelType;
|
use Engelsystem\Models\AngelType;
|
||||||
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Engelsystem\Models\User\User;
|
use Engelsystem\Models\User\User;
|
||||||
use Engelsystem\Models\UserAngelType;
|
use Engelsystem\Models\UserAngelType;
|
||||||
|
|
||||||
|
@ -47,8 +48,7 @@ class AngelTypeTest extends ModelTest
|
||||||
User::factory(1)->create();
|
User::factory(1)->create();
|
||||||
$user2 = User::factory()->create();
|
$user2 = User::factory()->create();
|
||||||
|
|
||||||
$angelType = new AngelType(['name' => 'Test']);
|
$angelType = AngelType::create(['name' => 'Test']);
|
||||||
$angelType->save();
|
|
||||||
|
|
||||||
$angelType->userAngelTypes()->attach($user1);
|
$angelType->userAngelTypes()->attach($user1);
|
||||||
$angelType->userAngelTypes()->attach($user2);
|
$angelType->userAngelTypes()->attach($user2);
|
||||||
|
@ -61,6 +61,18 @@ class AngelTypeTest extends ModelTest
|
||||||
$this->assertCount(2, $angeltypes);
|
$this->assertCount(2, $angeltypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Models\AngelType::shiftEntries
|
||||||
|
*/
|
||||||
|
public function testShiftEntries(): void
|
||||||
|
{
|
||||||
|
$angelType = AngelType::create(['name' => 'test type']);
|
||||||
|
|
||||||
|
ShiftEntry::factory(3)->create(['angel_type_id' => $angelType->id]);
|
||||||
|
|
||||||
|
$this->assertCount(3, $angelType->shiftEntries);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \Engelsystem\Models\AngelType::boot
|
* @covers \Engelsystem\Models\AngelType::boot
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Engelsystem\Test\Unit\Models\Shifts;
|
||||||
|
|
||||||
|
use Engelsystem\Models\AngelType;
|
||||||
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
|
use Engelsystem\Models\User\User;
|
||||||
|
use Engelsystem\Test\Unit\Models\ModelTest;
|
||||||
|
|
||||||
|
class ShiftEntryTest extends ModelTest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Models\Shifts\ShiftEntry::shift
|
||||||
|
* @covers \Engelsystem\Models\Shifts\ShiftEntry::angelType
|
||||||
|
*/
|
||||||
|
public function testShift(): void
|
||||||
|
{
|
||||||
|
/** @var Shift $shift */
|
||||||
|
$shift = Shift::factory()->create();
|
||||||
|
/** @var AngelType $angelType */
|
||||||
|
$angelType = AngelType::factory()->create();
|
||||||
|
/** @var User $user */
|
||||||
|
$user = User::factory()->create();
|
||||||
|
|
||||||
|
$model = new ShiftEntry();
|
||||||
|
$model->shift()->associate($shift);
|
||||||
|
$model->angelType()->associate($angelType);
|
||||||
|
$model->user()->associate($user);
|
||||||
|
$model->save();
|
||||||
|
|
||||||
|
$model = ShiftEntry::find(1);
|
||||||
|
$this->assertEquals($shift->id, $model->shift->id);
|
||||||
|
$this->assertEquals($angelType->id, $model->angelType->id);
|
||||||
|
$this->assertEquals($user->id, $model->user->id);
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ use Engelsystem\Models\Room;
|
||||||
use Engelsystem\Models\Shifts\Schedule;
|
use Engelsystem\Models\Shifts\Schedule;
|
||||||
use Engelsystem\Models\Shifts\ScheduleShift;
|
use Engelsystem\Models\Shifts\ScheduleShift;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Engelsystem\Models\Shifts\ShiftType;
|
use Engelsystem\Models\Shifts\ShiftType;
|
||||||
use Engelsystem\Models\User\User;
|
use Engelsystem\Models\User\User;
|
||||||
use Engelsystem\Test\Unit\Models\ModelTest;
|
use Engelsystem\Test\Unit\Models\ModelTest;
|
||||||
|
@ -73,4 +74,18 @@ class ShiftTest extends ModelTest
|
||||||
$this->assertEquals(1, Shift::find(2)->schedule->id);
|
$this->assertEquals(1, Shift::find(2)->schedule->id);
|
||||||
$this->assertEquals(1, Shift::find(3)->schedule->id);
|
$this->assertEquals(1, Shift::find(3)->schedule->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Models\Shifts\Shift::shiftEntries
|
||||||
|
*/
|
||||||
|
public function testShiftEntries(): void
|
||||||
|
{
|
||||||
|
/** @var Shift $shift */
|
||||||
|
$shift = Shift::factory()->make();
|
||||||
|
$shift->save();
|
||||||
|
|
||||||
|
ShiftEntry::factory(5)->create(['shift_id' => $shift->id]);
|
||||||
|
|
||||||
|
$this->assertCount(5, $shift->shiftEntries);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ namespace Engelsystem\Test\Unit\Models\User;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
|
use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
|
||||||
|
use Engelsystem\Config\Config;
|
||||||
use Engelsystem\Models\AngelType;
|
use Engelsystem\Models\AngelType;
|
||||||
use Engelsystem\Models\BaseModel;
|
use Engelsystem\Models\BaseModel;
|
||||||
use Engelsystem\Models\Group;
|
use Engelsystem\Models\Group;
|
||||||
|
@ -13,6 +14,7 @@ use Engelsystem\Models\OAuth;
|
||||||
use Engelsystem\Models\Privilege;
|
use Engelsystem\Models\Privilege;
|
||||||
use Engelsystem\Models\Question;
|
use Engelsystem\Models\Question;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Engelsystem\Models\User\Contact;
|
use Engelsystem\Models\User\Contact;
|
||||||
use Engelsystem\Models\User\HasUserModel;
|
use Engelsystem\Models\User\HasUserModel;
|
||||||
use Engelsystem\Models\User\License;
|
use Engelsystem\Models\User\License;
|
||||||
|
@ -209,6 +211,30 @@ class UserTest extends ModelTest
|
||||||
$this->assertEquals($relatedModelIds, $user->{$name}->modelKeys());
|
$this->assertEquals($relatedModelIds, $user->{$name}->modelKeys());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Models\User\User::isFreeloader
|
||||||
|
*/
|
||||||
|
public function testIsFreeloader(): void
|
||||||
|
{
|
||||||
|
$this->app->instance('config', new Config([
|
||||||
|
'max_freeloadable_shifts' => 2,
|
||||||
|
]));
|
||||||
|
|
||||||
|
$user = new User($this->data);
|
||||||
|
$user->save();
|
||||||
|
$this->assertFalse($user->isFreeloader());
|
||||||
|
|
||||||
|
ShiftEntry::factory()->create(['user_id' => $user->id]);
|
||||||
|
ShiftEntry::factory()->create(['user_id' => $user->id, 'freeloaded' => true]);
|
||||||
|
$this->assertFalse($user->isFreeloader());
|
||||||
|
|
||||||
|
ShiftEntry::factory()->create(['user_id' => $user->id, 'freeloaded' => true]);
|
||||||
|
$this->assertTrue($user->isFreeloader());
|
||||||
|
|
||||||
|
ShiftEntry::factory()->create(['user_id' => $user->id, 'freeloaded' => true]);
|
||||||
|
$this->assertTrue($user->isFreeloader());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \Engelsystem\Models\User\User::userAngelTypes
|
* @covers \Engelsystem\Models\User\User::userAngelTypes
|
||||||
*/
|
*/
|
||||||
|
@ -334,6 +360,19 @@ class UserTest extends ModelTest
|
||||||
$this->assertCount(1, $oauth);
|
$this->assertCount(1, $oauth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Models\User\User::shiftEntries
|
||||||
|
*/
|
||||||
|
public function testShiftEntries(): void
|
||||||
|
{
|
||||||
|
$user = new User($this->data);
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
ShiftEntry::factory(2)->create(['user_id' => $user->id]);
|
||||||
|
|
||||||
|
$this->assertCount(2, $user->shiftEntries);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \Engelsystem\Models\User\User::worklogs
|
* @covers \Engelsystem\Models\User\User::worklogs
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -40,7 +40,7 @@ abstract class ExtensionTest extends TestCase
|
||||||
*/
|
*/
|
||||||
protected function assertExtensionExists(
|
protected function assertExtensionExists(
|
||||||
string $name,
|
string $name,
|
||||||
callable $callback,
|
mixed $callback,
|
||||||
array $functions,
|
array $functions,
|
||||||
array $options = []
|
array $options = []
|
||||||
): void {
|
): void {
|
||||||
|
|
|
@ -136,7 +136,12 @@ class TwigServiceProviderTest extends ServiceProviderTest
|
||||||
->method('make')
|
->method('make')
|
||||||
->withConsecutive(
|
->withConsecutive(
|
||||||
[TwigLoader::class, ['paths' => $viewsPath]],
|
[TwigLoader::class, ['paths' => $viewsPath]],
|
||||||
[Twig::class, ['options' => ['cache' => false, 'auto_reload' => true, 'strict_variables' => true]]],
|
[Twig::class, ['options' => [
|
||||||
|
'cache' => false,
|
||||||
|
'auto_reload' => true,
|
||||||
|
'strict_variables' => true,
|
||||||
|
'debug' => true,
|
||||||
|
]]],
|
||||||
[TwigEngine::class]
|
[TwigEngine::class]
|
||||||
)->willReturnOnConsecutiveCalls(
|
)->willReturnOnConsecutiveCalls(
|
||||||
$twigLoader,
|
$twigLoader,
|
||||||
|
@ -162,10 +167,10 @@ class TwigServiceProviderTest extends ServiceProviderTest
|
||||||
|
|
||||||
$this->setExpects($app, 'tag', ['renderer.twigEngine', ['renderer.engine']]);
|
$this->setExpects($app, 'tag', ['renderer.twigEngine', ['renderer.engine']]);
|
||||||
|
|
||||||
$config->expects($this->exactly(3))
|
$config->expects($this->exactly(2))
|
||||||
->method('get')
|
->method('get')
|
||||||
->withConsecutive(['environment'], ['environment'], ['timezone'])
|
->withConsecutive(['environment'], ['timezone'])
|
||||||
->willReturnOnConsecutiveCalls('development', 'development', 'The/World');
|
->willReturnOnConsecutiveCalls('development', 'The/World');
|
||||||
|
|
||||||
$twig->expects($this->once())
|
$twig->expects($this->once())
|
||||||
->method('getExtension')
|
->method('getExtension')
|
||||||
|
|
Loading…
Reference in New Issue