src/Domain/Product/Model/Product.php line 22

Open in your IDE?
  1. <?php
  2. namespace Whater\Domain\Product\Model;
  3. use BornFree\TacticianDomainEvent\Recorder\ContainsRecordedEvents;
  4. use BornFree\TacticianDomainEvent\Recorder\EventRecorderCapabilities;
  5. use Ramsey\Uuid\Uuid;
  6. use Whater\Domain\Common\Exception\InvalidUUIDException;
  7. use Whater\Domain\User\Model\User;
  8. use Whater\Domain\Whater\Model\WhaterOrganization;
  9. use Whater\Domain\Whater\Model\WhaterPoint;
  10. use Doctrine\Common\Collections\ArrayCollection;
  11. use Doctrine\Common\Collections\Collection;
  12. use Whater\Domain\Product\Exception\InvalidProductShippingException;
  13. use Whater\Domain\Product\Exception\InvalidProductTypeException;
  14. /**
  15. * Class Product
  16. *
  17. * @package Whater\Domain\Product\Model
  18. */
  19. class Product implements ContainsRecordedEvents
  20. {
  21. use EventRecorderCapabilities;
  22. public const PRODUCT_TYPE_WATER_SUPPLY = "PT_WATER_SUPPLY";
  23. public const PRODUCT_TYPE_CATALOG = "PT_CATALOG";
  24. public const PRODUCT_TYPE_WATERCOINS = "PT_WATERCOINS";
  25. public const PRODUCT_TYPE_LICENSE = "PT_LICENSE";
  26. public const PRODUCT_TYPE_DISCOUNT = "PT_DISCOUNT";
  27. /**
  28. * @var string
  29. */
  30. private $uuid;
  31. /**
  32. * @var string
  33. */
  34. private $productLabel;
  35. /**
  36. * @var string
  37. */
  38. private $productSlug;
  39. /**
  40. * @var string
  41. */
  42. private $productShortDescription;
  43. /**
  44. * @var string
  45. */
  46. private $productDescription;
  47. /**
  48. * @var string
  49. */
  50. private $productType;
  51. /**
  52. * @var float
  53. */
  54. private $productPrice;
  55. /**
  56. * @var float
  57. */
  58. private $productVatPercent;
  59. /**
  60. * @var bool
  61. */
  62. private $isEnable;
  63. /**
  64. * @var bool
  65. */
  66. private $isShippable;
  67. /**
  68. * @var float
  69. */
  70. private $productWeight;
  71. /**
  72. * @var string
  73. */
  74. private $productLength;
  75. /**
  76. * @var string
  77. */
  78. private $productWidth;
  79. /**
  80. * @var string
  81. */
  82. private $productHeight;
  83. /**
  84. * @var WhaterPoint
  85. */
  86. private $whaterPoint;
  87. /**
  88. * @var WhaterOrganization
  89. */
  90. private $whaterOrganization;
  91. /**
  92. * @var boolean
  93. */
  94. private $isInternalProduct;
  95. /**
  96. * @var boolean
  97. */
  98. private $acceptWhatercoins;
  99. /**
  100. * @var \DateTime
  101. */
  102. private $createdAt;
  103. /**
  104. * @var null|\DateTime
  105. */
  106. private $updatedAt;
  107. /**
  108. * @var Collection
  109. */
  110. private $images;
  111. /**
  112. * @var Collection
  113. */
  114. private $productVariations;
  115. /**
  116. * @var Collection
  117. */
  118. private $productAttributes;
  119. /**
  120. * @var array
  121. */
  122. private $tags;
  123. /**
  124. * @var ProductCategory
  125. */
  126. private $productCategory;
  127. /**
  128. * @var float
  129. */
  130. private $whaterCommisionPercent;
  131. /**
  132. * @var Collection
  133. */
  134. private $countriesToRecommend;
  135. /**
  136. * @var Collection
  137. */
  138. private $countryAreasToRecommend;
  139. /**
  140. * @var bool
  141. */
  142. private $recommendToWaterStatusSuitable;
  143. /**
  144. * @var bool
  145. */
  146. private $recommendToWaterStatusNotSuitable;
  147. /**
  148. * @var bool
  149. */
  150. private $recommendToWaterStatusWithRestrictions;
  151. /**
  152. * @var bool
  153. */
  154. private $recommendToWaterStatusUnknown;
  155. /**
  156. * @var int
  157. */
  158. private $maxDiscountPercentageAllowed;
  159. /**
  160. * @var bool
  161. */
  162. private $requiresShippingCosts;
  163. /**
  164. * @var string
  165. */
  166. private $theThingsNetworkDeviceName;
  167. /**
  168. * @var int
  169. */
  170. private $whaterSupplyMiliseconds;
  171. /**
  172. * @var Collection
  173. */
  174. private $valorations;
  175. /**
  176. * @var float
  177. */
  178. private $averageValorations;
  179. /**
  180. * @param string $productId
  181. */
  182. public function __construct(
  183. string $productId = null,
  184. string $productLabel,
  185. string $productType,
  186. float $productPrice,
  187. float $productVatPercent,
  188. WhaterOrganization $whaterOrganization = null,
  189. string $productShortDescription = null,
  190. string $productDescription = null,
  191. WhaterPoint $whaterPoint = null,
  192. bool $isInternalProduct = false,
  193. float $whaterCommisionPercent = null
  194. ) {
  195. try {
  196. $this->uuid = Uuid::fromString($productId ?: Uuid::uuid4())->toString();
  197. } catch (\InvalidArgumentException $e) {
  198. throw new InvalidUUIDException();
  199. }
  200. $this->productLabel = $productLabel;
  201. $this->productSlug = $productLabel;
  202. $this->productShortDescription = $productShortDescription;
  203. $this->productDescription = $productDescription;
  204. switch ($productType) {
  205. case Product::PRODUCT_TYPE_CATALOG:
  206. case Product::PRODUCT_TYPE_DISCOUNT:
  207. case Product::PRODUCT_TYPE_LICENSE:
  208. case Product::PRODUCT_TYPE_WATER_SUPPLY:
  209. case Product::PRODUCT_TYPE_WATERCOINS:
  210. $this->productType = $productType;
  211. break;
  212. default:
  213. throw new InvalidProductTypeException();
  214. }
  215. $this->productPrice = $productPrice;
  216. $this->productVatPercent = $productVatPercent;
  217. $this->whaterCommisionPercent = $whaterCommisionPercent;
  218. $this->isEnable = false;
  219. $this->isShippable = ($this->productType == Product::PRODUCT_TYPE_CATALOG);
  220. $this->recommendToWaterStatusSuitable = false;
  221. $this->recommendToWaterStatusNotSuitable = false;
  222. $this->recommendToWaterStatusWithRestrictions = false;
  223. $this->recommendToWaterStatusUnknown = false;
  224. $this->isInternalProduct = $isInternalProduct;
  225. $this->whaterOrganization = $whaterOrganization;
  226. if ($productType == Product::PRODUCT_TYPE_WATER_SUPPLY) {
  227. $this->whaterPoint = $whaterPoint;
  228. $this->acceptWhatercoins = true;
  229. } else {
  230. $this->acceptWhatercoins = false;
  231. }
  232. if (!$isInternalProduct && $whaterOrganization == null) {
  233. throw new InvalidUUIDException();
  234. }
  235. $this->maxDiscountPercentageAllowed = 0;
  236. $this->requiresShippingCosts = false;
  237. $this->createdAt = new \DateTime();
  238. $this->updatedAt = new \DateTime();
  239. $this->images = new ArrayCollection();
  240. $this->productVariations = new ArrayCollection();
  241. $this->productAttributes = new ArrayCollection();
  242. $this->countriesToRecommend = new ArrayCollection();
  243. $this->countryAreasToRecommend = new ArrayCollection();
  244. $this->valorations = new ArrayCollection();
  245. $this->averageValorations = null;
  246. }
  247. public function editProduct(
  248. string $productLabel,
  249. float $productPrice,
  250. float $productVatPercent,
  251. string $productShortDescription = null,
  252. string $productDescription = null,
  253. bool $isEnable = false,
  254. bool $acceptWhatercoins = false,
  255. float $whaterCommisionPercent = null,
  256. array $tags = null,
  257. ProductCategory $productCategory = null,
  258. bool $recommendToWaterStatusSuitable = false,
  259. bool $recommendToWaterStatusNotSuitable = false,
  260. bool $recommendToWaterStatusWithRestrictions = false,
  261. bool $recommendToWaterStatusUnknown = false,
  262. int $maxDiscountPercentageAllowed = null
  263. ) {
  264. $this->productLabel = $productLabel;
  265. $this->productShortDescription = $productShortDescription;
  266. $this->productDescription = $productDescription;
  267. $this->productPrice = $productPrice;
  268. $this->productVatPercent = $productVatPercent;
  269. $this->whaterCommisionPercent = $whaterCommisionPercent;
  270. $this->acceptWhatercoins = $acceptWhatercoins;
  271. $this->isEnable = $isEnable;
  272. $this->tags = $tags;
  273. $this->productCategory = $productCategory;
  274. $this->recommendToWaterStatusSuitable = $recommendToWaterStatusSuitable;
  275. $this->recommendToWaterStatusNotSuitable = $recommendToWaterStatusNotSuitable;
  276. $this->recommendToWaterStatusWithRestrictions = $recommendToWaterStatusWithRestrictions;
  277. $this->recommendToWaterStatusUnknown = $recommendToWaterStatusUnknown;
  278. $this->maxDiscountPercentageAllowed = $maxDiscountPercentageAllowed;
  279. $this->updatedAt = new \DateTime();
  280. }
  281. public function editShipmentData(
  282. bool $isShippable = false,
  283. bool $requiresShippingCosts = false,
  284. float $productWeight = null,
  285. float $productLength = null,
  286. float $productWidth = null,
  287. float $productHeight = null
  288. ) {
  289. if ($this->productType() == Product::PRODUCT_TYPE_CATALOG) {
  290. $this->isShippable = $isShippable;
  291. } else {
  292. $this->isShippable = false;
  293. }
  294. $this->requiresShippingCosts = $requiresShippingCosts;
  295. $this->productWeight = $productWeight;
  296. $this->productLength = $productLength;
  297. $this->productWidth = $productWidth;
  298. $this->productHeight = $productHeight;
  299. if ($this->isShippable) {
  300. $this->productWeight = $this->productWeight ?? 1;
  301. $this->productLength = $this->productLength ?? 1;
  302. $this->productWidth = $this->productWidth ?? 1;
  303. $this->productHeight = $this->productHeight ?? 1;
  304. }
  305. }
  306. public function editWhaterSupply(
  307. string $theThingsNetworkDeviceName = null,
  308. int $whaterSupplyMiliseconds = null
  309. ) {
  310. if ($this->productType == Product::PRODUCT_TYPE_WATER_SUPPLY) {
  311. $this->theThingsNetworkDeviceName = $theThingsNetworkDeviceName;
  312. $this->whaterSupplyMiliseconds = $whaterSupplyMiliseconds;
  313. if ($whaterSupplyMiliseconds < 10) {
  314. $this->whaterSupplyMiliseconds = 10;
  315. }
  316. }
  317. }
  318. public function editZonesToRecommend(
  319. ArrayCollection $countriesToRecommend,
  320. ArrayCollection $countryAreasToRecommend
  321. ) {
  322. $this->countriesToRecommend()->clear();
  323. foreach ($countriesToRecommend as $country) {
  324. $this->countriesToRecommend->add($country);
  325. }
  326. $this->countryAreasToRecommend()->clear();
  327. foreach ($countryAreasToRecommend as $countryArea) {
  328. $this->countryAreasToRecommend->add($countryArea);
  329. }
  330. $this->updatedAt = new \DateTime();
  331. }
  332. public function updateAverageValorations()
  333. {
  334. $numValorations = 0;
  335. $sumValorations = 0;
  336. foreach ($this->valorations() as $valoration) {
  337. $numValorations++;
  338. $sumValorations = $sumValorations + $valoration->rating();
  339. }
  340. if ($numValorations == 0) {
  341. $this->averageValorations = null;
  342. } else {
  343. $this->averageValorations = round($sumValorations / $numValorations, 2);
  344. }
  345. }
  346. /**
  347. * @deprecated
  348. */
  349. public function calculateWhatercoinsForDiscount(float $discountPercent, string $productVariationId = null)
  350. {
  351. $productPrice = $this->productPrice();
  352. if ($productVariationId != null) {
  353. foreach ($this->productVariations() as $productVariation) {
  354. if ($productVariation->id() == $productVariationId) {
  355. $productPrice = $productVariation->productVariationPrice();
  356. break;
  357. }
  358. }
  359. }
  360. $discountInMoney = ($productPrice * $discountPercent / 100);
  361. $discountInWhatercoins = $discountInMoney * 100;
  362. if ($productPrice > 200) {
  363. $realDiscount = 0.9;
  364. } else if ($productPrice > 100) {
  365. $realDiscount = 0.85;
  366. } else if ($productPrice > 50) {
  367. $realDiscount = 0.8;
  368. } else {
  369. $realDiscount = 0.75;
  370. }
  371. return round($discountInWhatercoins * $realDiscount, 2);
  372. }
  373. public function setAsInternalProduct(
  374. bool $isInternalProduct
  375. ) {
  376. $this->isInternalProduct = $isInternalProduct;
  377. }
  378. public function firstImage()
  379. {
  380. $firstImage = null;
  381. foreach ($this->images() as $productImage) {
  382. $firstImage = $productImage;
  383. break;
  384. }
  385. return $firstImage;
  386. }
  387. /**
  388. * @return string
  389. */
  390. public function id(): string
  391. {
  392. return $this->uuid;
  393. }
  394. /**
  395. * @return string
  396. */
  397. public function productLabel(): string
  398. {
  399. return $this->productLabel;
  400. }
  401. /**
  402. * @return string
  403. */
  404. public function productSlug(): string
  405. {
  406. return $this->productSlug;
  407. }
  408. /**
  409. * @return string
  410. */
  411. public function theThingsNetworkDeviceName(): ?string
  412. {
  413. return $this->theThingsNetworkDeviceName;
  414. }
  415. /**
  416. * @return int
  417. */ public function whaterSupplyMiliseconds(): ?int
  418. {
  419. return $this->whaterSupplyMiliseconds;
  420. }
  421. /**
  422. * @return bool
  423. */
  424. public function isEnable(): bool
  425. {
  426. return $this->isEnable;
  427. }
  428. /**
  429. * @return bool
  430. */
  431. public function isShippable(): bool
  432. {
  433. return $this->isShippable;
  434. }
  435. /**
  436. * @return float
  437. */
  438. public function productWeight(): ?float
  439. {
  440. return $this->productWeight;
  441. }
  442. /**
  443. * @return float
  444. */
  445. public function productLength(): ?float
  446. {
  447. return $this->productLength;
  448. }
  449. /**
  450. * @return float
  451. */
  452. public function productWidth(): ?float
  453. {
  454. return $this->productWidth;
  455. }
  456. /**
  457. * @return float
  458. */
  459. public function productHeight(): ?float
  460. {
  461. return $this->productHeight;
  462. }
  463. /**
  464. * @return bool
  465. */
  466. public function acceptWhatercoins(): bool
  467. {
  468. return $this->acceptWhatercoins;
  469. }
  470. /**
  471. * @return float
  472. */
  473. public function averageValorations(): ?float
  474. {
  475. return $this->averageValorations;
  476. }
  477. /**
  478. * @return string
  479. */
  480. public function productShortDescription(): ?string
  481. {
  482. return $this->productShortDescription;
  483. }
  484. /**
  485. * @return string
  486. */
  487. public function productDescription(): ?string
  488. {
  489. return $this->productDescription;
  490. }
  491. /**
  492. * @return string
  493. */
  494. public function productType(): string
  495. {
  496. return $this->productType;
  497. }
  498. /**
  499. * @return float
  500. */
  501. public function productPrice(): float
  502. {
  503. return $this->productPrice;
  504. }
  505. /**
  506. * @return float
  507. */
  508. public function productVatPercent(): float
  509. {
  510. return $this->productVatPercent;
  511. }
  512. /**
  513. * @return float
  514. */
  515. public function whaterCommisionPercent(): float
  516. {
  517. return $this->whaterCommisionPercent;
  518. }
  519. /**
  520. * @return WhaterOrganization|null
  521. */
  522. public function whaterOrganization(): ?WhaterOrganization
  523. {
  524. return $this->whaterOrganization;
  525. }
  526. /**
  527. * @return bool
  528. */
  529. public function isInternalProduct(): bool
  530. {
  531. return $this->isInternalProduct;
  532. }
  533. /**
  534. * @return WhaterPoint|null
  535. */
  536. public function whaterPoint(): ?WhaterPoint
  537. {
  538. return $this->whaterPoint;
  539. }
  540. /**
  541. * @return \DateTime
  542. */
  543. public function createdAt(): \DateTime
  544. {
  545. return $this->createdAt;
  546. }
  547. /**
  548. * @return \DateTime|null
  549. */
  550. public function updatedAt()
  551. {
  552. return $this->updatedAt;
  553. }
  554. public function images(): Collection
  555. {
  556. return $this->images;
  557. }
  558. public function productAttributes(): Collection
  559. {
  560. return $this->productAttributes;
  561. }
  562. public function productVariations(): Collection
  563. {
  564. return $this->productVariations;
  565. }
  566. public function countriesToRecommend(): Collection
  567. {
  568. return $this->countriesToRecommend;
  569. }
  570. public function countryAreasToRecommend(): Collection
  571. {
  572. return $this->countryAreasToRecommend;
  573. }
  574. public function tags(): ?array
  575. {
  576. return $this->tags;
  577. }
  578. public function productCategory(): ?ProductCategory
  579. {
  580. return $this->productCategory;
  581. }
  582. /**
  583. * @return bool
  584. */
  585. public function recommendToWaterStatusSuitable(): bool
  586. {
  587. return $this->recommendToWaterStatusSuitable;
  588. }
  589. /**
  590. * @return bool
  591. */
  592. public function recommendToWaterStatusNotSuitable(): bool
  593. {
  594. return $this->recommendToWaterStatusNotSuitable;
  595. }
  596. /**
  597. * @return bool
  598. */
  599. public function recommendToWaterStatusWithRestrictions(): bool
  600. {
  601. return $this->recommendToWaterStatusWithRestrictions;
  602. }
  603. /**
  604. * @return bool
  605. */
  606. public function recommendToWaterStatusUnknown(): bool
  607. {
  608. return $this->recommendToWaterStatusUnknown;
  609. }
  610. /**
  611. * @return int
  612. */
  613. public function maxDiscountPercentageAllowed(): int
  614. {
  615. return $this->maxDiscountPercentageAllowed;
  616. }
  617. /**
  618. * @return bool
  619. */
  620. public function requiresShippingCosts(): bool
  621. {
  622. return $this->requiresShippingCosts;
  623. }
  624. /**
  625. * @return Collection
  626. */
  627. public function valorations(): Collection
  628. {
  629. return $this->valorations;
  630. }
  631. /**
  632. * @return bool
  633. */
  634. public function equals(Product $product)
  635. {
  636. return $this->id() === $product->id();
  637. }
  638. }