wip: implement model

This commit is contained in:
Björn Fromme committed 2026-07-16 17:13:15 +02:00
1 parent fafc60eba9
commit 13491f346d
18 files changed
+1001

No files matched your search

+40
View File
@@ -0,0 +1,40 @@
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
trait BlameableEntity
{
#[ORM\ManyToOne(targetEntity: User::class)]
#[ORM\JoinColumn(onDelete: 'SET NULL')]
private ?User $createdBy = null;
#[ORM\ManyToOne(targetEntity: User::class)]
#[ORM\JoinColumn(onDelete: 'SET NULL')]
private ?User $updatedBy = null;
public function getCreatedBy(): ?User
{
return $this->createdBy;
}
public function setCreatedBy(?User $createdBy): self
{
$this->createdBy = $createdBy;
return $this;
}
public function getUpdatedBy(): ?User
{
return $this->updatedBy;
}
public function setUpdatedBy(?User $updatedBy): self
{
$this->updatedBy = $updatedBy;
return $this;
}
}
+14
View File
@@ -0,0 +1,14 @@
<?php
namespace App\Entity;
interface BlameableEntityInterface
{
public function getCreatedBy(): ?User;
public function setCreatedBy(?User $createdBy);
public function getUpdatedBy(): ?User;
public function setUpdatedBy(?User $updatedBy);
}
+217
View File
@@ -0,0 +1,217 @@
<?php
namespace App\Entity\Groups;
use App\Entity\BlameableEntity;
use App\Entity\BlameableEntityInterface;
use App\Entity\TimestampableEntity;
use App\Entity\TimestampableEntityInterface;
use App\Repository\Groups\AccommodationRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: AccommodationRepository::class)]
class Accommodation implements BlameableEntityInterface, TimestampableEntityInterface
{
use BlameableEntity;
use TimestampableEntity;
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $name = null;
#[ORM\Column(length: 16, unique: true)]
private ?string $code = null;
#[ORM\Column]
private ?int $minPaxSummer = null;
/**
* @var Collection<int, AccommodationPrice>
*/
#[ORM\OneToMany(targetEntity: AccommodationPrice::class, mappedBy: 'accommodation')]
private Collection $accommodationPrices;
/**
* @var Collection<int, BoardService>
*/
#[ORM\OneToMany(targetEntity: BoardService::class, mappedBy: 'accommodation')]
private Collection $boardServices;
/**
* @var Collection<int, AdditionalService>
*/
#[ORM\OneToMany(targetEntity: AdditionalService::class, mappedBy: 'accommodation')]
private Collection $additionalServices;
#[ORM\Column]
private ?int $maxAdolescentAge = null;
#[ORM\Column(length: 3)]
private ?string $currency = 'EUR';
public function __construct()
{
$this->accommodationPrices = new ArrayCollection();
$this->boardServices = new ArrayCollection();
$this->additionalServices = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getCode(): ?string
{
return $this->code;
}
public function setCode(string $code): self
{
$this->code = $code;
return $this;
}
public function getMinPaxSummer(): ?int
{
return $this->minPaxSummer;
}
public function setMinPaxSummer(int $minPaxSummer): self
{
$this->minPaxSummer = $minPaxSummer;
return $this;
}
/**
* @return Collection<int, AccommodationPrice>
*/
public function getAccommodationPrices(): Collection
{
return $this->accommodationPrices;
}
public function addAccommodationPrice(AccommodationPrice $accommodationPrice): self
{
if (!$this->accommodationPrices->contains($accommodationPrice)) {
$this->accommodationPrices->add($accommodationPrice);
$accommodationPrice->setAccommodation($this);
}
return $this;
}
public function removeAccommodationPrice(AccommodationPrice $accommodationPrice): self
{
if ($this->accommodationPrices->removeElement($accommodationPrice)) {
// set the owning side to null (unless already changed)
if ($accommodationPrice->getAccommodation() === $this) {
$accommodationPrice->setAccommodation(null);
}
}
return $this;
}
public function getMaxAdolescentAge(): ?int
{
return $this->maxAdolescentAge;
}
public function setMaxAdolescentAge(int $maxAdolescentAge): self
{
$this->maxAdolescentAge = $maxAdolescentAge;
return $this;
}
public function getCurrency(): ?string
{
return $this->currency;
}
public function setCurrency(string $currency): self
{
$this->currency = $currency;
return $this;
}
/**
* @return Collection<int, BoardService>
*/
public function getBoardServices(): Collection
{
return $this->boardServices;
}
public function addBoardService(BoardService $boardService): self
{
if (!$this->boardServices->contains($boardService)) {
$this->boardServices->add($boardService);
$boardService->setAccommodation($this);
}
return $this;
}
public function removeBoardService(BoardService $boardService): self
{
if ($this->boardServices->removeElement($boardService)) {
if ($boardService->getAccommodation() === $this) {
$boardService->setAccommodation(null);
}
}
return $this;
}
/**
* @return Collection<int, AdditionalService>
*/
public function getAdditionalServices(): Collection
{
return $this->additionalServices;
}
public function addAdditionalService(AdditionalService $additionalService): self
{
if (!$this->additionalServices->contains($additionalService)) {
$this->additionalServices->add($additionalService);
$additionalService->setAccommodation($this);
}
return $this;
}
public function removeAdditionalService(AdditionalService $additionalService): self
{
if ($this->additionalServices->removeElement($additionalService)) {
if ($additionalService->getAccommodation() === $this) {
$additionalService->setAccommodation(null);
}
}
return $this;
}
}
+134
View File
@@ -0,0 +1,134 @@
<?php
namespace App\Entity\Groups;
use App\Entity\BlameableEntity;
use App\Entity\BlameableEntityInterface;
use App\Entity\TimestampableEntity;
use App\Entity\TimestampableEntityInterface;
use App\Repository\Groups\AccommodationPriceRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: AccommodationPriceRepository::class)]
class AccommodationPrice implements BlameableEntityInterface, TimestampableEntityInterface
{
use BlameableEntity;
use TimestampableEntity;
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\ManyToOne(inversedBy: 'accommodationPrices')]
#[ORM\JoinColumn(nullable: false)]
private ?Accommodation $accommodation = null;
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
private ?\DateTimeImmutable $dateFrom = null;
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
private ?\DateTimeImmutable $dateTo = null;
#[ORM\Column]
private ?int $includedPax = null;
#[ORM\Column]
private ?int $pricePerNight = null;
#[ORM\Column]
private ?int $priceAdditionalPerson = null;
#[ORM\Column]
private ?int $minNights = null;
public function getId(): ?int
{
return $this->id;
}
public function getAccommodation(): ?Accommodation
{
return $this->accommodation;
}
public function setAccommodation(?Accommodation $accommodation): self
{
$this->accommodation = $accommodation;
return $this;
}
public function getDateFrom(): ?\DateTimeImmutable
{
return $this->dateFrom;
}
public function setDateFrom(\DateTimeImmutable $dateFrom): self
{
$this->dateFrom = $dateFrom;
return $this;
}
public function getDateTo(): ?\DateTimeImmutable
{
return $this->dateTo;
}
public function setDateTo(\DateTimeImmutable $dateTo): self
{
$this->dateTo = $dateTo;
return $this;
}
public function getIncludedPax(): ?int
{
return $this->includedPax;
}
public function setIncludedPax(int $includedPax): self
{
$this->includedPax = $includedPax;
return $this;
}
public function getPricePerNight(): ?int
{
return $this->pricePerNight;
}
public function setPricePerNight(int $pricePerNight): self
{
$this->pricePerNight = $pricePerNight;
return $this;
}
public function getPriceAdditionalPerson(): ?int
{
return $this->priceAdditionalPerson;
}
public function setPriceAdditionalPerson(int $priceAdditionalPerson): self
{
$this->priceAdditionalPerson = $priceAdditionalPerson;
return $this;
}
public function getMinNights(): ?int
{
return $this->minNights;
}
public function setMinNights(int $minNights): self
{
$this->minNights = $minNights;
return $this;
}
}
+150
View File
@@ -0,0 +1,150 @@
<?php
namespace App\Entity\Groups;
use App\Entity\BlameableEntity;
use App\Entity\BlameableEntityInterface;
use App\Entity\TimestampableEntity;
use App\Entity\TimestampableEntityInterface;
use App\Enum\Groups\AdditionalServiceType;
use App\Repository\Groups\AdditionalServiceRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: AdditionalServiceRepository::class)]
class AdditionalService implements BlameableEntityInterface, TimestampableEntityInterface
{
use BlameableEntity;
use TimestampableEntity;
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\ManyToOne(inversedBy: 'additionalServices')]
#[ORM\JoinColumn(nullable: false)]
private ?Accommodation $accommodation = null;
#[ORM\Column(length: 255)]
private ?string $label = null;
#[ORM\Column]
private ?int $price = null;
#[ORM\Column(length: 20, enumType: AdditionalServiceType::class)]
private ?AdditionalServiceType $type = null;
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
private ?\DateTimeImmutable $dateFrom = null;
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
private ?\DateTimeImmutable $dateTo = null;
#[ORM\Column(length: 128)]
private ?string $grouping = null;
#[ORM\Column]
private ?int $sorting = 0;
public function getId(): ?int
{
return $this->id;
}
public function getAccommodation(): ?Accommodation
{
return $this->accommodation;
}
public function setAccommodation(?Accommodation $accommodation): self
{
$this->accommodation = $accommodation;
return $this;
}
public function getLabel(): ?string
{
return $this->label;
}
public function setLabel(string $label): self
{
$this->label = $label;
return $this;
}
public function getPrice(): ?int
{
return $this->price;
}
public function setPrice(int $price): self
{
$this->price = $price;
return $this;
}
public function getType(): ?AdditionalServiceType
{
return $this->type;
}
public function setType(AdditionalServiceType $type): self
{
$this->type = $type;
return $this;
}
public function getDateFrom(): ?\DateTimeImmutable
{
return $this->dateFrom;
}
public function setDateFrom(\DateTimeImmutable $dateFrom): self
{
$this->dateFrom = $dateFrom;
return $this;
}
public function getDateTo(): ?\DateTimeImmutable
{
return $this->dateTo;
}
public function setDateTo(\DateTimeImmutable $dateTo): self
{
$this->dateTo = $dateTo;
return $this;
}
public function getGrouping(): ?string
{
return $this->grouping;
}
public function setGrouping(?string $grouping): self
{
$this->grouping = $grouping;
return $this;
}
public function getSorting(): ?int
{
return $this->sorting;
}
public function setSorting(?int $sorting): self
{
$this->sorting = $sorting;
return $this;
}
}
+119
View File
@@ -0,0 +1,119 @@
<?php
namespace App\Entity\Groups;
use App\Entity\BlameableEntity;
use App\Entity\BlameableEntityInterface;
use App\Entity\TimestampableEntity;
use App\Entity\TimestampableEntityInterface;
use App\Repository\Groups\BoardServiceRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: BoardServiceRepository::class)]
class BoardService implements BlameableEntityInterface, TimestampableEntityInterface
{
use BlameableEntity;
use TimestampableEntity;
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\ManyToOne(inversedBy: 'boardServices')]
#[ORM\JoinColumn(nullable: false)]
private ?Accommodation $accommodation = null;
#[ORM\Column(length: 255)]
private ?string $label = null;
#[ORM\Column]
private ?int $price = null;
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
private ?\DateTimeImmutable $dateFrom = null;
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
private ?\DateTimeImmutable $dateTo = null;
#[ORM\Column]
private ?int $sorting = 0;
public function getId(): ?int
{
return $this->id;
}
public function getAccommodation(): ?Accommodation
{
return $this->accommodation;
}
public function setAccommodation(?Accommodation $accommodation): self
{
$this->accommodation = $accommodation;
return $this;
}
public function getLabel(): ?string
{
return $this->label;
}
public function setLabel(string $label): self
{
$this->label = $label;
return $this;
}
public function getPrice(): ?int
{
return $this->price;
}
public function setPrice(int $price): self
{
$this->price = $price;
return $this;
}
public function getDateFrom(): ?\DateTimeImmutable
{
return $this->dateFrom;
}
public function setDateFrom(\DateTimeImmutable $dateFrom): self
{
$this->dateFrom = $dateFrom;
return $this;
}
public function getDateTo(): ?\DateTimeImmutable
{
return $this->dateTo;
}
public function setDateTo(\DateTimeImmutable $dateTo): self
{
$this->dateTo = $dateTo;
return $this;
}
public function getSorting(): ?int
{
return $this->sorting;
}
public function setSorting(?int $sorting): self
{
$this->sorting = $sorting;
return $this;
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
trait TimestampableEntity
{
#[ORM\Column(type: 'datetime_immutable')]
private ?\DateTimeImmutable $createdAt = null;
#[ORM\Column(type: 'datetime_immutable', nullable: true)]
private ?\DateTimeImmutable $updatedAt = null;
public function getCreatedAt(): \DateTimeImmutable
{
return $this->createdAt;
}
public function setCreatedAt(\DateTimeImmutable $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getUpdatedAt(): ?\DateTimeImmutable
{
return $this->updatedAt;
}
public function setUpdatedAt(\DateTimeImmutable $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
}
@@ -0,0 +1,14 @@
<?php
namespace App\Entity;
interface TimestampableEntityInterface
{
public function getCreatedAt();
public function setCreatedAt(\DateTimeImmutable $createdAt);
public function getUpdatedAt();
public function setUpdatedAt(\DateTimeImmutable $updatedAt);
}
+11
View File
@@ -0,0 +1,11 @@
<?php
namespace App\Enum\Groups;
enum AdditionalServiceType: string
{
case Flat = 'flat';
case PerPerson = 'per_person';
case PerNight = 'per_night';
case PerPersonPerNight = 'per_person_per_night';
}
@@ -0,0 +1,41 @@
<?php
namespace App\EventListener;
use App\Entity\BlameableEntityInterface;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\ORM\Event\PrePersistEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Doctrine\ORM\Events;
use Symfony\Bundle\SecurityBundle\Security;
#[AsDoctrineListener(Events::prePersist)]
#[AsDoctrineListener(Events::preUpdate)]
class BlamableEntityListener
{
public function __construct(private Security $security)
{
}
public function prePersist(PrePersistEventArgs $args): void
{
$entity = $args->getObject();
if (!$entity instanceof BlameableEntityInterface) {
return;
}
$entity->setCreatedBy($this->security->getUser());
}
public function preUpdate(PreUpdateEventArgs $args): void
{
$entity = $args->getObject();
if (!$entity instanceof BlameableEntityInterface) {
return;
}
$entity->setUpdatedBy($this->security->getUser());
}
}
@@ -0,0 +1,34 @@
<?php
namespace App\EventListener;
use App\Entity\TimestampableEntityInterface;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\ORM\Event\PrePersistEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Doctrine\ORM\Events;
#[AsDoctrineListener(Events::prePersist)]
#[AsDoctrineListener(Events::preUpdate)]
class TimestampableEntityListener
{
public function prePersist(PrePersistEventArgs $args): void
{
$entity = $args->getObject();
if ($entity instanceof TimestampableEntityInterface) {
$now = new \DateTimeImmutable();
$entity->setCreatedAt($now);
}
}
public function preUpdate(PreUpdateEventArgs $args): void
{
$entity = $args->getObject();
if ($entity instanceof TimestampableEntityInterface) {
$now = new \DateTimeImmutable();
$entity->setUpdatedAt($now);
}
}
}
@@ -0,0 +1,43 @@
<?php
namespace App\Repository\Groups;
use App\Entity\Groups\AccommodationPrice;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<AccommodationPrice>
*/
class AccommodationPriceRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, AccommodationPrice::class);
}
// /**
// * @return AccommodationPrice[] Returns an array of AccommodationPrice objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('a')
// ->andWhere('a.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('a.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?AccommodationPrice
// {
// return $this->createQueryBuilder('a')
// ->andWhere('a.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}
@@ -0,0 +1,43 @@
<?php
namespace App\Repository\Groups;
use App\Entity\Groups\Accommodation;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<Accommodation>
*/
class AccommodationRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Accommodation::class);
}
// /**
// * @return Accommodation[] Returns an array of Accommodation objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('a')
// ->andWhere('a.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('a.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?Accommodation
// {
// return $this->createQueryBuilder('a')
// ->andWhere('a.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}
@@ -0,0 +1,18 @@
<?php
namespace App\Repository\Groups;
use App\Entity\Groups\AdditionalService;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<AdditionalService>
*/
class AdditionalServiceRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, AdditionalService::class);
}
}
@@ -0,0 +1,18 @@
<?php
namespace App\Repository\Groups;
use App\Entity\Groups\BoardService;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<BoardService>
*/
class BoardServiceRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, BoardService::class);
}
}