src/Evo/Infrastructure/MappingORM/Subscription.php line 45

Open in your IDE?
  1. <?php
  2. namespace Evo\Infrastructure\MappingORM;
  3. use ApiPlatform\Core\Annotation\ApiFilter;
  4. use ApiPlatform\Core\Annotation\ApiResource;
  5. use ApiPlatform\Core\Annotation\ApiSubresource;
  6. use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
  7. use ApiPlatform\Core\Serializer\Filter\PropertyFilter;
  8. use App\Enum\OrganizationStatusPayedEnum;
  9. use App\Enum\ProductKeyEnum;
  10. use App\Service\SubscriptionUtils;
  11. use App\Validator\Constraints\ServiceConstraint;
  12. use Doctrine\Common\Collections\ArrayCollection;
  13. use Doctrine\Common\Collections\Collection;
  14. use Doctrine\ORM\Mapping as ORM;
  15. use Symfony\Component\Serializer\Annotation\Groups;
  16. /**
  17.  * @ApiResource(
  18.  *     mercure="true",
  19.  *     attributes={
  20.  *          "normalization_context"={"groups"={"read_subscription"}},
  21.  *          "denormalization_context"={"groups"={"write_subscription"}},
  22.  *     },
  23.  *     subresourceOperations={
  24.  *          "api_organizations_subscriptions_get_subresource"={
  25.  *              "method"="GET",
  26.  *              "normalizationContext"={"groups"={"read_subscription"}},
  27.  *          },
  28.  *     },
  29.  *     itemOperations={
  30.  *     "get",
  31.  *     "put",
  32.  *     "delete"={"security"="is_granted('ROLE_ADMIN')"}
  33.  * })
  34.  * @ORM\Entity
  35.  * @ORM\Table(name="subscription")
  36.  * @ORM\Entity(repositoryClass="App\Repository\SubscriptionRepository")
  37.  * @ApiFilter(SearchFilter::class, properties={"organization": "exact", "hasBlockedService": "exact"})
  38.  * @ApiFilter(PropertyFilter::class)
  39.  *
  40.  * @ServiceConstraint
  41.  */
  42. class Subscription
  43. {
  44.     /**
  45.      * @var int The entity Id
  46.      *
  47.      * @ORM\Column(type="integer")
  48.      * @ORM\Id
  49.      * @ORM\GeneratedValue()
  50.      * @Groups({"admin_orga_list", "read_subscription", "read_organization", "read_pack"})
  51.      */
  52.     private ?int $id null;
  53.     /**
  54.      * @var bool The subscription active/inactive
  55.      *
  56.      * @Groups({"read_subscription", "write_subscription", "read_organization", "write_organization"})
  57.      * @ORM\Column(type="boolean")
  58.      */
  59.     private $active;
  60.     /**
  61.      * @Groups({"read_subscription", "write_subscription", "read_organization", "write_organization"})
  62.      * @ORM\Column(type="float", nullable=true)
  63.      */
  64.     private ?float $price null;
  65.     /**
  66.      * @var string The subscription type
  67.      *
  68.      * @Groups({"read_subscription", "write_subscription", "read_organization", "write_organization"})
  69.      * @ORM\Column(type="string", nullable=true)
  70.      */
  71.     private ?string $type null;
  72.     /**
  73.      * @var float The subscription deposit
  74.      *
  75.      * @Groups({"read_subscription", "write_subscription", "read_organization", "write_organization", "read_pack"})
  76.      * @ORM\Column(type="decimal", precision=13, scale=2, nullable=true)
  77.      */
  78.     private $subscriptionDeposit 0;
  79.     /**
  80.      * @var \DateTime
  81.      *
  82.      * @Groups({"read_subscription", "read_organization"})
  83.      * @ORM\Column(name="created_at", type="datetime")
  84.      */
  85.     private $createdAt;
  86.     /**
  87.      * @Groups({"read_subscription", "write_subscription", "read_organization", "write_organization", "read_pack"})
  88.      * @ORM\Column(type="float", nullable=true)
  89.      */
  90.     private $discountWithoutTax;
  91.     /**
  92.      * @Groups({"read_subscription", "write_subscription", "read_organization", "write_organization"})
  93.      * @ORM\Column(type="array", nullable=true)
  94.      */
  95.     private $paymentDates = [];
  96.     /**
  97.      * @Groups({"read_subscription", "write_subscription", "read_organization", "write_organization", "read_pack"})
  98.      * @ORM\Column(type="float", nullable=true)
  99.      */
  100.     private ?float $priceWithoutTax null;
  101.     /**
  102.      * @ORM\Column(type="float", nullable=true)
  103.      */
  104.     private ?float $storedTotalPriceWithoutTax null// used to store the totalPriceWithoutTax to get the first price in changeset on upsell et downsell
  105.     /**
  106.      * @Groups({"read_subscription", "write_subscription"})
  107.      * @ORM\Column(type="boolean", nullable=true)
  108.      */
  109.     private $isUpdatedPrice;
  110.     /**
  111.      * @Groups({"read_subscription", "write_subscription", "read_organization"})
  112.      * @ORM\Column(type="datetime", nullable=true)
  113.      */
  114.     private ?\DateTimeInterface $nextPayment null;
  115.     /**
  116.      * @ORM\Column(type="array", nullable=true)
  117.      */
  118.     private $packHistory = [];
  119.     /**
  120.      * @Groups({"read_subscription", "write_subscription", "read_organization"})
  121.      * @ORM\Column(type="boolean", nullable=true)
  122.      */
  123.     private $notAcceptedScanEnveloppe;
  124.     /**
  125.      * @Groups({"read_subscription", "write_subscription", "read_organization"})
  126.      * @ORM\Column(type="date", nullable=true)
  127.      */
  128.     private ?\DateTimeInterface $invoiceGenerationDate null;
  129.     /**
  130.      * @Groups({"read_subscription", "write_subscription"})
  131.      * @ORM\ManyToOne(targetEntity=Organization::class, inversedBy="subscriptions")
  132.      */
  133.     private ?Organization $organization null;
  134.     /**
  135.      * @Groups({"read_subscription", "write_subscription", "read_pack"})
  136.      * @ORM\Column(type="integer", nullable=true)
  137.      */
  138.     private ?int $monthNumber null;
  139.     /**
  140.      * @Groups({"read_subscription", "write_subscription", "read_pack"})
  141.      * @ORM\Column(type="array", nullable=true)
  142.      */
  143.     private $authorizedReccurency = [];
  144.     /**
  145.      * @Groups({"read_subscription", "write_subscription", "read_organization"})
  146.      * @ORM\Column(type="boolean", nullable=true)
  147.      */
  148.     private $isCancelUsingOffer;
  149.     /**
  150.      * @Groups({"read_subscription", "write_subscription", "read_organization", "write_organization" })
  151.      * @ORM\Column(type="boolean", nullable=true)
  152.      */
  153.     private $isDigipackOffer 0;
  154.     /**
  155.      * @Groups({"read_subscription", "write_subscription", "read_organization", "write_organization"})
  156.      * @ORM\Column(type="integer", nullable=true)
  157.      */
  158.     private ?int $deadlineOffered null;
  159.     /**
  160.      * @Groups({"read_subscription", "write_subscription", "read_organization", "write_organization"})
  161.      * @ORM\Column(type="integer", options={"default" : 1})
  162.      */
  163.     private ?int $prepaidMonths 1;
  164.     /**
  165.      * @Groups({"read_subscription", "read_organization", "write_subscription", "write_organization"})
  166.      * @ORM\OneToMany(targetEntity=Service::class, mappedBy="subscription", cascade={"persist", "remove"}, orphanRemoval=true)
  167.      * @ApiSubresource(maxDepth=1)
  168.      */
  169.     private Collection $services;
  170.     /**
  171.      * @Groups({"read_subscription", "write_subscription", "read_pack"})
  172.      * @ORM\OneToMany(targetEntity=Item::class, mappedBy="subscriptionIncluded", cascade={"persist", "remove"})
  173.      */
  174.     private Collection $includedProducts;
  175.     /**
  176.      * @Groups({"read_subscription", "write_subscription", "read_organization", "write_organization"})
  177.      * @ORM\Column(type="boolean", options={"default" : false})
  178.      */
  179.     private bool $hasBlockedService false;
  180.     /**
  181.      * @ORM\OneToOne(targetEntity=Pack::class, mappedBy="subscription", cascade={"persist"})
  182.      */
  183.     private ?Pack $pack null;
  184.     /**
  185.      * @Groups({"read_subscription", "write_subscription", "read_organization", "write_organization"})
  186.      * @ORM\Column(type="datetime", nullable=true)
  187.      */
  188.     private ?\DateTimeInterface $documentRecoveryDelay null;
  189.     /**
  190.      * @ORM\Column(type="datetime", nullable=true)
  191.      * @Groups({"read_subscription", "write_subscription"})
  192.      */
  193.     private ?\DateTimeInterface $updatedAt null;
  194.     /**
  195.      * @ORM\OneToMany(targetEntity=CommercialGesture::class, mappedBy="subscription", cascade={"remove"})
  196.      */
  197.     private Collection $commercialGestures;
  198.     public function __construct()
  199.     {
  200.         $this->active true;
  201.         $this->createdAt = new \DateTime();
  202.         $this->includedProducts = new ArrayCollection();
  203.         $this->services = new ArrayCollection();
  204.         $this->commercialGestures = new ArrayCollection();
  205.     }
  206.     public function resetId()
  207.     {
  208.         $this->id null;
  209.         return $this;
  210.     }
  211.     /**
  212.      * @return bool
  213.      */
  214.     public function getActive()
  215.     {
  216.         return $this->active;
  217.     }
  218.     public function setActive(bool $active): Subscription
  219.     {
  220.         $this->active $active;
  221.         return $this;
  222.     }
  223.     public function getPrice(): ?float
  224.     {
  225.         return $this->price;
  226.     }
  227.     public function setPrice(float $price): self
  228.     {
  229.         $this->price $price;
  230.         return $this;
  231.     }
  232.     public function getSubscriptionDeposit(): ?float
  233.     {
  234.         return $this->subscriptionDeposit;
  235.     }
  236.     public function setSubscriptionDeposit(?float $subscriptionDeposit): Subscription
  237.     {
  238.         $this->subscriptionDeposit = (float) $subscriptionDeposit;
  239.         return $this;
  240.     }
  241.     /**
  242.      * @return \DateTime
  243.      */
  244.     public function getCreatedAt()
  245.     {
  246.         return $this->createdAt;
  247.     }
  248.     /**
  249.      * @param \DateTime|\DateTimeImmutable|null $createdAt
  250.      */
  251.     public function setCreatedAt(?\DateTimeInterface $createdAt): Subscription
  252.     {
  253.         $this->createdAt $createdAt;
  254.         return $this;
  255.     }
  256.     public function getDiscountWithoutTax(): ?string
  257.     {
  258.         return $this->discountWithoutTax;
  259.     }
  260.     public function setDiscountWithoutTax(?string $discountWithoutTax): self
  261.     {
  262.         $this->discountWithoutTax $discountWithoutTax;
  263.         return $this;
  264.     }
  265.     public function __toString()
  266.     {
  267.         return '#'.$this->getId();
  268.     }
  269.     /**
  270.      * @return int
  271.      */
  272.     public function getId()
  273.     {
  274.         return $this->id;
  275.     }
  276.     /**
  277.      * @deprecated don't use directly, use SubscriptionUtils->getPackUniqueKey()
  278.      * Is override, don't forget declare the groups in SubscriptionNormalizer
  279.      */
  280.     public function getPack(): ?string
  281.     {
  282.         return '';
  283.     }
  284.     /**
  285.      * @return string
  286.      */
  287.     public function getType()
  288.     {
  289.         return $this->type;
  290.     }
  291.     public function setType(?string $type): Subscription
  292.     {
  293.         $this->type $type;
  294.         return $this;
  295.     }
  296.     /**
  297.      * @deprecated but don't remove it, it's used in the migration
  298.      */
  299.     public function getProducts(): array
  300.     {
  301.         return $this->getProductsFromServices();
  302.     }
  303.     /*
  304.      * Is the new getProducts() method
  305.      */
  306.     public function getProductsFromServices(): array
  307.     {
  308.         $products = [];
  309.         foreach ($this->getServices() as $service) {
  310.             $products[] = $service->getProduct();
  311.         }
  312.         return $products;
  313.     }
  314.     public function getPreviousPack()
  315.     {
  316.         if (!empty($this->getPackHistory())) {
  317.             $histories $this->getPackHistory();
  318.             if (isset($histories[count($histories) - 2])) {
  319.                 return $histories[count($histories) - 2];
  320.             }
  321.         }
  322.         return null;
  323.     }
  324.     public function getPackHistory(): ?array
  325.     {
  326.         return $this->packHistory;
  327.     }
  328.     public function setPackHistory(?array $packHistory): self
  329.     {
  330.         $this->packHistory $packHistory;
  331.         // si le tableau a plus de 4 Ã©léments, on supprime le premier
  332.         if (\count($this->packHistory) > 4) {
  333.             array_shift($this->packHistory);
  334.         }
  335.         return $this;
  336.     }
  337.     public function getPaymentDates(): ?array
  338.     {
  339.         return $this->paymentDates;
  340.     }
  341.     public function setPaymentDates(?array $paymentDates): self
  342.     {
  343.         $this->paymentDates $paymentDates;
  344.         return $this;
  345.     }
  346.     public function getPriceWithoutTax(): ?float
  347.     {
  348.         return $this->priceWithoutTax;
  349.     }
  350.     public function setPriceWithoutTax(?float $priceWithoutTax): self
  351.     {
  352.         $this->priceWithoutTax $priceWithoutTax;
  353.         return $this;
  354.     }
  355.     public function getStoredTotalPriceWithoutTax(): ?float
  356.     {
  357.         return $this->storedTotalPriceWithoutTax;
  358.     }
  359.     public function setStoredTotalPriceWithoutTax(float $storedTotalPriceWithoutTax): self
  360.     {
  361.         $this->storedTotalPriceWithoutTax $storedTotalPriceWithoutTax;
  362.         return $this;
  363.     }
  364.     public function getIsUpdatedPrice(): ?bool
  365.     {
  366.         return $this->isUpdatedPrice;
  367.     }
  368.     public function setIsUpdatedPrice(?bool $isUpdatedPrice): self
  369.     {
  370.         $this->isUpdatedPrice $isUpdatedPrice;
  371.         return $this;
  372.     }
  373.     public function getNextPayment(): ?\DateTimeInterface
  374.     {
  375.         return $this->nextPayment;
  376.     }
  377.     public function setNextPayment(?\DateTimeInterface $nextPayment): self
  378.     {
  379.         $this->nextPayment $nextPayment;
  380.         return $this;
  381.     }
  382.     /**
  383.      * @deprecated
  384.      */
  385.     public function getNotAcceptedScanEnveloppe(): ?bool
  386.     {
  387.         return $this->notAcceptedScanEnveloppe;
  388.     }
  389.     /**
  390.      * @deprecated
  391.      */
  392.     public function setNotAcceptedScanEnveloppe(?bool $notAcceptedScanEnveloppe): self
  393.     {
  394.         $this->notAcceptedScanEnveloppe $notAcceptedScanEnveloppe;
  395.         return $this;
  396.     }
  397.     public function getInvoiceGenerationDate(): ?\DateTimeInterface
  398.     {
  399.         return $this->invoiceGenerationDate;
  400.     }
  401.     public function setInvoiceGenerationDate(?\DateTimeInterface $invoiceGenerationDate): self
  402.     {
  403.         $this->invoiceGenerationDate $invoiceGenerationDate;
  404.         return $this;
  405.     }
  406.     public function getOrganization(): ?Organization
  407.     {
  408.         return $this->organization;
  409.     }
  410.     public function setOrganization(?Organization $organization): self
  411.     {
  412.         $this->organization $organization;
  413.         return $this;
  414.     }
  415.     public function getMonthNumber(): ?int
  416.     {
  417.         return $this->monthNumber;
  418.     }
  419.     public function setMonthNumber(?int $monthNumber): self
  420.     {
  421.         $this->monthNumber $monthNumber;
  422.         return $this;
  423.     }
  424.     public function getAuthorizedReccurency(): ?array
  425.     {
  426.         return $this->authorizedReccurency;
  427.     }
  428.     public function setAuthorizedReccurency(?array $authorizedReccurency): self
  429.     {
  430.         $this->authorizedReccurency $authorizedReccurency;
  431.         return $this;
  432.     }
  433.     public function getIsCancelUsingOffer(): ?bool
  434.     {
  435.         return $this->isCancelUsingOffer;
  436.     }
  437.     public function setIsCancelUsingOffer(?bool $isCancelUsingOffer): self
  438.     {
  439.         $this->isCancelUsingOffer $isCancelUsingOffer;
  440.         return $this;
  441.     }
  442.     public function getIsDigipackOffer(): ?bool
  443.     {
  444.         return $this->isDigipackOffer;
  445.     }
  446.     public function setIsDigipackOffer(?bool $isDigipackOffer): self
  447.     {
  448.         $this->isDigipackOffer $isDigipackOffer;
  449.         return $this;
  450.     }
  451.     public function getDeadlineOffered(): ?int
  452.     {
  453.         return $this->deadlineOffered;
  454.     }
  455.     public function setDeadlineOffered(?int $deadlineOffered): self
  456.     {
  457.         $this->deadlineOffered $deadlineOffered;
  458.         return $this;
  459.     }
  460.     public function getPrepaidMonths(): ?int
  461.     {
  462.         return $this->prepaidMonths;
  463.     }
  464.     public function setPrepaidMonths(int $prepaidMonths): self
  465.     {
  466.         $this->prepaidMonths $prepaidMonths;
  467.         return $this;
  468.     }
  469.     /**
  470.      * @return Collection<int, Item>
  471.      */
  472.     public function getIncludedProducts(): Collection
  473.     {
  474.         return $this->includedProducts;
  475.     }
  476.     /**
  477.      * @Groups({"read_subscription", "read_organization"})
  478.      *
  479.      * @return array <int, Service>
  480.      */
  481.     public function getIncludedServices(): array
  482.     {
  483.         return array_values($this->services->filter(function (Service $service) {
  484.             return Service::INCLUDED === $service->getType();
  485.         })->toArray());
  486.     }
  487.     /**
  488.      * @Groups({"read_subscription", "read_organization"})
  489.      *
  490.      * @return array<int, Service>
  491.      */
  492.     public function getOptionalServices(): array
  493.     {
  494.         return array_values($this->services->filter(function (Service $service) {
  495.             return Service::OPTIONAL === $service->getType();
  496.         })->toArray());
  497.     }
  498.     /**
  499.      * @return Collection<int, Service>
  500.      */
  501.     public function getServices(): Collection
  502.     {
  503.         return $this->services;
  504.     }
  505.     public function addService(Service $service): self
  506.     {
  507.         if (!$this->services->contains($service)) {
  508.             $this->services->add($service);
  509.             $service->setSubscription($this);
  510.         }
  511.         $_SESSION['hasChanged'] = 1;
  512.         if (!isset($_SESSION['typeChanged'])) {
  513.             $_SESSION['typeChanged'] = 'add';
  514.         } elseif ('remove' === $_SESSION['typeChanged']) {
  515.             $_SESSION['typeChanged'] = 'mixte';
  516.         }
  517.         if (ProductKeyEnum::SCAN_ENVELOPPE === $service->getProduct()->getUniqueKey()) {
  518.             $_SESSION['addScanEnveloppe'] = 1;
  519.         }
  520.         return $this;
  521.     }
  522.     public function removeService(Service $service): self
  523.     {
  524.         if ($this->services->contains($service)) {
  525.             $this->services->removeElement($service);
  526.         }
  527.         if (ProductKeyEnum::SCAN_ENVELOPPE === $service->getProduct()->getUniqueKey()) {
  528.             $_SESSION['isRemoved'] = 1;
  529.         }
  530.         $_SESSION['hasChanged'] = 1;
  531.         if (!isset($_SESSION['typeChanged'])) {
  532.             $_SESSION['typeChanged'] = 'remove';
  533.         } elseif ('add' === $_SESSION['typeChanged']) {
  534.             $_SESSION['typeChanged'] = 'mixte';
  535.         }
  536.         return $this;
  537.     }
  538.     public function isHasBlockedService(): bool
  539.     {
  540.         return $this->hasBlockedService;
  541.     }
  542.     public function hasBlockedService(): bool
  543.     {
  544.         return $this->hasBlockedService;
  545.     }
  546.     public function updateBlockedService(bool $hasBlockedService): self
  547.     {
  548.         $this->hasBlockedService $hasBlockedService;
  549.         return $this;
  550.     }
  551.     public function addProduct(Product $product): self
  552.     {
  553.         $service = new Service();
  554.         $service->setProduct($product);
  555.         $service->setSubscription($this);
  556.         $this->addService($service);
  557.         return $this;
  558.     }
  559.     public function getProductsIds(): array
  560.     {
  561.         $productsIds = [];
  562.         foreach ($this->getIncludedServices() as $service) {
  563.             $productsIds[] = $service->getProduct()->getId();
  564.         }
  565.         return $productsIds;
  566.     }
  567.     public function getDocumentRecoveryDelay(): ?\DateTimeInterface
  568.     {
  569.         return $this->documentRecoveryDelay;
  570.     }
  571.     public function setDocumentRecoveryDelay(?\DateTimeInterface $documentRecoveryDelay): self
  572.     {
  573.         $this->documentRecoveryDelay $documentRecoveryDelay;
  574.         return $this;
  575.     }
  576.     /**
  577.      * @Groups({"read_subscription", "read_organization"})
  578.      */
  579.     public function getBlockingReason(): array
  580.     {
  581.         $organization $this->getOrganization();
  582.         if (null === $organization) {
  583.             return [];
  584.         }
  585.         $isUnpaid OrganizationStatusPayedEnum::UNPAID === $organization->getStatusInvoicePayed();
  586.         return SubscriptionUtils::getBlockingReason($this$isUnpaid);
  587.     }
  588.     public function setPack(?Pack $pack): self
  589.     {
  590.         // unset the owning side of the relation if necessary
  591.         if (null === $pack && null !== $this->pack) {
  592.             $this->pack->setSubscription(null);
  593.         }
  594.         // set the owning side of the relation if necessary
  595.         if (null !== $pack && $pack->getSubscription() !== $this) {
  596.             $pack->setSubscription($this);
  597.         }
  598.         $this->pack $pack;
  599.         return $this;
  600.     }
  601.     public function create(array $data): self
  602.     {
  603.         $self = new self();
  604.         $self->active $data['active'] ?? true;
  605.         $self->createdAt $data['createdAt'] ?? new \DateTime();
  606.         $self->discountWithoutTax $data['discountWithoutTax'] ?? null;
  607.         $self->invoiceGenerationDate $data['invoiceGenerationDate'] ?? null;
  608.         $self->hasBlockedService $data['hasBlockedService'] ?? false;
  609.         $self->price $data['price'] ?? null;
  610.         $self->priceWithoutTax $data['priceWithoutTax'] ?? null;
  611.         $self->type $data['type'] ?? 'MONTHLY';
  612.         $self->notAcceptedScanEnveloppe $data['notAcceptedScanEnveloppe'] ?? null;
  613.         $self->subscriptionDeposit $data['subscriptionDeposit'] ?? 0;
  614.         $self->nextPayment $data['nextPayment'] ?? null;
  615.         $self->prepaidMonths $data['prepaidMonths'] ?? 0;
  616.         $self->services $data['services'] ?? null;
  617.         if (isset($data['products'])) {
  618.             foreach ($data['products'] as $product) {
  619.                 $self->addService(Service::create(['product' => $product'type' => 'included']));
  620.             }
  621.         }
  622.         return $self;
  623.     }
  624.     public static function createFixture(array $data): self
  625.     {
  626.         $self = new self();
  627.         $self->active $data['active'] ?? true;
  628.         $self->createdAt $data['createdAt'] ?? new \DateTime();
  629.         $self->discountWithoutTax $data['discountWithoutTax'] ?? null;
  630.         $self->invoiceGenerationDate $data['invoiceGenerationDate'] ?? null;
  631.         $self->hasBlockedService $data['hasBlockedService'] ?? false;
  632.         $self->price $data['price'] ?? null;
  633.         $self->priceWithoutTax $data['priceWithoutTax'] ?? null;
  634.         $self->type $data['type'] ?? 'MONTHLY';
  635.         $self->notAcceptedScanEnveloppe $data['notAcceptedScanEnveloppe'] ?? null;
  636.         $self->subscriptionDeposit $data['subscriptionDeposit'] ?? 0;
  637.         $self->nextPayment $data['nextPayment'] ?? null;
  638.         $self->prepaidMonths $data['prepaidMonths'] ?? 0;
  639.         $self->organization $data['organization'] ?? null;
  640.         if (isset($data['products'])) {
  641.             foreach ($data['products'] as $product) {
  642.                 $self->addService(Service::create(['product' => $product'type' => 'included']));
  643.             }
  644.         }
  645.         return $self;
  646.     }
  647.     public function removeExpiredTrialServices(): void
  648.     {
  649.         $services $this->getServices();
  650.         /** @var Service $service */
  651.         foreach ($services as $service) {
  652.             if (Service::OPTIONAL === $service->getType()) {
  653.                 if ($service->expiredAndMustToBeRemove() && !$service->isRemoveAfterTrial()) {
  654.                     $service->stopTrial();
  655.                 }
  656.                 if ($service->expiredAndMustToBeRemove() && $service->isRemoveAfterTrial()) {
  657.                     $this->removeService($service);
  658.                 }
  659.             }
  660.         }
  661.     }
  662.     // create function to check if the subscription have a service with product uniquekey is a param
  663.     public function hasServiceWithProductKey(string $productKey): bool
  664.     {
  665.         $services $this->getServices();
  666.         foreach ($services as $service) {
  667.             if ($service->getProduct()->getUniqueKey() === $productKey) {
  668.                 return true;
  669.             }
  670.         }
  671.         return false;
  672.     }
  673.     public function getUpdatedAt(): ?\DateTimeInterface
  674.     {
  675.         return $this->updatedAt;
  676.     }
  677.     public function setUpdatedAt(?\DateTimeInterface $updatedAt): Subscription
  678.     {
  679.         $this->updatedAt $updatedAt;
  680.         return $this;
  681.     }
  682.     public function getCommercialGestures(): Collection
  683.     {
  684.         return $this->commercialGestures;
  685.     }
  686.     public function addCommercialGesture(CommercialGesture $commercialGesture): self
  687.     {
  688.         if (!$this->commercialGestures->contains($commercialGesture)) {
  689.             $this->commercialGestures->add($commercialGesture);
  690.             $commercialGesture->setSubscription($this);
  691.         }
  692.         return $this;
  693.     }
  694.     public function removeServiceFromProduct(Product $product): self
  695.     {
  696.         $services $this->getServices();
  697.         foreach ($services as $service) {
  698.             if ($service->getProduct() === $product) {
  699.                 $this->removeService($service);
  700.             }
  701.         }
  702.         return $this;
  703.     }
  704.     public function removeProduct(Product $product): self
  705.     {
  706.         $this->removeServiceFromProduct($product);
  707.         return $this;
  708.     }
  709.     public function removeServiceByType(string $serviceType): self
  710.     {
  711.         $services $this->getServices();
  712.         foreach ($services as $service) {
  713.             if ($service->getType() === $serviceType) {
  714.                 $this->removeService($service);
  715.             }
  716.         }
  717.         return $this;
  718.     }
  719.     public function getServiceStoreAddition()
  720.     {
  721.         $services $this->getServices();
  722.         foreach ($services as $service) {
  723.             if (Service::STORE_ADDITION === $service->getType()) {
  724.                 return $service;
  725.             }
  726.         }
  727.         return null;
  728.     }
  729.     public function totalPriceWithoutTax(): float
  730.     {
  731.         $price $this->getPriceWithoutTax() ?? .0;
  732.         foreach ($this->getOptionalServices() as $service) {
  733.             if (!$service->isTrial()) {
  734.                 $price += $service->getPriceWithoutTax();
  735.             }
  736.         }
  737.         $storeAdditionService $this->getServiceStoreAddition();
  738.         if (null !== $storeAdditionService) {
  739.             $price += $storeAdditionService->getPriceWithoutTax();
  740.         }
  741.         $price -= (float) $this->getDiscountWithoutTax();
  742.         if ($price 0) {
  743.             $price 0;
  744.         }
  745.         return $price;
  746.     }
  747.     public function haveDomiciliation(): bool
  748.     {
  749.         return $this->hasServiceWithProductKey(ProductKeyEnum::DOMICILIATION_COMMERCIALE);
  750.     }
  751.     /**
  752.      * @Groups({"read_subscription", "read_organization"})
  753.      */
  754.     public function getTotalPriceWithoutTax(): float
  755.     {
  756.         return round($this->totalPriceWithoutTax(), 2);
  757.     }
  758.     /**
  759.      * @Groups({"read_subscription", "read_organization"})
  760.      */
  761.     public function getTotalPriceWithTax(): float
  762.     {
  763.         return round($this->totalPriceWithoutTax() * 1.22);
  764.     }
  765. }