<?php
namespace App\Entity\Cart;
use App\Entity\Garages\Garage;
use App\Entity\PointsCatalog\CatalogGiftProvider;
use App\Entity\Traits\GarageTrait;
use App\Repository\Cart\CartRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* @ORM\Table(name="cart")
*
* @ORM\Entity(repositoryClass=CartRepository::class)
*/
class Cart
{
use GarageTrait;
/**
* @ORM\Column(name="id", type="integer")
*
* @ORM\Id
*
* @ORM\GeneratedValue(strategy="AUTO")
*/
private int $id;
/**
* @ORM\Column(name="created_at", type="datetime")
*
* @Gedmo\Timestampable(on="create")
*/
private \DateTimeInterface $createdAt;
/**
* @ORM\Column(name="updated_at", type="datetime")
*
* @Gedmo\Timestampable(on="update")
*/
private \DateTimeInterface $updatedAt;
/**
* @ORM\OneToMany(targetEntity="App\Entity\Cart\CartItem", mappedBy="cart", cascade={"persist", "remove"})
*/
private ?Collection $cartitems;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Garages\Garage", fetch="EAGER")
*
* @ORM\JoinColumn(name="garage_id", referencedColumnName="id")
*/
private ?Garage $garage = null;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\User", fetch="EAGER")
*
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
*
* User who has placed the order (could be the associated but an admin too)
*/
private ?UserInterface $user = null;
/**
* @ORM\Column(type="text", length=10000, nullable=true)
*/
private ?string $commentUser = null;
/**
* @ORM\Column(type="text", length=10000, nullable=true)
*/
private ?string $commentAdmin = null;
public function __construct()
{
$this->cartitems = new ArrayCollection();
}
public function getId(): int
{
return $this->id;
}
public function setCreatedAt(\DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getCreatedAt(): \DateTimeInterface
{
return $this->createdAt;
}
public function setUpdatedAt(\DateTimeInterface $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
public function getUpdatedAt(): \DateTimeInterface
{
return $this->updatedAt;
}
public function setCartItems(?Collection $items): self
{
$this->cartitems = $items;
return $this;
}
public function addCartItem(CartItem $item): self
{
$item->setCart($this);
$this->cartitems[] = $item;
return $this;
}
public function getCartItems(): ?Collection
{
return $this->cartitems;
}
public function getCartItemsAmount(): int
{
return count($this->getCartItems());
}
public function cartItemsGroupByGiftProvider(): array
{
$cartItemsGroupByProvider = [];
foreach ($this->cartitems as $cartItem) {
$cartItemsGroupByProvider[$cartItem->getGiftItem()->firstProvider()->getId()][] = $cartItem;
}
return $cartItemsGroupByProvider;
}
public function cartItemsGroupBySupplier(): array
{
$cartItemsGroupBySupplier = [];
foreach ($this->cartitems as $cartItem) {
$item = $cartItem->getItem();
$cartItemsGroupBySupplier[$item->getFamily()->getSupplier()->getId()][] = $item;
}
return $cartItemsGroupBySupplier;
}
public function getItems(): array
{
$result = [];
foreach ($this->cartitems as $cartitem) {
$result[] = $cartitem->getItem();
}
return $result;
}
public function hasItem($item, int $sizeId = null): bool
{
foreach ($this->cartitems as $cartItem) {
if ($cartItem->getItem() === $item || ($cartItem->getGiftItem() === $item && (is_null($cartItem->size()) || $cartItem->size()->getId() === $sizeId))) {
return true;
}
}
return false;
}
public function getCartItemByItem($item, int $sizeId = null): ?CartItem
{
foreach ($this->cartitems as $cartItem) {
if ($cartItem->getItem() === $item || ($cartItem->getGiftItem() === $item && (is_null($cartItem->size()) || $cartItem->size()->getId() === $sizeId))) {
return $cartItem;
}
}
return null;
}
public function getTotalQuantity(): int
{
$quantity = 0;
foreach ($this->getCartItems() as $cartItem) {
$quantity += $cartItem->getQuantity();
}
return $quantity;
}
/**
* @throws \JsonException
*/
public function toJson(): string
{
$result = [];
$result['totalQuantity'] = $this->getTotalQuantity();
return json_encode($result, JSON_THROW_ON_ERROR);
}
public function getUser(): ?UserInterface
{
return $this->user;
}
public function setUser(UserInterface $user): self
{
$this->user = $user;
return $this;
}
public function getCommentUser(): ?string
{
return $this->commentUser;
}
public function setCommentUser(?string $commentUser): self
{
$this->commentUser = $commentUser;
return $this;
}
public function getCommentAdmin(): ?string
{
return $this->commentAdmin;
}
public function setCommentAdmin(?string $commentAdmin): self
{
$this->commentAdmin = $commentAdmin;
return $this;
}
public function canPlaceGiftOrder(): bool
{
if (!$this->getGarage()) {
return false;
}
if ($this->getGarage()->getOwner() && $this->totalGiftPoints() > $this->getGarage()->getOwner()->getCatalogPointsAmount()) {
return false;
}
foreach ($this->getCartItems() as $item) {
if (0 === count($item->getGiftItem()->getProviders())) {
return false;
}
}
if ($this->hasAnyProviderWithBlockedDelivery()) {
return false;
}
return true;
}
public function hasAnyProviderWithBlockedDelivery(): bool
{
foreach ($this->cartitems as $cartItem) {
if (!$cartItem->getGiftItem()) {
continue;
}
$provider = $cartItem->getGiftItem()->firstProvider();
if (!$provider) {
continue;
}
if ($provider->hasDeliveryBlocked()) {
return true;
}
}
return false;
}
public function providersWithBlockedDelivery(): array
{
$providers = [];
foreach ($this->cartitems as $cartItem) {
if (!$cartItem->getGiftItem()) {
continue;
}
$provider = $cartItem->getGiftItem()->firstProvider();
if (!$provider) {
continue;
}
if ($provider->hasDeliveryBlocked()) {
$providers[] = $provider;
}
}
return $providers;
}
public function totalGiftPoints(): int
{
$total = 0;
foreach ($this->getCartItems() as $cartItem) {
$total += $cartItem->totalGiftPoints();
}
$total += $this->totalDeliveryPoints();
return $total;
}
public function distinctGiftProviders(): array
{
$giftProviders = [];
foreach ($this->cartitems as $cartItem) {
if (!$cartItem->getGiftItem()) {
continue;
}
$provider = $cartItem->getGiftItem()->firstProvider();
if ($provider && !isset($giftProviders[$provider->getId()])) {
$giftProviders[$provider->getId()] = $provider;
}
}
return $giftProviders;
}
public function totalPointsInCartOfGiftProvider(CatalogGiftProvider $giftProvider): int
{
$totalPointsOfGiftProvider = 0;
foreach ($this->cartitems as $cartItem) {
$giftItem = $cartItem->getGiftItem();
if (!$giftItem) {
continue;
}
if ($giftItem->firstProvider() !== $giftProvider) {
continue;
}
$totalPointsOfGiftProvider += $cartItem->totalGiftPoints();
}
return $totalPointsOfGiftProvider;
}
private function totalDeliveryPoints(): int
{
$deliveryPoints = 0;
foreach ($this->giftProvidersWithDeliveryLine() as $provider) {
$deliveryPoints += $provider->getDeliveryManagementPoints();
}
return $deliveryPoints;
}
public function giftProvidersWithDeliveryLine(): array
{
$providers = [];
foreach ($this->distinctGiftProviders() as $giftProvider) {
if ($giftProvider->hasMinPointsRestriction() &&
!$giftProvider->exceedsMinPointsRestriction($this->totalPointsInCartOfGiftProvider($giftProvider))) {
$providers[] = $giftProvider;
}
}
return $providers;
}
public function hasProviderDeliveryLine($provider): bool
{
return in_array($provider, $this->giftProvidersWithDeliveryLine(), true);
}
public function containsItemsGarageHasNotAccess(): ?bool
{
if ($this->getGarage()) {
$garageOwner = $this->getGarage()->getOwner();
foreach ($this->cartitems as $cartItem) {
if (!$cartItem->getItem()->userHasAccess($garageOwner)) {
return true;
}
}
return false;
}
return null;
}
}