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

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