#85 - google calendar improvements (#86)

* google calendar improvements

* fix

* change vacation request name

* #85 - google calendar improvements

* #85 - fix

* #85 - fix

* #85 - fix
This commit is contained in:
Adrian Hopek 2022-03-18 08:11:34 +01:00 committed by GitHub
parent afb1a5e9ff
commit 8c1819aa01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 120 additions and 71 deletions

View File

@ -6,10 +6,8 @@ namespace Toby\Architecture\Providers;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Toby\Eloquent\Models\User; use Toby\Eloquent\Models\User;
use Toby\Eloquent\Models\VacationRequest;
use Toby\Eloquent\Models\YearPeriod; use Toby\Eloquent\Models\YearPeriod;
use Toby\Eloquent\Observers\UserObserver; use Toby\Eloquent\Observers\UserObserver;
use Toby\Eloquent\Observers\VacationRequestObserver;
use Toby\Eloquent\Observers\YearPeriodObserver; use Toby\Eloquent\Observers\YearPeriodObserver;
class ObserverServiceProvider extends ServiceProvider class ObserverServiceProvider extends ServiceProvider
@ -18,6 +16,5 @@ class ObserverServiceProvider extends ServiceProvider
{ {
User::observe(UserObserver::class); User::observe(UserObserver::class);
YearPeriod::observe(YearPeriodObserver::class); YearPeriod::observe(YearPeriodObserver::class);
VacationRequest::observe(VacationRequestObserver::class);
} }
} }

View File

@ -12,7 +12,6 @@ use Illuminate\Support\Carbon;
/** /**
* @property int $id * @property int $id
* @property Carbon $date * @property Carbon $date
* @property string $event_id
* @property User $user * @property User $user
* @property VacationRequest $vacationRequest * @property VacationRequest $vacationRequest
* @property YearPeriod $yearPeriod * @property YearPeriod $yearPeriod

View File

@ -6,6 +6,7 @@ namespace Toby\Eloquent\Models;
use Database\Factories\VacationRequestFactory; use Database\Factories\VacationRequestFactory;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\AsCollection;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
@ -18,6 +19,7 @@ use Toby\Domain\States\VacationRequest\VacationRequestState;
/** /**
* @property int $id * @property int $id
* @property string $name
* @property VacationType $type * @property VacationType $type
* @property VacationRequestState $state * @property VacationRequestState $state
* @property Carbon $from * @property Carbon $from
@ -29,6 +31,7 @@ use Toby\Domain\States\VacationRequest\VacationRequestState;
* @property YearPeriod $yearPeriod * @property YearPeriod $yearPeriod
* @property Collection $activities * @property Collection $activities
* @property Collection $vacations * @property Collection $vacations
* @property Collection $event_ids
* @property Carbon $created_at * @property Carbon $created_at
* @property Carbon $updated_at * @property Carbon $updated_at
*/ */
@ -44,6 +47,7 @@ class VacationRequest extends Model
"state" => VacationRequestState::class, "state" => VacationRequestState::class,
"from" => "date", "from" => "date",
"to" => "date", "to" => "date",
"event_ids" => AsCollection::class,
]; ];
public function user(): BelongsTo public function user(): BelongsTo
@ -87,6 +91,11 @@ class VacationRequest extends Model
->where("to", ">=", $vacationRequest->from); ->where("to", ">=", $vacationRequest->from);
} }
public function getNameAttribute(): string
{
return "{$this->id}/{$this->yearPeriod->year}";
}
public function hasFlowSkipped(): bool public function hasFlowSkipped(): bool
{ {
return $this->flow_skipped; return $this->flow_skipped;

View File

@ -1,28 +0,0 @@
<?php
declare(strict_types=1);
namespace Toby\Eloquent\Observers;
use Illuminate\Contracts\Auth\Factory as Auth;
use Illuminate\Contracts\Events\Dispatcher;
use Toby\Eloquent\Models\VacationRequest;
class VacationRequestObserver
{
public function __construct(
protected Auth $auth,
protected Dispatcher $dispatcher,
) {}
public function creating(VacationRequest $vacationRequest): void
{
$year = $vacationRequest->from->year;
$vacationRequestNumber = $vacationRequest->user->vacationRequests()
->whereYear("from", $year)
->count() + 1;
$vacationRequest->name = "{$vacationRequestNumber}/${year}";
}
}

View File

@ -8,7 +8,6 @@ use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Spatie\GoogleCalendar\Event; use Spatie\GoogleCalendar\Event;
use Toby\Eloquent\Models\Vacation;
use Toby\Eloquent\Models\VacationRequest; use Toby\Eloquent\Models\VacationRequest;
class ClearVacationRequestDaysInGoogleCalendar implements ShouldQueue class ClearVacationRequestDaysInGoogleCalendar implements ShouldQueue
@ -22,17 +21,16 @@ class ClearVacationRequestDaysInGoogleCalendar implements ShouldQueue
public function handle(): void public function handle(): void
{ {
$vacations = $this->vacationRequest->vacations() foreach ($this->vacationRequest->event_ids as $eventId) {
->whereNotNull("event_id") $calendarEvent = Event::find($eventId);
->get();
/** @var Vacation $vacation */ if ($calendarEvent->googleEvent->getStatus() !== "cancelled") {
foreach ($vacations as $vacation) { $calendarEvent->delete();
Event::find($vacation->event_id)->delete(); }
}
$vacation->update([ $this->vacationRequest->update([
"event_id" => null, "event_ids" => null,
]); ]);
} }
}
} }

