<?php
/**
* Created by simpson <simpsonwork@gmail.com>
* Date: 2019-08-23
* Time: 21:03
*/
namespace App\Entity\Sales\Profile;
use App\Entity\Profile\Profile;
use App\Entity\Sales\PaidPlacementPrice;
use App\Repository\ProfileAdBoardPlacementRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* Сортировка будет выглядеть следующим образом:
* 1. Ультра вип
* 2. Вип
* 3. Анкеты с подтвержденными фото
* 4. Подтвержденные оплаченные анкеты и наши анкеты (см. ниже)
* 5. Старые анкеты с подтвержденным фото
* 6. Старые анкеты
*
* где 1 - первые страницы, 6 - последние.
*
* @see https://redminez.net/issues/26983
*/
#[ORM\Table(name: 'profile_adboard_placements')]
#[ORM\Entity(repositoryClass: ProfileAdBoardPlacementRepository::class)]
class AdBoardPlacement
{
// Значение группы влияет на порядок сортировки на сайте
const POSITION_GROUP_ULTRA_VIP = 200;
const POSITION_GROUP_VIP = 100;
// Группы стандартных размещений
const POSITION_GROUP_STANDARD_APPROVED = 60;
const POSITION_GROUP_STANDARD = 50;
const POSITION_GROUP_WITHOUT_OWNER_APPROVED = 40;
const POSITION_GROUP_WITHOUT_OWNER = 30;
const POSITION_GROUP_FREE = 10;
#[ORM\JoinColumn(name: 'profile_id', referencedColumnName: 'id')]
#[ORM\Id]
#[ORM\OneToOne(targetEntity: Profile::class, inversedBy: 'adBoardPlacement')]
protected ?Profile $profile;
/**
* Тип размещения: ультра-вип, вип, стандарт и др.
*/
#[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;
/**
* Существует пул анкет которые не будут (скорее всего) подтверждать, но они должны иметь приоритет 4. Это анкеты у которых номера телефонов:
*/
private static array $reservedPhoneNumbers = [
"+79670621036",
"+79670668029",
"+79657648078",
"+79602362794",
"+79657647505",
"+79697928815",
"+79657656744",
"+79095836840",
"+79095868490",
"+79816893783",
"+79816884190",
"+79816881721",
"+79816892844",
"+79816894385",
"+79646132419",
"+79697390357",
"+79618107602",
];
public static function free(Profile $profile, int $position, ?PaidPlacementPrice $paidPlacementPrice, \DateTimeImmutable $placedAt, \DateTimeImmutable $placedUntil): self
{
$positionGroup = self::POSITION_GROUP_FREE;
return new static($profile, AdBoardPlacementType::free(), $paidPlacementPrice, $positionGroup, $position, $placedAt, $placedUntil);
}
public static function standard(Profile $profile, int $position, PaidPlacementPrice $paidPlacementPrice, \DateTimeImmutable $placedAt, \DateTimeImmutable $placedUntil): self
{
if ($profile->hasOwner()) {
$positionGroup = $profile->isApproved() ? self::POSITION_GROUP_STANDARD_APPROVED : self::POSITION_GROUP_STANDARD;
} else {
if (in_array($profile->getPhoneNumber(), self::$reservedPhoneNumbers, true)) {
$positionGroup = self::POSITION_GROUP_STANDARD;
} else {
$positionGroup = $profile->isApproved() ? self::POSITION_GROUP_WITHOUT_OWNER_APPROVED : self::POSITION_GROUP_WITHOUT_OWNER;
}
}
return new static($profile, AdBoardPlacementType::standard(), $paidPlacementPrice, $positionGroup, $position, $placedAt, $placedUntil);
}
public static function vip(Profile $profile, int $position, PaidPlacementPrice $paidPlacementPrice, \DateTimeImmutable $placedAt, \DateTimeImmutable $placedUntil): self
{
if (!$profile->hasOwner()) {
throw new \LogicException('Profile without owner cannot be placed at VIP position');
}
$positionGroup = self::POSITION_GROUP_VIP;
return new static($profile, AdBoardPlacementType::vip(), $paidPlacementPrice, $positionGroup, $position, $placedAt, $placedUntil);
}
public static function ultraVip(Profile $profile, int $position, PaidPlacementPrice $paidPlacementPrice, \DateTimeImmutable $placedAt, \DateTimeImmutable $placedUntil): self
{
if (!$profile->hasOwner()) {
throw new \LogicException('Profile without owner cannot be placed at UltraVIP position');
}
$positionGroup = self::POSITION_GROUP_ULTRA_VIP;
return new static($profile, AdBoardPlacementType::ultraVip(), $paidPlacementPrice, $positionGroup, $position, $placedAt, $placedUntil);
}
protected function __construct(Profile $profile, AdBoardPlacementType $type, ?PaidPlacementPrice $paidPlacementPrice, int $positionGroup, int $position, \DateTimeImmutable $placedAt, \DateTimeImmutable $placedUntil)
{
$this->profile = $profile;
$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 getProfile(): Profile
{
return $this->profile;
}
public function getType(): AdBoardPlacementType
{
return new AdBoardPlacementType($this->type);
}
public function getPositionGroup(): int
{
return $this->positionGroup;
}
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;
}
public function clearProfile():void
{
$this->profile = null;
}
}