Skip to content

Commit

Permalink
#108 - types of vacation request (#110)
Browse files Browse the repository at this point in the history
* #108 - wip

* #108 - add icon to absence

* #108 - wip

* #108 - fix

* #108 - fix title

Co-authored-by: EwelinaLasowy <ewelina.lasowy@blumilk.pl>
  • Loading branch information
Baakoma and EwelinaSkrzypacz authored Apr 6, 2022
1 parent fa244b9 commit 6af4380
Show file tree
Hide file tree
Showing 22 changed files with 208 additions and 48 deletions.
10 changes: 9 additions & 1 deletion app/Domain/Enums/VacationType.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Toby\Domain\Enums;

use Illuminate\Support\Collection;

enum VacationType: string
{
case Vacation = "vacation";
Expand All @@ -15,6 +17,7 @@ enum VacationType: string
case Volunteering = "volunteering_vacation";
case TimeInLieu = "time_in_lieu";
case Sick = "sick_vacation";
case Absence = "absence";

public function label(): string
{
Expand All @@ -23,7 +26,7 @@ public function label(): string

public static function casesToSelect(): array
{
$cases = collect(VacationType::cases());
$cases = VacationType::all();

return $cases->map(
fn(VacationType $enum) => [
Expand All @@ -32,4 +35,9 @@ public static function casesToSelect(): array
],
)->toArray();
}

public static function all(): Collection
{
return new Collection(VacationType::cases());
}
}
12 changes: 10 additions & 2 deletions app/Domain/TimesheetExport.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,21 @@

namespace Toby\Domain;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
use Toby\Eloquent\Models\User;

class TimesheetExport implements WithMultipleSheets
{
protected Collection $users;
protected Collection $types;
protected Carbon $month;

public function sheets(): array
{
return $this->users
->map(fn(User $user) => new TimesheetPerUserSheet($user, $this->month))
->map(fn(User $user) => new TimesheetPerUserSheet($user, $this->month, $this->types))
->toArray();
}

Expand All @@ -34,4 +35,11 @@ public function forMonth(Carbon $month): static

return $this;
}

public function forVacationTypes(Collection $types): static
{
$this->types = $types;

return $this;
}
}
7 changes: 4 additions & 3 deletions app/Domain/TimesheetPerUserSheet.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Carbon\CarbonInterface;
use Carbon\CarbonPeriod;
use Generator;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\FromGenerator;
Expand Down Expand Up @@ -40,6 +41,7 @@ class TimesheetPerUserSheet implements WithTitle, WithHeadings, WithEvents, With
public function __construct(
protected User $user,
protected Carbon $month,
protected Collection $types,
) {}

public function title(): string
Expand All @@ -49,8 +51,6 @@ public function title(): string

