src/Entity/PointsCatalog/CatalogOrder.php line 34

Open in your IDE?
  1. <?php
  2. namespace App\Entity\PointsCatalog;
  3. use App\Annotation\SiteAware;
  4. use App\Entity\AbstractBase;
  5. use App\Entity\Garages\Garage;
  6. use App\Entity\Interfaces\SiteInterface;
  7. use App\Entity\MiniAbstractBase;
  8. use App\Entity\Traits\GarageTrait;
  9. use App\Entity\Traits\SiteTrait;
  10. use App\Entity\User;
  11. use App\Enum\CatalogOrderStatusEnum;
  12. use App\Exception\CatalogOrderCannotBeCancelled;
  13. use App\Exception\CatalogOrderLineCannotBeCancelled;
  14. use App\Exception\PointsLimitException;
  15. use App\Repository\PointsCatalog\CatalogOrderRepository;
  16. use Doctrine\Common\Collections\ArrayCollection;
  17. use Doctrine\Common\Collections\Collection;
  18. use Doctrine\ORM\Mapping as ORM;
  19. use Gedmo\Mapping\Annotation as Gedmo;
  20. use Money\Currency;
  21. use Money\Money;
  22. /**
  23.  * @ORM\Table(name="vulco_points_catalog_order", indexes={@ORM\Index(name="catalog_order_site_idx", columns={"site"})})
  24.  *
  25.  * @ORM\Entity(repositoryClass=CatalogOrderRepository::class)
  26.  *
  27.  * @Gedmo\SoftDeleteable(fieldName="removedAt", timeAware=false)
  28.  *
  29.  * @SiteAware(siteFieldName="site")
  30.  */
  31. class CatalogOrder extends AbstractBase implements SiteInterface
  32. {
  33.     use GarageTrait;
  34.     use SiteTrait;
  35.     /**
  36.      * @ORM\ManyToOne(targetEntity="App\Entity\Garages\Garage", fetch="EAGER")
  37.      *
  38.      * @ORM\JoinColumn(name="garage_id", referencedColumnName="id")
  39.      */
  40.     private Garage $garage;
  41.     /**
  42.      * @ORM\ManyToOne(targetEntity="App\Entity\PointsCatalog\CatalogGiftProvider", fetch="EAGER")
  43.      *
  44.      * @ORM\JoinColumn(name="provider_id", referencedColumnName="id")
  45.      */
  46.     private CatalogGiftProvider $provider;
  47.     /**
  48.      * @ORM\OneToMany(targetEntity="App\Entity\PointsCatalog\CatalogOrderGift", mappedBy="catalogOrder", cascade={"persist"})
  49.      */
  50.     private Collection $gifts;
  51.     /**
  52.      * @ORM\ManyToOne(targetEntity="App\Entity\User", fetch="EAGER")
  53.      *
  54.      * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
  55.      */
  56.     private User $user;
  57.     /**
  58.      * @ORM\Column(type="integer")
  59.      */
  60.     private int $state;
  61.     /**
  62.      * @ORM\Column(type="datetime", nullable=true)
  63.      */
  64.     private ?\DateTimeInterface $processedAt null;
  65.     /**
  66.      * @ORM\Column(type="datetime", nullable=true)
  67.      */
  68.     private ?\DateTimeInterface $cancelledAt null;
  69.     public function __construct(Garage $garageCatalogGiftProvider $providerUser $user)
  70.     {
  71.         $this->garage $garage;
  72.         $this->provider $provider;
  73.         $this->user $user;
  74.         $this->state CatalogOrderStatusEnum::PENDING;
  75.         $this->gifts = new ArrayCollection();
  76.     }
  77.     public function description(): string
  78.     {
  79.         $result '';
  80.         if (count($this->gifts()) > 0) {
  81.             $result $this->gifts()->first()->name();
  82.         }
  83.         return $result;
  84.     }
  85.     public function getDescription(): string
  86.     {
  87.         return $this->description();
  88.     }
  89.     public function user(): User
  90.     {
  91.         return $this->user;
  92.     }
  93.     public function getUser(): User
  94.     {
  95.         return $this->user();
  96.     }
  97.     public function setUser(User $user): self
  98.     {
  99.         $this->user $user;
  100.         return $this;
  101.     }
  102.     public function garage(): Garage
  103.     {
  104.         return $this->garage;
  105.     }
  106.     public function provider(): CatalogGiftProvider
  107.     {
  108.         return $this->provider;
  109.     }
  110.     public function getProvider(): CatalogGiftProvider
  111.     {
  112.         return $this->provider();
  113.     }
  114.     public function setProvider(CatalogGiftProvider $provider): self
  115.     {
  116.         $this->provider $provider;
  117.         return $this;
  118.     }
  119.     public function state(): int
  120.     {
  121.         /** @var CatalogOrderGift $orderLines */
  122.         foreach ($this->gifts() as $orderLines) {
  123.             if ($orderLines->isPending()) {
  124.                 return CatalogOrderStatusEnum::PENDING;
  125.             }
  126.         }
  127.         if ($this->areAllLinesCancelled()) {
  128.             return CatalogOrderStatusEnum::CANCELLED;
  129.         }
  130.         return CatalogOrderStatusEnum::PROCESSED;
  131.     }
  132.     public function areAllLinesCancelled(): bool
  133.     {
  134.         /** @var CatalogOrderGift $orderLines */
  135.         foreach ($this->gifts() as $orderLines) {
  136.             if (!$orderLines->isCancelled()) {
  137.                 return false;
  138.             }
  139.         }
  140.         return true;
  141.     }
  142.     public function isPending(): bool
  143.     {
  144.         return CatalogOrderStatusEnum::PENDING === $this->state();
  145.     }
  146.     public function isProcessed(): bool
  147.     {
  148.         return CatalogOrderStatusEnum::PROCESSED === $this->state();
  149.     }
  150.     public function isCancelled(): bool
  151.     {
  152.         return CatalogOrderStatusEnum::CANCELLED === $this->state();
  153.     }
  154.     public function gifts(): Collection
  155.     {
  156.         return $this->gifts;
  157.     }
  158.     public function getGifts(): Collection
  159.     {
  160.         return $this->gifts();
  161.     }
  162.     public function setGifts(Collection $gifts): self
  163.     {
  164.         $this->gifts $gifts;
  165.         return $this;
  166.     }
  167.     public function addGift(CatalogGift $giftint $unitsCatalogSize $size null): self
  168.     {
  169.         $this->gifts->add(CatalogOrderGift::makeCatalogGiftOrderLine($this$gift$units$size));
  170.         return $this;
  171.     }
  172.     public function addDeliveryOrderLine(): self
  173.     {
  174.         $this->gifts->add(CatalogOrderGift::makeDeliveryOrderLine($this$this->provider));
  175.         return $this;
  176.     }
  177.     public function removeGift(CatalogOrderGift $gift): self
  178.     {
  179.         $this->gifts->removeElement($gift);
  180.         return $this;
  181.     }
  182.     public function process(): array
  183.     {
  184.         $processedOrderLinesIds = [];
  185.         /** @var CatalogOrderGift $orderLines */
  186.         foreach ($this->unprocessedOrderLines() as $orderLine) {
  187.             $processedOrderLinesIds[] = $orderLine->getId();
  188.             $orderLine->process();
  189.         }
  190.         $this->processedAt = new \DateTimeImmutable();
  191.         $this->state CatalogOrderStatusEnum::PROCESSED;
  192.         return $processedOrderLinesIds;
  193.     }
  194.     public function processedAt(): ?\DateTimeInterface
  195.     {
  196.         return $this->processedAt;
  197.     }
  198.     public function getProcessedAt(): ?\DateTimeInterface
  199.     {
  200.         return $this->processedAt();
  201.     }
  202.     public function setProcessedAt(?\DateTimeInterface $processedAt): self
  203.     {
  204.         $this->processedAt $processedAt;
  205.         return $this;
  206.     }
  207.     /**
  208.      * @throws PointsLimitException
  209.      * @throws CatalogOrderCannotBeCancelled
  210.      */
  211.     public function cancel(string $reasonToCancelDescription): array
  212.     {
  213.         if (!$this->canBeCancelled()) {
  214.             throw new CatalogOrderCannotBeCancelled();
  215.         }
  216.         $returnPointMovements = [];
  217.         /** @var CatalogOrderGift $orderLine */
  218.         foreach ($this->gifts as $orderLine) {
  219.             try {
  220.                 $reasonToCancelDescription str_replace(['%description%''%units%'], [$orderLine->name(), $orderLine->units()], $reasonToCancelDescription);
  221.                 $returnPointMovements[] = $orderLine->cancel($reasonToCancelDescription);
  222.             } catch (CatalogOrderLineCannotBeCancelled $e) {
  223.                 continue;
  224.             }
  225.         }
  226.         $this->state CatalogOrderStatusEnum::CANCELLED;
  227.         $this->cancelledAt = new \DateTimeImmutable();
  228.         return $returnPointMovements;
  229.     }
  230.     public function canBeCancelled(): bool
  231.     {
  232.         return CatalogOrderStatusEnum::PENDING === $this->state();
  233.     }
  234.     public function cancelledAt(): ?\DateTimeInterface
  235.     {
  236.         return $this->cancelledAt;
  237.     }
  238.     public function getCancelledAt(): ?\DateTimeInterface
  239.     {
  240.         return $this->cancelledAt();
  241.     }
  242.     public function setCancelledAt(?\DateTimeInterface $cancelledAt): self
  243.     {
  244.         $this->cancelledAt $cancelledAt;
  245.         return $this;
  246.     }
  247.     public function isDeliveryOrder(): bool
  248.     {
  249.         return !== count($this->gifts()) ? false $this->gifts()->first()->isDeliveryOrderLine();
  250.     }
  251.     public function isOrderLinesProcessingAllowed(): bool
  252.     {
  253.         return CatalogOrderStatusEnum::PENDING === $this->state() && count($this->gifts) > && !$this->hasAtLeastOneDeliveryLine();
  254.     }
  255.     private function hasAtLeastOneDeliveryLine(): bool
  256.     {
  257.         /** @var CatalogOrderGift $orderLines */
  258.         foreach ($this->gifts() as $orderLine) {
  259.             if ($orderLine->isDeliveryOrderLine()) {
  260.                 return true;
  261.             }
  262.         }
  263.         return false;
  264.     }
  265.     public function totalUnits(): int
  266.     {
  267.         $units 0;
  268.         /** @var CatalogOrderGift $gift */
  269.         foreach ($this->gifts() as $gift) {
  270.             $units += $gift->units();
  271.         }
  272.         return $units;
  273.     }
  274.     public function totalPoints(): int
  275.     {
  276.         $totalPoints 0;
  277.         /** @var CatalogOrderGift $catalogOrderGift */
  278.         foreach ($this->gifts as $catalogOrderGift) {
  279.             $totalPoints += $catalogOrderGift->totalPoints();
  280.         }
  281.         return $totalPoints;
  282.     }
  283.     public function totalPointsWithoutCancelledItems(): int
  284.     {
  285.         $totalPoints 0;
  286.         /** @var CatalogOrderGift $catalogOrderGift */
  287.         foreach ($this->gifts as $catalogOrderGift) {
  288.             if (!$catalogOrderGift->isCancelled()) {
  289.                 $totalPoints += $catalogOrderGift->totalPoints();
  290.             }
  291.         }
  292.         return $totalPoints;
  293.     }
  294.     public function totalPrice(): Money
  295.     {
  296.         $totalPrice = new Money(0, new Currency(MiniAbstractBase::DEFAULT_EURO_CURRENCY));
  297.         /** @var CatalogOrderGift $catalogOrderGift */
  298.         foreach ($this->gifts as $catalogOrderGift) {
  299.             $totalPrice $totalPrice->add($catalogOrderGift->totalPrice());
  300.         }
  301.         return $totalPrice;
  302.     }
  303.     public function lineCount(): int
  304.     {
  305.         return count($this->gifts());
  306.     }
  307.     public function owner(): User
  308.     {
  309.         return $this->getGarage()->getOwner();
  310.     }
  311.     private function unprocessedOrderLines(): array
  312.     {
  313.         return array_filter($this->gifts()->toArray(), static function (CatalogOrderGift $oderLine) {
  314.             return $oderLine->isPending();
  315.         });
  316.     }
  317.     public function __toString(): string
  318.     {
  319.         return $this->id.' · '.$this->getCreatedAtAsString().' · '.$this->user;
  320.     }
  321. }