src/Entity/Cart.php line 56
<?php
namespace App\Entity;
use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter;
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
use ApiPlatform\Doctrine\Orm\Filter\ExistsFilter;
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Delete;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\Put;
use App\Controller\OrdersExporter;
use App\Entity\Trait\IdTrait;
use App\Entity\Trait\TimestampableTrait;
use App\Entity\Trait\UuidTrait;
use App\Enum\PaymentMethod;
use App\Repository\CartRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use Gedmo\Mapping\Annotation as Gedmo;
#[ApiResource(
description: 'Carts',
operations: [
new GetCollection(),
new Post(),
new Get(),
new Put(),
new Delete(),
],
normalizationContext: ['groups' => [
'read',
'read:' . self::class,
]],
denormalizationContext: ['groups' => ['write']],
order: ['createdAt' => 'desc'],
security: 'is_granted("' . self::class . '")',
extraProperties: ['standard_put' => false],
)]
#[ApiFilter(DateFilter::class, properties: ['createdAt'])]
#[ApiFilter(SearchFilter::class, properties: ['orderId' => 'ipartial', 'createdAt' => 'ipartial', 'fullName' => 'ipartial'])]
#[ApiFilter(ExistsFilter::class, properties: ['orderId'])]
#[ApiFilter(BooleanFilter::class, properties: ['orderId'])]
#[ApiFilter(OrderFilter::class, properties: ['createdAt', 'totalPrice'])]
#[ORM\Entity(repositoryClass: CartRepository::class)]
class Cart
{
use IdTrait;
use UuidTrait;
use TimestampableTrait;
public const PAYU_STATUS_NEW = 'NEW';
public const PAYU_STATUS_PENDING = 'PENDING';
public const PAYU_STATUS_CANCELED = 'CANCELED';
public const PAYU_STATUS_REJECTED = 'REJECTED';
public const PAYU_STATUS_COMPLETED = 'COMPLETED';
public const PAYU_STATUS_WAITING = 'WAITING_FOR_CONFIRMATION';
#[ApiProperty(description: 'Creation date')]
#[Groups(['read:' . self::class, 'write', 'read:list', 'read:stats', 'read:autocomplete', 'read:minimal'])]
#[Gedmo\Timestampable(on: 'create')]
#[ORM\Column(type: Types::DATETIME_IMMUTABLE)]
protected \DateTimeImmutable $createdAt;
#[ApiProperty(description: 'Customer', writableLink: false)]
#[Groups(['read:' . self::class, 'write'])]
#[ORM\ManyToOne]
private ?Customer $customer = null;
#[ApiProperty(description: 'First name')]
#[Groups(['read:' . self::class, 'write'])]
#[Assert\NotBlank(groups: ['step3', 'step4'])]
#[ORM\Column(length: 255, nullable: true)]
private ?string $firstName = null;
#[ApiProperty(description: 'Last name')]
#[Groups(['read:' . self::class, 'write'])]
#[Assert\NotBlank(groups: ['step3', 'step4'])]
#[ORM\Column(length: 255, nullable: true)]
private ?string $lastName = null;
#[ApiProperty(description: 'Full name')]
#[Groups(['read:' . self::class, 'write'])]
#[ORM\Column(length: 255, nullable: true)]
private ?string $fullName = null;
#[ApiProperty(description: 'Phone number')]
#[Groups(['read:' . self::class, 'write'])]
#[ORM\Column(length: 255, nullable: true)]
private ?string $phone = null;
#[ApiProperty(description: 'Email')]
#[Groups(['read:' . self::class, 'write'])]
#[Assert\NotBlank(groups: ['step3', 'step4'])]
#[ORM\Column(length: 255, nullable: true)]
private ?string $email = null;
#[ApiProperty(description: 'Want fv')]
#[Groups(['read:' . self::class, 'write'])]
#[ORM\Column(options: ['default' => false])]
private bool $wantFv = false;
#[ApiProperty(description: 'Fv name')]
#[Groups(['read:' . self::class, 'write'])]
#[Assert\When(
expression: 'this.isWantFv()',
constraints: [
new Assert\NotBlank()
],
groups: ['step3', 'step4'],
)]
#[ORM\Column(length: 255, nullable: true)]
private ?string $fvName = null;
#[ApiProperty(description: 'Fv nip')]
#[Groups(['read:' . self::class, 'write'])]
#[Assert\When(
expression: 'this.isWantFv()',
constraints: [
new Assert\NotBlank()
],
groups: ['step3', 'step4'],
)]
#[ORM\Column(length: 255, nullable: true)]
private ?string $fvNip = null;
#[ApiProperty(description: 'Fv other tax id')]
#[Groups(['read:' . self::class, 'write'])]
#[ORM\Column(length: 255, nullable: true)]
private ?string $fvOtherTaxId = null;
#[ApiProperty(description: 'Fv city')]
#[Groups(['read:' . self::class, 'write'])]
#[Assert\When(
expression: 'this.isWantFv()',
constraints: [
new Assert\NotBlank()
],
groups: ['step3', 'step4'],
)]
#[ORM\Column(length: 255, nullable: true)]
private ?string $fvCity = null;
#[ApiProperty(description: 'Fv street')]
#[Groups(['read:' . self::class, 'write'])]
#[Assert\When(
expression: 'this.isWantFv()',
constraints: [
new Assert\NotBlank()
],
groups: ['step3', 'step4'],
)]
#[ORM\Column(length: 255, nullable: true)]
private ?string $fvStreet = null;
#[ApiProperty(description: 'Fv house number')]
#[Groups(['read:' . self::class, 'write'])]
#[Assert\When(
expression: 'this.isWantFv()',
constraints: [
new Assert\NotBlank()
],
groups: ['step3', 'step4'],
)]
#[ORM\Column(length: 255, nullable: true)]
private ?string $fvHouseNumber = null;
#[ApiProperty(description: 'Fv apartment number')]
#[Groups(['read:' . self::class, 'write'])]
#[ORM\Column(length: 255, nullable: true)]
private ?string $fvApartmentNumber = null;
#[ApiProperty(description: 'Fv postal code')]
#[Groups(['read:' . self::class, 'write'])]
#[Assert\When(
expression: 'this.isWantFv()',
constraints: [
new Assert\NotBlank()
],
groups: ['step3', 'step4'],
)]
#[ORM\Column(length: 255, nullable: true)]
private ?string $fvPostalCode = null;
#[ApiProperty(description: 'Client comment')]
#[Groups(['read:' . self::class, 'write'])]
#[ORM\Column(length: 1024, nullable: true)]
private ?string $fvComment = null;
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: CartProduct::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
private Collection $products;
#[ApiProperty(description: 'Country', writableLink: false)]
#[Groups(['read:' . self::class, 'write'])]
#[ORM\ManyToOne(inversedBy: 'carts')]
private ?CartCountry $country = null;
#[ApiProperty(description: 'Paid at')]
#[Groups(['read:' . self::class, 'write'])]
#[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $paidAt = null;
#[ApiProperty(description: 'PayU link')]
#[Groups(['read:' . self::class, 'write'])]
#[ORM\Column(type: 'string', length: 1023, nullable: true)]
private ?string $payuLink = null;
#[ApiProperty(description: 'PayU order id')]
#[Groups(['read:' . self::class, 'write'])]
#[ORM\Column(type: 'string', length: 63, nullable: true)]
private ?string $payuOrderId = null;
#[ApiProperty(description: 'PayU status')]
#[Groups(['read:' . self::class, 'write'])]
#[ORM\Column(type: 'string', length: 31, nullable: true)]
private ?string $payuStatus = self::PAYU_STATUS_NEW;
#[ApiProperty(description: 'Order id')]
#[Groups(['read:' . self::class])]
#[ORM\Column(nullable: true)]
private ?int $orderId = null;
#[ApiProperty(description: 'Payment method', writableLink: false)]
#[Groups(['read:' . self::class, 'write'])]
#[ORM\Column(
type: Types::STRING,
length: 255,
enumType: PaymentMethod::class,
options: ['default' => PaymentMethod::PAYU]
)]
private PaymentMethod $paymentMethod = PaymentMethod::PAYU;
#[ApiProperty(description: 'Total price')]
#[Groups(['read:' . self::class])]
#[ORM\Column(nullable: true)]
private ?float $totalPrice = null;
#[ApiProperty(description: 'Admin comment')]
#[Groups(['read:' . self::class, 'write'])]
#[ORM\Column(length: 4096, nullable: true)]
private ?string $adminComment = null;
#[ApiProperty(description: 'Locale')]
#[Groups(['read:' . self::class])]
#[ORM\Column(length: 255, nullable: true, options: ['default' => 'pl'])]
private string $locale = 'pl';
public function __construct()
{
$this->setUuid();
$this->products = new ArrayCollection();
$this->createdAt = new \DateTimeImmutable();
$this->updatedAt = new \DateTimeImmutable();
}
public function getCustomer(): ?Customer
{
return $this->customer;
}
public function setCustomer(?Customer $customer): self
{
$this->customer = $customer;
return $this;
}
public function getFirstName(): ?string
{
return $this->firstName;
}
public function setFirstName(?string $firstName): self
{
$this->firstName = $firstName;
$this->setFullName($this->getFirstName() . ' ' . $this->getLastName());
return $this;
}
public function getLastName(): ?string
{
return $this->lastName;
}
public function setLastName(?string $lastName): self
{
$this->lastName = $lastName;
$this->setFullName($this->getFirstName() . ' ' . $this->getLastName());
return $this;
}
public function getFullName(): ?string
{
return $this->fullName;
}
public function setFullName(?string $fullName): self
{
$this->fullName = $fullName;
return $this;
}
public function getPhone(): ?string
{
return $this->phone;
}
public function setPhone(?string $phone): static
{
$this->phone = $phone;
return $this;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(?string $email): self
{
$this->email = $email;
return $this;
}
public function getIsWantFv(): bool
{
return $this->wantFv;
}
public function isWantFv(): bool
{
return $this->wantFv;
}
public function getWantFv(): bool
{
return $this->wantFv;
}
public function setWantFv(bool $wantFv): self
{
$this->wantFv = $wantFv;
return $this;
}
public function getFvName(): ?string
{
return $this->fvName;
}
public function blabla(): ?string
{
return 'string';
}
public function setFvName(?string $fvName): self
{
$this->fvName = $fvName;
return $this;
}
public function getFvNip(): ?string
{
return $this->fvNip;
}
public function setFvNip(?string $fvNip): self
{
$this->fvNip = $fvNip;
return $this;
}
public function getFvOtherTaxId(): ?string
{
return $this->fvOtherTaxId;
}
public function setFvOtherTaxId(?string $fvOtherTaxId): self
{
$this->fvOtherTaxId = $fvOtherTaxId;
return $this;
}
public function getFvCity(): ?string
{
return $this->fvCity;
}
public function setFvCity(?string $fvCity): self
{
$this->fvCity = $fvCity;
return $this;
}
public function getFvStreet(): ?string
{
return $this->fvStreet;
}
public function setFvStreet(?string $fvStreet): self
{
$this->fvStreet = $fvStreet;
return $this;
}
public function getFvHouseNumber(): ?string
{
return $this->fvHouseNumber;
}
public function setFvHouseNumber(?string $fvHouseNumber): self
{
$this->fvHouseNumber = $fvHouseNumber;
return $this;
}
public function getFvApartmentNumber(): ?string
{
return $this->fvApartmentNumber;
}
public function setFvApartmentNumber(?string $fvApartmentNumber): self
{
$this->fvApartmentNumber = $fvApartmentNumber;
return $this;
}
public function getFvPostalCode(): ?string
{
return $this->fvPostalCode;
}
public function setFvPostalCode(?string $fvPostalCode): self
{
$this->fvPostalCode = $fvPostalCode;
return $this;
}
public function getFvComment(): ?string
{
return $this->fvComment;
}
public function setFvComment(?string $fvComment): self
{
$this->fvComment = $fvComment;
return $this;
}
/**
* @return Collection<int, CartProduct>
*/
public function getProducts(): Collection
{
return $this->products;
}
public function addProduct(CartProduct $product): self
{
if (!$this->products->contains($product)) {
$this->products->add($product);
$product->setParent($this);
}
return $this;
}
public function removeProduct(CartProduct $product): self
{
if ($this->products->removeElement($product)) {
// set the owning side to null (unless already changed)
if ($product->getParent() === $this) {
$product->setParent(null);
}
}
return $this;
}
public function getCountry(): ?CartCountry
{
return $this->country;
}
public function setCountry(?CartCountry $country): self
{
$this->country = $country;
if ($country) {
foreach ($this->getProducts() as $product) {
$product->setVat($country->getRegion()?->getVat() ?? 0);
}
}
return $this;
}
public function addArticle(JournalArticle $article): self
{
$found = null;
foreach ($this->products as $product) {
if ($product->getArticle() === $article) {
$found = $product;
break;
}
}
if (!$found) {
$found = new CartProduct();
$found->setParent($this);
$found->setArticle($article);
$this->addProduct($found);
}
return $this;
}
public function addIssue(JournalIssue $issue): self
{
$found = null;
foreach ($this->products as $product) {
if ($product->getIssue() === $issue) {
$found = $product;
break;
}
}
if (!$found) {
$found = new CartProduct();
$found->setParent($this);
$found->setIssue($issue);
$this->addProduct($found);
}
return $this;
}
public function canAccessStep2(): bool
{
if ($this->getProducts()->isEmpty()) {
return false;
}
return true;
}
public function canAccessStep3(): bool
{
if ($this->getProducts()->isEmpty()) {
return false;
}
if (
!$this->getFirstName() ||
!$this->getLastName() ||
!$this->getEmail()
) {
return false;
}
if (
$this->isWantFv() &&
(
!$this->getFvName() ||
!$this->getFvNip() ||
!$this->getFvCity() ||
!$this->getFvStreet() ||
!$this->getFvHouseNumber() ||
!$this->getFvPostalCode()
)
) {
return false;
}
return true;
}
public function getPaidAt(): ?\DateTimeImmutable
{
return $this->paidAt;
}
public function setPaidAt(?\DateTimeImmutable $paidAt): static
{
$this->paidAt = $paidAt;
return $this;
}
public function getPayuLink(): ?string
{
return $this->payuLink;
}
public function setPayuLink(?string $payuLink): self
{
$this->payuLink = $payuLink;
return $this;
}
public function getPayuOrderId(): ?string
{
return $this->payuOrderId;
}
public function setPayuOrderId(?string $payuOrderId): self
{
$this->payuOrderId = $payuOrderId;
return $this;
}
public function getPayuStatus(): ?string
{
return $this->payuStatus;
}
public function setPayuStatus(?string $payuStatus): self
{
$this->payuStatus = $payuStatus;
return $this;
}
public function getOrderId(): ?int
{
return $this->orderId;
}
public function setOrderId(?int $orderId): self
{
$this->orderId = $orderId;
return $this;
}
public function getPaymentMethod(): PaymentMethod
{
return $this->paymentMethod;
}
public function setPaymentMethod(PaymentMethod $paymentMethod): self
{
$this->paymentMethod = $paymentMethod;
return $this;
}
public function getTotalPrice(): ?float
{
return $this->totalPrice;
}
public function setTotalPrice(?float $totalPrice): self
{
$this->totalPrice = $totalPrice;
return $this;
}
public function getAdminComment(): ?string
{
return $this->adminComment;
}
public function setAdminComment(?string $adminComment): self
{
$this->adminComment = $adminComment;
return $this;
}
public function getTotalPriceFront(): float
{
$total = 0;
foreach ($this->products as $product) {
if ($product->getArticle()) {
$total += $product->getArticle()->getPrice();
}
if ($product->getIssue()) {
$total += $product->getIssue()->getPrice();
}
}
return round($total / 1000, 2);
}
#[ApiProperty(description: 'Total price cms')]
#[Groups(['read:' . self::class])]
public function getTotalPriceCms(): float
{
$total = 0;
foreach ($this->getProducts() as $product) {
if (!$product->getPrice()) {
continue;
}
$total += $product->getPrice();
}
return round($total / 1000, 2);
}
public function getTotalPriceMinor(): int
{
$total = 0;
foreach ($this->getProducts() as $product) {
if (!$product->getPrice()) {
continue;
}
$total += $product->getPrice();
}
return intval(round($total / 10, 2));
}
public function getTotalVat(): float
{
$total = $this->getTotalPriceFront();
$totalVat = 0.0;
foreach ($this->getProducts() as $product) {
if (!$product->getVat()) {
continue;
}
if ($product->getArticle()) {
$productPrice = $product->getArticle()->getPrice();
} else {
$productPrice = $product->getIssue()->getPrice();
}
$vatPercentage = $product->getVat() / 100; // Convert percentage to decimal
$productVat = (int)round($productPrice * $vatPercentage);
$totalVat += $productVat;
}
return $totalVat / 1000;
}
#[ApiProperty(description: 'Title')]
#[Groups(['read:' . self::class])]
public function getTitle(): ?string
{
return strval($this->orderId);
}
#[ApiProperty(description: 'Buyer cms')]
#[Groups(['read:' . self::class])]
public function getBuyerCms(): string
{
$buyer = sprintf(
'%s (%s)',
$this->getFullName(),
$this->getEmail(),
);
if ($this->phone) {
$buyer .= sprintf(', tel: %s', $this->getPhone());
}
return $buyer;
}
public function getLocale(): string
{
return $this->locale;
}
public function setLocale(string $locale): static
{
$this->locale = $locale;
return $this;
}
}