public function headings(): array
{
$types = VacationType::cases();

$headings = [
__("Date"),
__("Day of week"),
Expand All @@ -59,7 +59,7 @@ public function headings(): array
__("Worked hours"),
];

foreach ($types as $type) {
foreach ($this->types as $type) {
$headings[] = $type->label();
}

Expand Down Expand Up @@ -187,6 +187,7 @@ protected function getVacationsForPeriod(User $user, CarbonPeriod $period): Coll
{
return $user->vacations()
->with("vacationRequest")
->whereRelation("vacationRequest", fn(Builder $query) => $query->whereIn("type", $this->types))
->whereBetween("date", [$period->start, $period->end])
->approved()
->get()
Expand Down
4 changes: 2 additions & 2 deletions app/Domain/UserVacationStatsRetriever.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,14 @@ public function getVacationDaysLimit(User $user, YearPeriod $yearPeriod): int

protected function getLimitableVacationTypes(): Collection
{
$types = new Collection(VacationType::cases());
$types = VacationType::all();

return $types->filter(fn(VacationType $type) => $this->configRetriever->hasLimit($type));
}

protected function getNotLimitableVacationTypes(): Collection
{
$types = new Collection(VacationType::cases());
$types = VacationType::all();

return $types->filter(fn(VacationType $type) => !$this->configRetriever->hasLimit($type));
}
Expand Down
7 changes: 7 additions & 0 deletions app/Domain/VacationTypeConfigRetriever.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Toby\Domain;

use Illuminate\Contracts\Config\Repository;
use Toby\Domain\Enums\EmploymentForm;
use Toby\Domain\Enums\VacationType;

class VacationTypeConfigRetriever
Expand All @@ -13,6 +14,7 @@ class VacationTypeConfigRetriever
public const KEY_ADMINISTRATIVE_APPROVAL = "administrative_approval";
public const KEY_BILLABLE = "billable";
public const KEY_HAS_LIMIT = "has_limit";
public const KEY_AVAILABLE_FOR = "available_for";

public function __construct(
protected Repository $config,
Expand All @@ -38,6 +40,11 @@ public function hasLimit(VacationType $type): bool
return $this->getConfigFor($type)[static::KEY_HAS_LIMIT];
}

public function isAvailableFor(VacationType $type, EmploymentForm $employmentForm): bool
{
return in_array($employmentForm, $this->getConfigFor($type)[static::KEY_AVAILABLE_FOR], true);
}

protected function getConfigFor(VacationType $type): array
{
return $this->config->get("vacation_types.{$type->value}");
Expand Down
4 changes: 2 additions & 2 deletions app/Domain/Validation/Rules/DoesNotExceedLimitRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace Toby\Domain\Validation\Rules;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Collection;
use Toby\Domain\Enums\VacationType;
use Toby\Domain\VacationDaysCalculator;
use Toby\Domain\VacationRequestStatesRetriever;
Expand Down Expand Up @@ -59,7 +59,7 @@ protected function getVacationDaysWithLimit(User $user, YearPeriod $yearPeriod):

protected function getLimitableVacationTypes(): Collection
{
$types = new Collection(VacationType::cases());
$types = VacationType::all();

return $types->filter(fn(VacationType $type) => $this->configRetriever->hasLimit($type));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Toby\Infrastructure\Http\Controllers\Api;

use Illuminate\Http\JsonResponse;
use Toby\Domain\Enums\VacationType;
use Toby\Domain\VacationTypeConfigRetriever;
use Toby\Eloquent\Models\User;
use Toby\Infrastructure\Http\Controllers\Controller;
use Toby\Infrastructure\Http\Requests\Api\GetAvailableVacationTypesRequest;

class GetAvailableVacationTypesController extends Controller
{
public function __invoke(
GetAvailableVacationTypesRequest $request,
VacationTypeConfigRetriever $configRetriever,
): JsonResponse {
/** @var User $user */
$user = User::query()->find($request->get("user"));

$types = VacationType::all()
->filter(fn(VacationType $type) => $configRetriever->isAvailableFor($type, $user->employment_form))
->map(fn(VacationType $type) => [
"label" => $type->label(),
"value" => $type->value,
])
->values();

return new JsonResponse($types);
}
}
19 changes: 16 additions & 3 deletions app/Infrastructure/Http/Controllers/TimesheetController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,43 @@
use Illuminate\Support\Carbon;
use Maatwebsite\Excel\Facades\Excel;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Toby\Domain\Enums\EmploymentForm;
use Toby\Domain\Enums\Month;
use Toby\Domain\Enums\VacationType;
use Toby\Domain\TimesheetExport;
use Toby\Domain\VacationTypeConfigRetriever;
use Toby\Eloquent\Helpers\YearPeriodRetriever;
use Toby\Eloquent\Models\User;

class TimesheetController extends Controller
{
public function __invoke(Month $month, YearPeriodRetriever $yearPeriodRetriever): BinaryFileResponse
{
public function __invoke(
Month $month,
YearPeriodRetriever $yearPeriodRetriever,
VacationTypeConfigRetriever $configRetriever,
): BinaryFileResponse {
$this->authorize("generateTimesheet");

$yearPeriod = $yearPeriodRetriever->selected();
$carbonMonth = Carbon::create($yearPeriod->year, $month->toCarbonNumber());

$users = User::query()
->where("employment_form", EmploymentForm::EmploymentContract)
->orderBy("last_name")
->orderBy("first_name")
->get();

$types = VacationType::all()
->filter(
fn(VacationType $type) => $configRetriever->isAvailableFor($type, EmploymentForm::EmploymentContract),
);

$filename = "{$carbonMonth->translatedFormat("F Y")}.xlsx";

$timesheet = (new TimesheetExport())
->forMonth($carbonMonth)
->forUsers($users);
->forUsers($users)
->forVacationTypes($types);

return Excel::download($timesheet, $filename);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,7 @@ public function download(VacationRequest $vacationRequest): LaravelResponse

public function create(Request $request, YearPeriodRetriever $yearPeriodRetriever): Response
{
$yearPeriod = $yearPeriodRetriever->selected();

$users = User::query()
->withVacationLimitIn($yearPeriod)
->orderBy("last_name")
->orderBy("first_name")
->get();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace Toby\Infrastructure\Http\Requests\Api;

use Illuminate\Foundation\Http\FormRequest;

class GetAvailableVacationTypesRequest extends FormRequest
{
public function rules(): array
{
return [
"user" => ["required", "exists:users,id"],
];
}
}
48 changes: 48 additions & 0 deletions config/vacation_types.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

declare(strict_types=1);

use Toby\Domain\Enums\EmploymentForm;
use Toby\Domain\Enums\VacationType;
use Toby\Domain\VacationTypeConfigRetriever;

Expand All @@ -11,53 +12,100 @@
VacationTypeConfigRetriever::KEY_ADMINISTRATIVE_APPROVAL => true,
VacationTypeConfigRetriever::KEY_BILLABLE => true,
VacationTypeConfigRetriever::KEY_HAS_LIMIT => true,
VacationTypeConfigRetriever::KEY_AVAILABLE_FOR => [
EmploymentForm::EmploymentContract,
],
],
VacationType::OnRequest->value => [
VacationTypeConfigRetriever::KEY_TECHNICAL_APPROVAL => true,
VacationTypeConfigRetriever::KEY_ADMINISTRATIVE_APPROVAL => true,
VacationTypeConfigRetriever::KEY_BILLABLE => true,
VacationTypeConfigRetriever::KEY_HAS_LIMIT => true,
VacationTypeConfigRetriever::KEY_AVAILABLE_FOR => [
EmploymentForm::EmploymentContract,
],
],
VacationType::TimeInLieu->value => [
VacationTypeConfigRetriever::KEY_TECHNICAL_APPROVAL => false,
VacationTypeConfigRetriever::KEY_ADMINISTRATIVE_APPROVAL => false,
VacationTypeConfigRetriever::KEY_BILLABLE => true,
VacationTypeConfigRetriever::KEY_HAS_LIMIT => false,
VacationTypeConfigRetriever::KEY_AVAILABLE_FOR => [
EmploymentForm::EmploymentContract,
],
],
VacationType::Sick->value => [
VacationTypeConfigRetriever::KEY_TECHNICAL_APPROVAL => false,
VacationTypeConfigRetriever::KEY_ADMINISTRATIVE_APPROVAL => true,
VacationTypeConfigRetriever::KEY_BILLABLE => true,
VacationTypeConfigRetriever::KEY_HAS_LIMIT => false,
VacationTypeConfigRetriever::KEY_AVAILABLE_FOR => [
EmploymentForm::EmploymentContract,
],
],
VacationType::Unpaid->value => [
VacationTypeConfigRetriever::KEY_TECHNICAL_APPROVAL => true,
VacationTypeConfigRetriever::KEY_ADMINISTRATIVE_APPROVAL => true,
VacationTypeConfigRetriever::KEY_BILLABLE => false,
VacationTypeConfigRetriever::KEY_HAS_LIMIT => false,
VacationTypeConfigRetriever::KEY_AVAILABLE_FOR => [
EmploymentForm::EmploymentContract,
],
],
VacationType::Special->value => [
VacationTypeConfigRetriever::KEY_TECHNICAL_APPROVAL => true,
VacationTypeConfigRetriever::KEY_ADMINISTRATIVE_APPROVAL => true,
VacationTypeConfigRetriever::KEY_BILLABLE => false,
VacationTypeConfigRetriever::KEY_HAS_LIMIT => false,
VacationTypeConfigRetriever::KEY_AVAILABLE_FOR => [
EmploymentForm::EmploymentContract,
],
],
VacationType::Childcare->value => [
VacationTypeConfigRetriever::KEY_TECHNICAL_APPROVAL => true,
VacationTypeConfigRetriever::KEY_ADMINISTRATIVE_APPROVAL => true,
VacationTypeConfigRetriever::KEY_BILLABLE => false,
VacationTypeConfigRetriever::KEY_HAS_LIMIT => false,
VacationTypeConfigRetriever::KEY_AVAILABLE_FOR => [
EmploymentForm::EmploymentContract,
],
],
VacationType::Training->value => [
VacationTypeConfigRetriever::KEY_TECHNICAL_APPROVAL => true,
VacationTypeConfigRetriever::KEY_ADMINISTRATIVE_APPROVAL => true,
VacationTypeConfigRetriever::KEY_BILLABLE => true,
VacationTypeConfigRetriever::KEY_HAS_LIMIT => false,
VacationTypeConfigRetriever::KEY_AVAILABLE_FOR => [
EmploymentForm::EmploymentContract,
],
],
VacationType::Volunteering->value => [
VacationTypeConfigRetriever::KEY_TECHNICAL_APPROVAL => true,
VacationTypeConfigRetriever::KEY_ADMINISTRATIVE_APPROVAL => true,
VacationTypeConfigRetriever::KEY_BILLABLE => true,
VacationTypeConfigRetriever::KEY_HAS_LIMIT => false,
VacationTypeConfigRetriever::KEY_AVAILABLE_FOR => [
EmploymentForm::EmploymentContract,
],
],
VacationType::Volunteering->value => [
VacationTypeConfigRetriever::KEY_TECHNICAL_APPROVAL => true,
VacationTypeConfigRetriever::KEY_ADMINISTRATIVE_APPROVAL => true,
VacationTypeConfigRetriever::KEY_BILLABLE => true,
VacationTypeConfigRetriever::KEY_HAS_LIMIT => false,
VacationTypeConfigRetriever::KEY_AVAILABLE_FOR => [
EmploymentForm::EmploymentContract,
],
],
VacationType::Absence->value => [
VacationTypeConfigRetriever::KEY_TECHNICAL_APPROVAL => true,
VacationTypeConfigRetriever::KEY_ADMINISTRATIVE_APPROVAL => false,
VacationTypeConfigRetriever::KEY_BILLABLE => false,
VacationTypeConfigRetriever::KEY_HAS_LIMIT => false,
VacationTypeConfigRetriever::KEY_AVAILABLE_FOR => [
EmploymentForm::CommissionContract,
EmploymentForm::B2bContract,
EmploymentForm::BoardMemberContract,
],
],
];
Loading

0 comments on commit 6af4380

Please sign in to comment.