<?php
namespace App\Entity;
use App\Repository\SaleOrderRepository;
use App\Traits\DateTrait;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as Serializer;
use JMS\Serializer\Annotation\Expose;
use JMS\Serializer\Annotation\Groups;
use JMS\Serializer\Annotation\SerializedName;
use ReflectionClass;
use App\Constants\SaleOrder as SaleOrderConstant;
/**
* @ORM\Entity(repositoryClass=SaleOrderRepository::class)
* @ORM\Table(indexes={
* @ORM\Index(columns={"status"})
* })
*
* @Serializer\ExclusionPolicy("ALL")
*/
class SaleOrder
{
use DateTrait;
/**
* Identifiant interne auto incrémenté
*
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*
* @Expose
* @Groups({
* "sale_order:id",
* "sale_order:list",
* "sale_order:updated",
* "sale_order:item",
* "sale_order",
* "get:read",
* "post:read",
* "export_order_datatable"
* })
*/
private ?int $id = NULL;
/**
* Total de la commande HT
*
* @ORM\Column(type="decimal", precision=8, scale=2)
*
* @Expose
* @Groups({
* "sale_order:list",
* "sale_order:updated",
* "sale_order:item",
* "sale_order",
* "get:read",
* "export_order_datatable"
* })
*/
private float $total = 0.00;
/**
* Méthode d'expédition
*
* @ORM\Column(type="string", length=64, nullable=true)
*
* @Expose
* @Groups({
* "sale_order:updated",
* "sale_order",
* "get:read"
* })
*/
private ?string $shippingMethod = NULL;
/**
* Statut de la commande
* @ORM\Column(type="string", length=32, options={"default":"pending_processing"})
*
* @Expose
* @Groups({
* "sale_order:status",
* "sale_order:list",
* "sale_order:updated",
* "sale_order:item",
* "sale_order",
* "get:read",
* "post:read",
* "export_order_datatable"
* })
*/
private string $status = SaleOrderConstant::STATUS_PENDING_PROCESSING;
/**
* Statut de la commande à attribuer après l'application d'un statut "waiting"
* @ORM\Column(type="string", length=32, nullable=true)
*
* @Expose
* @Groups({
* "sale_order:status",
* "sale_order:list",
* "sale_order:updated",
* "sale_order:item",
* "sale_order",
* "get:read",
* "post:read",
* "export_order_datatable"
* })
*/
private ?string $waitingStatus = null;
/**
* @ORM\OneToOne(targetEntity=BankReturn::class, cascade={"persist", "remove"})
*/
private ?BankReturn $bankReturn = NULL;
/**
* Utilisateur
*
* @ORM\ManyToOne(targetEntity=User::class, inversedBy="orders")
*
* @Expose
* @Groups({
* "sale_order:user",
* "sale_order:item",
* "sale_order:post",
* "sale_order",
* "get:read",
* "post:read",
* "export_order_datatable"
* })
*/
private ?User $user = NULL;
/**
* Motif d'annulation
* @ORM\Column(type="text", nullable=true)
*
* @Expose
* @Groups({
* "sale_order:item",
* "sale_order:updated",
* "sale_order"
* })
*/
private ?string $cancelMotif = NULL;
/**
* Prix de la livraison
*
* @ORM\Column(type="decimal", precision=8, scale=2)
*
* @Expose
* @Groups({
* "sale_order:item",
* "sale_order:updated",
* "sale_order",
* "get:read"
* })
*/
private $shippingPrice;
/**
* Référence interne
*
* @ORM\Column(type="string", length=64, nullable=true)
*
* @Expose
* @Groups({
* "sale_order:item",
* "sale_order"
* })
*/
private ?string $internalReference = NULL;
/**
* Commentaire
*
* @ORM\Column(type="text", nullable=true)
*
* @Expose
* @Groups({
* "sale_order:item",
* "sale_order",
* "get:read"
* })
*/
private ?string $comment = NULL;
/**
* @ORM\Column(type="boolean", options={"default":false})
*
* @Expose
* @Groups({
* "sale_order",
* "get:read"
* })
*/
private bool $isManagedByCustomer = FALSE;
/**
* @ORM\Column(type="decimal", precision=8, scale=2, nullable=true)
*
* @Expose
* @Groups({
* "sale_order",
* "sale_order:updated"
* })
*/
private $feesOrder;
/**
* @ORM\Column(type="decimal", precision=8, scale=2, nullable=true)
*
* @Expose
* @Groups({"sale_order"})
*/
private $extraCbPayment;
/**
* @deprecated NON UTILISÉ
*
* @ORM\Column(type="decimal", precision=8, scale=2, nullable=true)
*
* @Expose
* @Groups({"sale_order"})
*/
private $totalBonusUsed;
/**
* @deprecated
* @ORM\ManyToOne(targetEntity=SaleOrder::class, inversedBy="saleOrders")
*/
private ?SaleOrder $saleorderGrouped = NULL;
/**
* @deprecated
* @ORM\OneToMany(targetEntity=SaleOrder::class, mappedBy="saleorderGrouped")
*/
private Collection $saleOrders;
/**
* @ORM\Column(type="boolean", nullable=true)
*
* @Expose
* @Groups({"sale_order"})
*/
private ?bool $notBillable = NULL;
/**
* @ORM\Column(type="array", nullable=true)
*
* @Expose
* @Groups({"sale_order","get:read"})
*/
private ?array $otherinformations = [];
/**
* Adresse de livraison
*
* @ORM\OneToOne(targetEntity=SaleOrderAddress::class, orphanRemoval=true, cascade={"persist", "remove"})
* @ORM\JoinColumn(onDelete="SET NULL")
*
* @Expose
* @Groups({"sale_order:item", "sale_order:post", "get:read", "sale_order", "export_order_datatable"})
*/
private ?SaleOrderAddress $shippingAddress = NULL;
/**
* Adresse de facturation
*
* @ORM\OneToOne(targetEntity=SaleOrderAddress::class, orphanRemoval=true, cascade={"persist", "remove"})
* @ORM\JoinColumn(onDelete="SET NULL")
*
* @Expose
* @Groups({"sale_order:item", "sale_order:post", "get:read"})
*/
private ?SaleOrderAddress $billingAddress = NULL;
/**
* Liste des produits commandés
* @ORM\OneToMany(targetEntity=SaleOrderItem::class, mappedBy="saleOrder", cascade={"persist", "remove"})
*
* @Expose
* @Groups({"sale_order:item", "sale_order:post", "get:read", "export_order_datatable"})
*/
private Collection $items;
/**
* @ORM\OneToMany(targetEntity=SaleOrderShipment::class, mappedBy="saleOrder", cascade={"remove"})
*
* @Expose
* @Groups({
* "sale_order",
* "sale_order:item",
* "sale_order:updated",
* "get:read",
* "export_order_datatable"
* })
*/
private Collection $shipments;
/**
* @ORM\OneToOne(targetEntity=Cart::class, inversedBy="saleOrder", cascade={"persist", "remove"})
*/
private ?Cart $cart = NULL;
/**
* @var Collection|PointTransaction[]
*
* @ORM\OneToMany(targetEntity=PointTransaction::class, mappedBy="saleOrder", cascade={"remove"})
*/
private Collection $pointTransactions;
/**
* @ORM\Column(type="integer", nullable=true)
*
* @Expose
* @Groups({
* "sale_order",
* "sale_order:updated",
* "get:read",
* "export_order_datatable"
* })
*/
private ?int $oldId = NULL;
/**
* @ORM\OneToOne(targetEntity=SaleOrderInvoice::class, inversedBy="saleOrder", cascade={"persist", "remove"})
*/
private ?SaleOrderInvoice $invoice = NULL;
/**
* @ORM\Column(type="text", nullable=true)
*/
private $categoryValues;
/**
* @ORM\Column(type="text", nullable=true)
*/
private $feesCategoryValues;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*
* @Expose
* @Groups({"sale_order", "export_order_datatable", "get:read"})
*/
private $customQuestion;
/**
* @ORM\Column(type="float", nullable=true)
*/
private $orderRate;
/**
* @ORM\Column(type="boolean", options={"default":false})
*/
private bool $isTrip = FALSE;
private ?string $agency = NULL;
/**
* @Expose
* @Groups({"get:read"})
* @ORM\Column(type="text", nullable=true)
*/
private ?string $orderExtraData = NULL;
private ?bool $updateFromBo = false;
/**
* @ORM\OneToMany(targetEntity=Invoice::class, mappedBy="saleOrder")
*/
private Collection $invoices;
public function __construct()
{
$this->saleOrders = new ArrayCollection();
$this->items = new ArrayCollection();
$this->shipments = new ArrayCollection();
$this->pointTransactions = new ArrayCollection();
$this->invoices = new ArrayCollection();
}
public static function getStatuses()
{
$statuses = [];
$reflect = new ReflectionClass(SaleOrder::class);
foreach ($reflect->getConstants() as $k => $const) {
if (preg_match("/^(STATUS)/", $k)) {
$statuses[ $const ] = 'capsule.order.status.' . $const;
}
}
return $statuses;
}
/**
* Retourne la société de l'admin adhérent (spécial algorel)
*
* @Serializer\VirtualProperty()
* @SerializedName("agency")
* @Expose()
* @Groups({"get:read"})
*
*/
public function getAgency(): ?string
{
return $this->agency;
}
public function setAgency(?string $agency): self
{
$this->agency = $agency;
return $this;
}
/**
* Retourne le cumul des produits + frais de port + frais de commande
*
* @Serializer\VirtualProperty()
* @SerializedName("totalAmount")
* @Expose()
* @Groups({"sale_order","sale_order:item", "sale_order:post", "get:read", "export_order_datatable"})
*
* @return float
*/
public function getTotalAmount(): float
{
return $this->total + $this->shippingPrice + ($this->feesOrder ?? 0);
}
/**
* Retourne le cumul en point des produits + frais de port + frais de commande
*
* @Serializer\VirtualProperty()
* @SerializedName("totalRateAmount")
* @Expose()
* @Groups({"sale_order","sale_order:item", "sale_order:post", "get:read", "export_order_datatable"})
*
* @return float
*/
public function getRateTotalAmount(): float
{
return round(
($this->total * $this->getOrderRate()) + ($this->shippingPrice * $this->getOrderRate()) + (($this->feesOrder ?? 0) * $this->getOrderRate())
);
}
/**
* @Serializer\VirtualProperty()
* @Serializer\SerializedName("array_category_values")
*
* @Expose()
* @Groups({ "sale_order:array_category_values", "export_order_datatable" })
*/
public function getArrayCategoryValues()
{
return json_decode($this->categoryValues, TRUE) ?? [];
}
/**
* @Serializer\VirtualProperty()
* @Serializer\SerializedName("array_category_values")
*
* @Expose()
* @Groups({ "sale_order:array_category_values", "export_order_datatable" })
*/
public function getArrayFeesCategoryValues()
{
return json_decode($this->feesCategoryValues, TRUE) ?? [];
}
/*
* ============================================================================================
* =============================== FONCTIONS CUSTOM ===========================================
* ============================================================================================
*/
/**
* @return string[]
*/
public static function getOrderedStatus(): array
{
return [
\App\Constants\SaleOrder::STATUS_SHIPPED,
\App\Constants\SaleOrder::STATUS_PROCESSING,
\App\Constants\SaleOrder::STATUS_PENDING_PROCESSING,
\App\Constants\SaleOrder::STATUS_TO_SHIP,
\App\Constants\SaleOrder::STATUS_PARTIALLY_SHIPPED,
];
}
public function __toString()
{
return $this->getSku();
}
public function getSku()
{
$id = strval($this->getId());
return 'SP' . str_pad($id, 10, '0', STR_PAD_LEFT);
}
public function getId(): ?int
{
return $this->id;
}
public function getAddressType(SaleOrderAddress $Address)
{
if ($this->billingAddress === $Address) {
return SaleOrderAddress::BILLING_ADDRESS;
} elseif ($this->shippingAddress === $Address) {
return SaleOrderAddress::SHIPPING_ADDRESS;
}
return FALSE;
}
public function getItemByReferenceWithStatus($reference, $statuses)
{
foreach ($this->getItems() as $item) {
if ($item->getReference() == $reference && in_array($item->getStatus(), $statuses)) {
return $item;
}
}
return NULL;
}
/**
* @return Collection|SaleOrderItem[]
*/
public function getItems(): Collection
{
return $this->items;
}
/**
* @param Collection $items
*
* @return $this
*/
public function setItems(Collection $items): SaleOrder
{
$this->items = $items;
return $this;
}
public function getStatus(): ?string
{
return $this->status;
}
public function setStatus(string $status): self
{
$this->status = $status;
return $this;
}
public function getItemsByReferenceWithStatus($reference, $statuses = [])
{
$items = [];
foreach ($this->getItems() as $item) {
if ($item->getReference() == $reference) {
if (empty($statuses) || in_array($item->getStatus(), $statuses)) {
$items[] = $item;
}
}
}
return $items;
}
/**
* Count items matching reference & status
*
* @param string $reference
* @param array $statuses
* @param bool $in
*
* @return int
*/
public function countItemsByReferenceWithStatus(string $reference, array $statuses, bool $in = TRUE): int
{
$totalRef = $cnt = 0;
foreach ($this->getItems() as $item) {
if ($item->getReference() == $reference) {
$totalRef++;
if (in_array($item->getStatus(), $statuses)) {
$cnt++;
}
}
}
return ($in) ? $cnt : ($totalRef - $cnt);
}
/*
* ============================================================================================
* ============================== FIN FONCTIONS CUSTOM ========================================
* ============================================================================================
*/
/**
* Count items matching status
*
* @param $statuses
* @param bool $in
*
* @return int
*/
public function countItemsWithStatus($statuses, bool $in = TRUE): int
{
$cnt = 0;
foreach ($this->getItems() as $item) {
if (in_array($item->getStatus(), $statuses)) {
$cnt++;
}
}
return ($in) ? $cnt : (count($this->getItems()) - $cnt);
}
/**
* Get an item from order matching reference
*
* @param $reference
*
* @return SaleOrderItem|null
*/
public function getItemByReference($reference)
{
foreach ($this->getItems() as $item) {
if ($item->getReference() == $reference) {
return $item;
}
}
return NULL;
}
public function hasAllItemsStatesCanceled()
{
return $this->hasAllItemsState(SaleOrderItem::STATUS_CANCELED);
}
private function hasAllItemsState($state)
{
foreach ($this->getItems() as $item) {
if ($item->getStatus() != $state) {
return FALSE;
}
}
return TRUE;
}
public function getTotal(): ?float
{
return $this->total;
}
public function setTotal($total): self
{
if (is_string($total)) {
$total = floatval($total);
}
$this->total = $total;
return $this;
}
public function getShippingMethod(): ?string
{
return $this->shippingMethod;
}
public function setShippingMethod(?string $shippingMethod): self
{
$this->shippingMethod = $shippingMethod;
return $this;
}
public function getCancelMotif(): ?string
{
return $this->cancelMotif;
}
public function setCancelMotif(?string $cancelMotif): self
{
$this->cancelMotif = $cancelMotif;
return $this;
}
public function getShippingPrice(): ?string
{
return $this->shippingPrice;
}
public function setShippingPrice(string $shippingPrice): self
{
$this->shippingPrice = $shippingPrice;
return $this;
}
public function getInternalReference(): ?string
{
return $this->internalReference;
}
public function setInternalReference(?string $internalReference): self
{
$this->internalReference = $internalReference;
return $this;
}
public function getComment(): ?string
{
return $this->comment;
}
public function setComment(?string $comment): self
{
$this->comment = $comment;
return $this;
}
public function getIsManagedByCustomer(): ?bool
{
return $this->isManagedByCustomer;
}
public function setIsManagedByCustomer(bool $isManagedByCustomer): self
{
$this->isManagedByCustomer = $isManagedByCustomer;
return $this;
}
public function getFeesOrder(): ?string
{
return $this->feesOrder;
}
public function setFeesOrder(?string $feesOrder): self
{
$this->feesOrder = $feesOrder;
return $this;
}
public function getExtraCbPayment(): ?string
{
return $this->extraCbPayment;
}
public function setExtraCbPayment(?string $extraCbPayment): self
{
$this->extraCbPayment = $extraCbPayment;
return $this;
}
/**
* @return string|null
* @deprecated NON UTILSÉ
*/
public function getTotalBonusUsed(): ?string
{
return $this->totalBonusUsed;
}
/**
* @param string|null $totalBonusUsed
*
* @return $this
* @deprecated NON UTILSÉ
*/
public function setTotalBonusUsed(?string $totalBonusUsed): self
{
$this->totalBonusUsed = $totalBonusUsed;
return $this;
}
public function getNotBillable(): ?bool
{
return $this->notBillable;
}
public function setNotBillable(?bool $notBillable): self
{
$this->notBillable = $notBillable;
return $this;
}
public function getOtherinformations(): ?array
{
return $this->otherinformations;
}
public function setOtherinformations(?array $otherinformations): self
{
$this->otherinformations = $otherinformations;
return $this;
}
public function getBankReturn(): ?BankReturn
{
return $this->bankReturn;
}
public function setBankReturn(?BankReturn $bankReturn): self
{
$this->bankReturn = $bankReturn;
return $this;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): self
{
$this->user = $user;
return $this;
}
/**
* @return Collection|SaleOrder[]
*/
public function getSaleOrders(): Collection
{
return $this->saleOrders;
}
/**
* @param SaleOrder $saleOrder
*
* @return $this
* @deprecated
*/
public function addSaleOrder(SaleOrder $saleOrder): self
{
if (!$this->saleOrders->contains($saleOrder)) {
$this->saleOrders[] = $saleOrder;
$saleOrder->setSaleorderGrouped($this);
}
return $this;
}
/**
* @param SaleOrder $saleOrder
*
* @return $this
* @deprecated
*/
public function removeSaleOrder(SaleOrder $saleOrder): self
{
if ($this->saleOrders->removeElement($saleOrder)) {
// set the owning side to null (unless already changed)
if ($saleOrder->getSaleorderGrouped() === $this) {
$saleOrder->setSaleorderGrouped(NULL);
}
}
return $this;
}
/**
* @deprecated
*/
public function getSaleorderGrouped(): ?SaleOrder
{
return $this->saleorderGrouped;
}
/**
* @deprecated
*/
public function setSaleorderGrouped(?self $saleorderGrouped): SaleOrder
{
$this->saleorderGrouped = $saleorderGrouped;
return $this;
}
public function getShippingAddress(): ?SaleOrderAddress
{
return $this->shippingAddress;
}
public function setShippingAddress(?SaleOrderAddress $shippingAddress): self
{
$this->shippingAddress = $shippingAddress;
return $this;
}
public function getBillingAddress(): ?SaleOrderAddress
{
return $this->billingAddress;
}
public function setBillingAddress(?SaleOrderAddress $billingAddress): self
{
$this->billingAddress = $billingAddress;
return $this;
}
public function addItem(SaleOrderItem $item): self
{
if (!$this->items->contains($item)) {
$this->items[] = $item;
$item->setSaleOrder($this);
}
return $this;
}
public function removeItem(SaleOrderItem $item): self
{
if ($this->items->removeElement($item)) {
// set the owning side to null (unless already changed)
if ($item->getSaleOrder() === $this) {
$item->setSaleOrder(NULL);
}
}
return $this;
}
/**
* @return Collection|SaleOrderShipment[]
*/
public function getShipments(): Collection
{
return $this->shipments;
}
public function addShipment(SaleOrderShipment $shipment): self
{
if (!$this->shipments->contains($shipment)) {
$this->shipments[] = $shipment;
$shipment->setSaleOrder($this);
}
return $this;
}
public function removeShipment(SaleOrderShipment $shipment): self
{
if ($this->shipments->removeElement($shipment)) {
// set the owning side to null (unless already changed)
if ($shipment->getSaleOrder() === $this) {
$shipment->setSaleOrder(NULL);
}
}
return $this;
}
public function getCart(): ?Cart
{
return $this->cart;
}
public function setCart(?Cart $cart): self
{
$this->cart = $cart;
return $this;
}
/**
* @Serializer\VirtualProperty()
*
* @Expose
* @Groups ({"get:read"})
* @SerializedName ("shipping_method")
*/
public function getApiShippingMethod()
{
return $this->shippingMethod;
}
/**
* @param string|null $type slug de pointTransactionType
* @return Collection|PointTransaction[]
*/
public function getPointTransactions(?string $type = null): Collection
{
if($type === null) return $this->pointTransactions;
return $this->pointTransactions->filter(function ($pointTransaction) use ($type) {
return $pointTransaction->getTransactionType(true) === $type;
});
}
public function addPointTransaction(PointTransaction $pointTransaction): self
{
if(!$this->pointTransactions->contains($pointTransaction))
{
$this->pointTransactions[] = $pointTransaction;
if($pointTransaction->getSaleOrder() !== $this) $pointTransaction->setSaleOrder($this);
}
return $this;
}
public function removePointTransaction(PointTransaction $pointTransaction): self
{
if($this->pointTransactions->removeElement($pointTransaction) && $pointTransaction->getSaleOrder() === $this)
{
$pointTransaction->setSaleOrder(null);
}
return $this;
}
public function getOldId(): ?int
{
return $this->oldId;
}
public function setOldId(?int $oldId): self
{
$this->oldId = $oldId;
return $this;
}
public function getInvoice(): ?SaleOrderInvoice
{
return $this->invoice;
}
public function setInvoice(?SaleOrderInvoice $invoice): self
{
$this->invoice = $invoice;
return $this;
}
public function getCategoryValues(): ?string
{
return $this->categoryValues;
}
public function setCategoryValues(?string $categoryValues): self
{
$this->categoryValues = $categoryValues;
return $this;
}
public function getFeesCategoryValues(): ?string
{
return $this->feesCategoryValues;
}
public function setFeesCategoryValues(?string $feesCategoryValues): self
{
$this->feesCategoryValues = $feesCategoryValues;
return $this;
}
public function getCustomQuestion(): ?string
{
return $this->customQuestion;
}
public function setCustomQuestion(?string $customQuestion): self
{
$this->customQuestion = $customQuestion;
return $this;
}
public function getOrderRate(): float
{
return $this->orderRate ?? 1;
}
public function setOrderRate(float $orderRate): self
{
$this->orderRate = $orderRate;
return $this;
}
public function isIsTrip(): ?bool
{
return $this->isTrip;
}
public function setIsTrip(bool $isTrip): self
{
$this->isTrip = $isTrip;
return $this;
}
public function getOrderExtraData(): ?string
{
return $this->orderExtraData;
}
public function setOrderExtraData(?string $orderExtraData): self
{
$this->orderExtraData = $orderExtraData;
return $this;
}
public function getUpdateFromBo(): ?bool
{
return $this->updateFromBo;
}
public function setUpdateFromBo(bool $updateFromBo): self
{
$this->updateFromBo = $updateFromBo;
return $this;
}
/**
* @return Collection<int, Invoice>
*/
public function getInvoices(): Collection
{
return $this->invoices;
}
public function addInvoice(Invoice $invoice): self
{
if (!$this->invoices->contains($invoice)) {
$this->invoices[] = $invoice;
$invoice->setSaleOrder($this);
}
return $this;
}
public function removeInvoice(Invoice $invoice): self
{
if ($this->invoices->removeElement($invoice)) {
// set the owning side to null (unless already changed)
if ($invoice->getSaleOrder() === $this) {
$invoice->setSaleOrder(null);
}
}
return $this;
}
/**
* @return string|null
*/
public function getWaitingStatus(): ?string
{
return $this->waitingStatus;
}
/**
* @param string|null $waitingStatus
*
* @return SaleOrder
*/
public function setWaitingStatus(?string $waitingStatus): SaleOrder
{
$this->waitingStatus = $waitingStatus;
return $this;
}
/**
* @return bool
*/
public function isWaitingPaiement(): bool
{
return $this->status === SaleOrderConstant::STATUS_WAITING_PAYMENT || $this->status === SaleOrderConstant::STATUS_PENDING_WAITING_PAYMENT;
}
/**
* @return bool
*/
public function isCanceled(): bool
{
return $this->status === SaleOrderConstant::STATUS_CANCELED;
}
/**
* @return bool
*/
public function isShipped(): bool
{
return $this->status === SaleOrderConstant::STATUS_SHIPPED;
}
}