#22 - wip
This commit is contained in:
		| @@ -50,8 +50,11 @@ class CalendarGenerator | |||||||
|     protected function generateCalendar(CarbonPeriod $period, Collection $holidays): array |     protected function generateCalendar(CarbonPeriod $period, Collection $holidays): array | ||||||
|     { |     { | ||||||
|         $calendar = []; |         $calendar = []; | ||||||
|  |         $vacations = $this->getVacationsForPeriod($period); | ||||||
|  |  | ||||||
|         foreach ($period as $day) { |         foreach ($period as $day) { | ||||||
|  |             $vacationsForDay = $vacations[$day->toDateString()] ?? new Collection(); | ||||||
|  |  | ||||||
|             $calendar[] = [ |             $calendar[] = [ | ||||||
|                 "date" => $day->toDateString(), |                 "date" => $day->toDateString(), | ||||||
|                 "dayOfMonth" => $day->translatedFormat("j"), |                 "dayOfMonth" => $day->translatedFormat("j"), | ||||||
| @@ -59,18 +62,19 @@ class CalendarGenerator | |||||||
|                 "isToday" => $day->isToday(), |                 "isToday" => $day->isToday(), | ||||||
|                 "isWeekend" => $day->isWeekend(), |                 "isWeekend" => $day->isWeekend(), | ||||||
|                 "isHoliday" => $holidays->contains($day), |                 "isHoliday" => $holidays->contains($day), | ||||||
|                 "vacations" => $this->getVacationsForDay($day), |                 "vacations" => $vacationsForDay->pluck("user_id"), | ||||||
|             ]; |             ]; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return $calendar; |         return $calendar; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     protected function getVacationsForDay(CarbonInterface $day): Collection |     protected function getVacationsForPeriod(CarbonPeriod $period): Collection | ||||||
|     { |     { | ||||||
|         return Vacation::query() |         return Vacation::query() | ||||||
|             ->whereDate("date", $day) |             ->whereBetween("date", [$period->start, $period->end]) | ||||||
|             ->whereRelation("vacationRequest", "state", VacationRequestState::APPROVED->value) |             ->whereRelation("vacationRequest", "state", VacationRequestState::APPROVED->value) | ||||||
|             ->pluck("user_id"); |             ->get() | ||||||
|  |             ->groupBy(fn(Vacation $vacation) => $vacation->date->toDateString()); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,23 +4,64 @@ declare(strict_types=1); | |||||||
|  |  | ||||||
| namespace Toby\Domain\Validation\Rules; | 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\Domain\VacationTypeConfigRetriever; | ||||||
|  | use Toby\Eloquent\Models\User; | ||||||
| use Toby\Eloquent\Models\VacationRequest; | use Toby\Eloquent\Models\VacationRequest; | ||||||
|  | use Toby\Eloquent\Models\YearPeriod; | ||||||
|  |  | ||||||
| class DoesNotExceedLimitRule implements VacationRequestRule | class DoesNotExceedLimitRule implements VacationRequestRule | ||||||
| { | { | ||||||
|     public function __construct( |     public function __construct( | ||||||
|         protected VacationTypeConfigRetriever $configRetriever, |         protected VacationTypeConfigRetriever $configRetriever, | ||||||
|  |         protected VacationDaysCalculator $vacationDaysCalculator, | ||||||
|     ) { |     ) { | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public function check(VacationRequest $vacationRequest): bool |     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 |     public function errorMessage(): string | ||||||
|     { |     { | ||||||
|         return __("You have exceeded your vacation limit."); |         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)); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -14,6 +14,7 @@ use Illuminate\Support\Carbon; | |||||||
|  * @property Carbon $date |  * @property Carbon $date | ||||||
|  * @property User $user |  * @property User $user | ||||||
|  * @property VacationRequest $vacationRequest |  * @property VacationRequest $vacationRequest | ||||||
|  |  * @property YearPeriod $yearPeriod | ||||||
|  */ |  */ | ||||||
| class Vacation extends Model | class Vacation extends Model | ||||||
| { | { | ||||||
| @@ -34,4 +35,9 @@ class Vacation extends Model | |||||||
|     { |     { | ||||||
|         return $this->belongsTo(VacationRequest::class); |         return $this->belongsTo(VacationRequest::class); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public function yearPeriod(): BelongsTo | ||||||
|  |     { | ||||||
|  |         return $this->belongsTo(YearPeriod::class); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -21,7 +21,6 @@ use Toby\Domain\Enums\VacationType; | |||||||
|  * @property VacationRequestState $state |  * @property VacationRequestState $state | ||||||
|  * @property Carbon $from |  * @property Carbon $from | ||||||
|  * @property Carbon $to |  * @property Carbon $to | ||||||
|  * @property int $estimated_days |  | ||||||
|  * @property string $comment |  * @property string $comment | ||||||
|  * @property User $user |  * @property User $user | ||||||
|  * @property YearPeriod $yearPeriod |  * @property YearPeriod $yearPeriod | ||||||
| @@ -75,6 +74,11 @@ class VacationRequest extends Model | |||||||
|         return $query->whereIn("state", $states); |         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 |     public function scopeOverlapsWith(Builder $query, self $vacationRequest): Builder | ||||||
|     { |     { | ||||||
|         return $query->where("from", "<=", $vacationRequest->to) |         return $query->where("from", "<=", $vacationRequest->to) | ||||||
|   | |||||||
| @@ -4,7 +4,6 @@ declare(strict_types=1); | |||||||
|  |  | ||||||
| namespace Toby\Infrastructure\Http\Controllers; | namespace Toby\Infrastructure\Http\Controllers; | ||||||
|  |  | ||||||
| use Carbon\CarbonInterface; |  | ||||||
| use Illuminate\Http\Request; | use Illuminate\Http\Request; | ||||||
| use Illuminate\Support\Carbon; | use Illuminate\Support\Carbon; | ||||||
| use Illuminate\Support\Str; | use Illuminate\Support\Str; | ||||||
| @@ -36,22 +35,4 @@ class VacationCalendarController extends Controller | |||||||
|             "users" => UserResource::collection($users), |             "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, |  | ||||||
|         }; |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -75,6 +75,9 @@ class VacationRequestController extends Controller | |||||||
|         /** @var VacationRequest $vacationRequest */ |         /** @var VacationRequest $vacationRequest */ | ||||||
|         $vacationRequest = $request->user()->vacationRequests()->make($request->data()); |         $vacationRequest = $request->user()->vacationRequests()->make($request->data()); | ||||||
|         $vacationRequestValidator->validate($vacationRequest); |         $vacationRequestValidator->validate($vacationRequest); | ||||||
|  |  | ||||||
|  |         dd("ok"); | ||||||
|  |  | ||||||
|         $vacationRequest->save(); |         $vacationRequest->save(); | ||||||
|  |  | ||||||
|         $days = $vacationDaysCalculator->calculateDays( |         $days = $vacationDaysCalculator->calculateDays( | ||||||
|   | |||||||
| @@ -8,15 +8,8 @@ use Illuminate\Database\Eloquent\Factories\Factory; | |||||||
|  |  | ||||||
| class VacationFactory extends Factory | class VacationFactory extends Factory | ||||||
| { | { | ||||||
|     /** |     public function definition(): array | ||||||
|      * Define the model's default state. |  | ||||||
|      * |  | ||||||
|      * @return array |  | ||||||
|      */ |  | ||||||
|     public function definition() |  | ||||||
|     { |     { | ||||||
|         return [ |         return []; | ||||||
|             // |  | ||||||
|         ]; |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ use Illuminate\Database\Schema\Blueprint; | |||||||
| use Illuminate\Support\Facades\Schema; | use Illuminate\Support\Facades\Schema; | ||||||
| use Toby\Eloquent\Models\User; | use Toby\Eloquent\Models\User; | ||||||
| use Toby\Eloquent\Models\VacationRequest; | use Toby\Eloquent\Models\VacationRequest; | ||||||
|  | use Toby\Eloquent\Models\YearPeriod; | ||||||
|  |  | ||||||
| return new class() extends Migration { | return new class() extends Migration { | ||||||
|     public function up(): void |     public function up(): void | ||||||
| @@ -15,6 +16,7 @@ return new class() extends Migration { | |||||||
|             $table->id(); |             $table->id(); | ||||||
|             $table->foreignIdFor(User::class)->constrained()->cascadeOnDelete(); |             $table->foreignIdFor(User::class)->constrained()->cascadeOnDelete(); | ||||||
|             $table->foreignIdFor(VacationRequest::class)->constrained()->cascadeOnDelete(); |             $table->foreignIdFor(VacationRequest::class)->constrained()->cascadeOnDelete(); | ||||||
|  |             $table->foreignIdFor(YearPeriod::class)->constrained()->cascadeOnDelete(); | ||||||
|             $table->date("date"); |             $table->date("date"); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -91,6 +91,7 @@ class DatabaseSeeder extends Seeder | |||||||
|                         $vacationRequest->vacations()->create([ |                         $vacationRequest->vacations()->create([ | ||||||
|                             "date" => $day, |                             "date" => $day, | ||||||
|                             "user_id" => $vacationRequest->user->id, |                             "user_id" => $vacationRequest->user->id, | ||||||
|  |                             "year_period_id" => $vacationRequest->yearPeriod->id, | ||||||
|                         ]); |                         ]); | ||||||
|                     } |                     } | ||||||
|                 }) |                 }) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user