<?php
namespace App\Entity;
use DateTime;
use DateTimeImmutable;
use Doctrine\ORM\Mapping as ORM;
use App\Repository\BookingRepository;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity(repositoryClass: BookingRepository::class)]
#[ORM\HasLifecycleCallbacks]
class Booking
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: "integer")]
private int $id;
#[ORM\Column(type: "string", length: 255)]
#[Assert\NotBlank]
private string $firstName;
#[ORM\Column(type: "string", length: 255)]
#[Assert\NotBlank]
private string $lastName;
#[ORM\Column(type: "string", length: 255)]
#[Assert\NotBlank]
private string $email;
#[ORM\Column(type: "string", length: 255)]
#[Assert\NotBlank]
private string $phone;
#[ORM\Column(type: "string", length: 255)]
#[Assert\NotBlank]
private string $gender;
#[ORM\Column(type: "boolean")]
private bool $approval;
#[ORM\Column(type: "boolean")]
private bool $rgpd;
#[ORM\Column(type: "string", length: 255)]
#[Assert\NotBlank]
private string $paymentMethod;
#[ORM\Column(type: "datetime_immutable")]
private DateTimeImmutable $createdAt;
#[ORM\Column(type: "text", nullable: true)]
private ?string $comment = null;
#[ORM\Column(type: "integer")]
#[Assert\NotBlank]
private int $number;
#[ORM\Column(type: "datetime")]
#[Assert\NotBlank]
#[Assert\GreaterThan("today", message: "La date d'arrivée doit être ultèrieur à la date d'aujourd'hui", groups: ["front"])]
private DateTime $startDate;
#[ORM\Column(type: "datetime")]
#[Assert\NotBlank]
private DateTime $endDate;
#[ORM\Column(type: "float")]
private float $amount;
#[ORM\ManyToOne(targetEntity: BookingConstraint::class, inversedBy: "bookings")]
#[ORM\JoinColumn(nullable: false)]
private BookingConstraint $bookingConstraint;
#[ORM\Column(type: "string")]
private string $uniqId;
#[ORM\Column(type: "float")]
private float $deposit;
#[ORM\Column(type: "float", nullable: true)]
private ?float $discount = null;
#[ORM\Column(type: "boolean", nullable: true)]
private ?bool $isAdvancePayed = null;
#[ORM\Column(type: "boolean", nullable: true)]
private ?bool $isBalancePayed = null;
#[ORM\Column(type: "datetime")]
private DateTime $balancePaymentDeadline;
#[ORM\Column(type: "float", nullable: true)]
private ?float $advancePayment = null;
#[ORM\Column(type: "datetime")]
private DateTime $advancePaymentDeadline;
#[ORM\Column(type: "string", length: 2, nullable: true)]
private $locale;
#[ORM\Column(type: "boolean", nullable: true)]
private $isAdvancePaymentAlert1;
#[ORM\Column(type: "boolean", nullable: true)]
private $isAdvancePaymentAlert2;
#[ORM\Column(type: "boolean", nullable: true)]
private $isBalancePaymentAlert1;
#[ORM\Column(type: "boolean", nullable: true)]
private $isBalancePaymentAlert2;
#[ORM\Column(type: "boolean", nullable: true)]
private $isForSoon;
#[ORM\Column(type: "boolean")]
private $tracking;
#[ORM\Column(type: "boolean", nullable: true)]
private $isCautionPayed;
#[ORM\Column(type: "datetime", nullable: true)]
private $cautionPaymentDeadline;
#[ORM\Column(type: "boolean", nullable: true)]
private $isCautionPaymentAlert1;
#[ORM\Column(type: "boolean", nullable: true)]
private $isCautionPaymentAlert2;
#[ORM\Column(type: "float")]
private $stayTax;
#[ORM\Column(type: "float", nullable: true)]
private $housework = null;
#[ORM\Column(type: "float")]
private $finalAmount;
#[ORM\Column(type: "float")]
private $dayPrice;
#[ORM\Column(type: "float")]
private $dayPriceWithTax;
#[ORM\Column(type: "string", length: 255)]
private $contract;
#[ORM\Column(type: "string", length: 255, nullable: true)]
private $swiklyRequestId;
#[ORM\Column(type: "text", nullable: true)]
private $swiklyUrl;
#[ORM\Column(type: "integer", nullable: true)]
private $children;
/**
* Callback appelé à chaque fois qu'on fait un reservation
*
* Ajoute une date
* Calcul et ajoute le prix de la reservation avant ménage, tax et éventuelle réduction
* Calcul et ajoute le prix total de la reservation
* Calcul et ajoute le prix de la tax de séjour
* Calcul et ajoute le prix du ménage
* Calcul et ajoute le prix de l'acompte
*
* @return void
*/
#[ORM\PrePersist]
#[ORM\PreUpdate]
public function prePersist()
{
if (empty($this->createdAt)) {
$this->createdAt = new \DateTimeImmutable();
}
if (empty($this->amount)) {
$this->amount = ($this->getPrice() * $this->getDuration()) * 100;
}
if (empty($this->stayTax)) {
$this->stayTax = ceil(($this->bookingConstraint->getStayTax() / 100) * $this->getDuration() * ($this->getNumber() - $this->getChildren())) * 100;
}
if (empty($this->housework)) {
$this->housework = $this->bookingConstraint->getHousework();
}
if (empty($this->finalAmount)) {
$this->finalAmount = $this->getTotalAmount() * 100;
}
if (empty($this->dayPrice)) {
$this->dayPrice = $this->getPrice() * 100;
}
if (empty($this->dayPriceWithTax)) {
$this->dayPriceWithTax = ceil(($this->getTotalAmount() * 100) / $this->getDuration());
}
if (empty($this->advancePayment)) {
if ($this->isForSoon != true) {
$this->advancePayment = ceil($this->getFinalAmount() * $this->bookingConstraint->getAdvancePayment());
} else {
$this->advancePayment = null;
}
}
}
/**
* Permet de calculer le montant total TTC/TCC de la réservation
*
* @return float
*/
public function getTotalAmount()
{
# On vérifie si la taxe de ménage existe
$housework = 0;
if ($this->bookingConstraint->getHousework() > 0) {
$housework = $this->bookingConstraint->getHousework() / 100;
}
# Ajouter la réduction pour long séjour si elle existe
if ($this->getDuration() >= 7 && $this->bookingConstraint->getLongStayDiscount() > 0) {
return ceil(($this->getPrice() * $this->getDuration()) / (1 + $this->bookingConstraint->getLongStayDiscount()) + $housework + ($this->getStayTax() / 100));
}
# Sinon
return ($this->getPrice() * $this->getDuration()) + $housework + ($this->getStayTax() / 100);
}
/**
* Permet de calculer le montant de l'acompte
*
* @return float|null
*/
public function getAdvanceAmount()
{
return null;
}
/**
* Permet de calculer la durée du séjour
*/
public function getDuration()
{
$diff = $this->endDate->diff($this->startDate);
return $diff->days;
}
/**
* Permet de déterminer si un jour et disponible à la réservation
*
* @return boolean
*/
public function isBookableDates()
{
# 1) il faut connaitre les dates qui sont impossible pour l'annonce
$notAvailableDays = $this->bookingConstraint->getNotAvailableDays();
# 2) il faut comparer avec les dates choisies
$bookingDays = $this->getDays();
# Fonction pour formater les jours
$formatDays = function ($day) {
return $day->format('Y-m-d');
};
# Tableau des strings de mes journées à reserver
$daysToReserve = array_map($formatDays, $bookingDays);
# Tableau des strings de mes journées non disponibles
$notAvailable = array_map($formatDays, $notAvailableDays);
# Pour chaques journeés à reserver je regarde si elle se trouve dans les journées non disponibles
foreach ($daysToReserve as $day) {
if (array_search($day, $notAvailable) !== false) {
return false;
} else {
return true;
}
}
}
/**
* Permet de récupérer un tableau des journées qui correspondent à ma reservation
*
* @return array Un tableau d'objets DateTime représentant les jours de la reservation
*/
public function getDays()
{
$resultat = range(
$this->startDate->getTimestamp(),
$this->endDate->getTimestamp(),
24 * 60 * 60
);
$days = array_map(function ($dayTimestamp) {
return new \DateTime(date('Y-m-d', $dayTimestamp));
}, $resultat);
return $days;
}
/**
* Permet de récupérer le prix par nuits en fonction de la saison
*
* @return int
*/
public function getPrice()
{
$saisons = $this->getSaison();
$saisonConstraints = $this->getBookingConstraint()->getSaisons();
$temp = [];
$temp['count'] = 0;
$temp['price'] = 0;
foreach ($saisonConstraints as $saisonConstraint) {
foreach ($saisons as $key => $saison) {
# On récupère les saisons dans les quelles on se trouve
if ($saisonConstraint->translate('fr')->getTitle() == $saison['saison']) {
# On incrémente le prix et le nombre de jour à chaque boucle
$temp['count'] += 1;
$temp['price'] += $saisonConstraint->getPrice();
}
}
}
$mediumPrice = ceil($temp['price'] / $temp['count']);
return $mediumPrice;
}
/**
* Fonction de récupération de la saison du séjour
*
* @return array Un tableau de jour avec la saison a laquelle ils appartiennent
*/
private function getSaison()
{
$saisons = $this->bookingConstraint->getSaisons();
$periods_days = [];
foreach ($saisons as $key => $saison) {
foreach ($saison->getPeriods() as $key => $period) {
$resultat = range(
$period->getStartDate()->getTimestamp(),
$period->getEndDate()->getTimestamp(),
24 * 60 * 60
);
$days = array_map(function ($dayTimestamp) {
return new \DateTime(date('Y-m-d', $dayTimestamp));
}, $resultat);
$periods_days[$saison->translate('fr')->getTitle()][$key] = $days;
}
}
$bookingDays = $this->getDays();
$formatDays = function ($day) {
return $day->format('Y-m-d');
};
# Tableau des strings de mes journées à reserver
$daysToReserve = array_map($formatDays, $bookingDays);
# Tableau des jours des diférentes saisons
foreach ($periods_days as $saison_key => $array) {
foreach ($array as $key => $item) {
$saisonsDays[$saison_key][$key] = array_map($formatDays, $item);
}
}
# Pour chaques journées à reserver je regarde si elle se trouve dans les journées d'une saison
$temp = [];
foreach ($daysToReserve as $day) {
foreach ($saisonsDays as $saison_key => $saison) {
foreach ($saison as $key => $item) {
if (array_search($day, $item) !== false) {
$temp[] = [
'day' => $day,
'saison' => $saison_key,
];
}
}
}
}
return $temp;
}
public function getId(): ?int
{
return $this->id;
}
public function getFirstName(): ?string
{
return $this->firstName;
}
public function setFirstName(string $firstName): self
{
$this->firstName = $firstName;
return $this;
}
public function getLastName(): ?string
{
return $this->lastName;
}
public function setLastName(string $lastName): self
{
$this->lastName = $lastName;
return $this;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getPhone(): ?string
{
return $this->phone;
}
public function setPhone(string $phone): self
{
$this->phone = $phone;
return $this;
}
public function getGender(): ?string
{
return $this->gender;
}
public function setGender(string $gender): self
{
$this->gender = $gender;
return $this;
}
public function getApproval(): ?bool
{
return $this->approval;
}
public function setApproval(bool $approval): self
{
$this->approval = $approval;
return $this;
}
public function getRgpd(): ?bool
{
return $this->rgpd;
}
public function setRgpd(bool $rgpd): self
{
$this->rgpd = $rgpd;
return $this;
}
public function getPaymentMethod(): ?string
{
return $this->paymentMethod;
}
public function setPaymentMethod(string $paymentMethod): self
{
$this->paymentMethod = $paymentMethod;
return $this;
}
public function getCreatedAt(): ?\DateTimeImmutable
{
return $this->createdAt;
}
public function setCreatedAt(\DateTimeImmutable $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getComment(): ?string
{
return $this->comment;
}
public function setComment(string $comment): self
{
$this->comment = $comment;
return $this;
}
public function getNumber(): ?int
{
return $this->number;
}
public function setNumber(int $number): self
{
$this->number = $number;
return $this;
}
public function getStartDate()
{
return $this->startDate;
}
public function setStartDate($startDate): self
{
$this->startDate = $startDate;
return $this;
}
public function getEndDate()
{
return $this->endDate;
}
public function setEndDate($endDate): self
{
$this->endDate = $endDate;
return $this;
}
public function getAmount(): ?float
{
return $this->amount;
}
public function setAmount(float $amount): self
{
$this->amount = $amount;
return $this;
}
public function getBookingConstraint(): ?BookingConstraint
{
return $this->bookingConstraint;
}
public function setBookingConstraint(?BookingConstraint $bookingConstraint): self
{
$this->bookingConstraint = $bookingConstraint;
return $this;
}
public function getUniqId(): ?string
{
return $this->uniqId;
}
public function setUniqId(string $uniqId): self
{
$this->uniqId = $uniqId;
return $this;
}
public function getDeposit(): ?int
{
return $this->deposit;
}
public function setDeposit(int $deposit): self
{
$this->deposit = $deposit;
return $this;
}
public function getDiscount(): ?float
{
return $this->discount;
}
public function setDiscount(?float $discount): self
{
$this->discount = $discount;
return $this;
}
public function getIsAdvancePayed(): ?bool
{
return $this->isAdvancePayed;
}
public function setIsAdvancePayed(?bool $isAdvancePayed): self
{
$this->isAdvancePayed = $isAdvancePayed;
return $this;
}
public function getIsBalancePayed(): ?bool
{
return $this->isBalancePayed;
}
public function setIsBalancePayed(?bool $isBalancePayed): self
{
$this->isBalancePayed = $isBalancePayed;
return $this;
}
public function getAdvancePayment(): ?float
{
return $this->advancePayment;
}
public function setAdvancePayment(float $advancePayment): self
{
$this->advancePayment = $advancePayment;
return $this;
}
public function getBalancePaymentDeadline(): ?\DateTimeInterface
{
return $this->balancePaymentDeadline;
}
public function setBalancePaymentDeadline(\DateTimeInterface $balancePaymentDeadline): self
{
$this->balancePaymentDeadline = $balancePaymentDeadline;
return $this;
}
public function getAdvancePaymentDeadline(): ?\DateTimeInterface
{
return $this->advancePaymentDeadline;
}
public function setAdvancePaymentDeadline(\DateTimeInterface $advancePaymentDeadline): self
{
$this->advancePaymentDeadline = $advancePaymentDeadline;
return $this;
}
public function getLocale(): ?string
{
return $this->locale;
}
public function setLocale(?string $locale): self
{
$this->locale = $locale;
return $this;
}
public function getIsAdvancePaymentAlert1(): ?bool
{
return $this->isAdvancePaymentAlert1;
}
public function setIsAdvancePaymentAlert1(?bool $isAdvancePaymentAlert1): self
{
$this->isAdvancePaymentAlert1 = $isAdvancePaymentAlert1;
return $this;
}
public function getIsAdvancePaymentAlert2(): ?bool
{
return $this->isAdvancePaymentAlert2;
}
public function setIsAdvancePaymentAlert2(?bool $isAdvancePaymentAlert2): self
{
$this->isAdvancePaymentAlert2 = $isAdvancePaymentAlert2;
return $this;
}
public function getIsBalancePaymentAlert1(): ?bool
{
return $this->isBalancePaymentAlert1;
}
public function setIsBalancePaymentAlert1(?bool $isBalancePaymentAlert1): self
{
$this->isBalancePaymentAlert1 = $isBalancePaymentAlert1;
return $this;
}
public function getIsBalancePaymentAlert2(): ?bool
{
return $this->isBalancePaymentAlert2;
}
public function setIsBalancePaymentAlert2(?bool $isBalancePaymentAlert2): self
{
$this->isBalancePaymentAlert2 = $isBalancePaymentAlert2;
return $this;
}
public function getIsForSoon(): ?bool
{
return $this->isForSoon;
}
public function setIsForSoon(?bool $isForSoon): self
{
$this->isForSoon = $isForSoon;
return $this;
}
public function getTracking(): ?bool
{
return $this->tracking;
}
public function setTracking(bool $tracking): self
{
$this->tracking = $tracking;
return $this;
}
public function getIsCautionPayed(): ?bool
{
return $this->isCautionPayed;
}
public function setIsCautionPayed(bool $isCautionPayed): self
{
$this->isCautionPayed = $isCautionPayed;
return $this;
}
public function getCautionPaymentDeadline(): ?\DateTimeInterface
{
return $this->cautionPaymentDeadline;
}
public function setCautionPaymentDeadline(\DateTimeInterface $cautionPaymentDeadline): self
{
$this->cautionPaymentDeadline = $cautionPaymentDeadline;
return $this;
}
public function getIsCautionPaymentAlert1(): ?bool
{
return $this->isCautionPaymentAlert1;
}
public function setIsCautionPaymentAlert1(?bool $isCautionPaymentAlert1): self
{
$this->isCautionPaymentAlert1 = $isCautionPaymentAlert1;
return $this;
}
public function getIsCautionPaymentAlert2(): ?bool
{
return $this->isCautionPaymentAlert2;
}
public function setIsCautionPaymentAlert2(?bool $isCautionPaymentAlert2): self
{
$this->isCautionPaymentAlert2 = $isCautionPaymentAlert2;
return $this;
}
public function getStayTax(): ?float
{
return $this->stayTax;
}
public function setStayTax(float $stayTax): self
{
$this->stayTax = $stayTax;
return $this;
}
public function getHousework(): ?float
{
return $this->housework;
}
public function setHousework(?float $housework): self
{
$this->housework = $housework;
return $this;
}
public function getFinalAmount(): ?float
{
return $this->finalAmount;
}
public function setFinalAmount(float $finalAmount): self
{
$this->finalAmount = $finalAmount;
return $this;
}
public function getDayPrice(): ?float
{
return $this->dayPrice;
}
public function setDayPrice(float $dayPrice): self
{
$this->dayPrice = $dayPrice;
return $this;
}
public function getDayPriceWithTax(): ?float
{
return $this->dayPriceWithTax;
}
public function setDayPriceWithTax(float $dayPriceWithTax): self
{
$this->dayPriceWithTax = $dayPriceWithTax;
return $this;
}
public function getContract(): ?string
{
return $this->contract;
}
public function setContract(string $contract): self
{
$this->contract = $contract;
return $this;
}
public function getChildren(): ?int
{
return $this->children;
}
public function setChildren(?int $children): self
{
$this->children = $children;
return $this;
}
public function getSwiklyRequestId(): ?string
{
return $this->swiklyRequestId;
}
public function setSwiklyRequestId(?string $swiklyRequestId): self
{
$this->swiklyRequestId = $swiklyRequestId;
return $this;
}
public function getSwiklyUrl(): ?string
{
return $this->swiklyUrl;
}
public function setSwiklyUrl(?string $swiklyUrl): self
{
$this->swiklyUrl = $swiklyUrl;
return $this;
}
}