View File

@ -7,8 +7,9 @@ namespace Toby\Infrastructure\Jobs;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Spatie\GoogleCalendar\Event; use Spatie\GoogleCalendar\Event;
use Toby\Eloquent\Models\Vacation;
use Toby\Eloquent\Models\VacationRequest; use Toby\Eloquent\Models\VacationRequest;
class SendVacationRequestDaysToGoogleCalendar implements ShouldQueue class SendVacationRequestDaysToGoogleCalendar implements ShouldQueue
@ -22,21 +23,57 @@ class SendVacationRequestDaysToGoogleCalendar implements ShouldQueue
public function handle(): void public function handle(): void
{ {
$vacations = $this->vacationRequest->vacations() $days = $this->vacationRequest
->whereNull("event_id") ->vacations()
->get(); ->orderBy("date")
->pluck("date");
$this->vacationRequest->event_ids = new Collection();
$ranges = $this->prepareRanges($days);
foreach ($ranges as $range) {
$text = "{$this->vacationRequest->type->label()} - {$this->vacationRequest->user->fullName} [{$this->vacationRequest->name}]";
/** @var Vacation $vacation */
foreach ($vacations as $vacation) {
$event = Event::create([ $event = Event::create([
"name" => "{$this->vacationRequest->type->label()} - {$this->vacationRequest->user->fullName}", "name" => $text,
"startDate" => $vacation->date, "startDate" => Carbon::create($range["from"]),
"endDate" => $vacation->date, "endDate" => Carbon::create($range["to"])->addDay(),
]); ]);
$vacation->update([ $this->vacationRequest->event_ids->add($event->id);
"event_id" => $event->id,
]);
} }
$this->vacationRequest->save();
}
protected function prepareRanges(Collection $days): array
{
$ranges = [];
$index = 0;
$first = $days->shift();
$ranges[$index] = [
"from" => $first,
"to" => $first,
];
foreach ($days as $day) {
if ($day->diffInDays($ranges[$index]["to"]) > 1) {
$index++;
$ranges[$index] = [
"from" => $day,
"to" => $day,
];
continue;
}
if ($day->isAfter($ranges[$index]["to"])) {
$ranges[$index]["to"] = $day;
}
}
return $ranges;
} }
} }

View File

@ -15,7 +15,6 @@ use Toby\Eloquent\Models\YearPeriod;
class VacationRequestFactory extends Factory class VacationRequestFactory extends Factory
{ {
protected $model = VacationRequest::class; protected $model = VacationRequest::class;
private static int $number = 1;
public function definition(): array public function definition(): array
{ {
@ -26,7 +25,6 @@ class VacationRequestFactory extends Factory
"user_id" => User::factory(), "user_id" => User::factory(),
"creator_id" => fn(array $attributes): int => $attributes["user_id"], "creator_id" => fn(array $attributes): int => $attributes["user_id"],
"year_period_id" => YearPeriod::factory(), "year_period_id" => YearPeriod::factory(),
"name" => fn(array $attributes): string => $this->generateName($attributes),
"type" => $this->faker->randomElement(VacationType::cases()), "type" => $this->faker->randomElement(VacationType::cases()),
"state" => $this->faker->randomElement(VacationRequestStatesRetriever::all()), "state" => $this->faker->randomElement(VacationRequestStatesRetriever::all()),
"from" => $from, "from" => $from,
@ -34,12 +32,4 @@ class VacationRequestFactory extends Factory
"comment" => $this->faker->boolean ? $this->faker->paragraph() : null, "comment" => $this->faker->boolean ? $this->faker->paragraph() : null,
]; ];
} }
protected function generateName(array $attributes): string
{
$year = YearPeriod::find($attributes["year_period_id"])->year;
$number = static::$number++;
return "{$number}/{$year}";
}
} }

