vendor/roothirsch/shop-bundle/Entity/Estimate.php line 75

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