vendor/roothirsch/shop-bundle/Entity/Order.php line 81

Open in your IDE?
  1. <?php
  2. namespace Roothirsch\ShopBundle\Entity;
  3. use ApiPlatform\Core\Annotation\ApiFilter;
  4. use ApiPlatform\Core\Annotation\ApiResource;
  5. use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
  6. use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\OrderFilter;
  7. use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\ExistsFilter;
  8. use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\NumericFilter;
  9. use Roothirsch\CoreBundle\Behaviors\Attributable\Attribute\AttributeInterface;
  10. use Roothirsch\CoreBundle\Behaviors\Attributable\AttributeValue\AttributeValueAwareInterface;
  11. use Roothirsch\CoreBundle\Behaviors\Attributable\AttributeValue\AttributeValueAwareTrait;
  12. use Roothirsch\CoreBundle\Behaviors\Attributable\AttributeValue\AttributeValueInterface;
  13. use Roothirsch\CoreBundle\Behaviors\Attributable\MappedSuperclass\AbstractAttributable;
  14. use Roothirsch\CoreBundle\Entity\Traits\TimetrackedTrait;
  15. use Roothirsch\CoreBundle\UserAware\UserAwareInterface;
  16. use Roothirsch\CoreBundle\UserAware\UserAwareTrait;
  17. use Doctrine\Common\Collections\ArrayCollection;
  18. use Doctrine\Common\Collections\Collection;
  19. use Doctrine\ORM\Mapping as ORM;
  20. use Gedmo\Mapping\Annotation as Gedmo;
  21. use Symfony\Component\Serializer\Annotation\Groups;
  22. use Roothirsch\ShopBundle\Entity\Estimate\EstimateAttribute;
  23. use Roothirsch\ShopBundle\Entity\Estimate\EstimateAttributeValue;
  24. use Roothirsch\ShopBundle\Entity\Order\OrderAttributeValue;
  25. use Roothirsch\ShopBundle\API\Filter\HasPositionsFilter;
  26. use Symfony\Component\Serializer\Annotation\SerializedName;
  27. /**
  28. * @ORM\Entity(repositoryClass="Roothirsch\ShopBundle\Repository\OrderRepository")
  29. * @ORM\Table(name="shop_order")
  30. * @ApiResource(
  31. * normalizationContext={"groups"={"list"}, "enable_max_depth"=true},
  32. * denormalizationContext={"groups"={"list"}},
  33. * shortName="Shop/Order",
  34. * itemOperations={
  35. * "get",
  36. * "put",
  37. * "delete"
  38. * },
  39. * collectionOperations={
  40. * "duplicate"={"method"="POST", "path"="/orders/{id}/duplicate", "requirements"={"id"=".+"}},
  41. * "get",
  42. * "post"
  43. * }
  44. * )
  45. * @ApiFilter(Roothirsch\ShopBundle\API\Filter\AttributeOrderFilter::class, properties={
  46. * "createdAt",
  47. * "orderedAt",
  48. * "totalPrice",
  49. * "total",
  50. * "name",
  51. * "comment",
  52. * "id",
  53. * "state",
  54. * "type",
  55. * "applyMwst",
  56. * "attributes.reference",
  57. * "attributes.customer",
  58. * "attributes.address",
  59. * "attributes.contactPerson",
  60. * "attributes.comission",
  61. * "attributes.deliveryDate"
  62. * }, arguments={"orderParameterName"="order"})
  63. * @ApiFilter(SearchFilter::class, properties={
  64. * "state": "exact",
  65. * "type": "exact",
  66. * "id": "exact",
  67. * "name": "partial",
  68. * "comment": "partial",
  69. * "attributes.reference": "partial",
  70. * "attributes.customer": "partial",
  71. * "attributes.address": "partial",
  72. * "attributes.contactPerson": "partial",
  73. * "attributes.tax": "exact"
  74. * })
  75. * @ApiFilter(NumericFilter::class, properties={"totalPrice", "total"})
  76. * @ApiFilter(HasPositionsFilter::class)
  77. */
  78. class Order extends AbstractAttributable implements UserAwareInterface
  79. {
  80. use UserAwareTrait;
  81. use TimetrackedTrait;
  82. /**
  83. * @ORM\Id
  84. * @ORM\GeneratedValue
  85. * @ORM\Column(type="integer")
  86. * @Groups({"list"})
  87. */
  88. private $id;
  89. /**
  90. * @ORM\Column(type="string", length=255)
  91. * @Groups({"list"})
  92. */
  93. private $state = 'cart';
  94. /**
  95. * @ORM\Column(type="string", length=255, nullable=true)
  96. * @Groups({"list"})
  97. */
  98. private $name;
  99. /**
  100. * @ORM\Column(type="string", length=255, options={"default" : "configurator"})
  101. * @Groups({"list"})
  102. */
  103. private $type = 'configurator';
  104. /**
  105. * @ORM\OneToMany(targetEntity=OrderPosition::class, mappedBy="order", orphanRemoval=true, cascade={"persist"})
  106. * @Groups({"list"})
  107. */
  108. private $positions;
  109. /**
  110. * @ORM\Column(type="boolean")
  111. * @Groups({"list"})
  112. */
  113. private $applyDiscount = true;
  114. /**
  115. * @ORM\Column(type="boolean")
  116. * @Groups({"list"})
  117. */
  118. private $applyMwst = false;
  119. /**
  120. * @ORM\Column(type="string", nullable=true)
  121. * @Groups({"list"})
  122. */
  123. private $comment;
  124. /**
  125. * @var \DateTime
  126. * @ORM\Column(type="datetime", nullable=true)
  127. * @Groups({"list"})
  128. */
  129. private $orderedAt;
  130. /**
  131. * @ORM\OneToMany(targetEntity=OrderAttributeValue::class, mappedBy="order", orphanRemoval=true, cascade={"persist"})
  132. */
  133. private $attributeValues;
  134. public function __construct()
  135. {
  136. $this->positions = new ArrayCollection();
  137. $this->attributeValues = new ArrayCollection();
  138. }
  139. public function __clone() {
  140. $this->id = null;
  141. $this->setCreatedAt(new \DateTime());
  142. $this->setUpdatedAt(new \DateTime());
  143. $this->orderedAt = null;
  144. $oldPositions = $this->positions;
  145. $this->positions = new ArrayCollection();
  146. foreach($oldPositions as $oldPosition) {
  147. $this->addPosition(clone $oldPosition);
  148. }
  149. $oldAttributeValues = $this->attributeValues;
  150. $this->attributeValues = new ArrayCollection();
  151. foreach($oldAttributeValues as $oldAttributeValue) {
  152. $this->addAttributeValue(clone $oldAttributeValue);
  153. }
  154. }
  155. /**
  156. * @return mixed
  157. */
  158. public function getId()
  159. {
  160. return $this->id;
  161. }
  162. /**
  163. * @param mixed $id
  164. */
  165. public function setId($id)
  166. {
  167. $this->id = $id;
  168. }
  169. public function getName(): ?string
  170. {
  171. return $this->name;
  172. }
  173. public function setName(?string $name): self
  174. {
  175. $this->name = $name;
  176. return $this;
  177. }
  178. public function getAttributes()
  179. {
  180. return $this->attributes;
  181. }
  182. /**
  183. * @return Collection|OrderPosition[]
  184. */
  185. public function getPositions(): Collection
  186. {
  187. return $this->positions;
  188. }
  189. public function addPosition(OrderPosition $position): self
  190. {
  191. if (!$this->positions->contains($position)) {
  192. $this->positions[] = $position;
  193. $position->setOrder($this);
  194. }
  195. return $this;
  196. }
  197. public function removePosition(OrderPosition $position): self
  198. {
  199. if ($this->positions->removeElement($position)) {
  200. // set the owning side to null (unless already changed)
  201. if ($position->getOrder() === $this) {
  202. $position->setOrder(null);
  203. }
  204. }
  205. return $this;
  206. }
  207. /**
  208. * @return bool
  209. */
  210. public function isApplyDiscount(): bool
  211. {
  212. return $this->applyDiscount;
  213. }
  214. /**
  215. * @param bool $applyDiscount
  216. */
  217. public function setApplyDiscount(bool $applyDiscount): void
  218. {
  219. $this->applyDiscount = $applyDiscount;
  220. }
  221. /**
  222. * @return bool
  223. */
  224. public function isApplyMwst(): bool
  225. {
  226. return $this->applyMwst;
  227. }
  228. /**
  229. * @param bool $applyMwst
  230. */
  231. public function setApplyMwst(bool $applyMwst): void
  232. {
  233. $this->applyMwst = $applyMwst;
  234. }
  235. /**
  236. * @return mixed
  237. */
  238. public function getComment()
  239. {
  240. return $this->comment;
  241. }
  242. /**
  243. * @param mixed $comment
  244. */
  245. public function setComment($comment): void
  246. {
  247. $this->comment = $comment;
  248. }
  249. /**
  250. * @return \DateTime
  251. */
  252. public function getOrderedAt(): ?\DateTime
  253. {
  254. return $this->orderedAt;
  255. }
  256. /**
  257. * @param \DateTime $orderedAt
  258. */
  259. public function setOrderedAt(\DateTime $orderedAt): void
  260. {
  261. $this->orderedAt = $orderedAt;
  262. }
  263. /**
  264. * @return mixed
  265. */
  266. public function getState()
  267. {
  268. return $this->state;
  269. }
  270. /**
  271. * @param mixed $state
  272. */
  273. public function setState($state): void
  274. {
  275. $this->state = $state;
  276. }
  277. /**
  278. * @Groups({"list"})
  279. * @SerializedName("total")
  280. * @return int|null
  281. */
  282. public function getTotal(): int
  283. {
  284. $total = 0;
  285. foreach ($this->positions as $position) {
  286. if ($position->getState() == 'draft') {
  287. continue;
  288. }
  289. $total += $position->getTotalWithTax();
  290. }
  291. return $total;
  292. }
  293. public function getArticleCount()
  294. {
  295. $total = 0;
  296. /** @var OrderPosition $position */
  297. foreach ($this->positions as $position) {
  298. if ($position->getState() == 'added') {
  299. foreach ($position->getArticles() as $article) {
  300. $total += $article['amount'];
  301. }
  302. }
  303. }
  304. return $total;
  305. }
  306. public function newValue(AttributeInterface $attribute): AttributeValueInterface
  307. {
  308. return new OrderAttributeValue($attribute);
  309. }
  310. /**
  311. * @Groups({"list"})
  312. * @SerializedName("tax")
  313. * @return string|null
  314. */
  315. public function getTax()
  316. {
  317. if(!$this->isApplyMwst()){
  318. return 1;
  319. }
  320. /** @var EstimateAttribute $tax */
  321. $taxAttribute = $this->getAttribute('tax');
  322. if(!$taxAttribute){
  323. return 1;
  324. }
  325. /** @var EstimateAttributeValue $value */
  326. $value = $this->getAttributeValue($taxAttribute);
  327. $tax = $value->getValue();
  328. if(!is_float($tax)){
  329. $tax = floatval($tax);
  330. }
  331. return (100 + $tax) / 100;
  332. }
  333. public function getTotalPriceBrutto()
  334. {
  335. return $total / 100 * (100 + $tax);
  336. }
  337. public function setAttributeValues(Collection $attributeValues): AttributeValueAwareInterface
  338. {
  339. $this->attributeValues = $attributeValues;
  340. return $this;
  341. }
  342. /**
  343. * @return Collection|EstimateAttributeValue []
  344. */
  345. public function getAttributeValues(): Collection
  346. {
  347. return $this->attributeValues;
  348. }
  349. public function getHighlightedDiscounts() {
  350. $discounts = [];
  351. /** @var EstimatePosition $position */
  352. foreach($this->positions as $position) {
  353. foreach($position->getDiscounts() as $discount) {
  354. if (isset($discount['highlight']) && $discount['highlight'] == true) {
  355. if (!isset($discounts[$discount['description']])) {
  356. $discounts[$discount['description']] = $discount;
  357. } else {
  358. $discounts[$discount['description']]['total'] += $discount['total'];
  359. }
  360. }
  361. }
  362. }
  363. return $discounts;
  364. }
  365. public function isAllPositionsValid(){
  366. return $this->getPositions()->filter(function($position){
  367. return $position->isPositionInvalid();
  368. })->count() === 0;
  369. }
  370. /**
  371. * @return mixed
  372. */
  373. public function getType()
  374. {
  375. return $this->type;
  376. }
  377. /**
  378. * @param mixed $type
  379. */
  380. public function setType($type): void
  381. {
  382. $this->type = $type;
  383. }
  384. }