103 lines
3 KiB
PHP
103 lines
3 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace DishPlanner\Schedule\Actions;
|
||
|
|
|
||
|
|
use App\Models\Planner;
|
||
|
|
use App\Models\Schedule;
|
||
|
|
use App\Models\ScheduledUserDish;
|
||
|
|
use App\Models\User;
|
||
|
|
use Carbon\Carbon;
|
||
|
|
use Illuminate\Support\Collection;
|
||
|
|
use Illuminate\Support\Facades\DB;
|
||
|
|
|
||
|
|
class GenerateScheduleForMonthAction
|
||
|
|
{
|
||
|
|
public function execute(
|
||
|
|
Planner $planner,
|
||
|
|
int $month,
|
||
|
|
int $year,
|
||
|
|
array $userIds,
|
||
|
|
bool $clearExisting = true
|
||
|
|
): void {
|
||
|
|
DB::transaction(function () use ($planner, $month, $year, $userIds, $clearExisting) {
|
||
|
|
$startDate = Carbon::createFromDate($year, $month, 1);
|
||
|
|
$endDate = $startDate->copy()->endOfMonth();
|
||
|
|
|
||
|
|
if ($clearExisting) {
|
||
|
|
$this->clearExistingSchedules($planner, $startDate, $endDate, $userIds);
|
||
|
|
}
|
||
|
|
|
||
|
|
$userDishesMap = $this->loadUserDishes($planner, $userIds);
|
||
|
|
|
||
|
|
$this->generateSchedulesForPeriod($planner, $startDate, $endDate, $userIds, $userDishesMap);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
private function clearExistingSchedules(
|
||
|
|
Planner $planner,
|
||
|
|
Carbon $startDate,
|
||
|
|
Carbon $endDate,
|
||
|
|
array $userIds
|
||
|
|
): void {
|
||
|
|
$scheduleIds = Schedule::withoutGlobalScopes()
|
||
|
|
->where('planner_id', $planner->id)
|
||
|
|
->whereBetween('date', [$startDate, $endDate])
|
||
|
|
->pluck('id');
|
||
|
|
|
||
|
|
ScheduledUserDish::whereIn('schedule_id', $scheduleIds)
|
||
|
|
->whereIn('user_id', $userIds)
|
||
|
|
->delete();
|
||
|
|
}
|
||
|
|
|
||
|
|
private function loadUserDishes(Planner $planner, array $userIds): array
|
||
|
|
{
|
||
|
|
$users = User::query()
|
||
|
|
->with('userDishes.dish')
|
||
|
|
->whereIn('id', $userIds)
|
||
|
|
->where('planner_id', $planner->id)
|
||
|
|
->get()
|
||
|
|
->keyBy('id');
|
||
|
|
|
||
|
|
$userDishesMap = [];
|
||
|
|
foreach ($users as $userId => $user) {
|
||
|
|
if ($user->userDishes->isNotEmpty()) {
|
||
|
|
$userDishesMap[$userId] = $user->userDishes;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return $userDishesMap;
|
||
|
|
}
|
||
|
|
|
||
|
|
private function generateSchedulesForPeriod(
|
||
|
|
Planner $planner,
|
||
|
|
Carbon $startDate,
|
||
|
|
Carbon $endDate,
|
||
|
|
array $userIds,
|
||
|
|
array $userDishesMap
|
||
|
|
): void {
|
||
|
|
$currentDate = $startDate->copy();
|
||
|
|
|
||
|
|
while ($currentDate <= $endDate) {
|
||
|
|
$schedule = Schedule::firstOrCreate(
|
||
|
|
['planner_id' => $planner->id, 'date' => $currentDate->format('Y-m-d')],
|
||
|
|
['is_skipped' => false]
|
||
|
|
);
|
||
|
|
|
||
|
|
foreach ($userIds as $userId) {
|
||
|
|
if (!isset($userDishesMap[$userId]) || $userDishesMap[$userId]->isEmpty()) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
$randomUserDish = $userDishesMap[$userId]->random();
|
||
|
|
|
||
|
|
ScheduledUserDish::firstOrCreate(
|
||
|
|
['schedule_id' => $schedule->id, 'user_id' => $userId],
|
||
|
|
['user_dish_id' => $randomUserDish->id, 'is_skipped' => false]
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
$currentDate->addDay();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|