<?php
namespace App\Entity\ECommerce;
use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as JMS;
use App\Entity\ECommerce\Traits\DatesInterface;
use App\Entity\ECommerce\Traits\DatesTrait;
use App\Entity\ECommerce\Traits\RemoteInterface;
use App\Entity\ECommerce\Traits\RemoteTrait;
/**
* Invoice
*
* @ORM\Table(
* name="invoice",
* uniqueConstraints={@ORM\UniqueConstraint(name="invoice_number", columns={"number", "year"})}
* )
* @ORM\Entity(repositoryClass="App\Repository\ECommerce\InvoiceRepository")
*/
class Invoice implements RemoteInterface, DatesInterface
{
public const SHIPPED_STATUS = 'shipped';
public const PARTIALLY_SHIPPED_STATUS = 'partially';
public const UNSHIPPED_STATUS = 'not-shipped';
/**
*
* @ORM\Column(name="id", type="string", length=8)
* @ORM\Id
*/
private string $id;
/**
* @var int
*
* @ORM\Column(name="number", type="integer")
*
* @JMS\Expose()
* @JMS\Groups({"cart_private"})
*/
private $number;
/**
*
* @ORM\Column(name="year", type="integer")
*
* @JMS\Expose()
* @JMS\Groups({"cart_private"})
*/
private int $year;
/**
* @var DateTime
*
* @ORM\Column(name="due_date", type="date", nullable=true)
*
* @JMS\Expose()
* @JMS\Groups({"cart_private"})
*/
private $dueDate;
/**
* @var Cart
*
* @ORM\OneToMany(targetEntity="App\Entity\ECommerce\Bill", mappedBy="invoice")
*/
private $bills;
use RemoteTrait;
/**
* Dates trait
* createdAt, updatedAt, IndexAt, syncedAt
*/
use DatesTrait {
DatesTrait::__construct as __DT__construct;
}
/**
* Invoice constructor.
*/
public function __construct(/**
*
* @ORM\OneToOne(targetEntity="App\Entity\ECommerce\Cart", inversedBy="invoice", cascade={"persist"})
* @ORM\JoinColumn(name="cart", referencedColumnName="id")
*/
private Cart $cart)
{
$this->bills = new ArrayCollection();
$this->year = (integer) (new DateTime())->format('Y');
$this->id = hash('crc32b', $this->cart . $this->year);
$this->__DT__construct();
}
/**
* Get id
*/
public function getId(): string
{
return $this->id;
}
/**
* Set number
*
*
*/
public function setNumber(int $number): self
{
$this->number = $number;
return $this;
}
/**
* Get number
*
* @return integer
*/
public function getNumber(): ?int
{
return $this->number;
}
/**
* Set year
*/
public function setYear(int $year): self
{
$this->year = $year;
return $this;
}
/**
* Get year
*
* @return int
*/
public function getYear():? int
{
return $this->year;
}
/**
* Set carts
*
* @param Cart|null $cart
*/
public function setCart(Cart $cart = null): self
{
$this->cart = $cart;
return $this;
}
/**
* Get carts
*/
public function getCart(): Cart
{
return $this->cart;
}
/**
* Set id
*
*
*/
public function setId(string $id): self
{
$this->id = $id;
return $this;
}
public function isNew(): bool
{
return $this->createdAt->diff(new DateTime())->days < 1;
}
public function getInvoiceNumber(): string
{
return $this->number . '-' . $this->year;
}
/**
* Add bill.
*
*
*/
public function addBill(Bill $bill): self
{
$this->bills[] = $bill;
return $this;
}
/**
* Remove bill.
*
*
* @return boolean TRUE if this collection contained the specified element, FALSE otherwise.
*/
public function removeBill(Bill $bill): bool
{
return $this->bills->removeElement($bill);
}
/**
* Get bills.
*/
public function getBills(): Collection
{
return $this->bills;
}
/**
* Set dueDate.
*
* @param DateTime|null $dueDate
*/
public function setDueDate(DateTime $dueDate = null): self
{
$this->dueDate = $dueDate;
return $this;
}
/**
* Get dueDate.
*/
public function getDueDate(): ?DateTime
{
return $this->dueDate;
}
public function getStatus(): string
{
$quantity = $this->cart->getItems()->map(fn(CartItem $item): ?int => $item->getQuantity())->toArray();
$quantity = array_sum($quantity);
$billItems = $this->bills->map(fn(Bill $bill) => $bill->getItems()->toArray())->toArray();
if (empty($billItems)) {
return self::UNSHIPPED_STATUS;
}
$billItems = call_user_func(array_merge(...), ...$billItems);
$statuses = array_map(fn(BillItem $billItem): int => $billItem->getBill()->getShipped() ? $billItem->getQuantity() : 0,$billItems);
$sum =array_sum($statuses);
if ($sum === 0) {
return self::UNSHIPPED_STATUS;
}
if ($quantity === $sum) {
return self::SHIPPED_STATUS;
}
return self::PARTIALLY_SHIPPED_STATUS;
}
}