Implemented loading angels by shift type on schedule import
This commit is contained in:
parent
909f7bba5a
commit
4bbeb93d64
|
@ -17,11 +17,12 @@ class NeededAngelTypeFactory extends Factory
|
||||||
|
|
||||||
public function definition(): array
|
public function definition(): array
|
||||||
{
|
{
|
||||||
$forLocation = $this->faker->boolean();
|
$type = $this->faker->numberBetween(0, 2);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'location_id' => $forLocation ? Location::factory() : null,
|
'location_id' => $type == 0 ? Location::factory() : null,
|
||||||
'shift_id' => $forLocation ? null : Shift::factory(),
|
'shift_id' => $type == 1 ? null : Shift::factory(),
|
||||||
|
'shift_type_id' => $type == 2 ? null : Shift::factory(),
|
||||||
'angel_type_id' => AngelType::factory(),
|
'angel_type_id' => AngelType::factory(),
|
||||||
'count' => $this->faker->numberBetween(1, 5),
|
'count' => $this->faker->numberBetween(1, 5),
|
||||||
];
|
];
|
||||||
|
|
|
@ -18,6 +18,7 @@ class ScheduleFactory extends Factory
|
||||||
'name' => $this->faker->unique()->words(4, true),
|
'name' => $this->faker->unique()->words(4, true),
|
||||||
'url' => $this->faker->parse('https://{{safeEmailDomain}}/{{slug}}.xml'),
|
'url' => $this->faker->parse('https://{{safeEmailDomain}}/{{slug}}.xml'),
|
||||||
'shift_type' => $this->faker->numberBetween(1, 5),
|
'shift_type' => $this->faker->numberBetween(1, 5),
|
||||||
|
'needed_from_shift_type' => $this->faker->boolean(.2),
|
||||||
'minutes_before' => 15,
|
'minutes_before' => 15,
|
||||||
'minutes_after' => 15,
|
'minutes_after' => 15,
|
||||||
];
|
];
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Engelsystem\Migrations;
|
||||||
|
|
||||||
|
use Engelsystem\Database\Migration\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
|
||||||
|
class ScheduleShiftTypeNeededAngelTypes extends Migration
|
||||||
|
{
|
||||||
|
use Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the migration
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('schedules', function (Blueprint $table): void {
|
||||||
|
$table->boolean('needed_from_shift_type')->after('shift_type')->default(false);
|
||||||
|
});
|
||||||
|
$this->schema->table('needed_angel_types', function (Blueprint $table): void {
|
||||||
|
$this->references($table, 'shift_types')->after('shift_id')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migration
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$this->schema->table('schedules', function (Blueprint $table): void {
|
||||||
|
$table->dropColumn('needed_from_shift_type');
|
||||||
|
});
|
||||||
|
$this->schema->table('needed_angel_types', function (Blueprint $table): void {
|
||||||
|
$table->dropForeign('needed_angel_types_shift_type_id_foreign');
|
||||||
|
$table->dropColumn('shift_type_id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -74,7 +74,7 @@ function shift_edit_controller()
|
||||||
$angeltypes = AngelType::all()->pluck('name', 'id')->toArray();
|
$angeltypes = AngelType::all()->pluck('name', 'id')->toArray();
|
||||||
$shifttypes = ShiftType::all()->pluck('name', 'id')->toArray();
|
$shifttypes = ShiftType::all()->pluck('name', 'id')->toArray();
|
||||||
|
|
||||||
$needed_angel_types = collect(NeededAngelTypes_by_shift($shift_id))->pluck('count', 'angel_type_id')->toArray();
|
$needed_angel_types = collect(NeededAngelTypes_by_shift($shift))->pluck('count', 'angel_type_id')->toArray();
|
||||||
foreach (array_keys($angeltypes) as $angeltype_id) {
|
foreach (array_keys($angeltypes) as $angeltype_id) {
|
||||||
if (!isset($needed_angel_types[$angeltype_id])) {
|
if (!isset($needed_angel_types[$angeltype_id])) {
|
||||||
$needed_angel_types[$angeltype_id] = 0;
|
$needed_angel_types[$angeltype_id] = 0;
|
||||||
|
|
|
@ -1,47 +1,70 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Engelsystem\Database\Db;
|
use Engelsystem\Database\Db;
|
||||||
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
use Engelsystem\Models\Shifts\ShiftEntry;
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all needed angeltypes and already taken needs.
|
* Returns all needed angeltypes and already taken needs.
|
||||||
*
|
*
|
||||||
* @param int $shiftId id of shift
|
* @param Shift $shift
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
function NeededAngelTypes_by_shift($shiftId)
|
function NeededAngelTypes_by_shift($shift)
|
||||||
{
|
{
|
||||||
|
$needed_angeltypes_source = [];
|
||||||
|
// Select from shift
|
||||||
|
if (!$shift->schedule) {
|
||||||
$needed_angeltypes_source = Db::select(
|
$needed_angeltypes_source = Db::select(
|
||||||
'
|
'
|
||||||
SELECT
|
SELECT
|
||||||
`needed_angel_types`.*,
|
`needed_angel_types`.*,
|
||||||
`angel_types`.`id`,
|
|
||||||
`angel_types`.`name`,
|
`angel_types`.`name`,
|
||||||
`angel_types`.`restricted`,
|
`angel_types`.`restricted`,
|
||||||
`angel_types`.`shift_self_signup`
|
`angel_types`.`shift_self_signup`
|
||||||
FROM `needed_angel_types`
|
FROM `needed_angel_types`
|
||||||
JOIN `angel_types` ON `angel_types`.`id` = `needed_angel_types`.`angel_type_id`
|
JOIN `angel_types` ON `angel_types`.`id` = `needed_angel_types`.`angel_type_id`
|
||||||
WHERE `shift_id` = ?
|
WHERE `needed_angel_types`.`shift_id` = ?
|
||||||
ORDER BY `location_id` DESC',
|
ORDER BY `location_id` DESC
|
||||||
[$shiftId]
|
',
|
||||||
|
[$shift->id]
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Use settings from location
|
// Get needed by shift type
|
||||||
if (count($needed_angeltypes_source) == 0) {
|
if ($shift->schedule && $shift->schedule->needed_from_shift_type) {
|
||||||
$needed_angeltypes_source = Db::select('
|
$needed_angeltypes_source = Db::select('
|
||||||
SELECT `needed_angel_types`.*, `angel_types`.`name`, `angel_types`.`restricted`
|
SELECT
|
||||||
|
`needed_angel_types`.*,
|
||||||
|
`angel_types`.`name`,
|
||||||
|
`angel_types`.`restricted`,
|
||||||
|
`angel_types`.`shift_self_signup`
|
||||||
FROM `needed_angel_types`
|
FROM `needed_angel_types`
|
||||||
JOIN `angel_types` ON `angel_types`.`id` = `needed_angel_types`.`angel_type_id`
|
JOIN `angel_types` ON `angel_types`.`id` = `needed_angel_types`.`angel_type_id`
|
||||||
JOIN `shifts` ON `shifts`.`location_id` = `needed_angel_types`.`location_id`
|
WHERE `needed_angel_types`.`shift_type_id` = ?
|
||||||
WHERE `shifts`.`id` = ?
|
|
||||||
ORDER BY `location_id` DESC
|
ORDER BY `location_id` DESC
|
||||||
', [$shiftId]);
|
', [$shift->shift_type_id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load from room
|
||||||
|
if ($shift->schedule && !$shift->schedule->needed_from_shift_type) {
|
||||||
|
$needed_angeltypes_source = Db::select('
|
||||||
|
SELECT
|
||||||
|
`needed_angel_types`.*,
|
||||||
|
`angel_types`.`name`,
|
||||||
|
`angel_types`.`restricted`,
|
||||||
|
`angel_types`.`shift_self_signup`
|
||||||
|
FROM `needed_angel_types`
|
||||||
|
JOIN `angel_types` ON `angel_types`.`id` = `needed_angel_types`.`angel_type_id`
|
||||||
|
WHERE `needed_angel_types`.`location_id` = ?
|
||||||
|
ORDER BY `location_id` DESC
|
||||||
|
', [$shift->location_id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var ShiftEntry[]|Collection $shift_entries */
|
/** @var ShiftEntry[]|Collection $shift_entries */
|
||||||
$shift_entries = ShiftEntry::with('user', 'angelType')
|
$shift_entries = ShiftEntry::with('user', 'angelType')
|
||||||
->where('shift_id', $shiftId)
|
->where('shift_id', $shift->id)
|
||||||
->get();
|
->get();
|
||||||
$needed_angeltypes = [];
|
$needed_angeltypes = [];
|
||||||
foreach ($needed_angeltypes_source as $angeltype) {
|
foreach ($needed_angeltypes_source as $angeltype) {
|
||||||
|
|
|
@ -28,12 +28,26 @@ function Shifts_by_angeltype(AngelType $angeltype)
|
||||||
|
|
||||||
UNION
|
UNION
|
||||||
|
|
||||||
|
/* By shift type */
|
||||||
|
SELECT DISTINCT `shifts`.* FROM `shifts`
|
||||||
|
JOIN `needed_angel_types` ON `needed_angel_types`.`shift_type_id` = `shifts`.`shift_type_id`
|
||||||
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE `needed_angel_types`.`angel_type_id` = ?
|
||||||
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = TRUE
|
||||||
|
|
||||||
|
UNION
|
||||||
|
|
||||||
|
/* By location */
|
||||||
SELECT DISTINCT `shifts`.* FROM `shifts`
|
SELECT DISTINCT `shifts`.* FROM `shifts`
|
||||||
JOIN `needed_angel_types` ON `needed_angel_types`.`location_id` = `shifts`.`location_id`
|
JOIN `needed_angel_types` ON `needed_angel_types`.`location_id` = `shifts`.`location_id`
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
WHERE `needed_angel_types`.`angel_type_id` = ?
|
WHERE `needed_angel_types`.`angel_type_id` = ?
|
||||||
AND NOT s.shift_id IS NULL
|
AND NOT s.shift_id IS NULL
|
||||||
', [$angeltype->id, $angeltype->id]);
|
AND se.needed_from_shift_type = FALSE
|
||||||
|
', [$angeltype->id, $angeltype->id, $angeltype->id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,7 +67,7 @@ function Shifts_free($start, $end, ShiftsFilter $filter = null)
|
||||||
$shifts = Db::select('
|
$shifts = Db::select('
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM (
|
FROM (
|
||||||
SELECT id, start
|
SELECT shifts.id, start
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
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` < ?)
|
||||||
|
@ -64,13 +78,30 @@ function Shifts_free($start, $end, ShiftsFilter $filter = null)
|
||||||
|
|
||||||
UNION
|
UNION
|
||||||
|
|
||||||
SELECT id, start
|
/* By shift type */
|
||||||
|
SELECT shifts.id, start
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE (`end` > ? AND `start` < ?)
|
||||||
|
AND (SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`' . ($filter ? ' AND needed_angel_types.angel_type_id 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 NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = TRUE
|
||||||
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
|
|
||||||
|
UNION
|
||||||
|
|
||||||
|
/* By location */
|
||||||
|
SELECT shifts.id, start
|
||||||
|
FROM `shifts`
|
||||||
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
WHERE (`end` > ? AND `start` < ?)
|
WHERE (`end` > ? AND `start` < ?)
|
||||||
AND (SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`location_id`=`shifts`.`location_id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
AND (SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`location_id`=`shifts`.`location_id`' . ($filter ? ' AND needed_angel_types.angel_type_id 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()) . ')' : '') . ')
|
> (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 NOT s.shift_id IS NULL
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = FALSE
|
||||||
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
) AS `tmp`
|
) AS `tmp`
|
||||||
ORDER BY `tmp`.`start`
|
ORDER BY `tmp`.`start`
|
||||||
|
@ -79,6 +110,8 @@ function Shifts_free($start, $end, ShiftsFilter $filter = null)
|
||||||
$end,
|
$end,
|
||||||
$start,
|
$start,
|
||||||
$end,
|
$end,
|
||||||
|
$start,
|
||||||
|
$end,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$shifts = collect($shifts);
|
$shifts = collect($shifts);
|
||||||
|
@ -110,16 +143,35 @@ function Shifts_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
|
||||||
|
|
||||||
UNION
|
UNION
|
||||||
|
|
||||||
|
/* By shift type */
|
||||||
|
SELECT DISTINCT `shifts`.*, `shift_types`.`name`, `locations`.`name` AS `location_name`
|
||||||
|
FROM `shifts`
|
||||||
|
JOIN `locations` ON `shifts`.`location_id` = `locations`.`id`
|
||||||
|
JOIN `shift_types` ON `shift_types`.`id` = `shifts`.`shift_type_id`
|
||||||
|
JOIN `needed_angel_types` ON `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`
|
||||||
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
|
||||||
|
AND `start` BETWEEN ? AND ?
|
||||||
|
AND `needed_angel_types`.`angel_type_id` IN (' . implode(',', $shiftsFilter->getTypes()) . ')
|
||||||
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = TRUE
|
||||||
|
|
||||||
|
UNION
|
||||||
|
|
||||||
|
/* By location */
|
||||||
SELECT DISTINCT `shifts`.*, `shift_types`.`name`, `locations`.`name` AS `location_name`
|
SELECT DISTINCT `shifts`.*, `shift_types`.`name`, `locations`.`name` AS `location_name`
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
JOIN `locations` ON `shifts`.`location_id` = `locations`.`id`
|
JOIN `locations` ON `shifts`.`location_id` = `locations`.`id`
|
||||||
JOIN `shift_types` ON `shift_types`.`id` = `shifts`.`shift_type_id`
|
JOIN `shift_types` ON `shift_types`.`id` = `shifts`.`shift_type_id`
|
||||||
JOIN `needed_angel_types` ON `needed_angel_types`.`location_id`=`shifts`.`location_id`
|
JOIN `needed_angel_types` ON `needed_angel_types`.`location_id`=`shifts`.`location_id`
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
|
WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
|
||||||
AND `start` BETWEEN ? AND ?
|
AND `start` BETWEEN ? AND ?
|
||||||
AND `needed_angel_types`.`angel_type_id` IN (' . implode(',', $shiftsFilter->getTypes()) . ')
|
AND `needed_angel_types`.`angel_type_id` IN (' . implode(',', $shiftsFilter->getTypes()) . ')
|
||||||
AND NOT s.shift_id IS NULL
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = FALSE
|
||||||
) AS tmp_shifts
|
) AS tmp_shifts
|
||||||
|
|
||||||
ORDER BY `location_name`, `start`
|
ORDER BY `location_name`, `start`
|
||||||
|
@ -132,6 +184,8 @@ function Shifts_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
|
||||||
$shiftsFilter->getEnd(),
|
$shiftsFilter->getEnd(),
|
||||||
$shiftsFilter->getStart(),
|
$shiftsFilter->getStart(),
|
||||||
$shiftsFilter->getEnd(),
|
$shiftsFilter->getEnd(),
|
||||||
|
$shiftsFilter->getStart(),
|
||||||
|
$shiftsFilter->getEnd(),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -167,6 +221,27 @@ function NeededAngeltypes_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
|
||||||
|
|
||||||
UNION
|
UNION
|
||||||
|
|
||||||
|
/* By shift type */
|
||||||
|
SELECT
|
||||||
|
`needed_angel_types`.*,
|
||||||
|
`shifts`.`id` AS shift_id,
|
||||||
|
`angel_types`.`id`,
|
||||||
|
`angel_types`.`name`,
|
||||||
|
`angel_types`.`restricted`,
|
||||||
|
`angel_types`.`shift_self_signup`
|
||||||
|
FROM `shifts`
|
||||||
|
JOIN `needed_angel_types` ON `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`
|
||||||
|
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
|
||||||
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
|
||||||
|
AND shifts.`start` BETWEEN ? AND ?
|
||||||
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = TRUE
|
||||||
|
|
||||||
|
UNION
|
||||||
|
|
||||||
|
/* By location */
|
||||||
SELECT
|
SELECT
|
||||||
`needed_angel_types`.*,
|
`needed_angel_types`.*,
|
||||||
`shifts`.`id` AS shift_id,
|
`shifts`.`id` AS shift_id,
|
||||||
|
@ -178,9 +253,11 @@ function NeededAngeltypes_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
|
||||||
JOIN `needed_angel_types` ON `needed_angel_types`.`location_id`=`shifts`.`location_id`
|
JOIN `needed_angel_types` ON `needed_angel_types`.`location_id`=`shifts`.`location_id`
|
||||||
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
|
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
|
WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
|
||||||
AND shifts.`start` BETWEEN ? AND ?
|
AND shifts.`start` BETWEEN ? AND ?
|
||||||
AND NOT s.shift_id IS NULL
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = FALSE
|
||||||
';
|
';
|
||||||
|
|
||||||
return Db::select(
|
return Db::select(
|
||||||
|
@ -190,6 +267,8 @@ function NeededAngeltypes_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
|
||||||
$shiftsFilter->getEnd(),
|
$shiftsFilter->getEnd(),
|
||||||
$shiftsFilter->getStart(),
|
$shiftsFilter->getStart(),
|
||||||
$shiftsFilter->getEnd(),
|
$shiftsFilter->getEnd(),
|
||||||
|
$shiftsFilter->getStart(),
|
||||||
|
$shiftsFilter->getEnd(),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -220,6 +299,27 @@ function NeededAngeltype_by_Shift_and_Angeltype(Shift $shift, AngelType $angelty
|
||||||
|
|
||||||
UNION
|
UNION
|
||||||
|
|
||||||
|
/* By shift type */
|
||||||
|
SELECT
|
||||||
|
`needed_angel_types`.*,
|
||||||
|
`shifts`.`id` AS shift_id,
|
||||||
|
`angel_types`.`id`,
|
||||||
|
`angel_types`.`name`,
|
||||||
|
`angel_types`.`restricted`,
|
||||||
|
`angel_types`.`shift_self_signup`
|
||||||
|
FROM `shifts`
|
||||||
|
JOIN `needed_angel_types` ON `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`
|
||||||
|
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
|
||||||
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE `shifts`.`id`=?
|
||||||
|
AND `angel_types`.`id`=?
|
||||||
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = TRUE
|
||||||
|
|
||||||
|
UNION
|
||||||
|
|
||||||
|
/* By location */
|
||||||
SELECT
|
SELECT
|
||||||
`needed_angel_types`.*,
|
`needed_angel_types`.*,
|
||||||
`shifts`.`id` AS shift_id,
|
`shifts`.`id` AS shift_id,
|
||||||
|
@ -231,15 +331,19 @@ function NeededAngeltype_by_Shift_and_Angeltype(Shift $shift, AngelType $angelty
|
||||||
JOIN `needed_angel_types` ON `needed_angel_types`.`location_id`=`shifts`.`location_id`
|
JOIN `needed_angel_types` ON `needed_angel_types`.`location_id`=`shifts`.`location_id`
|
||||||
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
|
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
WHERE `shifts`.`id`=?
|
WHERE `shifts`.`id`=?
|
||||||
AND `angel_types`.`id`=?
|
AND `angel_types`.`id`=?
|
||||||
AND NOT s.shift_id IS NULL
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = FALSE
|
||||||
',
|
',
|
||||||
[
|
[
|
||||||
$shift->id,
|
$shift->id,
|
||||||
$angeltype->id,
|
$angeltype->id,
|
||||||
$shift->id,
|
$shift->id,
|
||||||
$angeltype->id,
|
$angeltype->id,
|
||||||
|
$shift->id,
|
||||||
|
$angeltype->id,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -559,7 +663,7 @@ function Shift($shift)
|
||||||
}
|
}
|
||||||
|
|
||||||
$neededAngels = [];
|
$neededAngels = [];
|
||||||
$angelTypes = NeededAngelTypes_by_shift($shift->id);
|
$angelTypes = NeededAngelTypes_by_shift($shift);
|
||||||
foreach ($angelTypes as $type) {
|
foreach ($angelTypes as $type) {
|
||||||
$neededAngels[] = [
|
$neededAngels[] = [
|
||||||
'angel_type_id' => $type['angel_type_id'],
|
'angel_type_id' => $type['angel_type_id'],
|
||||||
|
|
|
@ -47,19 +47,36 @@ function stats_hours_to_work(ShiftsFilter $filter = null)
|
||||||
* TIMESTAMPDIFF(MINUTE, `shifts`.`start`, `shifts`.`end`) / 60 AS `count`
|
* TIMESTAMPDIFF(MINUTE, `shifts`.`start`, `shifts`.`end`) / 60 AS `count`
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
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 `shifts`.`end` >= NOW()
|
WHERE shifts.`end` >= NOW()
|
||||||
AND s.shift_id IS NULL
|
AND s.shift_id IS NULL
|
||||||
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
|
|
||||||
UNION ALL
|
UNION ALL
|
||||||
|
|
||||||
|
/* By shift type */
|
||||||
|
SELECT
|
||||||
|
(SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
||||||
|
* TIMESTAMPDIFF(MINUTE, `shifts`.`start`, `shifts`.`end`) / 60 AS `count`
|
||||||
|
FROM `shifts`
|
||||||
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE shifts.`end` >= NOW()
|
||||||
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = TRUE
|
||||||
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
|
||||||
|
/* By location */
|
||||||
SELECT
|
SELECT
|
||||||
(SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`location_id`=`shifts`.`location_id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
(SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`location_id`=`shifts`.`location_id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
|
||||||
* TIMESTAMPDIFF(MINUTE, `shifts`.`start`, `shifts`.`end`) / 60 AS `count`
|
* TIMESTAMPDIFF(MINUTE, `shifts`.`start`, `shifts`.`end`) / 60 AS `count`
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
WHERE shifts.`end` >= NOW()
|
WHERE shifts.`end` >= NOW()
|
||||||
AND NOT s.shift_id IS NULL
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = FALSE
|
||||||
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
) AS `tmp`
|
) AS `tmp`
|
||||||
'
|
'
|
||||||
|
@ -90,7 +107,8 @@ function stats_angels_needed_three_hours(ShiftsFilter $filter = null)
|
||||||
AND `needed_angel_types`.`shift_id`=`shifts`.`id`
|
AND `needed_angel_types`.`shift_id`=`shifts`.`id`
|
||||||
' . ($filter ? 'AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
' . ($filter ? 'AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
) - (
|
) - (
|
||||||
SELECT COUNT(*) FROM `shift_entries`
|
SELECT COUNT(*)
|
||||||
|
FROM `shift_entries`
|
||||||
JOIN `angel_types` ON `angel_types`.`id`=`shift_entries`.`angel_type_id`
|
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 `shift_entries`.`shift_id`=`shifts`.`id`
|
AND `shift_entries`.`shift_id`=`shifts`.`id`
|
||||||
|
@ -107,6 +125,38 @@ function stats_angels_needed_three_hours(ShiftsFilter $filter = null)
|
||||||
|
|
||||||
UNION ALL
|
UNION ALL
|
||||||
|
|
||||||
|
/* By shift type */
|
||||||
|
SELECT
|
||||||
|
GREATEST(0,
|
||||||
|
(
|
||||||
|
SELECT SUM(needed_angel_types.`count`)
|
||||||
|
FROM `needed_angel_types`
|
||||||
|
JOIN `angel_types` ON `angel_types`.`id`=`needed_angel_types`.`angel_type_id`
|
||||||
|
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
||||||
|
AND `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`
|
||||||
|
' . ($filter ? 'AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
|
) - (
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM `shift_entries`
|
||||||
|
JOIN `angel_types` ON `angel_types`.`id`=`shift_entries`.`angel_type_id`
|
||||||
|
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
||||||
|
AND `shift_entries`.`shift_id`=`shifts`.`id`
|
||||||
|
AND `freeloaded`=0
|
||||||
|
' . ($filter ? 'AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
|
)
|
||||||
|
)
|
||||||
|
AS `count`
|
||||||
|
FROM `shifts`
|
||||||
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE shifts.`end` > NOW() AND shifts.`start` < ?
|
||||||
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = TRUE
|
||||||
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
|
||||||
|
/* By location */
|
||||||
SELECT
|
SELECT
|
||||||
GREATEST(0,
|
GREATEST(0,
|
||||||
(
|
(
|
||||||
|
@ -129,12 +179,15 @@ function stats_angels_needed_three_hours(ShiftsFilter $filter = null)
|
||||||
AS `count`
|
AS `count`
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
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` > NOW() AND `start` < ?
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE shifts.`end` > NOW() AND shifts.`start` < ?
|
||||||
AND NOT s.shift_id IS NULL
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = FALSE
|
||||||
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
) AS `tmp`', [
|
) AS `tmp`', [
|
||||||
$in3hours,
|
$in3hours,
|
||||||
$in3hours,
|
$in3hours,
|
||||||
|
$in3hours,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $result['count'] ?: '-';
|
return $result['count'] ?: '-';
|
||||||
|
@ -189,6 +242,37 @@ function stats_angels_needed_for_nightshifts(ShiftsFilter $filter = null)
|
||||||
|
|
||||||
UNION ALL
|
UNION ALL
|
||||||
|
|
||||||
|
/* By shift type */
|
||||||
|
SELECT
|
||||||
|
GREATEST(0,
|
||||||
|
(
|
||||||
|
SELECT SUM(needed_angel_types.`count`)
|
||||||
|
FROM `needed_angel_types`
|
||||||
|
JOIN `angel_types` ON `angel_types`.`id`=`needed_angel_types`.`angel_type_id`
|
||||||
|
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
||||||
|
AND `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`
|
||||||
|
' . ($filter ? 'AND angel_types.id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
|
) - (
|
||||||
|
SELECT COUNT(*) FROM `shift_entries`
|
||||||
|
JOIN `angel_types` ON `angel_types`.`id`=`shift_entries`.`angel_type_id`
|
||||||
|
WHERE `angel_types`.`show_on_dashboard`=TRUE
|
||||||
|
AND `shift_entries`.`shift_id`=`shifts`.`id`
|
||||||
|
AND shift_entries.`freeloaded`=0
|
||||||
|
' . ($filter ? 'AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
|
)
|
||||||
|
)
|
||||||
|
AS `count`
|
||||||
|
FROM `shifts`
|
||||||
|
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
|
||||||
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE shifts.`end` > ? AND shifts.`start` < ?
|
||||||
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = TRUE
|
||||||
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
|
||||||
|
/* By location */
|
||||||
SELECT
|
SELECT
|
||||||
GREATEST(0,
|
GREATEST(0,
|
||||||
(
|
(
|
||||||
|
@ -203,21 +287,25 @@ function stats_angels_needed_for_nightshifts(ShiftsFilter $filter = null)
|
||||||
JOIN `angel_types` ON `angel_types`.`id`=`shift_entries`.`angel_type_id`
|
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 `shift_entries`.`shift_id`=`shifts`.`id`
|
AND `shift_entries`.`shift_id`=`shifts`.`id`
|
||||||
AND `freeloaded`=0
|
AND shift_entries.`freeloaded`=0
|
||||||
' . ($filter ? 'AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
' . ($filter ? 'AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
AS `count`
|
AS `count`
|
||||||
FROM `shifts`
|
FROM `shifts`
|
||||||
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` < ?
|
LEFT JOIN schedules AS se on s.schedule_id = se.id
|
||||||
|
WHERE shifts.`end` > ? AND shifts.`start` < ?
|
||||||
AND NOT s.shift_id IS NULL
|
AND NOT s.shift_id IS NULL
|
||||||
|
AND se.needed_from_shift_type = FALSE
|
||||||
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
|
||||||
) AS `tmp`', [
|
) AS `tmp`', [
|
||||||
$night_start,
|
$night_start,
|
||||||
$night_end,
|
$night_end,
|
||||||
$night_start,
|
$night_start,
|
||||||
$night_end,
|
$night_end,
|
||||||
|
$night_start,
|
||||||
|
$night_end,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $result['count'] ?: '-';
|
return $result['count'] ?: '-';
|
||||||
|
|
|
@ -171,7 +171,9 @@ function admin_shifts()
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->has('angelmode')) {
|
if ($request->has('angelmode')) {
|
||||||
if ($request->input('angelmode') == 'location') {
|
if ($request->input('angelmode') == 'shift_type') {
|
||||||
|
$angelmode = 'shift_type';
|
||||||
|
} elseif ($request->input('angelmode') == 'location') {
|
||||||
$angelmode = 'location';
|
$angelmode = 'location';
|
||||||
} elseif ($request->input('angelmode') == 'manually') {
|
} elseif ($request->input('angelmode') == 'manually') {
|
||||||
foreach ($types as $type) {
|
foreach ($types as $type) {
|
||||||
|
@ -203,7 +205,11 @@ function admin_shifts()
|
||||||
|
|
||||||
// Alle Eingaben in Ordnung
|
// Alle Eingaben in Ordnung
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($angelmode == 'location') {
|
if ($angelmode == 'shift_type') {
|
||||||
|
$needed_angel_types = NeededAngelType::whereShiftTypeId($shifttype_id)
|
||||||
|
->pluck('count', 'angel_type_id')
|
||||||
|
->toArray() + $needed_angel_types;
|
||||||
|
} elseif ($angelmode == 'location') {
|
||||||
$needed_angel_types = NeededAngelType::whereLocationId($lid)
|
$needed_angel_types = NeededAngelType::whereLocationId($lid)
|
||||||
->pluck('count', 'angel_type_id')
|
->pluck('count', 'angel_type_id')
|
||||||
->toArray() + $needed_angel_types;
|
->toArray() + $needed_angel_types;
|
||||||
|
@ -541,7 +547,13 @@ function admin_shifts()
|
||||||
form_info(__('Needed angels')),
|
form_info(__('Needed angels')),
|
||||||
form_radio(
|
form_radio(
|
||||||
'angelmode',
|
'angelmode',
|
||||||
__('Take needed angels from location settings'),
|
__('Copy needed angels from shift type settings'),
|
||||||
|
$angelmode == 'shift_type',
|
||||||
|
'shift_type'
|
||||||
|
),
|
||||||
|
form_radio(
|
||||||
|
'angelmode',
|
||||||
|
__('Copy needed angels from location settings'),
|
||||||
$angelmode == 'location',
|
$angelmode == 'location',
|
||||||
'location'
|
'location'
|
||||||
),
|
),
|
||||||
|
|
|
@ -118,6 +118,7 @@ class ImportSchedule extends BaseController
|
||||||
'name' => 'required',
|
'name' => 'required',
|
||||||
'url' => 'required',
|
'url' => 'required',
|
||||||
'shift_type' => 'required|int',
|
'shift_type' => 'required|int',
|
||||||
|
'needed_from_shift_type' => 'optional|checked',
|
||||||
'minutes_before' => 'int',
|
'minutes_before' => 'int',
|
||||||
'minutes_after' => 'int',
|
'minutes_after' => 'int',
|
||||||
]);
|
]);
|
||||||
|
@ -129,17 +130,19 @@ class ImportSchedule extends BaseController
|
||||||
$schedule->name = $data['name'];
|
$schedule->name = $data['name'];
|
||||||
$schedule->url = $data['url'];
|
$schedule->url = $data['url'];
|
||||||
$schedule->shift_type = $data['shift_type'];
|
$schedule->shift_type = $data['shift_type'];
|
||||||
|
$schedule->needed_from_shift_type = (bool) $data['needed_from_shift_type'];
|
||||||
$schedule->minutes_before = $data['minutes_before'];
|
$schedule->minutes_before = $data['minutes_before'];
|
||||||
$schedule->minutes_after = $data['minutes_after'];
|
$schedule->minutes_after = $data['minutes_after'];
|
||||||
|
|
||||||
$schedule->save();
|
$schedule->save();
|
||||||
|
|
||||||
$this->log->info(
|
$this->log->info(
|
||||||
'Schedule {name}: Url {url}, Shift Type {shift_type}, minutes before/after {before}/{after}',
|
'Schedule {name}: Url {url}, Shift Type {shift_type}, ({need}), minutes before/after {before}/{after}',
|
||||||
[
|
[
|
||||||
'name' => $schedule->name,
|
'name' => $schedule->name,
|
||||||
'url' => $schedule->name,
|
'url' => $schedule->name,
|
||||||
'shift_type' => $schedule->shift_type,
|
'shift_type' => $schedule->shift_type,
|
||||||
|
'need' => $schedule->needed_from_shift_type ? 'from shift type' : 'from room',
|
||||||
'before' => $schedule->minutes_before,
|
'before' => $schedule->minutes_before,
|
||||||
'after' => $schedule->minutes_after,
|
'after' => $schedule->minutes_after,
|
||||||
]
|
]
|
||||||
|
@ -169,8 +172,8 @@ class ImportSchedule extends BaseController
|
||||||
''
|
''
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->fireDeleteShiftEntryEvents($event);
|
$this->fireDeleteShiftEntryEvents($event, $schedule);
|
||||||
$this->deleteEvent($event);
|
$this->deleteEvent($event, $schedule);
|
||||||
}
|
}
|
||||||
$schedule->delete();
|
$schedule->delete();
|
||||||
|
|
||||||
|
@ -271,13 +274,14 @@ class ImportSchedule extends BaseController
|
||||||
$shiftType,
|
$shiftType,
|
||||||
$locations
|
$locations
|
||||||
->where('name', $event->getRoom()->getName())
|
->where('name', $event->getRoom()->getName())
|
||||||
->first()
|
->first(),
|
||||||
|
$scheduleUrl
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($deleteEvents as $event) {
|
foreach ($deleteEvents as $event) {
|
||||||
$this->fireDeleteShiftEntryEvents($event);
|
$this->fireDeleteShiftEntryEvents($event, $scheduleUrl);
|
||||||
$this->deleteEvent($event);
|
$this->deleteEvent($event, $scheduleUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
$scheduleUrl->touch();
|
$scheduleUrl->touch();
|
||||||
|
@ -296,7 +300,7 @@ class ImportSchedule extends BaseController
|
||||||
$this->log('Created schedule location "{location}"', ['location' => $room->getName()]);
|
$this->log('Created schedule location "{location}"', ['location' => $room->getName()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function fireDeleteShiftEntryEvents(Event $event): void
|
protected function fireDeleteShiftEntryEvents(Event $event, ScheduleUrl $schedule): void
|
||||||
{
|
{
|
||||||
$shiftEntries = $this->db
|
$shiftEntries = $this->db
|
||||||
->table('shift_entries')
|
->table('shift_entries')
|
||||||
|
@ -310,6 +314,7 @@ class ImportSchedule extends BaseController
|
||||||
->join('angel_types', 'angel_types.id', 'shift_entries.angel_type_id')
|
->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())
|
||||||
|
->where('schedule_shift.schedule_id', $schedule->id)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
foreach ($shiftEntries as $shiftEntry) {
|
foreach ($shiftEntries as $shiftEntry) {
|
||||||
|
@ -359,13 +364,13 @@ class ImportSchedule extends BaseController
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function updateEvent(Event $event, int $shiftTypeId, Location $location): void
|
protected function updateEvent(Event $event, int $shiftTypeId, Location $location, ScheduleUrl $schedule): void
|
||||||
{
|
{
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$eventTimeZone = Carbon::now()->timezone;
|
$eventTimeZone = Carbon::now()->timezone;
|
||||||
|
|
||||||
/** @var ScheduleShift $scheduleShift */
|
/** @var ScheduleShift $scheduleShift */
|
||||||
$scheduleShift = ScheduleShift::whereGuid($event->getGuid())->first();
|
$scheduleShift = ScheduleShift::whereGuid($event->getGuid())->where('schedule_id', $schedule->id)->first();
|
||||||
$shift = $scheduleShift->shift;
|
$shift = $scheduleShift->shift;
|
||||||
$shift->title = $event->getTitle();
|
$shift->title = $event->getTitle();
|
||||||
$shift->shift_type_id = $shiftTypeId;
|
$shift->shift_type_id = $shiftTypeId;
|
||||||
|
@ -388,10 +393,10 @@ class ImportSchedule extends BaseController
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function deleteEvent(Event $event): void
|
protected function deleteEvent(Event $event, ScheduleUrl $schedule): void
|
||||||
{
|
{
|
||||||
/** @var ScheduleShift $scheduleShift */
|
/** @var ScheduleShift $scheduleShift */
|
||||||
$scheduleShift = ScheduleShift::whereGuid($event->getGuid())->first();
|
$scheduleShift = ScheduleShift::whereGuid($event->getGuid())->where('schedule_id', $schedule->id)->first();
|
||||||
$shift = $scheduleShift->shift;
|
$shift = $scheduleShift->shift;
|
||||||
$shift->delete();
|
$shift->delete();
|
||||||
|
|
||||||
|
@ -509,10 +514,10 @@ class ImportSchedule extends BaseController
|
||||||
|
|
||||||
$scheduleEventsGuidList = array_keys($scheduleEvents);
|
$scheduleEventsGuidList = array_keys($scheduleEvents);
|
||||||
$existingShifts = $this->getScheduleShiftsByGuid($scheduleUrl, $scheduleEventsGuidList);
|
$existingShifts = $this->getScheduleShiftsByGuid($scheduleUrl, $scheduleEventsGuidList);
|
||||||
foreach ($existingShifts as $shift) {
|
foreach ($existingShifts as $scheduleShift) {
|
||||||
$guid = $shift->guid;
|
$guid = $scheduleShift->guid;
|
||||||
/** @var Shift $shift */
|
/** @var Shift $shift */
|
||||||
$shift = Shift::with('location')->find($shift->shift_id);
|
$shift = Shift::with('location')->find($scheduleShift->shift_id);
|
||||||
$event = $scheduleEvents[$guid];
|
$event = $scheduleEvents[$guid];
|
||||||
$location = $locations->where('name', $event->getRoom()->getName())->first();
|
$location = $locations->where('name', $event->getRoom()->getName())->first();
|
||||||
|
|
||||||
|
@ -535,8 +540,8 @@ class ImportSchedule extends BaseController
|
||||||
}
|
}
|
||||||
|
|
||||||
$scheduleShifts = $this->getScheduleShiftsWhereNotGuid($scheduleUrl, $scheduleEventsGuidList);
|
$scheduleShifts = $this->getScheduleShiftsWhereNotGuid($scheduleUrl, $scheduleEventsGuidList);
|
||||||
foreach ($scheduleShifts as $shift) {
|
foreach ($scheduleShifts as $scheduleShift) {
|
||||||
$event = $this->eventFromScheduleShift($shift);
|
$event = $this->eventFromScheduleShift($scheduleShift);
|
||||||
$deleteEvents[$event->getGuid()] = $event;
|
$deleteEvents[$event->getGuid()] = $event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,8 +550,7 @@ class ImportSchedule extends BaseController
|
||||||
|
|
||||||
protected function eventFromScheduleShift(ScheduleShift $scheduleShift): Event
|
protected function eventFromScheduleShift(ScheduleShift $scheduleShift): Event
|
||||||
{
|
{
|
||||||
/** @var Shift $shift */
|
$shift = $scheduleShift->shift;
|
||||||
$shift = Shift::with('location')->find($scheduleShift->shift_id);
|
|
||||||
$duration = $shift->start->diff($shift->end);
|
$duration = $shift->start->diff($shift->end);
|
||||||
|
|
||||||
return new Event(
|
return new Event(
|
||||||
|
|
|
@ -126,7 +126,9 @@ function load_locations(bool $onlyWithActiveShifts = false)
|
||||||
|
|
||||||
$locationIdsFromShift = Shift::query()
|
$locationIdsFromShift = Shift::query()
|
||||||
->leftJoin('needed_angel_types', 'shifts.id', 'needed_angel_types.shift_id')
|
->leftJoin('needed_angel_types', 'shifts.id', 'needed_angel_types.shift_id')
|
||||||
->whereNotNull('needed_angel_types.shift_id')
|
->leftJoin('needed_angel_types AS nast', 'shifts.shift_type_id', 'nast.shift_type_id')
|
||||||
|
->whereNotNull('needed_angel_types.id')
|
||||||
|
->orWhereNotNull('nast.id')
|
||||||
->select('shifts.location_id');
|
->select('shifts.location_id');
|
||||||
|
|
||||||
$locations->whereIn('id', $locationIdsFromAngelType)
|
$locations->whereIn('id', $locationIdsFromAngelType)
|
||||||
|
|
|
@ -722,8 +722,11 @@ msgstr "Schichtwechsel-Stunden"
|
||||||
msgid "Create a shift over midnight."
|
msgid "Create a shift over midnight."
|
||||||
msgstr "Erstelle Schichten über Mitternacht"
|
msgstr "Erstelle Schichten über Mitternacht"
|
||||||
|
|
||||||
msgid "Take needed angels from location settings"
|
msgid "Copy needed angels from location settings"
|
||||||
msgstr "Übernehme benötigte Engel von den Ort-Einstellungen"
|
msgstr "Kopiere benötigte Engel von den Ort-Einstellungen"
|
||||||
|
|
||||||
|
msgid "Copy needed angels from shift type settings"
|
||||||
|
msgstr "Kopiere benötigte Engel von den Schichttyp-Einstellungen"
|
||||||
|
|
||||||
msgid "The following angels are needed"
|
msgid "The following angels are needed"
|
||||||
msgstr "Die folgenden Engel werden benötigt"
|
msgstr "Die folgenden Engel werden benötigt"
|
||||||
|
@ -1447,6 +1450,9 @@ msgstr "Programm URL (schedule.xml)"
|
||||||
msgid "schedule.shift-type"
|
msgid "schedule.shift-type"
|
||||||
msgstr "Schichttyp"
|
msgstr "Schichttyp"
|
||||||
|
|
||||||
|
msgid "schedule.needed-from-shift-type"
|
||||||
|
msgstr "Engeltypen vom Schichttyp laden (sonst vom Ort)"
|
||||||
|
|
||||||
msgid "schedule.minutes-before"
|
msgid "schedule.minutes-before"
|
||||||
msgstr "Minuten vor Talk beginn hinzufügen"
|
msgstr "Minuten vor Talk beginn hinzufügen"
|
||||||
|
|
||||||
|
@ -1934,7 +1940,7 @@ msgid "location.map_url"
|
||||||
msgstr "Karte"
|
msgstr "Karte"
|
||||||
|
|
||||||
msgid "location.required_angels"
|
msgid "location.required_angels"
|
||||||
msgstr "Benötigte Engel"
|
msgstr "Benötigte Engel (bei Fahrplan import)"
|
||||||
|
|
||||||
msgid "location.map_url.info"
|
msgid "location.map_url.info"
|
||||||
msgstr "Die Karte wird auf der Ort-Seite als iframe eingebettet."
|
msgstr "Die Karte wird auf der Ort-Seite als iframe eingebettet."
|
||||||
|
@ -1960,6 +1966,9 @@ msgstr "Schichttyp erstellen"
|
||||||
msgid "shifttype.delete.title"
|
msgid "shifttype.delete.title"
|
||||||
msgstr "Schichttyp \"%s\" löschen"
|
msgstr "Schichttyp \"%s\" löschen"
|
||||||
|
|
||||||
|
msgid "shifttype.required_angels"
|
||||||
|
msgstr "Benötigte Engel (bei Fahrplan import)"
|
||||||
|
|
||||||
msgid "event.day"
|
msgid "event.day"
|
||||||
msgstr "Tag %1$d"
|
msgstr "Tag %1$d"
|
||||||
|
|
||||||
|
|
|
@ -151,6 +151,9 @@ msgstr "Schedule URL (schedule.xml)"
|
||||||
msgid "schedule.shift-type"
|
msgid "schedule.shift-type"
|
||||||
msgstr "Shift type"
|
msgstr "Shift type"
|
||||||
|
|
||||||
|
msgid "schedule.needed-from-shift-type"
|
||||||
|
msgstr "Load angel types from shift type (else from location)"
|
||||||
|
|
||||||
msgid "schedule.minutes-before"
|
msgid "schedule.minutes-before"
|
||||||
msgstr "Add minutes before talk begins"
|
msgstr "Add minutes before talk begins"
|
||||||
|
|
||||||
|
@ -664,7 +667,7 @@ msgid "location.map_url"
|
||||||
msgstr "Map"
|
msgstr "Map"
|
||||||
|
|
||||||
msgid "location.required_angels"
|
msgid "location.required_angels"
|
||||||
msgstr "Required angels"
|
msgstr "Required angels (on schedule import)"
|
||||||
|
|
||||||
msgid "location.map_url.info"
|
msgid "location.map_url.info"
|
||||||
msgstr "The map will be embedded on the location page as an iframe."
|
msgstr "The map will be embedded on the location page as an iframe."
|
||||||
|
@ -690,6 +693,9 @@ msgstr "Create shift type"
|
||||||
msgid "shifttype.delete.title"
|
msgid "shifttype.delete.title"
|
||||||
msgstr "Delete shift type \"%s\""
|
msgstr "Delete shift type \"%s\""
|
||||||
|
|
||||||
|
msgid "shifttype.required_angels"
|
||||||
|
msgstr "Required angels (on schedule import)"
|
||||||
|
|
||||||
msgid "event.day"
|
msgid "event.day"
|
||||||
msgstr "Day %1$d"
|
msgstr "Day %1$d"
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,10 @@
|
||||||
'selected': schedule ? schedule.shift_type : '',
|
'selected': schedule ? schedule.shift_type : '',
|
||||||
}) }}
|
}) }}
|
||||||
|
|
||||||
|
{{ f.checkbox('needed_from_shift_type', __('schedule.needed-from-shift-type'), {
|
||||||
|
'checked': schedule ? schedule.needed_from_shift_type : '',
|
||||||
|
}) }}
|
||||||
|
|
||||||
{{ f.input('minutes_before', __('schedule.minutes-before'), {
|
{{ f.input('minutes_before', __('schedule.minutes-before'), {
|
||||||
'type': 'number',
|
'type': 'number',
|
||||||
'required': true,
|
'required': true,
|
||||||
|
|
|
@ -23,6 +23,27 @@
|
||||||
'info': __('form.markdown')
|
'info': __('form.markdown')
|
||||||
}) }}
|
}) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<h4>{{ __('shifttype.required_angels') }}</h4>
|
||||||
|
{% for types in angel_types.chunk(3) %}
|
||||||
|
<div class="row">
|
||||||
|
{% for angel_type in types %}
|
||||||
|
{% set needed = shifttype
|
||||||
|
? shifttype.neededAngelTypes.where('angel_type_id', angel_type.id).first()
|
||||||
|
: null %}
|
||||||
|
{% set name = 'angel_type_' ~ angel_type.id %}
|
||||||
|
<div class="col-md-4">
|
||||||
|
{{ f.number(name, angel_type.name, {
|
||||||
|
'value': f.formData(name, needed ? needed.count : 0),
|
||||||
|
'min': 0,
|
||||||
|
'step': 1,
|
||||||
|
}) }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
|
|
|
@ -11,7 +11,10 @@ use Engelsystem\Http\Redirector;
|
||||||
use Engelsystem\Http\Request;
|
use Engelsystem\Http\Request;
|
||||||
use Engelsystem\Http\Response;
|
use Engelsystem\Http\Response;
|
||||||
use Engelsystem\Http\Validation\Validator;
|
use Engelsystem\Http\Validation\Validator;
|
||||||
|
use Engelsystem\Models\AngelType;
|
||||||
|
use Engelsystem\Models\Shifts\NeededAngelType;
|
||||||
use Engelsystem\Models\Shifts\ShiftType;
|
use Engelsystem\Models\Shifts\ShiftType;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
class ShiftTypesController extends BaseController
|
class ShiftTypesController extends BaseController
|
||||||
|
@ -48,10 +51,15 @@ class ShiftTypesController extends BaseController
|
||||||
$shiftTypeId = (int) $request->getAttribute('shift_type_id');
|
$shiftTypeId = (int) $request->getAttribute('shift_type_id');
|
||||||
|
|
||||||
$shiftType = $this->shiftType->find($shiftTypeId);
|
$shiftType = $this->shiftType->find($shiftTypeId);
|
||||||
|
$angeltypes = AngelType::all()
|
||||||
|
->sortBy('name');
|
||||||
|
|
||||||
return $this->response->withView(
|
return $this->response->withView(
|
||||||
'admin/shifttypes/edit',
|
'admin/shifttypes/edit',
|
||||||
['shifttype' => $shiftType]
|
[
|
||||||
|
'shifttype' => $shiftType,
|
||||||
|
'angel_types' => $angeltypes,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,12 +85,19 @@ class ShiftTypesController extends BaseController
|
||||||
return $this->delete($request);
|
return $this->delete($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @var Collection|AngelType[] $angelTypes */
|
||||||
|
$angelTypes = AngelType::all();
|
||||||
|
$validation = [];
|
||||||
|
foreach ($angelTypes as $angelType) {
|
||||||
|
$validation['angel_type_' . $angelType->id] = 'optional|int';
|
||||||
|
}
|
||||||
|
|
||||||
$data = $this->validate(
|
$data = $this->validate(
|
||||||
$request,
|
$request,
|
||||||
[
|
[
|
||||||
'name' => 'required',
|
'name' => 'required',
|
||||||
'description' => 'required|optional',
|
'description' => 'required|optional',
|
||||||
]
|
] + $validation
|
||||||
);
|
);
|
||||||
|
|
||||||
if (ShiftType::whereName($data['name'])->where('id', '!=', $shiftType->id)->exists()) {
|
if (ShiftType::whereName($data['name'])->where('id', '!=', $shiftType->id)->exists()) {
|
||||||
|
@ -93,12 +108,33 @@ class ShiftTypesController extends BaseController
|
||||||
$shiftType->description = $data['description'];
|
$shiftType->description = $data['description'];
|
||||||
|
|
||||||
$shiftType->save();
|
$shiftType->save();
|
||||||
|
$shiftType->neededAngelTypes()->delete();
|
||||||
|
|
||||||
|
$angelsInfo = '';
|
||||||
|
foreach ($angelTypes as $angelType) {
|
||||||
|
$count = $data['angel_type_' . $angelType->id];
|
||||||
|
if (!$count) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$neededAngelType = new NeededAngelType();
|
||||||
|
|
||||||
|
$neededAngelType->shiftType()->associate($shiftType);
|
||||||
|
$neededAngelType->angelType()->associate($angelType);
|
||||||
|
|
||||||
|
$neededAngelType->count = $data['angel_type_' . $angelType->id];
|
||||||
|
|
||||||
|
$neededAngelType->save();
|
||||||
|
|
||||||
|
$angelsInfo .= sprintf(', %s: %s', $angelType->name, $count);
|
||||||
|
}
|
||||||
|
|
||||||
$this->log->info(
|
$this->log->info(
|
||||||
'Updated shift type "{name}": {description}',
|
'Updated shift type "{name}": {description} {angels}',
|
||||||
[
|
[
|
||||||
'name' => $shiftType->name,
|
'name' => $shiftType->name,
|
||||||
'description' => $shiftType->description,
|
'description' => $shiftType->description,
|
||||||
|
'angels' => $angelsInfo,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,10 @@ class ShiftsController extends BaseController
|
||||||
$query->on('needed_angel_types.shift_id', '=', 'shifts.id')
|
$query->on('needed_angel_types.shift_id', '=', 'shifts.id')
|
||||||
->whereNull('schedule_shift.shift_id');
|
->whereNull('schedule_shift.shift_id');
|
||||||
})
|
})
|
||||||
|
->leftJoin('needed_angel_types AS nast', function (JoinClause $query): void {
|
||||||
|
$query->on('nast.shift_type_id', '=', 'shifts.shift_type_id')
|
||||||
|
->whereNotNull('schedule_shift.shift_id');
|
||||||
|
})
|
||||||
->leftJoin('needed_angel_types AS nas', function (JoinClause $query): void {
|
->leftJoin('needed_angel_types AS nas', function (JoinClause $query): void {
|
||||||
$query->on('nas.location_id', '=', 'shifts.location_id')
|
$query->on('nas.location_id', '=', 'shifts.location_id')
|
||||||
->whereNotNull('schedule_shift.shift_id');
|
->whereNotNull('schedule_shift.shift_id');
|
||||||
|
@ -88,6 +92,7 @@ class ShiftsController extends BaseController
|
||||||
->where(function (EloquentBuilder $query) use ($angelTypes): void {
|
->where(function (EloquentBuilder $query) use ($angelTypes): void {
|
||||||
$query
|
$query
|
||||||
->whereIn('needed_angel_types.angel_type_id', $angelTypes)
|
->whereIn('needed_angel_types.angel_type_id', $angelTypes)
|
||||||
|
->orWhereIn('nast.angel_type_id', $angelTypes)
|
||||||
->orWhereIn('nas.angel_type_id', $angelTypes);
|
->orWhereIn('nas.angel_type_id', $angelTypes);
|
||||||
})
|
})
|
||||||
// Starts soon
|
// Starts soon
|
||||||
|
@ -98,7 +103,7 @@ class ShiftsController extends BaseController
|
||||||
->from('shift_entries')
|
->from('shift_entries')
|
||||||
->selectRaw('COUNT(*)')
|
->selectRaw('COUNT(*)')
|
||||||
->where(fn(Builder $query) => $this->queryShiftEntries($query));
|
->where(fn(Builder $query) => $this->queryShiftEntries($query));
|
||||||
}, '<', Shift::query()->raw('COALESCE(needed_angel_types.count, nas.count)'))
|
}, '<', Shift::query()->raw('COALESCE(needed_angel_types.count, nast.count, nas.count)'))
|
||||||
->limit(10)
|
->limit(10)
|
||||||
->orderBy('start');
|
->orderBy('start');
|
||||||
|
|
||||||
|
|
|
@ -15,16 +15,19 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property int|null $location_id
|
* @property int|null $location_id
|
||||||
* @property int|null $shift_id
|
* @property int|null $shift_id
|
||||||
|
* @property int|null $shift_type_id
|
||||||
* @property int $angel_type_id
|
* @property int $angel_type_id
|
||||||
* @property int $count
|
* @property int $count
|
||||||
*
|
*
|
||||||
* @property-read Location|null $location
|
* @property-read Location|null $location
|
||||||
* @property-read Shift|null $shift
|
* @property-read Shift|null $shift
|
||||||
|
* @property-read ShiftType|null $shiftType
|
||||||
* @property-read AngelType $angelType
|
* @property-read AngelType $angelType
|
||||||
*
|
*
|
||||||
* @method static QueryBuilder|NeededAngelType[] whereId($value)
|
* @method static QueryBuilder|NeededAngelType[] whereId($value)
|
||||||
* @method static QueryBuilder|NeededAngelType[] whereLocationId($value)
|
* @method static QueryBuilder|NeededAngelType[] whereLocationId($value)
|
||||||
* @method static QueryBuilder|NeededAngelType[] whereShiftId($value)
|
* @method static QueryBuilder|NeededAngelType[] whereShiftId($value)
|
||||||
|
* @method static QueryBuilder|NeededAngelType[] whereShiftTypeId($value)
|
||||||
* @method static QueryBuilder|NeededAngelType[] whereAngelTypeId($value)
|
* @method static QueryBuilder|NeededAngelType[] whereAngelTypeId($value)
|
||||||
* @method static QueryBuilder|NeededAngelType[] whereCount($value)
|
* @method static QueryBuilder|NeededAngelType[] whereCount($value)
|
||||||
*/
|
*/
|
||||||
|
@ -36,12 +39,14 @@ class NeededAngelType extends BaseModel
|
||||||
protected $attributes = [ // phpcs:ignore
|
protected $attributes = [ // phpcs:ignore
|
||||||
'location_id' => null,
|
'location_id' => null,
|
||||||
'shift_id' => null,
|
'shift_id' => null,
|
||||||
|
'shift_type_id' => null,
|
||||||
];
|
];
|
||||||
|
|
||||||
/** @var array<string> */
|
/** @var array<string> */
|
||||||
protected $fillable = [ // phpcs:ignore
|
protected $fillable = [ // phpcs:ignore
|
||||||
'location_id',
|
'location_id',
|
||||||
'shift_id',
|
'shift_id',
|
||||||
|
'shift_type_id',
|
||||||
'angel_type_id',
|
'angel_type_id',
|
||||||
'count',
|
'count',
|
||||||
];
|
];
|
||||||
|
@ -56,6 +61,11 @@ class NeededAngelType extends BaseModel
|
||||||
return $this->belongsTo(Shift::class);
|
return $this->belongsTo(Shift::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function shiftType(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(ShiftType::class);
|
||||||
|
}
|
||||||
|
|
||||||
public function angelType(): BelongsTo
|
public function angelType(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(AngelType::class);
|
return $this->belongsTo(AngelType::class);
|
||||||
|
|
|
@ -18,6 +18,7 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
|
||||||
* @property string $name
|
* @property string $name
|
||||||
* @property string $url
|
* @property string $url
|
||||||
* @property int $shift_type
|
* @property int $shift_type
|
||||||
|
* @property bool $needed_from_shift_type
|
||||||
* @property int $minutes_before
|
* @property int $minutes_before
|
||||||
* @property int $minutes_after
|
* @property int $minutes_after
|
||||||
* @property Carbon $created_at
|
* @property Carbon $created_at
|
||||||
|
@ -31,6 +32,7 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
|
||||||
* @method static QueryBuilder|Schedule[] whereName($value)
|
* @method static QueryBuilder|Schedule[] whereName($value)
|
||||||
* @method static QueryBuilder|Schedule[] whereUrl($value)
|
* @method static QueryBuilder|Schedule[] whereUrl($value)
|
||||||
* @method static QueryBuilder|Schedule[] whereShiftType($value)
|
* @method static QueryBuilder|Schedule[] whereShiftType($value)
|
||||||
|
* @method static QueryBuilder|Schedule[] whereNeededFromShiftType($value)
|
||||||
* @method static QueryBuilder|Schedule[] whereMinutesBefore($value)
|
* @method static QueryBuilder|Schedule[] whereMinutesBefore($value)
|
||||||
* @method static QueryBuilder|Schedule[] whereMinutesAfter($value)
|
* @method static QueryBuilder|Schedule[] whereMinutesAfter($value)
|
||||||
* @method static QueryBuilder|Schedule[] whereCreatedAt($value)
|
* @method static QueryBuilder|Schedule[] whereCreatedAt($value)
|
||||||
|
@ -46,6 +48,7 @@ class Schedule extends BaseModel
|
||||||
/** @var array<string> */
|
/** @var array<string> */
|
||||||
protected $casts = [ // phpcs:ignore
|
protected $casts = [ // phpcs:ignore
|
||||||
'shift_type' => 'integer',
|
'shift_type' => 'integer',
|
||||||
|
'needed_from_shift_type' => 'boolean',
|
||||||
'minutes_before' => 'integer',
|
'minutes_before' => 'integer',
|
||||||
'minutes_after' => 'integer',
|
'minutes_after' => 'integer',
|
||||||
];
|
];
|
||||||
|
@ -55,6 +58,7 @@ class Schedule extends BaseModel
|
||||||
'name',
|
'name',
|
||||||
'url',
|
'url',
|
||||||
'shift_type',
|
'shift_type',
|
||||||
|
'needed_from_shift_type',
|
||||||
'minutes_before',
|
'minutes_before',
|
||||||
'minutes_after',
|
'minutes_after',
|
||||||
];
|
];
|
||||||
|
|
|
@ -15,6 +15,7 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
|
||||||
* @property string $name
|
* @property string $name
|
||||||
* @property string $description
|
* @property string $description
|
||||||
*
|
*
|
||||||
|
* @property-read Collection|NeededAngelType[] $neededAngelTypes
|
||||||
* @property-read Collection|Schedule[] $schedules
|
* @property-read Collection|Schedule[] $schedules
|
||||||
* @property-read Collection|Shift[] $shifts
|
* @property-read Collection|Shift[] $shifts
|
||||||
*
|
*
|
||||||
|
@ -32,6 +33,11 @@ class ShiftType extends BaseModel
|
||||||
'description',
|
'description',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public function neededAngelTypes(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(NeededAngelType::class);
|
||||||
|
}
|
||||||
|
|
||||||
public function schedules(): HasMany
|
public function schedules(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(Schedule::class, 'shift_type');
|
return $this->hasMany(Schedule::class, 'shift_type');
|
||||||
|
|
|
@ -11,6 +11,7 @@ use Engelsystem\Http\Exceptions\ValidationException;
|
||||||
use Engelsystem\Http\Redirector;
|
use Engelsystem\Http\Redirector;
|
||||||
use Engelsystem\Http\Request;
|
use Engelsystem\Http\Request;
|
||||||
use Engelsystem\Http\Validation\Validator;
|
use Engelsystem\Http\Validation\Validator;
|
||||||
|
use Engelsystem\Models\AngelType;
|
||||||
use Engelsystem\Models\Shifts\ShiftEntry;
|
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||||
use Engelsystem\Models\Shifts\ShiftType;
|
use Engelsystem\Models\Shifts\ShiftType;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
|
@ -18,7 +19,7 @@ use Engelsystem\Models\User\User;
|
||||||
use Engelsystem\Test\Unit\Controllers\ControllerTest;
|
use Engelsystem\Test\Unit\Controllers\ControllerTest;
|
||||||
use PHPUnit\Framework\MockObject\MockObject;
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
|
|
||||||
class ShiftTypeControllerTest extends ControllerTest
|
class ShiftTypesControllerTest extends ControllerTest
|
||||||
{
|
{
|
||||||
protected Redirector|MockObject $redirect;
|
protected Redirector|MockObject $redirect;
|
||||||
|
|
||||||
|
@ -82,6 +83,7 @@ class ShiftTypeControllerTest extends ControllerTest
|
||||||
$this->assertEquals($shifttype->id, $data['shifttype']?->id);
|
$this->assertEquals($shifttype->id, $data['shifttype']?->id);
|
||||||
$this->assertNotEmpty($data['shifttype']?->name);
|
$this->assertNotEmpty($data['shifttype']?->name);
|
||||||
$this->assertNotEmpty($data['shifttype']?->description);
|
$this->assertNotEmpty($data['shifttype']?->description);
|
||||||
|
$this->assertNotNull($data['angel_types']);
|
||||||
return $this->response;
|
return $this->response;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -104,6 +106,7 @@ class ShiftTypeControllerTest extends ControllerTest
|
||||||
$this->assertEquals('admin/shifttypes/edit', $view);
|
$this->assertEquals('admin/shifttypes/edit', $view);
|
||||||
$this->assertArrayHasKey('shifttype', $data);
|
$this->assertArrayHasKey('shifttype', $data);
|
||||||
$this->assertNull($data['shifttype']);
|
$this->assertNull($data['shifttype']);
|
||||||
|
$this->assertNotNull($data['angel_types']);
|
||||||
return $this->response;
|
return $this->response;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -115,6 +118,8 @@ class ShiftTypeControllerTest extends ControllerTest
|
||||||
*/
|
*/
|
||||||
public function testSave(): void
|
public function testSave(): void
|
||||||
{
|
{
|
||||||
|
$angelType = AngelType::factory(2)->create()->first();
|
||||||
|
|
||||||
/** @var ShiftTypesController $controller */
|
/** @var ShiftTypesController $controller */
|
||||||
$controller = $this->app->make(ShiftTypesController::class);
|
$controller = $this->app->make(ShiftTypesController::class);
|
||||||
$controller->setValidator(new Validator());
|
$controller->setValidator(new Validator());
|
||||||
|
@ -124,6 +129,8 @@ class ShiftTypeControllerTest extends ControllerTest
|
||||||
$this->request = $this->request->withParsedBody([
|
$this->request = $this->request->withParsedBody([
|
||||||
'name' => 'Test shift type',
|
'name' => 'Test shift type',
|
||||||
'description' => 'Something',
|
'description' => 'Something',
|
||||||
|
'angel_type_' . $angelType->id => 3,
|
||||||
|
'angel_type_' . $angelType->id + 1 => 0,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$controller->save($this->request);
|
$controller->save($this->request);
|
||||||
|
@ -131,6 +138,7 @@ class ShiftTypeControllerTest extends ControllerTest
|
||||||
$this->assertTrue($this->log->hasInfoThatContains('Updated shift type'));
|
$this->assertTrue($this->log->hasInfoThatContains('Updated shift type'));
|
||||||
$this->assertHasNotification('shifttype.edit.success');
|
$this->assertHasNotification('shifttype.edit.success');
|
||||||
$this->assertCount(1, ShiftType::whereName('Test shift type')->get());
|
$this->assertCount(1, ShiftType::whereName('Test shift type')->get());
|
||||||
|
$this->assertCount(1, ShiftType::first()->neededAngelTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -8,6 +8,7 @@ use Engelsystem\Models\AngelType;
|
||||||
use Engelsystem\Models\Location;
|
use Engelsystem\Models\Location;
|
||||||
use Engelsystem\Models\Shifts\NeededAngelType;
|
use Engelsystem\Models\Shifts\NeededAngelType;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
|
use Engelsystem\Models\Shifts\ShiftType;
|
||||||
use Engelsystem\Test\Unit\Models\ModelTest;
|
use Engelsystem\Test\Unit\Models\ModelTest;
|
||||||
|
|
||||||
class NeededAngelTypeTest extends ModelTest
|
class NeededAngelTypeTest extends ModelTest
|
||||||
|
@ -15,6 +16,7 @@ class NeededAngelTypeTest extends ModelTest
|
||||||
/**
|
/**
|
||||||
* @covers \Engelsystem\Models\Shifts\NeededAngelType::location
|
* @covers \Engelsystem\Models\Shifts\NeededAngelType::location
|
||||||
* @covers \Engelsystem\Models\Shifts\NeededAngelType::shift
|
* @covers \Engelsystem\Models\Shifts\NeededAngelType::shift
|
||||||
|
* @covers \Engelsystem\Models\Shifts\NeededAngelType::shiftType
|
||||||
* @covers \Engelsystem\Models\Shifts\NeededAngelType::angelType
|
* @covers \Engelsystem\Models\Shifts\NeededAngelType::angelType
|
||||||
*/
|
*/
|
||||||
public function testShift(): void
|
public function testShift(): void
|
||||||
|
@ -23,12 +25,15 @@ class NeededAngelTypeTest extends ModelTest
|
||||||
$location = Location::factory()->create();
|
$location = Location::factory()->create();
|
||||||
/** @var Shift $shift */
|
/** @var Shift $shift */
|
||||||
$shift = Shift::factory()->create();
|
$shift = Shift::factory()->create();
|
||||||
|
/** @var ShiftType $shiftType */
|
||||||
|
$shiftType = ShiftType::factory()->create();
|
||||||
/** @var AngelType $angelType */
|
/** @var AngelType $angelType */
|
||||||
$angelType = AngelType::factory()->create();
|
$angelType = AngelType::factory()->create();
|
||||||
|
|
||||||
$model = new NeededAngelType();
|
$model = new NeededAngelType();
|
||||||
$model->location()->associate($location);
|
$model->location()->associate($location);
|
||||||
$model->shift()->associate($shift);
|
$model->shift()->associate($shift);
|
||||||
|
$model->shiftType()->associate($shiftType);
|
||||||
$model->angelType()->associate($angelType);
|
$model->angelType()->associate($angelType);
|
||||||
$model->count = 3;
|
$model->count = 3;
|
||||||
$model->save();
|
$model->save();
|
||||||
|
@ -36,6 +41,7 @@ class NeededAngelTypeTest extends ModelTest
|
||||||
$model = NeededAngelType::find(1);
|
$model = NeededAngelType::find(1);
|
||||||
$this->assertEquals($location->id, $model->location->id);
|
$this->assertEquals($location->id, $model->location->id);
|
||||||
$this->assertEquals($shift->id, $model->shift->id);
|
$this->assertEquals($shift->id, $model->shift->id);
|
||||||
|
$this->assertEquals($shiftType->id, $model->shiftType->id);
|
||||||
$this->assertEquals($angelType->id, $model->angelType->id);
|
$this->assertEquals($angelType->id, $model->angelType->id);
|
||||||
$this->assertEquals(3, $model->count);
|
$this->assertEquals(3, $model->count);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ class ScheduleTest extends ModelTest
|
||||||
'url' => 'https://foo.bar/schedule.xml',
|
'url' => 'https://foo.bar/schedule.xml',
|
||||||
'name' => 'Testing',
|
'name' => 'Testing',
|
||||||
'shift_type' => 1,
|
'shift_type' => 1,
|
||||||
|
'needed_from_shift_type' => false,
|
||||||
'minutes_before' => 10,
|
'minutes_before' => 10,
|
||||||
'minutes_after' => 10,
|
'minutes_after' => 10,
|
||||||
];
|
];
|
||||||
|
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Engelsystem\Test\Unit\Models\Shifts;
|
namespace Engelsystem\Test\Unit\Models\Shifts;
|
||||||
|
|
||||||
|
use Engelsystem\Models\Shifts\NeededAngelType;
|
||||||
use Engelsystem\Models\Shifts\Schedule;
|
use Engelsystem\Models\Shifts\Schedule;
|
||||||
use Engelsystem\Models\Shifts\Shift;
|
use Engelsystem\Models\Shifts\Shift;
|
||||||
use Engelsystem\Models\Shifts\ShiftType;
|
use Engelsystem\Models\Shifts\ShiftType;
|
||||||
|
@ -11,6 +12,19 @@ use Engelsystem\Test\Unit\Models\ModelTest;
|
||||||
|
|
||||||
class ShiftTypeTest extends ModelTest
|
class ShiftTypeTest extends ModelTest
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Models\Shifts\ShiftType::neededAngelTypes
|
||||||
|
*/
|
||||||
|
public function testNeededAngelTypes(): void
|
||||||
|
{
|
||||||
|
$shiftType = new ShiftType(['name' => 'Another type', 'description' => '']);
|
||||||
|
$shiftType->save();
|
||||||
|
|
||||||
|
NeededAngelType::factory()->create(['shift_type_id' => 1]);
|
||||||
|
|
||||||
|
$this->assertCount(1, ShiftType::find(1)->neededAngelTypes);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \Engelsystem\Models\Shifts\ShiftType::schedules
|
* @covers \Engelsystem\Models\Shifts\ShiftType::schedules
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue