src/Entity/Reservation.php line 18

Open in your IDE?
  1. <?php
  2. namespace App\Entity;
  3. use App\Entity\CustomExtra;
  4. use App\Entity\History\Reservation\ReservationHistory;
  5. use App\Entity\Payment\AbstractPayment;
  6. use App\Entity\Payment\CarteCadeauPayment;
  7. use App\Entity\Payment\EmptyPayment;
  8. use App\Repository\ReservationRepository;
  9. use Doctrine\Common\Collections\ArrayCollection;
  10. use Doctrine\Common\Collections\Collection;
  11. use Doctrine\ORM\Mapping as ORM;
  12. /**
  13.  * @ORM\Entity(repositoryClass=ReservationRepository::class)
  14.  */
  15. class Reservation extends AbstractReservation
  16. {
  17.     /**
  18.      * @ORM\Column(type="string", length=255)
  19.      */
  20.     private $bains;
  21.     /**
  22.      * @ORM\Column(type="boolean")
  23.      */
  24.     private $confirmed;
  25.     /**
  26.      * @ORM\Column(type="string", length=255)
  27.      */
  28.     private $token;
  29.     /**
  30.      * @ORM\Column(type="boolean", nullable=true)
  31.      */
  32.     private $deleted;
  33.     /**
  34.      * @ORM\Column(type="string", length=255, nullable=true)
  35.      */
  36.     private $comment;
  37.     /**
  38.      * @ORM\OneToMany(targetEntity=ExtraReservation::class, mappedBy="reservation", orphanRemoval=true, cascade={"persist", "remove"})
  39.      */
  40.     protected $extraReservations;
  41.     /**
  42.      * @ORM\OneToMany(targetEntity=CustomExtra::class, mappedBy="reservation", orphanRemoval=true, cascade={"persist", "remove"})
  43.      */
  44.     private $customExtras;
  45.     /**
  46.      * @ORM\OneToMany(targetEntity=Participant::class, mappedBy="reservation", orphanRemoval=true, cascade={"persist", "remove"})
  47.      */
  48.     protected $participants;
  49.     /**
  50.      * @ORM\OneToMany(targetEntity=Token::class, mappedBy="reservation", cascade={"persist", "remove"})
  51.      */
  52.     private $tokens;
  53.     /**
  54.      * @ORM\Column(type="float", nullable=true)
  55.      */
  56.     private $resteAPayer;
  57.     /**
  58.      * @ORM\OneToMany(targetEntity=AbstractPayment::class, mappedBy="reservation", cascade={"remove"})
  59.      */
  60.     private $abstractPayments;
  61.     /**
  62.      * @ORM\ManyToOne(targetEntity=Contact::class, inversedBy="reservations", cascade={"persist"})
  63.      */
  64.     private $contact;
  65.     /**
  66.      * @ORM\OneToMany(targetEntity=ReservationHistory::class, mappedBy="reservation", cascade={"remove"})
  67.      */
  68.     private $reservationHistories;
  69.     /**
  70.      * @ORM\Column(type="boolean", nullable=true)
  71.      */
  72.     private $isSatisfied;
  73.     /**
  74.      * @ORM\Column(type="boolean", nullable=true)
  75.      */
  76.     private $isClientMissing;
  77.     /**
  78.      * @ORM\Column(type="string", length=255, nullable=true)
  79.      */
  80.     private $clientMissingReason;
  81.     /**
  82.      * @ORM\Column(type="string", length=255, nullable=true)
  83.      */
  84.     private $cancelReason;
  85.     /**
  86.      * @ORM\OneToMany(targetEntity=Code::class, mappedBy="createdFromReservation", cascade={"remove"})
  87.      */
  88.     private $createdCodes;
  89.     /**
  90.      * Constructor
  91.      */
  92.     public function __construct()
  93.     {
  94.         parent::__construct();
  95.         $this->deleted false;
  96.         $this->confirmed false;
  97.         $this->bains '[]'// Initialize with empty JSON array
  98.         $this->participants = new ArrayCollection();
  99.         $this->extraReservations = new ArrayCollection();
  100.         $this->customExtras = new ArrayCollection();
  101.         $this->tokens = new ArrayCollection();
  102.         $this->abstractPayments = new ArrayCollection();
  103.         $this->reservationHistories = new ArrayCollection();
  104.         $this->createdCodes = new ArrayCollection();
  105.     }
  106.     public function __clone()
  107.     {
  108.         $participants = new ArrayCollection();
  109.         foreach($this->getParticipants() as $participant) {
  110.             $newParticipant = clone $participant;
  111.             $participants->add($newParticipant);
  112.             $this->removeParticipant($participant);
  113.         }
  114.         $this->participants $participants;
  115.         $extraReservations = new ArrayCollection();
  116.         foreach($this->getExtraReservations() as $extraReservation) {
  117.             $newExtraReservation = clone $extraReservation;
  118.             $extraReservations->add($newExtraReservation);
  119.             $this->removeExtraReservation($extraReservation);
  120.         }
  121.         $this->extraReservations $extraReservations;
  122.         $customExtras = new ArrayCollection();
  123.         foreach($this->getCustomExtras() as $customExtra) {
  124.             $newCustomExtra = clone $customExtra;
  125.             $newCustomExtra->setReservation($this);
  126.             $customExtras->add($newCustomExtra);
  127.         }
  128.         $this->customExtras $customExtras;
  129.     }
  130.     public function getBains(): ?string
  131.     {
  132.         return $this->bains;
  133.     }
  134.     public function setBains(string $bains): self
  135.     {
  136.         $this->bains $bains;
  137.         return $this;
  138.     }
  139.     public function getConfirmed(): ?bool
  140.     {
  141.         return $this->confirmed;
  142.     }
  143.     public function setConfirmed(bool $confirmed): self
  144.     {
  145.         $this->confirmed $confirmed;
  146.         return $this;
  147.     }
  148.     public function getToken(): ?string
  149.     {
  150.         return $this->token;
  151.     }
  152.     public function setToken(string $token): self
  153.     {
  154.         $this->token $token;
  155.         return $this;
  156.     }
  157.     public function getDeleted(): ?bool
  158.     {
  159.         return $this->deleted;
  160.     }
  161.     public function setDeleted(?bool $deleted): self
  162.     {
  163.         $this->deleted $deleted;
  164.         return $this;
  165.     }
  166.     public function getComment(): ?string
  167.     {
  168.         return $this->comment;
  169.     }
  170.     public function setComment(?string $comment): self
  171.     {
  172.         $this->comment $comment;
  173.         return $this;
  174.     }
  175.     /**
  176.      * @return Collection<int, ExtraReservation>
  177.      */
  178.     public function getExtraReservations(): Collection
  179.     {
  180.         return $this->extraReservations;
  181.     }
  182.     /**
  183.      * @return Collection<int, ExtraReservation>
  184.      */
  185.     public function getActiveExtraReservations(): Collection
  186.     {
  187.         return $this->extraReservations->filter(function(ExtraReservation $extraReservation) {
  188.             return !$extraReservation->isEmpty();
  189.         });
  190.     }
  191.     public function addExtraReservation(ExtraReservation $extraReservation): self
  192.     {
  193.         if (!$this->extraReservations->contains($extraReservation)) {
  194.             $this->extraReservations[] = $extraReservation;
  195.             $extraReservation->setReservation($this);
  196.         }
  197.         return $this;
  198.     }
  199.     public function removeExtraReservation(ExtraReservation $extraReservation): self
  200.     {
  201.         if ($this->extraReservations->removeElement($extraReservation)) {
  202.             // set the owning side to null (unless already changed)
  203.             if ($extraReservation->getReservation() === $this) {
  204.                 $extraReservation->setReservation(null);
  205.             }
  206.         }
  207.         return $this;
  208.     }
  209.     /**
  210.      * @return Collection<int, CustomExtra>
  211.      */
  212.     public function getCustomExtras(): Collection
  213.     {
  214.         return $this->customExtras;
  215.     }
  216.     public function addCustomExtra(CustomExtra $customExtra): self
  217.     {
  218.         if (!$this->customExtras->contains($customExtra)) {
  219.             $this->customExtras[] = $customExtra;
  220.             $customExtra->setReservation($this);
  221.         }
  222.         return $this;
  223.     }
  224.     public function removeCustomExtra(CustomExtra $customExtra): self
  225.     {
  226.         if ($this->customExtras->removeElement($customExtra)) {
  227.             if ($customExtra->getReservation() === $this) {
  228.                 $customExtra->setReservation(null);
  229.             }
  230.         }
  231.         return $this;
  232.     }
  233.     /**
  234.      * @return Collection<int, Participant>
  235.      */
  236.     public function getParticipants(): Collection
  237.     {
  238.         return $this->participants;
  239.     }
  240.     public function addParticipant(Participant $participant): self
  241.     {
  242.         if (!$this->participants->contains($participant)) {
  243.             $this->participants[] = $participant;
  244.             $participant->setReservation($this);
  245.         }
  246.         return $this;
  247.     }
  248.     public function removeParticipant(Participant $participant): self
  249.     {
  250.         if ($this->participants->removeElement($participant)) {
  251.             // set the owning side to null (unless already changed)
  252.             if ($participant->getReservation() === $this) {
  253.                 $participant->setReservation(null);
  254.             }
  255.         }
  256.         return $this;
  257.     }
  258.     /**
  259.      * @return Collection<int, Token>
  260.      */
  261.     public function getTokens(): Collection
  262.     {
  263.         return $this->tokens;
  264.     }
  265.     public function addToken(Token $token): self
  266.     {
  267.         if (!$this->tokens->contains($token)) {
  268.             $this->tokens[] = $token;
  269.             $token->setReservation($this);
  270.         }
  271.         return $this;
  272.     }
  273.     public function removeToken(Token $token): self
  274.     {
  275.         if ($this->tokens->removeElement($token)) {
  276.             // set the owning side to null (unless already changed)
  277.             if ($token->getReservation() === $this) {
  278.                 $token->setReservation(null);
  279.             }
  280.         }
  281.         return $this;
  282.     }
  283.     public function getResteAPayer(): ?float
  284.     {
  285.         return $this->resteAPayer ?? 0;
  286.     }
  287.     public function setResteAPayer(?float $resteAPayer): self
  288.     {
  289.         $this->resteAPayer $resteAPayer;
  290.         return $this;
  291.     }
  292.     /**
  293.      * @return Collection<int, AbstractPayment>
  294.      */
  295.     public function getAbstractPayments(): Collection
  296.     {
  297.         return $this->abstractPayments;
  298.     }
  299.     public function isPaidWithCarteCadeau(): bool
  300.     {
  301.         foreach ($this->abstractPayments as $payment) {
  302.             if ($payment instanceof CarteCadeauPayment) {
  303.                 return true;
  304.             }
  305.         }
  306.         return false;
  307.     }
  308.     public function getUsedCarteCadeaux(): Collection
  309.     {
  310.         $carteCadeaux = new ArrayCollection();
  311.         foreach ($this->abstractPayments as $payment) {
  312.             if ($payment instanceof CarteCadeauPayment) {
  313.                 $carteCadeaux->add($payment->getCartecadeau());
  314.             }
  315.         }
  316.         return $carteCadeaux;
  317.     }
  318.     public function addAbstractPayment(AbstractPayment $abstractPayment): self
  319.     {
  320.         if (!$this->abstractPayments->contains($abstractPayment)) {
  321.             $this->abstractPayments[] = $abstractPayment;
  322.             $abstractPayment->setReservation($this);
  323.         }
  324.         return $this;
  325.     }
  326.     public function removeAbstractPayment(AbstractPayment $abstractPayment): self
  327.     {
  328.         if ($this->abstractPayments->removeElement($abstractPayment)) {
  329.             // set the owning side to null (unless already changed)
  330.             if ($abstractPayment->getReservation() === $this) {
  331.                 $abstractPayment->setReservation(null);
  332.             }
  333.         }
  334.         return $this;
  335.     }
  336.     public function getContact(): ?Contact
  337.     {
  338.         return $this->contact;
  339.     }
  340.     public function setContact(?Contact $contact): self
  341.     {
  342.         $this->contact $contact;
  343.         return $this;
  344.     }
  345.     public function getAllHistories(): array
  346.     {
  347.         $histories = new ArrayCollection();
  348.         foreach($this->getReservationHistories() as $history) {
  349.             $histories->add($history);
  350.         }
  351.         foreach($this->getAbstractPayments() as $payment) {
  352.             if (!$payment instanceof EmptyPayment) {
  353.                 $histories->add($payment);
  354.             }
  355. //            foreach($payment->getPaymentHistories() as $history) {
  356. //                $histories->add($history->getPayment());
  357. //            }
  358.         }
  359.         // sort by createdAt
  360.         $histories $histories->toArray();
  361.         usort($histories, function($a$b) {
  362.             return $b->getCreatedAt() <=> $a->getCreatedAt();
  363.         });
  364.         return $histories;
  365.     }
  366.     /**
  367.      * Get only payment histories from all histories
  368.      * @return array Payment histories sorted by creation date (newest first)
  369.      */
  370.     public function getPaymentHistories(): array
  371.     {
  372.         $paymentHistories = new ArrayCollection();
  373.         
  374.         foreach($this->getAbstractPayments() as $payment) {
  375.             if (!$payment instanceof EmptyPayment) {
  376.                 $paymentHistories->add($payment);
  377.             }
  378.         }
  379.         // sort by createdAt
  380.         $histories $paymentHistories->toArray();
  381.         usort($histories, function($a$b) {
  382.             return $b->getCreatedAt() <=> $a->getCreatedAt();
  383.         });
  384.         return $histories;
  385.     }
  386.     /**
  387.      * @return Collection<int, ReservationHistory>
  388.      */
  389.     public function getReservationHistories(): Collection
  390.     {
  391.         return $this->reservationHistories;
  392.     }
  393.     public function addReservationHistory(ReservationHistory $reservationHistory): self
  394.     {
  395.         if (!$this->reservationHistories->contains($reservationHistory)) {
  396.             $this->reservationHistories[] = $reservationHistory;
  397.             $reservationHistory->setReservation($this);
  398.         }
  399.         return $this;
  400.     }
  401.     public function removeReservationHistory(ReservationHistory $reservationHistory): self
  402.     {
  403.         $this->reservationHistories->removeElement($reservationHistory);
  404.         return $this;
  405.     }
  406.     public function getTotalPeople(): int
  407.     {
  408.         return ( $this->getSolo() ?? )
  409.             + ( ($this->getDuo() ?? 0) * 2);
  410.     }
  411.     public function getTotalBaths(): int
  412.     {
  413.         return ( $this->getSolo() ?? )
  414.             + ( $this->getDuo() ?? 0) ;
  415.     }
  416.     public function getArrivalDate(): ?\DateTimeInterface
  417.     {
  418.         return $this->getDate()->modify('-15 minutes');
  419.     }
  420.     public function getDepartureDate(): ?\DateTimeInterface
  421.     {
  422.         return $this->getOffer() == "60" ?
  423.             $this->getDate()->modify('+80 minutes') :
  424.             $this->getDate()->modify('+110 minutes')
  425.             ;
  426.     }
  427.     public function getIsSatisfied(): ?bool
  428.     {
  429.         return $this->isSatisfied;
  430.     }
  431.     public function setIsSatisfied(?bool $isSatisfied): self
  432.     {
  433.         $this->isSatisfied $isSatisfied;
  434.         return $this;
  435.     }
  436.     public function getIsClientMissing(): ?bool
  437.     {
  438.         return $this->isClientMissing;
  439.     }
  440.     public function setIsClientMissing(?bool $isClientMissing): self
  441.     {
  442.         $this->isClientMissing $isClientMissing;
  443.         return $this;
  444.     }
  445.     public function getDateFormated(): string
  446.     {
  447.         // French day and month names
  448.         $days = [
  449.             'Sunday' => 'Dimanche',
  450.             'Monday' => 'Lundi',
  451.             'Tuesday' => 'Mardi',
  452.             'Wednesday' => 'Mercredi',
  453.             'Thursday' => 'Jeudi',
  454.             'Friday' => 'Vendredi',
  455.             'Saturday' => 'Samedi'
  456.         ];
  457.         $months = [
  458.             'January' => 'janvier',
  459.             'February' => 'février',
  460.             'March' => 'mars',
  461.             'April' => 'avril',
  462.             'May' => 'mai',
  463.             'June' => 'juin',
  464.             'July' => 'juillet',
  465.             'August' => 'août',
  466.             'September' => 'septembre',
  467.             'October' => 'octobre',
  468.             'November' => 'novembre',
  469.             'December' => 'décembre'
  470.         ];
  471.         $date $this->getDate();
  472.         // Format components
  473.         $dayName $days[$date->format('l')]; // Full day name
  474.         $day $date->format('d'); // Day of the month
  475.         $monthName $months[$date->format('F')]; // Full month name
  476.         $year $date->format('Y'); // Year
  477.         $time $date->format('H\h') . str_pad($date->format('i'), 2'0'STR_PAD_LEFT);
  478.         // Combine the formatted string
  479.         $formattedDate "$dayName $day $monthName $year à $time";
  480.         return $formattedDate;
  481.     }
  482.     public function getIsPast() {
  483.         return $this->getEndDate() < new \DateTime();
  484.     }
  485.     public function getEndDate(): \DateTimeInterface
  486.     {
  487.         $offerDuration $this->getOffer() == "60" 60 90// Durée en minutes
  488.         return (clone $this->getDate())->modify("+$offerDuration minutes");
  489.     }
  490.     public function getClientMissingReason(): ?string
  491.     {
  492.         return $this->clientMissingReason;
  493.     }
  494.     public function setClientMissingReason(?string $clientMissingReason): self
  495.     {
  496.         $this->clientMissingReason $clientMissingReason;
  497.         return $this;
  498.     }
  499.     public function getCancelReason(): ?string
  500.     {
  501.         return $this->cancelReason;
  502.     }
  503.     public function setCancelReason(?string $cancelReason): self
  504.     {
  505.         $this->cancelReason $cancelReason;
  506.         return $this;
  507.     }
  508.     /**
  509.      * @return Collection<int, Code>
  510.      */
  511.     public function getCreatedCodes(): Collection
  512.     {
  513.         return $this->createdCodes;
  514.     }
  515.     public function addCreatedCode(Code $createdCode): self
  516.     {
  517.         if (!$this->createdCodes->contains($createdCode)) {
  518.             $this->createdCodes[] = $createdCode;
  519.             $createdCode->setCreatedFromReservation($this);
  520.         }
  521.         return $this;
  522.     }
  523.     public function removeCreatedCode(Code $createdCode): self
  524.     {
  525.         if ($this->createdCodes->removeElement($createdCode)) {
  526.             // set the owning side to null (unless already changed)
  527.             if ($createdCode->getCreatedFromReservation() === $this) {
  528.                 $createdCode->setCreatedFromReservation(null);
  529.             }
  530.         }
  531.         return $this;
  532.     }
  533.     /**
  534.      * Count the number of times a client (non-admin) has edited this reservation
  535.      * @return int The number of client edits
  536.      */
  537.     public function getClientEditCount(): int
  538.     {
  539.         $count 0;
  540.         foreach($this->getReservationHistories() as $history) {
  541.             if ($history instanceof \App\Entity\History\Reservation\UpdateReservationHistory
  542.                 && $history->getModifier() !== "admin@taakabeerspa.com") {
  543.                 $count++;
  544.             }
  545.         }
  546.         return $count;
  547.     }
  548.     
  549.     /**
  550.      * Check if a client can edit this reservation (limit to 3 edits)
  551.      * @return bool Whether the client can edit the reservation
  552.      */
  553.     public function canClientEdit(): bool
  554.     {
  555.         return $this->getClientEditCount() < 3;
  556.     }
  557.     /**
  558.      * Get the current status of the reservation based on business rules
  559.      * @return string The status constant from ReservationStatus
  560.      */
  561.     public function getStatus(): string
  562.     {
  563.         if ($this->getDeleted()) {
  564.             return ReservationStatus::ANNULE;
  565.         }
  566.         
  567.         if ($this->getConfirmed() && $this->getIsClientMissing()) {
  568.             return ReservationStatus::ABSENT;
  569.         }
  570.         
  571.         if ($this->getConfirmed()) {
  572.             return ReservationStatus::CONFIRME;
  573.         }
  574.         
  575.         return ReservationStatus::NON_CONFIRME;
  576.     }
  577.     /**
  578.      * Get the human-readable label for the current status
  579.      * @return string The French label for the status
  580.      */
  581.     public function getStatusLabel(): string
  582.     {
  583.         return ReservationStatus::getLabel($this->getStatus());
  584.     }
  585.     /**
  586.      * Get the CSS class for the current status
  587.      * @return string The CSS class name for styling
  588.      */
  589.     public function getStatusCssClass(): string
  590.     {
  591.         return ReservationStatus::getCssStatusClass($this->getStatus());
  592.     }
  593.     /**
  594.      * String representation of the reservation for debugging purposes
  595.      * @return string
  596.      */
  597.     public function __toString(): string
  598.     {
  599.         return sprintf(
  600.             'Reservation(id: %s, token: %s, date: %s, confirmed: %s)',
  601.             $this->getId() ?? 'new',
  602.             $this->getToken() ?? 'none',
  603.             $this->getDate() ? $this->getDate()->format('Y-m-d H:i:s') : 'none',
  604.             $this->getConfirmed() ? 'true' 'false'
  605.         );
  606.     }
  607. }