<?php
namespace App\Entity\TimeNormalization;
use ApiPlatform\Core\Annotation\ApiFilter;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\DateFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\OrderFilter;
use App\Interfaces\UuidKeyInterface;
use App\Repository\TimeNormalization\WorkDayRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\{
Serializer\Annotation\Context,
Serializer\Annotation\Groups,
Serializer\Normalizer\DateTimeNormalizer,
Validator\Constraints as Assert
};
/**
* День рабочего календаря.
*/
#[ApiResource(
collectionOperations: [
'get' => [
'openapi_context' => ['summary' => 'Получить список дней рабочего календаря', 'description' => 'Получить список дней рабочего календаря'],
],
],
itemOperations: [
'get' => [
'openapi_context' => [
'summary' => 'Получить данные дня рабочего календаря',
'description' => 'публичный метод для получения данных по дню рабочего календаря',
],
],
'patch' => [
'security' => "is_granted('ROLE_ADMIN')",
'denormalization_context' => ['groups' => [self::PATCH_GROUP]],
'openapi_context' => [
'summary' => 'Изменить день рабочего календаря',
'description' => 'требуется роль Администратора (ROLE_ADMIN)',
],
],
],
order: ['day' => 'ASC'],
paginationItemsPerPage: 31,
)]
#[ApiFilter(DateFilter::class, properties: ['day'])]
#[ApiFilter(OrderFilter::class, properties: ['day' => 'ASC'])]
#[ORM\Entity(repositoryClass: WorkDayRepository::class)]
#[ORM\Table(name: 'work_days')]
#[UniqueEntity(fields: ['day'])]
class WorkDay implements UuidKeyInterface
{
public const READ_GROUP = 'WorkDay:read';
public const WRITE_GROUP = 'WorkDay:write';
public const PATCH_GROUP = 'WorkDay:patch';
public const TYPE_WORKDAY = 'workday';
public const TYPE_WEEKEND = 'weekend';
public const TYPE_HOLIDAY = 'holiday';
public const TYPE_SHORTDAY = 'shortday';
public const TYPES = [
self::TYPE_WORKDAY,
self::TYPE_WEEKEND,
self::TYPE_HOLIDAY,
self::TYPE_SHORTDAY,
];
/** список типов рабочих дней */
public const TYPES_WORKDAYS = [
self::TYPE_SHORTDAY,
self::TYPE_WORKDAY,
];
#[Groups([self::READ_GROUP])]
#[ApiProperty(writable: false, identifier: false)]
#[ORM\Id]
#[ORM\Column(type: 'uuid', unique: true)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: 'App\Doctrine\Generator\UuidGenerator')]
protected ?string $id = null;
#[Assert\NotBlank(groups: [self::WRITE_GROUP])]
#[Groups([self::READ_GROUP, self::WRITE_GROUP])]
#[ApiProperty(description: 'дата', writable: false, identifier: true, openapiContext: ['format' => 'date'])]
#[ORM\Column(type: 'date', nullable: false, unique: true)]
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
private \DateTimeInterface $day;
#[Assert\Choice(choices: self::TYPES)]
#[ApiProperty(
description: 'тип',
required: false,
example: self::TYPE_WORKDAY,
openapiContext: [
'type' => 'string',
'enum' => self::TYPES,
]
)]
#[Groups([self::READ_GROUP, self::WRITE_GROUP, self::PATCH_GROUP])]
#[ORM\Column(name: 'day_type', type: 'string', length: 10, options: ['default' => 'workday'])]
private string $dayType = self::TYPE_WORKDAY;
#[Groups([self::READ_GROUP, self::WRITE_GROUP, self::PATCH_GROUP])]
#[ApiProperty(description: 'выходной?', required: false)]
#[ORM\Column(name: 'is_weekend', type: 'boolean', nullable: false, options: ['default' => false])]
private bool $isWeekend = false;
public function __construct(\DateTimeInterface $day, string $dayType, bool $isWeekend = null)
{
$this->setDay($day);
$this->dayType = $dayType;
$this->setIsWeekend($isWeekend);
}
public function getId(): ?string
{
return $this->id;
}
#[ApiProperty(identifier: true, description: 'дата', openapiContext: ['format' => 'date'])]
public function getDay(): string
{
return $this->day->format('Y-m-d');
}
#[ApiProperty(readable: false)]
public function getDate(): \DateTimeInterface
{
return $this->day;
}
public function setDay(\DateTimeInterface $day): self
{
$this->day = \DateTime::createFromInterface($day);
return $this;
}
public function getDayType(): ?string
{
return $this->dayType;
}
public function setDayType(string $dayType): self
{
$this->dayType = $dayType;
return $this;
}
public function getIsWeekend(): ?bool
{
return $this->isWeekend;
}
public function setIsWeekend(bool $isWeekend = null): self
{
$this->isWeekend = $isWeekend ?? self::isWeekend($this->day);
return $this;
}
/** является ли день субботой или воскресеньем */
public static function isWeekend(\DateTimeInterface $day): bool
{
return $day->format('N') > 5;
}
/** является ли день рабочим */
public function isWorkDay(): bool
{
return \in_array($this->dayType, self::TYPES_WORKDAYS);
}
}