<?php
namespace App\Entity;
use App\Repository\SaleRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity
*
* @UniqueEntity("id")
*
* @ORM\Entity(repositoryClass="App\Repository\SaleRepository")
*
* @ORM\InheritanceType("JOINED")
*
* @ORM\DiscriminatorColumn(name="discr", type="string")
*
* @ORM\DiscriminatorMap({"sale" = "Sale", "external_sale" = "ExternalSale"})
*
* @ORM\Table(
* name="sale",
* indexes={
*
* @ORM\Index(columns={"startDate"})
* }
* )
*
* @ORM\HasLifecycleCallbacks()
*/
class Sale implements \Stringable
{
// Status constants?
public const STATUS_CLOSED = 'Fermée';
public const STATUS_OPENED = 'Ouverte';
public const STATUS_PAUSED = 'En pause';
// Phases constants
public const PHASE_ANNOUNCED = 'Annoncée';
public const PHASE_EXPOSITION = 'Exposition';
public const PHASE_IN_PROGRESS = 'En cours';
public const PHASE_AFTER_SALES = 'Après vente';
public const PHASE_ENDED = 'Terminée';
// Taken from webservice documentation.
public const TYPE_ONLINE = 'Electronique';
public const TYPE_PHYSICAL = 'Physique';
public const TYPE_LIVE = 'Live';
public const OPTION_GP = 'al';
public const SALING_STATE_AUCTION = 'Enchères';
public const SALING_STATE_MIXED = 'Enchères et achats immédiats';
public const SALING_STATE_BUYOUT = 'Achats immédiats';
public const SALING_STATE_TENDER = 'Par soumission';
public const PUBLIC_PRO = 'Professionnel';
public const PUBLIC_ING = 'ING Car Lease';
public const PUBLIC_PRIVATE = 'Vente privée';
public const PUBLIC_FREE = 'Grand public';
public const PUBLIC_VPINDUSTRIE = 'VPIndustrie';
public const PUBLIC_FALFLEET = 'FalFleet';
public const PUBLIC_PEUGEOT = 'Peugeot';
/**
* @ORM\Id
*
* @ORM\Column(type="string")
*
* @ORM\GeneratedValue(strategy="NONE")
*
* @Assert\NotBlank(groups={"api_rms_saleevent"})
*
* @Groups({"read", "read_sale_event"})
*/
protected $id;
/**
* @ORM\Column(type="string")
*
* @Groups({"read", "read_sale_event"})
*/
protected $type;
/**
* @ORM\OneToMany(targetEntity="App\Entity\SaleEvent", mappedBy="sale")
*
* @Groups({"read"})
*/
protected $events;
/**
* @ORM\Column(type="string")
*
* @Assert\NotBlank(groups={"api_rms_saleevent", "api_iridium_sale"})
*
* @Groups({"read", "read_sale_event"})
*/
protected $title;
/**
* Room.
*
* @ORM\ManyToOne(targetEntity="App\Entity\Room", cascade={"persist"})
*
* @Groups({"read", "read_sale_event"})
*/
protected $room;
/**
* @var \DateTime
*
* @ORM\Column(type="datetime", nullable=true)
*
* @Assert\NotBlank(groups={"api_rms_saleevent", "api_iridium_sale"})
*
* @Groups({"read", "read_sale_event"})
*/
protected $startDate;
/**
* @var \DateTime
*
* @ORM\Column(type="datetime", nullable=true)
*
* @Assert\NotBlank(groups={"api_rms_saleevent", "api_iridium_sale"})
*
* @Groups({"read", "read_sale_event"})
*/
protected $endDate;
/**
* @ORM\Column(type="datetime", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
protected $recoveryAt;
/**
* @ORM\Column(type="string", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
protected $description;
/**
* @ORM\Column(type="string")
*
* @Assert\NotBlank(groups={"api_rms_saleevent"})
*
* @Groups({"read", "read_sale_event"})
*/
protected $status;
/**
* @ORM\Column(type="integer", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
protected $bidIncrement;
/**
* @ORM\Column(type="decimal", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
protected $vatRate;
/**
* @ORM\Column(type="boolean", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
protected $dynamicClosing;
/**
* Extra time in seconds.
*
* @ORM\Column(type="integer", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
protected $extraTime;
/**
* @ORM\Column(type="string", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
protected $salingType;
/**
* @ORM\Column(type="date", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
protected $publicationDate;
/**
* @ORM\Column(type="datetime", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
protected $expositionStartDate;
/**
* @ORM\Column(type="datetime", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
protected $expositionEndDate;
/**
* @ORM\Column(type="time", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
protected $dayExpositionTime;
/**
* @ORM\Column(type="datetime")
*
* @Groups({"read", "read_sale_event"})
*/
protected $createdAt;
/**
* @ORM\Column(type="datetime")
*
* @Groups({"read", "read_sale_event"})
*/
protected $updatedAt;
/**
* @ORM\OneToMany(targetEntity="App\Entity\SaleHighlight", mappedBy="sale", cascade={"persist", "remove"})
*
* @Groups({"read", "read_sale_event"})
*/
protected $highlights;
/**
* @ORM\OneToMany(targetEntity="App\Entity\SaleBehaviour", mappedBy="sale", cascade={"remove"})
*
* @Groups({"read", "read_sale_event"})
*/
protected $behaviours;
/**
* @ORM\Column(type="array", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
private $hours;
/**
* @ORM\Column(type="string", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
private $bannerUrl;
/**
* @ORM\Column(type="string", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
private $logoUrl;
/**
* @ORM\Column(type="string", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
private $company;
/**
* @ORM\Column(type="boolean", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
private $stock;
/**
* @ORM\Column(type="string", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
private $public;
/**
* @ORM\Column(type="boolean", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
private $displayExplodedView;
/**
* @ORM\Column(type="boolean", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
private $displayReconditioningFees;
/**
* @ORM\Column(type="boolean")
*
* @Groups({"read", "read_sale_event"})
*/
private $isLive;
/**
* @ORM\OneToMany(targetEntity="App\Entity\Transaction", mappedBy="sale", cascade={"remove"})
*
* @Groups({"read", "read_sale_event"})
*/
private $transactions;
/**
* @ORM\OneToOne(targetEntity="App\Entity\Vehicle")
*
* @ORM\JoinColumn(name="vehicle_opened_id", referencedColumnName="id")
*
* @Groups({"read", "read_sale_event"})
*/
private $openedVehicle;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Vehicle")
*
* @ORM\JoinColumn(name="last_opened_vehicle_id", referencedColumnName="id")
*
* @Groups({"read", "read_sale_event"})
*/
private $lastOpenedVehicle;
/**
* @ORM\OneToMany(targetEntity="App\Entity\PurchaseInstructionRule", mappedBy="sale", cascade={"remove"})
*
* @ORM\OrderBy({"updatedAt" = "asc"})
*
* @Groups({"read", "read_sale_event"})
*/
private $purchaseInstructionRules;
/**
* @ORM\Column(type = "boolean")
*
* @Groups({"read", "read_sale_event"})
*/
private $noVehicles;
/**
* @ORM\Column(type="integer")
*
* @Groups({"read", "read_sale_event"})
*/
private $liveVisitors;
/**
* @ORM\ManyToMany(targetEntity="App\Entity\BuyersGroup", inversedBy="sales", cascade={"persist"})
*
* @Groups({"read", "read_sale_event"})
*/
private $buyersGroups;
/**
* @ORM\Column(type="integer")
*
* @Groups({"read", "read_sale_event"})
*/
private $afterSaleDuration = 0;
/**
* @ORM\Column(type="boolean")
*
* @Groups({"read", "read_sale_event"})
*/
private $exclusive = true;
/**
* @ORM\Column(type="boolean")
*
* @Groups({"read", "read_sale_event"})
*/
private $prepared = false;
/**
* @ORM\Column(type="integer", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
private $fixedFees;
/**
* @var \DateTime Sale closed date
*
* @ORM\Column(type="datetime", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
private $closedAt;
/**
* @ORM\Column(type="string", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
private $country;
/**
* @todo VPA-1635: generate migration
*
* @ORM\Column(type="string", nullable=true)
*
* @Groups({"read", "read_sale_event"})
*/
private $iridiumId;
public function __construct()
{
$this->events = new ArrayCollection();
$this->highlights = new ArrayCollection();
$this->noVehicles = false;
$this->transactions = new ArrayCollection();
$this->buyersGroups = new ArrayCollection();
$this->purchaseInstructionRules = [];
$this->isLive = true;
$this->liveVisitors = 0;
$this->behaviours = new ArrayCollection();
}
public function __toString(): string
{
return (string) $this->id;
}
public function getDisplayedName()
{
return match ($this->getType()) {
self::TYPE_ONLINE => $this->getDisplayedNameWithoutDate(),
self::TYPE_PHYSICAL => sprintf(
'%s %s',
$this->getDisplayedNameWithoutDate(),
$this->getStartDate()->format('d/m/Y')
),
self::TYPE_LIVE => $this->getDisplayedNameWithoutDate(),
default => sprintf('Vente #%s', $this->getId()),
};
}
public function getDisplayedNameWithoutDate()
{
return match ($this->getType()) {
self::TYPE_ONLINE => $this->description,
self::TYPE_PHYSICAL => $this->getRoom() ? strtoupper((string) $this->getRoom()->getName()) : 'N/A',
self::TYPE_LIVE => sprintf(
'Vente live du %s',
$this->getStartDate()->format('d/m/Y')
),
default => sprintf('Vente #%s', $this->getId()),
};
}
public function setId($saleid): void
{
$this->id = $saleid;
}
public function getId()
{
return $this->id;
}
public function setType($type): void
{
$this->type = $type;
}
public function getType()
{
return $this->type;
}
public function addEvent(SaleEvent $event): void
{
$this->events[] = $event;
}
public function removeEvent(SaleEvent $event): void
{
$this->events->removeElement($event);
}
public function getEvents()
{
$iterator = $this->events->getIterator();
$iterator->uasort(fn ($a, $b) => strtotime((string) $a->getStartTime()) - strtotime((string) $b->getStartTime()));
return new ArrayCollection(iterator_to_array($iterator));
}
public function setTitle($title): void
{
$this->title = $title;
}
public function getTitle()
{
return $this->title;
}
public function getRoom()
{
return $this->room;
}
public function setRoom(Room $room): void
{
$this->room = $room;
}
public function getStartDate()
{
return $this->startDate;
}
public function setStartDate($startDate): void
{
$this->startDate = $startDate;
}
public function setEndDate($endDate): void
{
$this->endDate = $endDate;
}
public function getEndDate()
{
return $this->endDate;
}
public function setRecoveryAt(?\DateTime $recoveryAt = null)
{
$this->recoveryAt = $recoveryAt;
return $this;
}
public function getRecoveryAt()
{
return $this->recoveryAt;
}
public function setDescription($description): void
{
$this->description = $description;
}
public function getDescription()
{
return $this->description;
}
public function setStatus($status): void
{
$this->setClosedAt(self::STATUS_CLOSED === $status ? new \DateTime() : null);
$this->status = $status;
}
public function getStatus()
{
return $this->status;
}
public function setBidIncrement($bidIncrement): void
{
$this->bidIncrement = $bidIncrement;
}
public function getBidIncrement(): int
{
return intval($this->bidIncrement);
}
public function setVatRate($vatRate): void
{
$this->vatRate = $vatRate;
}
public function getVatRate()
{
return $this->vatRate;
}
public function setDynamicClosing($dynamicClosing): void
{
$this->dynamicClosing = $dynamicClosing;
}
public function isDynamicClosing()
{
return (bool) $this->dynamicClosing;
}
public function setExtraTime($extraTime): void
{
$this->extraTime = $extraTime;
}
public function getExtraTime()
{
return $this->extraTime;
}
public function setSalingType($salingType): void
{
$this->salingType = $salingType;
}
public function getSalingType()
{
return $this->salingType;
}
public function setPublicationDate($publicationDate): void
{
$this->publicationDate = $publicationDate;
}
public function getPublicationDate()
{
return $this->publicationDate;
}
public function setHours(array $hours): void
{
$this->hours = $hours;
}
public function getHours()
{
return $this->hours;
}
public function setBannerUrl($bannerUrl): void
{
$this->bannerUrl = $bannerUrl;
}
public function getBannerUrl()
{
return $this->bannerUrl;
}
public function setLogoUrl($logoUrl): void
{
$this->logoUrl = $logoUrl;
}
public function getLogoUrl()
{
return $this->logoUrl;
}
public function setCompany($company): void
{
$this->company = $company;
}
public function getCompany()
{
return $this->company;
}
public function setStock($stock): void
{
$this->stock = $stock;
}
public function getStock()
{
return (bool) $this->stock;
}
public function setPublic($public): void
{
$this->public = $public;
}
public function getPublic()
{
return $this->public;
}
public function setDisplayExplodedView($displayExplodedView): void
{
$this->displayExplodedView = $displayExplodedView;
}
public function isDisplayExplodedView()
{
return (bool) $this->displayExplodedView;
}
public function setDisplayReconditioningFees($displayReconditioningFees): void
{
$this->displayReconditioningFees = $displayReconditioningFees;
}
public function isDisplayReconditioningFees()
{
return (bool) $this->displayReconditioningFees;
}
public function setIsLive($isLive): void
{
$this->isLive = $isLive;
}
public function getIsLive()
{
return $this->isLive;
}
public function getLiveVisitors()
{
return $this->liveVisitors;
}
public function setLiveVisitors($count): void
{
$this->liveVisitors = $count;
}
public function addOneLiveVisitor(): void
{
++$this->liveVisitors;
}
public function addTransaction(Transaction $transactions): void
{
$this->transactions[] = $transactions;
}
public function getTransactions()
{
return $this->transactions;
}
public function getOpenedVehicle()
{
return $this->openedVehicle;
}
public function setOpenedVehicle(?Vehicle $vehicle = null)
{
$this->openedVehicle = $vehicle;
return $this;
}
public function setLastOpenedVehicle(?Vehicle $lastOpenedVehicle = null)
{
$this->lastOpenedVehicle = $lastOpenedVehicle;
return $this;
}
public function getLastOpenedVehicle()
{
return $this->lastOpenedVehicle;
}
public function setPurchaseInstructionRules(array $purchaseInstructionRules): void
{
$this->purchaseInstructionRules = $purchaseInstructionRules;
}
public function getPurchaseInstructionRules()
{
return $this->purchaseInstructionRules;
}
public function setNoVehicles($boolean): void
{
$this->noVehicles = $boolean;
}
public function getNoVehicles()
{
return $this->noVehicles;
}
public function addBuyersGroup(BuyersGroup $group): void
{
if (!$this->buyersGroups->contains($group)) {
$this->buyersGroups[] = $group;
}
}
public function removeBuyersGroup(BuyersGroup $group): void
{
$this->buyersGroups->remove($group);
}
public function getBuyersGroups()
{
return $this->buyersGroups;
}
public function setExpositionStartDate(?\DateTime $expositionStartDate = null): void
{
$this->expositionStartDate = $expositionStartDate;
}
public function getExpositionStartDate()
{
return $this->expositionStartDate;
}
public function setExpositionEndDate(?\DateTime $expositionEndDate = null): void
{
$this->expositionEndDate = $expositionEndDate;
}
public function getExpositionEndDate()
{
return $this->expositionEndDate;
}
public function setDayExpositionTime(?\DateTime $dayExpositionTime = null): void
{
$this->dayExpositionTime = $dayExpositionTime;
}
public function getDayExpositionTime()
{
return $this->dayExpositionTime;
}
/**
* @ORM\PrePersist
*/
public function setCreatedAt(): void
{
$this->createdAt = new \DateTime();
$this->updatedAt = new \DateTime();
}
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* @ORM\PreUpdate
*/
public function setUpdatedAt(): void
{
$this->updatedAt = new \DateTime();
}
public function getUpdatedAt()
{
return $this->updatedAt;
}
public function setAfterSaleDuration($afterSaleDuration): void
{
$this->afterSaleDuration = $afterSaleDuration;
}
public function getAfterSaleDuration()
{
return $this->afterSaleDuration;
}
public function getAfterSaleEndDate()
{
$endDate = clone $this->endDate;
return $endDate->modify(sprintf('+%d hours', $this->afterSaleDuration));
}
public function isExclusive()
{
return $this->exclusive;
}
public function setExclusive($exclusive): void
{
$this->exclusive = $exclusive;
}
public function isPrepared()
{
return $this->prepared;
}
public function setPrepared($prepared): void
{
$this->prepared = $prepared;
}
public function setFixedFees($fixedFees): void
{
$this->fixedFees = $fixedFees;
}
public function getFixedFees()
{
return $this->fixedFees;
}
public function setClosedAt(?\DateTime $closedAt = null): void
{
$this->closedAt = $closedAt;
}
public function getClosedAt()
{
return $this->closedAt;
}
public function getVehicles()
{
$vehicles = [];
foreach ($this->getEvents() as $event) {
$vehicles = array_merge($vehicles, $event->getVehicles()->toArray());
}
return new ArrayCollection($vehicles);
}
public function giveMeEvent($id)
{
foreach ($this->getEvents() as $event) {
if ($id === $event->getId()) {
return $event;
}
}
}
public function giveMeEventVehicles($id)
{
foreach ($this->getEvents() as $event) {
if ($id === $event->getId()) {
return $event->getVehicles()->toArray();
}
}
}
/**
* Checks whether the sale is imported and active or not.
*
* @return bool
*/
public function isActive()
{
$now = new \DateTime();
if (self::TYPE_ONLINE === $this->type) {
$active = ($now >= $this->startDate) && ($now <= $this->endDate);
} else {
$active = ($now >= \DateTime::createFromFormat('Y-m-d H:i:s', $this->startDate->format('Y-m-d 00:00:00'))) && ($now <= \DateTime::createFromFormat('Y-m-d H:i:s', $this->endDate->format('Y-m-d 23:59:59')));
}
return $active && self::STATUS_CLOSED !== $this->getStatus();
}
/**
* Return true if each sale's vehicle has a final amount.
*
* @return bool
*/
public function isSetAllFinalAmount()
{
foreach ($this->getVehicles() as $vehicle) {
if ($vehicle->getPurchaseInstructions() && ($vehicle->getFinalAmount() < $vehicle->getSaleprice()
|| 0 == $vehicle->getFinalAmount())) {
return false;
}
}
return true;
}
public function getPICount()
{
$c = 0;
foreach ($this->getVehicles() as $v) {
$c += $v->getPICount();
}
return $c;
}
public function setCountry($country): void
{
$this->country = $country;
}
public function getCountry()
{
return $this->country;
}
public function addHighlight(SaleHighlight $highlight)
{
$this->highlights[] = $highlight;
$highlight->setSale($this);
return $this;
}
public function removeHighlight(SaleHighlight $highlight): void
{
$this->highlights->removeElement($highlight);
}
public function getHighlights()
{
return $this->highlights;
}
public function addBehaviour(SaleBehaviour $behaviour)
{
$this->behaviours[] = $behaviour;
$behaviour->setSale($this);
return $this;
}
public function removeBehaviour(SaleBehaviour $behaviour): void
{
$this->behaviours->removeElement($behaviour);
}
public function getBehaviours()
{
return $this->behaviours;
}
public function setSentToSap($sentToSap): void
{
foreach ($this->getVehicles() as $vehicle) {
$vehicle->setSentToSap($sentToSap);
}
}
/**
* Indicates whether the specified sale is compatible for the the live auctions.
*
* @return bool
*/
public function isLiveCompatible()
{
return in_array($this->getType(), self::getLiveCompatibleTypes()) && $this->isLive;
}
/**
* Returns the type values for the sales compatible with the live auctions.
*
* @return array
*/
public static function getLiveCompatibleTypes()
{
return [
static::TYPE_PHYSICAL,
static::TYPE_LIVE,
];
}
public function getActiveVehicles()
{
$criteria = Criteria::create();
$criteria->where(
Criteria::expr()->neq('salingState', Vehicle::SALING_STATE_EXCLUS)
)->andWhere(
Criteria::expr()->neq('salingState', Vehicle::SALING_STATE_SUPPRIME)
)->andWhere(
Criteria::expr()->neq('salingState', Vehicle::SALING_STATE_NO_STARTING_PRICE)
);
return $this->getVehicles()->matching($criteria);
}
public function getExcludedVehicles()
{
$criteria = Criteria::create();
$criteria
->where(
Criteria::expr()->eq('salingState', Vehicle::SALING_STATE_EXCLUS)
)
->orderBy(['order' => Criteria::ASC]);
return $this->getVehicles()->matching($criteria);
}
public function getByRankRangeVehicles($rankFrom, $rankTo)
{
$criteria = Criteria::create();
$criteria
->where(
Criteria::expr()->gte('order', $rankFrom)
)
->andWhere(
Criteria::expr()->lte('order', $rankTo)
)
->andWhere(
Criteria::expr()->neq('salingState', Vehicle::SALING_STATE_EXCLUS)
)
->andWhere(
Criteria::expr()->neq('salingState', Vehicle::SALING_STATE_SUPPRIME)
)
->andWhere(
Criteria::expr()->neq('salingState', Vehicle::SALING_STATE_NO_STARTING_PRICE)
);
return $this->getVehicles()->matching($criteria);
}
public function isClosed()
{
return self::STATUS_CLOSED === $this->getStatus();
}
public function noVehiclesInStateNone()
{
return $this->getVehicles()->filter(function ($vehicle) {
return Vehicle::SALING_STATE_NONE === $vehicle->getSalingState();
})->isEmpty();
}
public function isAllVehiclesClosed()
{
if (self::TYPE_ONLINE === $this->getType()) {
$ended = $this->getVehicles()->filter(fn ($vehicle) => $vehicle->getAuction()->isClosed());
return count($this->getVehicles()) === count($ended);
}
$criteria = Criteria::create();
$criteria
->where(
Criteria::expr()->eq('salingState', Vehicle::SALING_STATE_ADJUGE)
);
return count($this->getVehicles()) == count($this->getVehicles()->matching($criteria));
}
public function isAllVehiclesOrdered()
{
$criteria = Criteria::create();
$criteria
->where(
Criteria::expr()->neq('lot', null)
)
->andWhere(
Criteria::expr()->neq('salingState', Vehicle::SALING_STATE_EXCLUS)
)
->andWhere(
Criteria::expr()->neq('salingState', Vehicle::SALING_STATE_SUPPRIME)
)
->andWhere(
Criteria::expr()->neq('salingState', Vehicle::SALING_STATE_NO_STARTING_PRICE)
);
return count($this->getActiveVehicles()) === count($this->getVehicles()->matching($criteria));
}
public function hasPriorExposition()
{
return (null !== $this->expositionStartDate) && ('1901-01-01 00:00:00' !== $this->expositionStartDate->format('Y-m-d H:i:s'));
}
/**
* Returns all phases the sales goes through.
*
* @return array The phases constants
*/
public static function getPhases()
{
return [
static::PHASE_ANNOUNCED,
static::PHASE_EXPOSITION,
static::PHASE_IN_PROGRESS,
static::PHASE_AFTER_SALES,
static::PHASE_ENDED,
];
}
/**
* Returns all phases that occur before auctions can be made.
*
* @return array The phases constants
*/
public static function getPhasesPriorToAuctions()
{
return [
static::PHASE_ANNOUNCED,
static::PHASE_EXPOSITION,
];
}
/**
* Return the current phase of this sale
* Caution: Phases do not describe what's happening now, but rather the sale's different timeframes.
* This is why there is no "PHASE_PAUSED" or whatever, that's a status, not a phase.
*
* @return int A constant describing the phase
*/
public function getCurrentPhase()
{
$now = new \DateTime();
$end = clone $this->endDate;
$end->add(new \DateInterval(sprintf('PT%dH', $this->afterSaleDuration)));
if ($this->expositionStartDate < $now and $now < $this->expositionEndDate) {
return static::PHASE_EXPOSITION;
} elseif ($this->startDate < $now and $now < $this->endDate) {
return static::PHASE_IN_PROGRESS;
} elseif ($this->endDate < $now and $now < $end) {
return static::PHASE_AFTER_SALES;
} elseif ($now > $end) {
return static::PHASE_ENDED;
}
return static::PHASE_ANNOUNCED;
}
public function isTypePhysical(): bool
{
return self::TYPE_PHYSICAL === $this->getType();
}
public function setIridiumId($saleReference): void
{
$this->iridiumId = $saleReference;
}
public function getIridiumId()
{
return $this->iridiumId;
}
public function getDayExpositionDateTime()
{
return new \DateTime($this->getStartDate()->format('Y-m-d').' '.$this->dayExpositionTime->format('H:i'));
}
public function isSameCountry(?User $user)
{
if (null === $user) {
return false;
}
$countryUser = strtolower((string) $user->getCountry());
return isset(SaleRepository::COUNTRIES[$countryUser]) && SaleRepository::COUNTRIES[$countryUser] === $this->getCountry();
}
}