feat(services): add database storage for public holidays

This commit is contained in:
2024-08-07 12:55:57 +02:00
parent 24f36c16d0
commit 9b907cf25d
4 changed files with 216 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
<?php
declare(strict_types=1);
namespace App\Services\WorkingDays\PublicHolidays\Storage;
use App\Models\Country;
use App\Models\NonWorkingDays;
use Illuminate\Database\UniqueConstraintViolationException;
use Illuminate\Support\Facades\Log;
class DatabaseStorage implements PublicHolidaysStorageInterface
{
public function isPublicHoliday(string $countryCode, \DateTimeImmutable $holidayDate): bool
{
$country = $this->getCountryByCountryCode($countryCode);
return NonWorkingDays::where('country_id', $country->id)
->where('non_working_date', $holidayDate->format('Y-m-d'))
->exists();
}
public function storePublicHoliday(string $countryCode, \DateTimeImmutable $holidayDate): ?NonWorkingDays
{
$country = $this->getCountryByCountryCode($countryCode);
try {
return NonWorkingDays::create([
'country_id' => $country->id,
'non_working_date' => $holidayDate->format('Y-m-d'),
]);
} catch (UniqueConstraintViolationException $e) {
// safe to ignore ... combination exists
Log::warning("Non-working day already exists for country: " . $country . ", date: {$holidayDate->format('Y-m-d')}");
}
return null;
}
public function getPublicHolidaysInInterval(string $countryCode, \DateTimeImmutable $startDate, \DateTimeImmutable $endDate): array
{
$country = $this->getCountryByCountryCode($countryCode);
return NonWorkingDays::where('country_id', $country->id)
->whereBetween('non_working_date', [$startDate->format('Y-m-d'), $endDate->format('Y-m-d')])
->get()->all();
}
public function countPublicHolidaysInInterval(string $countryCode, \DateTimeImmutable $startDate, \DateTimeImmutable $endDate): int
{
$country = $this->getCountryByCountryCode($countryCode);
return NonWorkingDays::where('country_id', $country->id)
->whereBetween('non_working_date', [$startDate->format('Y-m-d'), $endDate->format('Y-m-d')])
->count();
}
protected function getCountryByCountryCode(string $countryCode): Country
{
return Country::where('country_code', $countryCode)->first() ?? throw new \InvalidArgumentException("Country code '$countryCode' does not exist.");
}
}

View File

@@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
namespace App\Services\WorkingDays\PublicHolidays\Storage;
use App\Models\NonWorkingDays;
/**
* Interface for storing and retrieving public holidays independent on country.
*/
interface PublicHolidaysStorageInterface
{
/**
* Determine if a given public holiday is in a given country.
* @param string $countryCode
* @param \DateTimeImmutable $holidayDate
* @return bool
*/
public function isPublicHoliday(string $countryCode, \DateTimeImmutable $holidayDate): bool;
/**
* Returns all public holidays in a given country within a given interval.
* @param string $countryCode
* @param \DateTimeImmutable $startDate
* @param \DateTimeImmutable $endDate
* @return NonWorkingDays[]
*/
public function getPublicHolidaysInInterval(string $countryCode, \DateTimeImmutable $startDate, \DateTimeImmutable $endDate): array;
/**
* Counts all public holidays in a given country within a given interval.
* @param string $countryCode
* @param \DateTimeImmutable $startDate
* @param \DateTimeImmutable $endDate
* @return int
*/
public function countPublicHolidaysInInterval(string $countryCode, \DateTimeImmutable $startDate, \DateTimeImmutable $endDate): int;
/**
* Stores a public holiday in the storage.
* @param string $countryCode
* @param \DateTimeImmutable $holidayDate
* @return NonWorkingDays|null
*/
public function storePublicHoliday(string $countryCode, \DateTimeImmutable $holidayDate): ?NonWorkingDays;
}