This commit is contained in:
Adrian Hopek 2022-02-14 14:56:30 +01:00
parent d3d6e3080c
commit 1fe6e72e9a
9 changed files with 69 additions and 34 deletions

View File

@ -50,8 +50,11 @@ class CalendarGenerator
protected function generateCalendar(CarbonPeriod $period, Collection $holidays): array
{
$calendar = [];
$vacations = $this->getVacationsForPeriod($period);
foreach ($period as $day) {
$vacationsForDay = $vacations[$day->toDateString()] ?? new Collection();
$calendar[] = [
"date" => $day->toDateString(),
"dayOfMonth" => $day->translatedFormat("j"),
@ -59,18 +62,19 @@ class CalendarGenerator
"isToday" => $day->isToday(),
"isWeekend" => $day->isWeekend(),
"isHoliday" => $holidays->contains($day),
"vacations" => $this->getVacationsForDay($day),
"vacations" => $vacationsForDay->pluck("user_id"),
];
}
return $calendar;
}
protected function getVacationsForDay(CarbonInterface $day): Collection
protected function getVacationsForPeriod(CarbonPeriod $period): Collection
{
return Vacation::query()
->whereDate("date", $day)
->whereBetween("date", [$period->start, $period->end])
->whereRelation("vacationRequest", "state", VacationRequestState::APPROVED->value)
->pluck("user_id");
->get()
->groupBy(fn(Vacation $vacation) => $vacation->date->toDateString());
}
}

View File

@ -4,23 +4,64 @@ declare(strict_types=1);
namespace Toby\Domain\Validation\Rules;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Toby\Domain\Enums\VacationRequestState;
use Toby\Domain\Enums\VacationType;
use Toby\Domain\VacationDaysCalculator;
use Toby\Domain\VacationTypeConfigRetriever;
use Toby\Eloquent\Models\User;
use Toby\Eloquent\Models\VacationRequest;
use Toby\Eloquent\Models\YearPeriod;
class DoesNotExceedLimitRule implements VacationRequestRule
{
public function __construct(
protected VacationTypeConfigRetriever $configRetriever,
protected VacationDaysCalculator $vacationDaysCalculator,
) {
}
public function check(VacationRequest $vacationRequest): bool
{
return true;
if (!$this->configRetriever->hasLimit($vacationRequest->type)) {
return true;
}
$limit = $this->getUserVacationLimit($vacationRequest->user, $vacationRequest->yearPeriod);
$vacationDays = $this->getVacationDaysWithLimit($vacationRequest->user, $vacationRequest->yearPeriod);
$estimatedDays = $this->vacationDaysCalculator->calculateDays($vacationRequest->yearPeriod, $vacationRequest->from, $vacationRequest->to)->count();
return $limit >= ($vacationDays + $estimatedDays);
}
public function errorMessage(): string
{
return __("You have exceeded your vacation limit.");
}
protected function getUserVacationLimit(User $user, YearPeriod $yearPeriod): int
{
return $user->vacationLimits()->where("year_period_id", $yearPeriod->id)->first()->days ?? 0;
}
protected function getVacationDaysWithLimit(User $user, YearPeriod $yearPeriod): int
{
return $user->vacations()
->where("year_period_id", $yearPeriod->id)
->whereRelation(
"vacationRequest",
fn(Builder $query) => $query
->whereIn("type", $this->getLimitableVacationTypes())
->noStates(VacationRequestState::failedStates()),
)
->count();
}
protected function getLimitableVacationTypes(): Collection
{
$types = new Collection(VacationType::cases());
return $types->filter(fn(VacationType $type) => $this->configRetriever->hasLimit($type));
}
}

View File

@ -14,6 +14,7 @@ use Illuminate\Support\Carbon;
* @property Carbon $date
* @property User $user
* @property VacationRequest $vacationRequest
* @property YearPeriod $yearPeriod
*/
class Vacation extends Model
{
@ -34,4 +35,9 @@ class Vacation extends Model
{
return $this->belongsTo(VacationRequest::class);
}
public function yearPeriod(): BelongsTo
{
return $this->belongsTo(YearPeriod::class);
}
}

View File

@ -21,7 +21,6 @@ use Toby\Domain\Enums\VacationType;
* @property VacationRequestState $state
* @property Carbon $from
* @property Carbon $to
* @property int $estimated_days
* @property string $comment
* @property User $user
* @property YearPeriod $yearPeriod
@ -75,6 +74,11 @@ class VacationRequest extends Model
return $query->whereIn("state", $states);
}
public function scopeNoStates(Builder $query, array $states): Builder
{
return $query->whereNotIn("state", $states);
}
public function scopeOverlapsWith(Builder $query, self $vacationRequest): Builder
{
return $query->where("from", "<=", $vacationRequest->to)

View File

@ -4,7 +4,6 @@ declare(strict_types=1);
namespace Toby\Infrastructure\Http\Controllers;
use Carbon\CarbonInterface;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;
@ -36,22 +35,4 @@ class VacationCalendarController extends Controller
"users" => UserResource::collection($users),
]);
}
protected function monthNameToNumber(?string $name): int
{
return match ($name) {
default => CarbonInterface::JANUARY,
"february" => CarbonInterface::FEBRUARY,
"march" => CarbonInterface::MARCH,
"april" => CarbonInterface::APRIL,
"may" => CarbonInterface::MAY,
"june" => CarbonInterface::JUNE,
"july" => CarbonInterface::JULY,
"august" => CarbonInterface::AUGUST,
"september" => CarbonInterface::SEPTEMBER,
"october" => CarbonInterface::OCTOBER,
"november" => CarbonInterface::NOVEMBER,
"december" => CarbonInterface::DECEMBER,
};
}
}

View File

@ -75,6 +75,9 @@ class VacationRequestController extends Controller
/** @var VacationRequest $vacationRequest */
$vacationRequest = $request->user()->vacationRequests()->make($request->data());
$vacationRequestValidator->validate($vacationRequest);
dd("ok");
$vacationRequest->save();
$days = $vacationDaysCalculator->calculateDays(

View File

@ -8,15 +8,8 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class VacationFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
public function definition(): array
{
return [
//
];
return [];
}
}

View File

@ -7,6 +7,7 @@ use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Toby\Eloquent\Models\User;
use Toby\Eloquent\Models\VacationRequest;
use Toby\Eloquent\Models\YearPeriod;
return new class() extends Migration {
public function up(): void
@ -15,6 +16,7 @@ return new class() extends Migration {
$table->id();
$table->foreignIdFor(User::class)->constrained()->cascadeOnDelete();
$table->foreignIdFor(VacationRequest::class)->constrained()->cascadeOnDelete();
$table->foreignIdFor(YearPeriod::class)->constrained()->cascadeOnDelete();
$table->date("date");
});
}

View File

@ -91,6 +91,7 @@ class DatabaseSeeder extends Seeder
$vacationRequest->vacations()->create([
"date" => $day,
"user_id" => $vacationRequest->user->id,
"year_period_id" => $vacationRequest->yearPeriod->id,
]);
}
})