src/Entity/Sale.php line 36

Open in your IDE?
  1. <?php
  2. namespace App\Entity;
  3. use App\Repository\SaleRepository;
  4. use Doctrine\Common\Collections\ArrayCollection;
  5. use Doctrine\Common\Collections\Criteria;
  6. use Doctrine\ORM\Mapping as ORM;
  7. use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
  8. use Symfony\Component\Serializer\Annotation\Groups;
  9. use Symfony\Component\Validator\Constraints as Assert;
  10. /**
  11.  * @ORM\Entity
  12.  *
  13.  * @UniqueEntity("id")
  14.  *
  15.  * @ORM\Entity(repositoryClass="App\Repository\SaleRepository")
  16.  *
  17.  * @ORM\InheritanceType("JOINED")
  18.  *
  19.  * @ORM\DiscriminatorColumn(name="discr", type="string")
  20.  *
  21.  * @ORM\DiscriminatorMap({"sale" = "Sale", "external_sale" = "ExternalSale"})
  22.  *
  23.  * @ORM\Table(
  24.  *     name="sale",
  25.  *     indexes={
  26.  *
  27.  *         @ORM\Index(columns={"startDate"})
  28.  *     }
  29.  * )
  30.  *
  31.  * @ORM\HasLifecycleCallbacks()
  32.  */
  33. class Sale implements \Stringable
  34. {
  35.     // Status constants?
  36.     public const STATUS_CLOSED 'Fermée';
  37.     public const STATUS_OPENED 'Ouverte';
  38.     public const STATUS_PAUSED 'En pause';
  39.     // Phases constants
  40.     public const PHASE_ANNOUNCED 'Annoncée';
  41.     public const PHASE_EXPOSITION 'Exposition';
  42.     public const PHASE_IN_PROGRESS 'En cours';
  43.     public const PHASE_AFTER_SALES 'Après vente';
  44.     public const PHASE_ENDED 'Terminée';
  45.     // Taken from webservice documentation.
  46.     public const TYPE_ONLINE 'Electronique';
  47.     public const TYPE_PHYSICAL 'Physique';
  48.     public const TYPE_LIVE 'Live';
  49.     public const OPTION_GP 'al';
  50.     public const SALING_STATE_AUCTION 'Enchères';
  51.     public const SALING_STATE_MIXED 'Enchères et achats immédiats';
  52.     public const SALING_STATE_BUYOUT 'Achats immédiats';
  53.     public const SALING_STATE_TENDER 'Par soumission';
  54.     public const PUBLIC_PRO 'Professionnel';
  55.     public const PUBLIC_ING 'ING Car Lease';
  56.     public const PUBLIC_PRIVATE 'Vente privée';
  57.     public const PUBLIC_FREE 'Grand public';
  58.     public const PUBLIC_VPINDUSTRIE 'VPIndustrie';
  59.     public const PUBLIC_FALFLEET 'FalFleet';
  60.     public const PUBLIC_PEUGEOT 'Peugeot';
  61.     /**
  62.      * @ORM\Id
  63.      *
  64.      * @ORM\Column(type="string")
  65.      *
  66.      * @ORM\GeneratedValue(strategy="NONE")
  67.      *
  68.      * @Assert\NotBlank(groups={"api_rms_saleevent"})
  69.      *
  70.      * @Groups({"read", "read_sale_event"})
  71.      */
  72.     protected $id;
  73.     /**
  74.      * @ORM\Column(type="string")
  75.      *
  76.      * @Groups({"read", "read_sale_event"})
  77.      */
  78.     protected $type;
  79.     /**
  80.      * @ORM\OneToMany(targetEntity="App\Entity\SaleEvent", mappedBy="sale")
  81.      *
  82.      * @Groups({"read"})
  83.      */
  84.     protected $events;
  85.     /**
  86.      * @ORM\Column(type="string")
  87.      *
  88.      * @Assert\NotBlank(groups={"api_rms_saleevent", "api_iridium_sale"})
  89.      *
  90.      * @Groups({"read", "read_sale_event"})
  91.      */
  92.     protected $title;
  93.     /**
  94.      * Room.
  95.      *
  96.      * @ORM\ManyToOne(targetEntity="App\Entity\Room", cascade={"persist"})
  97.      *
  98.      * @Groups({"read", "read_sale_event"})
  99.      */
  100.     protected $room;
  101.     /**
  102.      * @var \DateTime
  103.      *
  104.      * @ORM\Column(type="datetime", nullable=true)
  105.      *
  106.      * @Assert\NotBlank(groups={"api_rms_saleevent", "api_iridium_sale"})
  107.      *
  108.      * @Groups({"read", "read_sale_event"})
  109.      */
  110.     protected $startDate;
  111.     /**
  112.      * @var \DateTime
  113.      *
  114.      * @ORM\Column(type="datetime", nullable=true)
  115.      *
  116.      * @Assert\NotBlank(groups={"api_rms_saleevent", "api_iridium_sale"})
  117.      *
  118.      * @Groups({"read", "read_sale_event"})
  119.      */
  120.     protected $endDate;
  121.     /**
  122.      * @ORM\Column(type="datetime", nullable=true)
  123.      *
  124.      * @Groups({"read", "read_sale_event"})
  125.      */
  126.     protected $recoveryAt;
  127.     /**
  128.      * @ORM\Column(type="string", nullable=true)
  129.      *
  130.      * @Groups({"read", "read_sale_event"})
  131.      */
  132.     protected $description;
  133.     /**
  134.      * @ORM\Column(type="string")
  135.      *
  136.      * @Assert\NotBlank(groups={"api_rms_saleevent"})
  137.      *
  138.      * @Groups({"read", "read_sale_event"})
  139.      */
  140.     protected $status;
  141.     /**
  142.      * @ORM\Column(type="integer", nullable=true)
  143.      *
  144.      * @Groups({"read", "read_sale_event"})
  145.      */
  146.     protected $bidIncrement;
  147.     /**
  148.      * @ORM\Column(type="decimal", nullable=true)
  149.      *
  150.      * @Groups({"read", "read_sale_event"})
  151.      */
  152.     protected $vatRate;
  153.     /**
  154.      * @ORM\Column(type="boolean", nullable=true)
  155.      *
  156.      * @Groups({"read", "read_sale_event"})
  157.      */
  158.     protected $dynamicClosing;
  159.     /**
  160.      * Extra time in seconds.
  161.      *
  162.      * @ORM\Column(type="integer", nullable=true)
  163.      *
  164.      * @Groups({"read", "read_sale_event"})
  165.      */
  166.     protected $extraTime;
  167.     /**
  168.      * @ORM\Column(type="string", nullable=true)
  169.      *
  170.      * @Groups({"read", "read_sale_event"})
  171.      */
  172.     protected $salingType;
  173.     /**
  174.      * @ORM\Column(type="date", nullable=true)
  175.      *
  176.      * @Groups({"read", "read_sale_event"})
  177.      */
  178.     protected $publicationDate;
  179.     /**
  180.      * @ORM\Column(type="datetime", nullable=true)
  181.      *
  182.      * @Groups({"read", "read_sale_event"})
  183.      */
  184.     protected $expositionStartDate;
  185.     /**
  186.      * @ORM\Column(type="datetime", nullable=true)
  187.      *
  188.      * @Groups({"read", "read_sale_event"})
  189.      */
  190.     protected $expositionEndDate;
  191.     /**
  192.      * @ORM\Column(type="time", nullable=true)
  193.      *
  194.      * @Groups({"read", "read_sale_event"})
  195.      */
  196.     protected $dayExpositionTime;
  197.     /**
  198.      * @ORM\Column(type="datetime")
  199.      *
  200.      * @Groups({"read", "read_sale_event"})
  201.      */
  202.     protected $createdAt;
  203.     /**
  204.      * @ORM\Column(type="datetime")
  205.      *
  206.      * @Groups({"read", "read_sale_event"})
  207.      */
  208.     protected $updatedAt;
  209.     /**
  210.      * @ORM\OneToMany(targetEntity="App\Entity\SaleHighlight", mappedBy="sale", cascade={"persist", "remove"})
  211.      *
  212.      * @Groups({"read", "read_sale_event"})
  213.      */
  214.     protected $highlights;
  215.     /**
  216.      * @ORM\OneToMany(targetEntity="App\Entity\SaleBehaviour", mappedBy="sale", cascade={"remove"})
  217.      *
  218.      * @Groups({"read", "read_sale_event"})
  219.      */
  220.     protected $behaviours;
  221.     /**
  222.      * @ORM\Column(type="array", nullable=true)
  223.      *
  224.      * @Groups({"read", "read_sale_event"})
  225.      */
  226.     private $hours;
  227.     /**
  228.      * @ORM\Column(type="string", nullable=true)
  229.      *
  230.      * @Groups({"read", "read_sale_event"})
  231.      */
  232.     private $bannerUrl;
  233.     /**
  234.      * @ORM\Column(type="string", nullable=true)
  235.      *
  236.      * @Groups({"read", "read_sale_event"})
  237.      */
  238.     private $logoUrl;
  239.     /**
  240.      * @ORM\Column(type="string", nullable=true)
  241.      *
  242.      * @Groups({"read", "read_sale_event"})
  243.      */
  244.     private $company;
  245.     /**
  246.      * @ORM\Column(type="boolean", nullable=true)
  247.      *
  248.      * @Groups({"read", "read_sale_event"})
  249.      */
  250.     private $stock;
  251.     /**
  252.      * @ORM\Column(type="string", nullable=true)
  253.      *
  254.      * @Groups({"read", "read_sale_event"})
  255.      */
  256.     private $public;
  257.     /**
  258.      * @ORM\Column(type="boolean", nullable=true)
  259.      *
  260.      * @Groups({"read", "read_sale_event"})
  261.      */
  262.     private $displayExplodedView;
  263.     /**
  264.      * @ORM\Column(type="boolean", nullable=true)
  265.      *
  266.      * @Groups({"read", "read_sale_event"})
  267.      */
  268.     private $displayReconditioningFees;
  269.     /**
  270.      * @ORM\Column(type="boolean")
  271.      *
  272.      * @Groups({"read", "read_sale_event"})
  273.      */
  274.     private $isLive;
  275.     /**
  276.      * @ORM\OneToMany(targetEntity="App\Entity\Transaction", mappedBy="sale", cascade={"remove"})
  277.      *
  278.      * @Groups({"read", "read_sale_event"})
  279.      */
  280.     private $transactions;
  281.     /**
  282.      * @ORM\OneToOne(targetEntity="App\Entity\Vehicle")
  283.      *
  284.      * @ORM\JoinColumn(name="vehicle_opened_id", referencedColumnName="id")
  285.      *
  286.      * @Groups({"read", "read_sale_event"})
  287.      */
  288.     private $openedVehicle;
  289.     /**
  290.      * @ORM\ManyToOne(targetEntity="App\Entity\Vehicle")
  291.      *
  292.      * @ORM\JoinColumn(name="last_opened_vehicle_id", referencedColumnName="id")
  293.      *
  294.      * @Groups({"read", "read_sale_event"})
  295.      */
  296.     private $lastOpenedVehicle;
  297.     /**
  298.      * @ORM\OneToMany(targetEntity="App\Entity\PurchaseInstructionRule", mappedBy="sale", cascade={"remove"})
  299.      *
  300.      * @ORM\OrderBy({"updatedAt" = "asc"})
  301.      *
  302.      * @Groups({"read", "read_sale_event"})
  303.      */
  304.     private $purchaseInstructionRules;
  305.     /**
  306.      * @ORM\Column(type = "boolean")
  307.      *
  308.      * @Groups({"read", "read_sale_event"})
  309.      */
  310.     private $noVehicles;
  311.     /**
  312.      * @ORM\Column(type="integer")
  313.      *
  314.      * @Groups({"read", "read_sale_event"})
  315.      */
  316.     private $liveVisitors;
  317.     /**
  318.      * @ORM\ManyToMany(targetEntity="App\Entity\BuyersGroup", inversedBy="sales", cascade={"persist"})
  319.      *
  320.      * @Groups({"read", "read_sale_event"})
  321.      */
  322.     private $buyersGroups;
  323.     /**
  324.      * @ORM\Column(type="integer")
  325.      *
  326.      * @Groups({"read", "read_sale_event"})
  327.      */
  328.     private $afterSaleDuration 0;
  329.     /**
  330.      * @ORM\Column(type="boolean")
  331.      *
  332.      * @Groups({"read", "read_sale_event"})
  333.      */
  334.     private $exclusive true;
  335.     /**
  336.      * @ORM\Column(type="boolean")
  337.      *
  338.      * @Groups({"read", "read_sale_event"})
  339.      */
  340.     private $prepared false;
  341.     /**
  342.      * @ORM\Column(type="integer", nullable=true)
  343.      *
  344.      * @Groups({"read", "read_sale_event"})
  345.      */
  346.     private $fixedFees;
  347.     /**
  348.      * @var \DateTime Sale closed date
  349.      *
  350.      * @ORM\Column(type="datetime", nullable=true)
  351.      *
  352.      * @Groups({"read", "read_sale_event"})
  353.      */
  354.     private $closedAt;
  355.     /**
  356.      * @ORM\Column(type="string", nullable=true)
  357.      *
  358.      * @Groups({"read", "read_sale_event"})
  359.      */
  360.     private $country;
  361.     /**
  362.      * @todo VPA-1635: generate migration
  363.      *
  364.      * @ORM\Column(type="string", nullable=true)
  365.      *
  366.      * @Groups({"read", "read_sale_event"})
  367.      */
  368.     private $iridiumId;
  369.     public function __construct()
  370.     {
  371.         $this->events = new ArrayCollection();
  372.         $this->highlights = new ArrayCollection();
  373.         $this->noVehicles false;
  374.         $this->transactions = new ArrayCollection();
  375.         $this->buyersGroups = new ArrayCollection();
  376.         $this->purchaseInstructionRules = [];
  377.         $this->isLive true;
  378.         $this->liveVisitors 0;
  379.         $this->behaviours = new ArrayCollection();
  380.     }
  381.     public function __toString(): string
  382.     {
  383.         return (string) $this->id;
  384.     }
  385.     public function getDisplayedName()
  386.     {
  387.         return match ($this->getType()) {
  388.             self::TYPE_ONLINE => $this->getDisplayedNameWithoutDate(),
  389.             self::TYPE_PHYSICAL => sprintf(
  390.                 '%s %s',
  391.                 $this->getDisplayedNameWithoutDate(),
  392.                 $this->getStartDate()->format('d/m/Y')
  393.             ),
  394.             self::TYPE_LIVE => $this->getDisplayedNameWithoutDate(),
  395.             default => sprintf('Vente #%s'$this->getId()),
  396.         };
  397.     }
  398.     public function getDisplayedNameWithoutDate()
  399.     {
  400.         return match ($this->getType()) {
  401.             self::TYPE_ONLINE => $this->description,
  402.             self::TYPE_PHYSICAL => $this->getRoom() ? strtoupper((string) $this->getRoom()->getName()) : 'N/A',
  403.             self::TYPE_LIVE => sprintf(
  404.                 'Vente live du %s',
  405.                 $this->getStartDate()->format('d/m/Y')
  406.             ),
  407.             default => sprintf('Vente #%s'$this->getId()),
  408.         };
  409.     }
  410.     public function setId($saleid): void
  411.     {
  412.         $this->id $saleid;
  413.     }
  414.     public function getId()
  415.     {
  416.         return $this->id;
  417.     }
  418.     public function setType($type): void
  419.     {
  420.         $this->type $type;
  421.     }
  422.     public function getType()
  423.     {
  424.         return $this->type;
  425.     }
  426.     public function addEvent(SaleEvent $event): void
  427.     {
  428.         $this->events[] = $event;
  429.     }
  430.     public function removeEvent(SaleEvent $event): void
  431.     {
  432.         $this->events->removeElement($event);
  433.     }
  434.     public function getEvents()
  435.     {
  436.         $iterator $this->events->getIterator();
  437.         $iterator->uasort(fn ($a$b) => strtotime((string) $a->getStartTime()) - strtotime((string) $b->getStartTime()));
  438.         return new ArrayCollection(iterator_to_array($iterator));
  439.     }
  440.     public function setTitle($title): void
  441.     {
  442.         $this->title $title;
  443.     }
  444.     public function getTitle()
  445.     {
  446.         return $this->title;
  447.     }
  448.     public function getRoom()
  449.     {
  450.         return $this->room;
  451.     }
  452.     public function setRoom(Room $room): void
  453.     {
  454.         $this->room $room;
  455.     }
  456.     public function getStartDate()
  457.     {
  458.         return $this->startDate;
  459.     }
  460.     public function setStartDate($startDate): void
  461.     {
  462.         $this->startDate $startDate;
  463.     }
  464.     public function setEndDate($endDate): void
  465.     {
  466.         $this->endDate $endDate;
  467.     }
  468.     public function getEndDate()
  469.     {
  470.         return $this->endDate;
  471.     }
  472.     public function setRecoveryAt(?\DateTime $recoveryAt null)
  473.     {
  474.         $this->recoveryAt $recoveryAt;
  475.         return $this;
  476.     }
  477.     public function getRecoveryAt()
  478.     {
  479.         return $this->recoveryAt;
  480.     }
  481.     public function setDescription($description): void
  482.     {
  483.         $this->description $description;
  484.     }
  485.     public function getDescription()
  486.     {
  487.         return $this->description;
  488.     }
  489.     public function setStatus($status): void
  490.     {
  491.         $this->setClosedAt(self::STATUS_CLOSED === $status ? new \DateTime() : null);
  492.         $this->status $status;
  493.     }
  494.     public function getStatus()
  495.     {
  496.         return $this->status;
  497.     }
  498.     public function setBidIncrement($bidIncrement): void
  499.     {
  500.         $this->bidIncrement $bidIncrement;
  501.     }
  502.     public function getBidIncrement(): int
  503.     {
  504.         return intval($this->bidIncrement);
  505.     }
  506.     public function setVatRate($vatRate): void
  507.     {
  508.         $this->vatRate $vatRate;
  509.     }
  510.     public function getVatRate()
  511.     {
  512.         return $this->vatRate;
  513.     }
  514.     public function setDynamicClosing($dynamicClosing): void
  515.     {
  516.         $this->dynamicClosing $dynamicClosing;
  517.     }
  518.     public function isDynamicClosing()
  519.     {
  520.         return (bool) $this->dynamicClosing;
  521.     }
  522.     public function setExtraTime($extraTime): void
  523.     {
  524.         $this->extraTime $extraTime;
  525.     }
  526.     public function getExtraTime()
  527.     {
  528.         return $this->extraTime;
  529.     }
  530.     public function setSalingType($salingType): void
  531.     {
  532.         $this->salingType $salingType;
  533.     }
  534.     public function getSalingType()
  535.     {
  536.         return $this->salingType;
  537.     }
  538.     public function setPublicationDate($publicationDate): void
  539.     {
  540.         $this->publicationDate $publicationDate;
  541.     }
  542.     public function getPublicationDate()
  543.     {
  544.         return $this->publicationDate;
  545.     }
  546.     public function setHours(array $hours): void
  547.     {
  548.         $this->hours $hours;
  549.     }
  550.     public function getHours()
  551.     {
  552.         return $this->hours;
  553.     }
  554.     public function setBannerUrl($bannerUrl): void
  555.     {
  556.         $this->bannerUrl $bannerUrl;
  557.     }
  558.     public function getBannerUrl()
  559.     {
  560.         return $this->bannerUrl;
  561.     }
  562.     public function setLogoUrl($logoUrl): void
  563.     {
  564.         $this->logoUrl $logoUrl;
  565.     }
  566.     public function getLogoUrl()
  567.     {
  568.         return $this->logoUrl;
  569.     }
  570.     public function setCompany($company): void
  571.     {
  572.         $this->company $company;
  573.     }
  574.     public function getCompany()
  575.     {
  576.         return $this->company;
  577.     }
  578.     public function setStock($stock): void
  579.     {
  580.         $this->stock $stock;
  581.     }
  582.     public function getStock()
  583.     {
  584.         return (bool) $this->stock;
  585.     }
  586.     public function setPublic($public): void
  587.     {
  588.         $this->public $public;
  589.     }
  590.     public function getPublic()
  591.     {
  592.         return $this->public;
  593.     }
  594.     public function setDisplayExplodedView($displayExplodedView): void
  595.     {
  596.         $this->displayExplodedView $displayExplodedView;
  597.     }
  598.     public function isDisplayExplodedView()
  599.     {
  600.         return (bool) $this->displayExplodedView;
  601.     }
  602.     public function setDisplayReconditioningFees($displayReconditioningFees): void
  603.     {
  604.         $this->displayReconditioningFees $displayReconditioningFees;
  605.     }
  606.     public function isDisplayReconditioningFees()
  607.     {
  608.         return (bool) $this->displayReconditioningFees;
  609.     }
  610.     public function setIsLive($isLive): void
  611.     {
  612.         $this->isLive $isLive;
  613.     }
  614.     public function getIsLive()
  615.     {
  616.         return $this->isLive;
  617.     }
  618.     public function getLiveVisitors()
  619.     {
  620.         return $this->liveVisitors;
  621.     }
  622.     public function setLiveVisitors($count): void
  623.     {
  624.         $this->liveVisitors $count;
  625.     }
  626.     public function addOneLiveVisitor(): void
  627.     {
  628.         ++$this->liveVisitors;
  629.     }
  630.     public function addTransaction(Transaction $transactions): void
  631.     {
  632.         $this->transactions[] = $transactions;
  633.     }
  634.     public function getTransactions()
  635.     {
  636.         return $this->transactions;
  637.     }
  638.     public function getOpenedVehicle()
  639.     {
  640.         return $this->openedVehicle;
  641.     }
  642.     public function setOpenedVehicle(?Vehicle $vehicle null)
  643.     {
  644.         $this->openedVehicle $vehicle;
  645.         return $this;
  646.     }
  647.     public function setLastOpenedVehicle(?Vehicle $lastOpenedVehicle null)
  648.     {
  649.         $this->lastOpenedVehicle $lastOpenedVehicle;
  650.         return $this;
  651.     }
  652.     public function getLastOpenedVehicle()
  653.     {
  654.         return $this->lastOpenedVehicle;
  655.     }
  656.     public function setPurchaseInstructionRules(array $purchaseInstructionRules): void
  657.     {
  658.         $this->purchaseInstructionRules $purchaseInstructionRules;
  659.     }
  660.     public function getPurchaseInstructionRules()
  661.     {
  662.         return $this->purchaseInstructionRules;
  663.     }
  664.     public function setNoVehicles($boolean): void
  665.     {
  666.         $this->noVehicles $boolean;
  667.     }
  668.     public function getNoVehicles()
  669.     {
  670.         return $this->noVehicles;
  671.     }
  672.     public function addBuyersGroup(BuyersGroup $group): void
  673.     {
  674.         if (!$this->buyersGroups->contains($group)) {
  675.             $this->buyersGroups[] = $group;
  676.         }
  677.     }
  678.     public function removeBuyersGroup(BuyersGroup $group): void
  679.     {
  680.         $this->buyersGroups->remove($group);
  681.     }
  682.     public function getBuyersGroups()
  683.     {
  684.         return $this->buyersGroups;
  685.     }
  686.     public function setExpositionStartDate(?\DateTime $expositionStartDate null): void
  687.     {
  688.         $this->expositionStartDate $expositionStartDate;
  689.     }
  690.     public function getExpositionStartDate()
  691.     {
  692.         return $this->expositionStartDate;
  693.     }
  694.     public function setExpositionEndDate(?\DateTime $expositionEndDate null): void
  695.     {
  696.         $this->expositionEndDate $expositionEndDate;
  697.     }
  698.     public function getExpositionEndDate()
  699.     {
  700.         return $this->expositionEndDate;
  701.     }
  702.     public function setDayExpositionTime(?\DateTime $dayExpositionTime null): void
  703.     {
  704.         $this->dayExpositionTime $dayExpositionTime;
  705.     }
  706.     public function getDayExpositionTime()
  707.     {
  708.         return $this->dayExpositionTime;
  709.     }
  710.     /**
  711.      * @ORM\PrePersist
  712.      */
  713.     public function setCreatedAt(): void
  714.     {
  715.         $this->createdAt = new \DateTime();
  716.         $this->updatedAt = new \DateTime();
  717.     }
  718.     public function getCreatedAt()
  719.     {
  720.         return $this->createdAt;
  721.     }
  722.     /**
  723.      * @ORM\PreUpdate
  724.      */
  725.     public function setUpdatedAt(): void
  726.     {
  727.         $this->updatedAt = new \DateTime();
  728.     }
  729.     public function getUpdatedAt()
  730.     {
  731.         return $this->updatedAt;
  732.     }
  733.     public function setAfterSaleDuration($afterSaleDuration): void
  734.     {
  735.         $this->afterSaleDuration $afterSaleDuration;
  736.     }
  737.     public function getAfterSaleDuration()
  738.     {
  739.         return $this->afterSaleDuration;
  740.     }
  741.     public function getAfterSaleEndDate()
  742.     {
  743.         $endDate = clone $this->endDate;
  744.         return $endDate->modify(sprintf('+%d hours'$this->afterSaleDuration));
  745.     }
  746.     public function isExclusive()
  747.     {
  748.         return $this->exclusive;
  749.     }
  750.     public function setExclusive($exclusive): void
  751.     {
  752.         $this->exclusive $exclusive;
  753.     }
  754.     public function isPrepared()
  755.     {
  756.         return $this->prepared;
  757.     }
  758.     public function setPrepared($prepared): void
  759.     {
  760.         $this->prepared $prepared;
  761.     }
  762.     public function setFixedFees($fixedFees): void
  763.     {
  764.         $this->fixedFees $fixedFees;
  765.     }
  766.     public function getFixedFees()
  767.     {
  768.         return $this->fixedFees;
  769.     }
  770.     public function setClosedAt(?\DateTime $closedAt null): void
  771.     {
  772.         $this->closedAt $closedAt;
  773.     }
  774.     public function getClosedAt()
  775.     {
  776.         return $this->closedAt;
  777.     }
  778.     public function getVehicles()
  779.     {
  780.         $vehicles = [];
  781.         foreach ($this->getEvents() as $event) {
  782.             $vehicles array_merge($vehicles$event->getVehicles()->toArray());
  783.         }
  784.         return new ArrayCollection($vehicles);
  785.     }
  786.     public function giveMeEvent($id)
  787.     {
  788.         foreach ($this->getEvents() as $event) {
  789.             if ($id === $event->getId()) {
  790.                 return $event;
  791.             }
  792.         }
  793.     }
  794.     public function giveMeEventVehicles($id)
  795.     {
  796.         foreach ($this->getEvents() as $event) {
  797.             if ($id === $event->getId()) {
  798.                 return $event->getVehicles()->toArray();
  799.             }
  800.         }
  801.     }
  802.     /**
  803.      * Checks whether the sale is imported and active or not.
  804.      *
  805.      * @return bool
  806.      */
  807.     public function isActive()
  808.     {
  809.         $now = new \DateTime();
  810.         if (self::TYPE_ONLINE === $this->type) {
  811.             $active = ($now >= $this->startDate) && ($now <= $this->endDate);
  812.         } else {
  813.             $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')));
  814.         }
  815.         return $active && self::STATUS_CLOSED !== $this->getStatus();
  816.     }
  817.     /**
  818.      *   Return true if each sale's vehicle has a final amount.
  819.      *
  820.      * @return bool
  821.      */
  822.     public function isSetAllFinalAmount()
  823.     {
  824.         foreach ($this->getVehicles() as $vehicle) {
  825.             if ($vehicle->getPurchaseInstructions() && ($vehicle->getFinalAmount() < $vehicle->getSaleprice()
  826.                     || == $vehicle->getFinalAmount())) {
  827.                 return false;
  828.             }
  829.         }
  830.         return true;
  831.     }
  832.     public function getPICount()
  833.     {
  834.         $c 0;
  835.         foreach ($this->getVehicles() as $v) {
  836.             $c += $v->getPICount();
  837.         }
  838.         return $c;
  839.     }
  840.     public function setCountry($country): void
  841.     {
  842.         $this->country $country;
  843.     }
  844.     public function getCountry()
  845.     {
  846.         return $this->country;
  847.     }
  848.     public function addHighlight(SaleHighlight $highlight)
  849.     {
  850.         $this->highlights[] = $highlight;
  851.         $highlight->setSale($this);
  852.         return $this;
  853.     }
  854.     public function removeHighlight(SaleHighlight $highlight): void
  855.     {
  856.         $this->highlights->removeElement($highlight);
  857.     }
  858.     public function getHighlights()
  859.     {
  860.         return $this->highlights;
  861.     }
  862.     public function addBehaviour(SaleBehaviour $behaviour)
  863.     {
  864.         $this->behaviours[] = $behaviour;
  865.         $behaviour->setSale($this);
  866.         return $this;
  867.     }
  868.     public function removeBehaviour(SaleBehaviour $behaviour): void
  869.     {
  870.         $this->behaviours->removeElement($behaviour);
  871.     }
  872.     public function getBehaviours()
  873.     {
  874.         return $this->behaviours;
  875.     }
  876.     public function setSentToSap($sentToSap): void
  877.     {
  878.         foreach ($this->getVehicles() as $vehicle) {
  879.             $vehicle->setSentToSap($sentToSap);
  880.         }
  881.     }
  882.     /**
  883.      * Indicates whether the specified sale is compatible for the the live auctions.
  884.      *
  885.      * @return bool
  886.      */
  887.     public function isLiveCompatible()
  888.     {
  889.         return in_array($this->getType(), self::getLiveCompatibleTypes()) && $this->isLive;
  890.     }
  891.     /**
  892.      * Returns the type values for the sales compatible with the live auctions.
  893.      *
  894.      * @return array
  895.      */
  896.     public static function getLiveCompatibleTypes()
  897.     {
  898.         return [
  899.             static::TYPE_PHYSICAL,
  900.             static::TYPE_LIVE,
  901.         ];
  902.     }
  903.     public function getActiveVehicles()
  904.     {
  905.         $criteria Criteria::create();
  906.         $criteria->where(
  907.             Criteria::expr()->neq('salingState'Vehicle::SALING_STATE_EXCLUS)
  908.         )->andWhere(
  909.             Criteria::expr()->neq('salingState'Vehicle::SALING_STATE_SUPPRIME)
  910.         )->andWhere(
  911.             Criteria::expr()->neq('salingState'Vehicle::SALING_STATE_NO_STARTING_PRICE)
  912.         );
  913.         return $this->getVehicles()->matching($criteria);
  914.     }
  915.     public function getExcludedVehicles()
  916.     {
  917.         $criteria Criteria::create();
  918.         $criteria
  919.             ->where(
  920.                 Criteria::expr()->eq('salingState'Vehicle::SALING_STATE_EXCLUS)
  921.             )
  922.             ->orderBy(['order' => Criteria::ASC]);
  923.         return $this->getVehicles()->matching($criteria);
  924.     }
  925.     public function getByRankRangeVehicles($rankFrom$rankTo)
  926.     {
  927.         $criteria Criteria::create();
  928.         $criteria
  929.             ->where(
  930.                 Criteria::expr()->gte('order'$rankFrom)
  931.             )
  932.             ->andWhere(
  933.                 Criteria::expr()->lte('order'$rankTo)
  934.             )
  935.             ->andWhere(
  936.                 Criteria::expr()->neq('salingState'Vehicle::SALING_STATE_EXCLUS)
  937.             )
  938.             ->andWhere(
  939.                 Criteria::expr()->neq('salingState'Vehicle::SALING_STATE_SUPPRIME)
  940.             )
  941.             ->andWhere(
  942.                 Criteria::expr()->neq('salingState'Vehicle::SALING_STATE_NO_STARTING_PRICE)
  943.             );
  944.         return $this->getVehicles()->matching($criteria);
  945.     }
  946.     public function isClosed()
  947.     {
  948.         return self::STATUS_CLOSED === $this->getStatus();
  949.     }
  950.     public function noVehiclesInStateNone()
  951.     {
  952.         return $this->getVehicles()->filter(function ($vehicle) {
  953.             return Vehicle::SALING_STATE_NONE === $vehicle->getSalingState();
  954.         })->isEmpty();
  955.     }
  956.     public function isAllVehiclesClosed()
  957.     {
  958.         if (self::TYPE_ONLINE === $this->getType()) {
  959.             $ended $this->getVehicles()->filter(fn ($vehicle) => $vehicle->getAuction()->isClosed());
  960.             return count($this->getVehicles()) === count($ended);
  961.         }
  962.         $criteria Criteria::create();
  963.         $criteria
  964.             ->where(
  965.                 Criteria::expr()->eq('salingState'Vehicle::SALING_STATE_ADJUGE)
  966.             );
  967.         return count($this->getVehicles()) == count($this->getVehicles()->matching($criteria));
  968.     }
  969.     public function isAllVehiclesOrdered()
  970.     {
  971.         $criteria Criteria::create();
  972.         $criteria
  973.             ->where(
  974.                 Criteria::expr()->neq('lot'null)
  975.             )
  976.             ->andWhere(
  977.                 Criteria::expr()->neq('salingState'Vehicle::SALING_STATE_EXCLUS)
  978.             )
  979.             ->andWhere(
  980.                 Criteria::expr()->neq('salingState'Vehicle::SALING_STATE_SUPPRIME)
  981.             )
  982.             ->andWhere(
  983.                 Criteria::expr()->neq('salingState'Vehicle::SALING_STATE_NO_STARTING_PRICE)
  984.             );
  985.         return count($this->getActiveVehicles()) === count($this->getVehicles()->matching($criteria));
  986.     }
  987.     public function hasPriorExposition()
  988.     {
  989.         return (null !== $this->expositionStartDate) && ('1901-01-01 00:00:00' !== $this->expositionStartDate->format('Y-m-d H:i:s'));
  990.     }
  991.     /**
  992.      * Returns all phases the sales goes through.
  993.      *
  994.      * @return array The phases constants
  995.      */
  996.     public static function getPhases()
  997.     {
  998.         return [
  999.             static::PHASE_ANNOUNCED,
  1000.             static::PHASE_EXPOSITION,
  1001.             static::PHASE_IN_PROGRESS,
  1002.             static::PHASE_AFTER_SALES,
  1003.             static::PHASE_ENDED,
  1004.         ];
  1005.     }
  1006.     /**
  1007.      * Returns all phases that occur before auctions can be made.
  1008.      *
  1009.      * @return array The phases constants
  1010.      */
  1011.     public static function getPhasesPriorToAuctions()
  1012.     {
  1013.         return [
  1014.             static::PHASE_ANNOUNCED,
  1015.             static::PHASE_EXPOSITION,
  1016.         ];
  1017.     }
  1018.     /**
  1019.      * Return the current phase of this sale
  1020.      * Caution: Phases do not describe what's happening now, but rather the sale's different timeframes.
  1021.      *          This is why there is no "PHASE_PAUSED" or whatever, that's a status, not a phase.
  1022.      *
  1023.      * @return int A constant describing the phase
  1024.      */
  1025.     public function getCurrentPhase()
  1026.     {
  1027.         $now = new \DateTime();
  1028.         $end = clone $this->endDate;
  1029.         $end->add(new \DateInterval(sprintf('PT%dH'$this->afterSaleDuration)));
  1030.         if ($this->expositionStartDate $now and $now $this->expositionEndDate) {
  1031.             return static::PHASE_EXPOSITION;
  1032.         } elseif ($this->startDate $now and $now $this->endDate) {
  1033.             return static::PHASE_IN_PROGRESS;
  1034.         } elseif ($this->endDate $now and $now $end) {
  1035.             return static::PHASE_AFTER_SALES;
  1036.         } elseif ($now $end) {
  1037.             return static::PHASE_ENDED;
  1038.         }
  1039.         return static::PHASE_ANNOUNCED;
  1040.     }
  1041.     public function isTypePhysical(): bool
  1042.     {
  1043.         return self::TYPE_PHYSICAL === $this->getType();
  1044.     }
  1045.     public function setIridiumId($saleReference): void
  1046.     {
  1047.         $this->iridiumId $saleReference;
  1048.     }
  1049.     public function getIridiumId()
  1050.     {
  1051.         return $this->iridiumId;
  1052.     }
  1053.     public function getDayExpositionDateTime()
  1054.     {
  1055.         return new \DateTime($this->getStartDate()->format('Y-m-d').' '.$this->dayExpositionTime->format('H:i'));
  1056.     }
  1057.     public function isSameCountry(?User $user)
  1058.     {
  1059.         if (null === $user) {
  1060.             return false;
  1061.         }
  1062.         $countryUser strtolower((string) $user->getCountry());
  1063.         return isset(SaleRepository::COUNTRIES[$countryUser]) && SaleRepository::COUNTRIES[$countryUser] === $this->getCountry();
  1064.     }
  1065. }