<?php
namespace Roothirsch\ShopBundle\Entity;
use ApiPlatform\Core\Annotation\ApiFilter;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
use \ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\OrderFilter;
use Roothirsch\CoreBundle\Behaviors\Attributable\Attribute\AttributeInterface;
use Roothirsch\CoreBundle\Behaviors\Attributable\AttributeValue\AttributeValueAwareInterface;
use Roothirsch\CoreBundle\Behaviors\Attributable\AttributeValue\AttributeValueAwareTrait;
use Roothirsch\CoreBundle\Behaviors\Attributable\AttributeValue\AttributeValueInterface;
use Roothirsch\CoreBundle\Behaviors\Attributable\MappedSuperclass\AbstractAttributable;
use Roothirsch\CoreBundle\Entity\Traits\TimetrackedTrait;
use Roothirsch\CoreBundle\UserAware\UserAwareInterface;
use Roothirsch\CoreBundle\UserAware\UserAwareTrait;
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\Serializer\Annotation\Groups;
use Roothirsch\ShopBundle\Entity\Estimate\EstimateAttribute;
use Roothirsch\ShopBundle\Entity\Estimate\EstimateAttributeValue;
use Roothirsch\ShopBundle\Entity\Order\OrderAttributeValue;
use Symfony\Component\Serializer\Annotation\SerializedName;
/**
* @ORM\Entity(repositoryClass="Roothirsch\ShopBundle\Repository\OrderRepository")
* @ORM\Table(name="shop_order")
* @ApiResource(
* normalizationContext={"groups"={"list"}, "enable_max_depth"=true},
* denormalizationContext={"groups"={"list"}},
* shortName="Shop/Order",
* itemOperations={
* "get",
* "put",
* "delete"
* },
* collectionOperations={
* "duplicate"={"method"="POST", "path"="/orders/{id}/duplicate", "requirements"={"id"=".+"}},
* "get",
* "post"
* }
* )
* @ApiFilter(OrderFilter::class, properties={"createdAt", "orderedAt"}, arguments={"orderParameterName"="order"})
* @ApiFilter(SearchFilter::class, properties={
* "state": "exact",
* "type": "exact"
* })
*/
class Order extends AbstractAttributable implements UserAwareInterface
{
use UserAwareTrait;
use TimetrackedTrait;
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
* @Groups({"list"})
*/
private $state = 'cart';
/**
* @ORM\Column(type="string", length=255, nullable=true)
* @Groups({"list"})
*/
private $name;
/**
* @ORM\Column(type="string", length=255, options={"default" : "configurator"})
* @Groups({"list"})
*/
private $type = 'configurator';
/**
* @ORM\OneToMany(targetEntity=OrderPosition::class, mappedBy="order", orphanRemoval=true, cascade={"persist"})
* @Groups({"list"})
*/
private $positions;
/**
* @ORM\Column(type="boolean")
* @Groups({"list"})
*/
private $applyDiscount = true;
/**
* @ORM\Column(type="boolean")
* @Groups({"list"})
*/
private $applyMwst = false;
/**
* @ORM\Column(type="string", nullable=true)
* @Groups({"list"})
*/
private $comment;
/**
* @var \DateTime
* @ORM\Column(type="datetime", nullable=true)
* @Groups({"list"})
*/
private $orderedAt;
/**
* @ORM\OneToMany(targetEntity=OrderAttributeValue::class, mappedBy="order", orphanRemoval=true, cascade={"persist"})
*/
private $attributeValues;
public function __construct()
{
$this->positions = new ArrayCollection();
$this->attributeValues = new ArrayCollection();
}
public function __clone() {
$this->id = null;
$this->setCreatedAt(new \DateTime());
$this->setUpdatedAt(new \DateTime());
$this->orderedAt = null;
$oldPositions = $this->positions;
$this->positions = new ArrayCollection();
foreach($oldPositions as $oldPosition) {
$this->addPosition(clone $oldPosition);
}
$oldAttributeValues = $this->attributeValues;
$this->attributeValues = new ArrayCollection();
foreach($oldAttributeValues as $oldAttributeValue) {
$this->addAttributeValue(clone $oldAttributeValue);
}
}
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @param mixed $id
*/
public function setId($id)
{
$this->id = $id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(?string $name): self
{
$this->name = $name;
return $this;
}
public function getAttributes()
{
return $this->attributes;
}
/**
* @return Collection|OrderPosition[]
*/
public function getPositions(): Collection
{
return $this->positions;
}
public function addPosition(OrderPosition $position): self
{
if (!$this->positions->contains($position)) {
$this->positions[] = $position;
$position->setOrder($this);
}
return $this;
}
public function removePosition(OrderPosition $position): self
{
if ($this->positions->removeElement($position)) {
// set the owning side to null (unless already changed)
if ($position->getOrder() === $this) {
$position->setOrder(null);
}
}
return $this;
}
/**
* @return bool
*/
public function isApplyDiscount(): bool
{
return $this->applyDiscount;
}
/**
* @param bool $applyDiscount
*/
public function setApplyDiscount(bool $applyDiscount): void
{
$this->applyDiscount = $applyDiscount;
}
/**
* @return bool
*/
public function isApplyMwst(): bool
{
return $this->applyMwst;
}
/**
* @param bool $applyMwst
*/
public function setApplyMwst(bool $applyMwst): void
{
$this->applyMwst = $applyMwst;
}
/**
* @return mixed
*/
public function getComment()
{
return $this->comment;
}
/**
* @param mixed $comment
*/
public function setComment($comment): void
{
$this->comment = $comment;
}
/**
* @return \DateTime
*/
public function getOrderedAt(): ?\DateTime
{
return $this->orderedAt;
}
/**
* @param \DateTime $orderedAt
*/
public function setOrderedAt(\DateTime $orderedAt): void
{
$this->orderedAt = $orderedAt;
}
/**
* @return mixed
*/
public function getState()
{
return $this->state;
}
/**
* @param mixed $state
*/
public function setState($state): void
{
$this->state = $state;
}
/**
* @Groups({"list"})
* @SerializedName("total")
* @return int|null
*/
public function getTotal(): int
{
$total = 0;
foreach ($this->positions as $position) {
if ($position->getState() == 'draft') {
continue;
}
$total += $position->getTotalWithTax();
}
return $total;
}
public function getArticleCount()
{
$total = 0;
/** @var OrderPosition $position */
foreach ($this->positions as $position) {
if ($position->getState() == 'added') {
foreach ($position->getArticles() as $article) {
$total += $article['amount'];
}
}
}
return $total;
}
public function newValue(AttributeInterface $attribute): AttributeValueInterface
{
return new OrderAttributeValue($attribute);
}
/**
* @Groups({"list"})
* @SerializedName("tax")
* @return string|null
*/
public function getTax()
{
if(!$this->isApplyMwst()){
return 1;
}
/** @var EstimateAttribute $tax */
$taxAttribute = $this->getAttribute('tax');
if(!$taxAttribute){
return 1;
}
/** @var EstimateAttributeValue $value */
$value = $this->getAttributeValue($taxAttribute);
$tax = $value->getValue();
if(!is_float($tax)){
$tax = floatval($tax);
}
return (100 + $tax) / 100;
}
public function getTotalPriceBrutto()
{
return $total / 100 * (100 + $tax);
}
public function setAttributeValues(Collection $attributeValues): AttributeValueAwareInterface
{
$this->attributeValues = $attributeValues;
return $this;
}
/**
* @return Collection|EstimateAttributeValue []
*/
public function getAttributeValues(): Collection
{
return $this->attributeValues;
}
public function getHighlightedDiscounts() {
$discounts = [];
/** @var EstimatePosition $position */
foreach($this->positions as $position) {
foreach($position->getDiscounts() as $discount) {
if (isset($discount['highlight']) && $discount['highlight'] == true) {
if (!isset($discounts[$discount['description']])) {
$discounts[$discount['description']] = $discount;
} else {
$discounts[$discount['description']]['total'] += $discount['total'];
}
}
}
}
return $discounts;
}
public function isAllPositionsValid(){
return $this->getPositions()->filter(function($position){
return $position->isPositionInvalid();
})->count() === 0;
}
/**
* @return mixed
*/
public function getType()
{
return $this->type;
}
/**
* @param mixed $type
*/
public function setType($type): void
{
$this->type = $type;
}
}