<?php
namespace App\Entity\Sales\Saloon;
use App\Entity\Sales\PaidPlacementPrice;
use App\Entity\Saloon\Saloon;
use App\Repository\SaloonAdBoardPlacementRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* Сортировка будет выглядеть следующим образом:
* 1. Ультра вип
* 2. Вип (пока не сообщается)
* 3. Стандврт
*
* где 1 - первые страницы.
*
* @see https://redminez.net/issues/27368
*/
#[ORM\Table(name: 'saloon_adboard_placements')]
#[ORM\Entity(repositoryClass: SaloonAdBoardPlacementRepository::class)]
class AdBoardPlacement
{
// Значение группы влияет на порядок сортировки на сайте
const POSITION_GROUP_ULTRA_VIP = 200;
const POSITION_GROUP_VIP = 100;
// Группы стандартных размещений
const POSITION_GROUP_STANDARD = 50;
const POSITION_GROUP_WITHOUT_OWNER = 30;
#[ORM\JoinColumn(name: 'saloon_id', referencedColumnName: 'id')]
#[ORM\Id]
#[ORM\OneToOne(targetEntity: Saloon::class, inversedBy: 'adBoardPlacement')]
protected Saloon $saloon;
/**
* Тип размещения: ультра-вип, вип, стандарт и др.
*/
#[ORM\Column(name: 'type', type: 'smallint')]
protected int $type;
#[ORM\Column(name: 'position_group', type: 'smallint')]
protected int $positionGroup;
/**
* Позиция для сортировки, меняется несколько раз в течение в часа
*
* Новые анкеты добавляются всегда с наименьшим числом (может быть и отрицательным).
* При ротации позиции увеличиваются на 2.
*/
#[ORM\Column(name: 'position', type: 'integer')]
protected int $position;
/**
* Время добавления анкеты с указанным типом в список
*/
#[ORM\Column(name: 'placed_at', type: 'datetimetz_immutable')]
protected \DateTimeImmutable $placedAt;
/**
* Время следующего списания за показ в списке
*/
#[ORM\Column(name: 'placed_until', type: 'datetimetz_immutable')]
protected \DateTimeImmutable $placedUntil;
/**
* Цена, по которой было размещено (для продления по этой же цене)
*/
#[ORM\JoinColumn(name: 'placement_price_id', referencedColumnName: 'id', nullable: true)]
#[ORM\ManyToOne(targetEntity: PaidPlacementPrice::class)]
protected ?PaidPlacementPrice $placementPrice;
public static function standard(Saloon $saloon, int $position, PaidPlacementPrice $paidPlacementPrice, \DateTimeImmutable $placedAt, \DateTimeImmutable $placedUntil): self
{
$positionGroup = $saloon->hasOwner() ? self::POSITION_GROUP_STANDARD : self::POSITION_GROUP_WITHOUT_OWNER;
return new static($saloon, AdBoardPlacementType::standard(), $paidPlacementPrice, $positionGroup, $position, $placedAt, $placedUntil);
}
public static function vip(Saloon $saloon, int $position, PaidPlacementPrice $paidPlacementPrice, \DateTimeImmutable $placedAt, \DateTimeImmutable $placedUntil): self
{
if (!$saloon->hasOwner()) {
throw new \LogicException('Saloon without owner cannot be placed at VIP position');
}
$positionGroup = self::POSITION_GROUP_VIP;
return new static($saloon, AdBoardPlacementType::vip(), $paidPlacementPrice, $positionGroup, $position, $placedAt, $placedUntil);
}
public static function ultraVip(Saloon $saloon, int $position, PaidPlacementPrice $paidPlacementPrice, \DateTimeImmutable $placedAt, \DateTimeImmutable $placedUntil): self
{
if (!$saloon->hasOwner()) {
throw new \LogicException('Saloon without owner cannot be placed at UltraVIP position');
}
$positionGroup = self::POSITION_GROUP_ULTRA_VIP;
return new static($saloon, AdBoardPlacementType::ultraVip(), $paidPlacementPrice, $positionGroup, $position, $placedAt, $placedUntil);
}
protected function __construct(Saloon $saloon, AdBoardPlacementType $type, PaidPlacementPrice $paidPlacementPrice, int $positionGroup, int $position, \DateTimeImmutable $placedAt, \DateTimeImmutable $placedUntil)
{
$this->saloon = $saloon;
$this->type = $type->getValue();
$this->positionGroup = $positionGroup;
$this->position = $position;
$this->placedAt = $placedAt;
$this->placedUntil = $placedUntil;
$this->placementPrice = $paidPlacementPrice;
}
/**
* Продление показа анкеты в выдаче на сайте
*/
public function prolong(\DateTimeImmutable $placedUntil): void
{
$this->placedUntil = $placedUntil;
}
public function getSaloon(): Saloon
{
return $this->saloon;
}
public function getType(): AdBoardPlacementType
{
return new AdBoardPlacementType($this->type);
}
public function getPosition(): int
{
return $this->position;
}
public function getPlacedAt(): \DateTimeImmutable
{
return $this->placedAt;
}
public function getPlacedUntil(): \DateTimeImmutable
{
return $this->placedUntil;
}
public function getPlacementPrice(): ?PaidPlacementPrice
{
return $this->placementPrice;
}
}