View File

@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class() extends Migration {
public function up(): void
{
Schema::table("vacations", function (Blueprint $table): void {
$table->dropColumn("event_id");
});
}
public function down(): void
{
Schema::table("vacations", function (Blueprint $table): void {
$table->string("event_id")->nullable();
});
}
};

View File

@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class() extends Migration {
public function up(): void
{
Schema::table("vacation_requests", function (Blueprint $table): void {
$table->json("event_ids")->nullable();
$table->dropColumn("name");
});
}
public function down(): void
{
Schema::table("vacation_requests", function (Blueprint $table): void {
$table->dropColumn("event_ids");
$table->string("name")->nullable();
});
}
};

View File

@ -1,5 +1,5 @@
<template> <template>
<InertiaHead title="Użytkownicy" /> <InertiaHead title="Dostępne dni urlopu dla użytkowników" />
<div class="bg-white shadow-md"> <div class="bg-white shadow-md">
<div class="flex justify-between items-center p-4 sm:px-6"> <div class="flex justify-between items-center p-4 sm:px-6">
<div> <div>

View File

@ -1,10 +1,10 @@
<template> <template>
<InertiaHead title="Twoje wnioski urlopowe" /> <InertiaHead title="Moje wnioski urlopowe" />
<div class="bg-white shadow-md"> <div class="bg-white shadow-md">
<div class="flex justify-between items-center p-4 sm:px-6"> <div class="flex justify-between items-center p-4 sm:px-6">
<div> <div>
<h2 class="text-lg leading-6 font-medium text-gray-900"> <h2 class="text-lg leading-6 font-medium text-gray-900">
Twoje wnioski urlopowe Moje wnioski urlopowe
</h2> </h2>
</div> </div>
<div> <div>

View File

@ -84,7 +84,6 @@ class VacationRequestTest extends FeatureTestCase
$this->assertDatabaseHas("vacation_requests", [ $this->assertDatabaseHas("vacation_requests", [
"user_id" => $user->id, "user_id" => $user->id,
"year_period_id" => $currentYearPeriod->id, "year_period_id" => $currentYearPeriod->id,
"name" => "1/" . $currentYearPeriod->year,
"type" => VacationType::Vacation->value, "type" => VacationType::Vacation->value,
"state" => WaitingForTechnical::$name, "state" => WaitingForTechnical::$name,
"from" => Carbon::create($currentYearPeriod->year, 2, 7)->toDateString(), "from" => Carbon::create($currentYearPeriod->year, 2, 7)->toDateString(),
@ -121,7 +120,6 @@ class VacationRequestTest extends FeatureTestCase
"user_id" => $user->id, "user_id" => $user->id,
"creator_id" => $creator->id, "creator_id" => $creator->id,
"year_period_id" => $currentYearPeriod->id, "year_period_id" => $currentYearPeriod->id,
"name" => "1/" . $currentYearPeriod->year,
"type" => VacationType::Vacation->value, "type" => VacationType::Vacation->value,
"state" => WaitingForTechnical::$name, "state" => WaitingForTechnical::$name,
"from" => Carbon::create($currentYearPeriod->year, 2, 7)->toDateString(), "from" => Carbon::create($currentYearPeriod->year, 2, 7)->toDateString(),
@ -161,7 +159,6 @@ class VacationRequestTest extends FeatureTestCase
"user_id" => $user->id, "user_id" => $user->id,
"creator_id" => $creator->id, "creator_id" => $creator->id,
"year_period_id" => $currentYearPeriod->id, "year_period_id" => $currentYearPeriod->id,
"name" => "1/" . $currentYearPeriod->year,
"type" => VacationType::Vacation->value, "type" => VacationType::Vacation->value,
"state" => Approved::$name, "state" => Approved::$name,
"from" => Carbon::create($currentYearPeriod->year, 2, 7)->toDateString(), "from" => Carbon::create($currentYearPeriod->year, 2, 7)->toDateString(),

View File

@ -6,6 +6,7 @@ namespace Tests\Unit;
use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Notification; use Illuminate\Support\Facades\Notification;
use Tests\TestCase; use Tests\TestCase;
use Tests\Traits\InteractsWithYearPeriods; use Tests\Traits\InteractsWithYearPeriods;
@ -30,6 +31,7 @@ class VacationRequestStatesTest extends TestCase
parent::setUp(); parent::setUp();
Notification::fake(); Notification::fake();
Bus::fake();
$this->stateManager = $this->app->make(VacationRequestStateManager::class); $this->stateManager = $this->app->make(VacationRequestStateManager::class);