dishplanner/src/DishPlanner/Schedule/Actions/GenerateScheduleForMonthAction.php

102 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();
}
}
}