Immobilien & User hinzugefügt
This commit is contained in:
37
src/Controller/ImmobilieController.php
Normal file
37
src/Controller/ImmobilieController.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Immobilie;
|
||||
use App\Repository\ImmobilieRepository;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
#[Route('/immobilien')]
|
||||
class ImmobilieController extends AbstractController
|
||||
{
|
||||
#[Route('/', name: 'app_immobilie_index')]
|
||||
public function index(ImmobilieRepository $repository): Response
|
||||
{
|
||||
$immobilien = $repository->findVerfuegbare();
|
||||
|
||||
return $this->render('immobilie/index.html.twig', [
|
||||
'immobilien' => $immobilien,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/{id}', name: 'app_immobilie_show', requirements: ['id' => '\d+'])]
|
||||
public function show(Immobilie $immobilie): Response
|
||||
{
|
||||
return $this->render('immobilie/show.html.twig', [
|
||||
'immobilie' => $immobilie,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/suche', name: 'app_immobilie_suche')]
|
||||
public function suche(ImmobilieRepository $repository): Response
|
||||
{
|
||||
return $this->render('immobilie/suche.html.twig');
|
||||
}
|
||||
}
|
||||
325
src/Entity/Immobilie.php
Normal file
325
src/Entity/Immobilie.php
Normal file
@@ -0,0 +1,325 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use App\Enum\ImmobilienTyp;
|
||||
use App\Repository\ImmobilieRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
|
||||
#[ORM\Entity(repositoryClass: ImmobilieRepository::class)]
|
||||
#[ORM\Table(name: 'immobilien')]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ApiResource]
|
||||
class Immobilie
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(type: 'integer')]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'immobilien')]
|
||||
#[ORM\JoinColumn(nullable: false)]
|
||||
#[Assert\NotNull]
|
||||
private User $verwalter;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 255)]
|
||||
#[Assert\NotBlank]
|
||||
#[Assert\Length(min: 5, max: 255)]
|
||||
private string $adresse;
|
||||
|
||||
#[ORM\Column(type: 'decimal', precision: 10, scale: 2)]
|
||||
#[Assert\NotBlank]
|
||||
#[Assert\Positive]
|
||||
private float $preis;
|
||||
|
||||
#[ORM\Column(type: 'decimal', precision: 8, scale: 2)]
|
||||
#[Assert\NotBlank]
|
||||
#[Assert\Positive]
|
||||
private float $flaeche;
|
||||
|
||||
#[ORM\Column(type: 'boolean')]
|
||||
private bool $garage = false;
|
||||
|
||||
#[ORM\Column(type: 'integer')]
|
||||
#[Assert\NotBlank]
|
||||
#[Assert\Positive]
|
||||
private int $zimmer;
|
||||
|
||||
#[ORM\Column(type: 'integer', nullable: true)]
|
||||
#[Assert\Range(min: 1800, max: 2100)]
|
||||
private ?int $baujahr = null;
|
||||
|
||||
#[ORM\Column(type: 'string', enumType: ImmobilienTyp::class)]
|
||||
private ImmobilienTyp $typ;
|
||||
|
||||
#[ORM\Column(type: 'text', nullable: true)]
|
||||
private ?string $beschreibung = null;
|
||||
|
||||
#[ORM\Column(type: 'boolean')]
|
||||
private bool $verfuegbar = true;
|
||||
|
||||
#[ORM\Column(type: 'integer', nullable: true)]
|
||||
#[Assert\PositiveOrZero]
|
||||
private ?int $balkonFlaeche = null;
|
||||
|
||||
#[ORM\Column(type: 'integer', nullable: true)]
|
||||
#[Assert\PositiveOrZero]
|
||||
private ?int $kellerFlaeche = null;
|
||||
|
||||
#[ORM\Column(type: 'integer', nullable: true)]
|
||||
#[Assert\Min(0)]
|
||||
#[Assert\Max(10)]
|
||||
private ?int $etage = null;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 100, nullable: true)]
|
||||
private ?string $heizungstyp = null;
|
||||
|
||||
#[ORM\Column(type: 'decimal', precision: 6, scale: 2, nullable: true)]
|
||||
#[Assert\PositiveOrZero]
|
||||
private ?float $nebenkosten = null;
|
||||
|
||||
#[ORM\Column(type: 'datetime')]
|
||||
private \DateTimeInterface $createdAt;
|
||||
|
||||
#[ORM\Column(type: 'datetime')]
|
||||
private \DateTimeInterface $updatedAt;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->createdAt = new \DateTime();
|
||||
$this->updatedAt = new \DateTime();
|
||||
$this->typ = ImmobilienTyp::WOHNUNG;
|
||||
}
|
||||
|
||||
#[ORM\PreUpdate]
|
||||
public function setUpdatedAtValue(): void
|
||||
{
|
||||
$this->updatedAt = new \DateTime();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getAdresse(): string
|
||||
{
|
||||
return $this->adresse;
|
||||
}
|
||||
|
||||
public function setAdresse(string $adresse): self
|
||||
{
|
||||
$this->adresse = $adresse;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPreis(): float
|
||||
{
|
||||
return $this->preis;
|
||||
}
|
||||
|
||||
public function setPreis(float $preis): self
|
||||
{
|
||||
$this->preis = $preis;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFlaeche(): float
|
||||
{
|
||||
return $this->flaeche;
|
||||
}
|
||||
|
||||
public function setFlaeche(float $flaeche): self
|
||||
{
|
||||
$this->flaeche = $flaeche;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getGarage(): bool
|
||||
{
|
||||
return $this->garage;
|
||||
}
|
||||
|
||||
public function isGarage(): bool
|
||||
{
|
||||
return $this->garage;
|
||||
}
|
||||
|
||||
public function setGarage(bool $garage): self
|
||||
{
|
||||
$this->garage = $garage;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getZimmer(): int
|
||||
{
|
||||
return $this->zimmer;
|
||||
}
|
||||
|
||||
public function setZimmer(int $zimmer): self
|
||||
{
|
||||
$this->zimmer = $zimmer;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBaujahr(): ?int
|
||||
{
|
||||
return $this->baujahr;
|
||||
}
|
||||
|
||||
public function setBaujahr(?int $baujahr): self
|
||||
{
|
||||
$this->baujahr = $baujahr;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTyp(): ImmobilienTyp
|
||||
{
|
||||
return $this->typ;
|
||||
}
|
||||
|
||||
public function setTyp(ImmobilienTyp $typ): self
|
||||
{
|
||||
$this->typ = $typ;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBeschreibung(): ?string
|
||||
{
|
||||
return $this->beschreibung;
|
||||
}
|
||||
|
||||
public function setBeschreibung(?string $beschreibung): self
|
||||
{
|
||||
$this->beschreibung = $beschreibung;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isVerfuegbar(): bool
|
||||
{
|
||||
return $this->verfuegbar;
|
||||
}
|
||||
|
||||
public function setVerfuegbar(bool $verfuegbar): self
|
||||
{
|
||||
$this->verfuegbar = $verfuegbar;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBalkonFlaeche(): ?int
|
||||
{
|
||||
return $this->balkonFlaeche;
|
||||
}
|
||||
|
||||
public function setBalkonFlaeche(?int $balkonFlaeche): self
|
||||
{
|
||||
$this->balkonFlaeche = $balkonFlaeche;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getKellerFlaeche(): ?int
|
||||
{
|
||||
return $this->kellerFlaeche;
|
||||
}
|
||||
|
||||
public function setKellerFlaeche(?int $kellerFlaeche): self
|
||||
{
|
||||
$this->kellerFlaeche = $kellerFlaeche;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEtage(): ?int
|
||||
{
|
||||
return $this->etage;
|
||||
}
|
||||
|
||||
public function setEtage(?int $etage): self
|
||||
{
|
||||
$this->etage = $etage;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHeizungstyp(): ?string
|
||||
{
|
||||
return $this->heizungstyp;
|
||||
}
|
||||
|
||||
public function setHeizungstyp(?string $heizungstyp): self
|
||||
{
|
||||
$this->heizungstyp = $heizungstyp;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNebenkosten(): ?float
|
||||
{
|
||||
return $this->nebenkosten;
|
||||
}
|
||||
|
||||
public function setNebenkosten(?float $nebenkosten): self
|
||||
{
|
||||
$this->nebenkosten = $nebenkosten;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): \DateTimeInterface
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function setCreatedAt(\DateTimeInterface $createdAt): self
|
||||
{
|
||||
$this->createdAt = $createdAt;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): \DateTimeInterface
|
||||
{
|
||||
return $this->updatedAt;
|
||||
}
|
||||
|
||||
public function setUpdatedAt(\DateTimeInterface $updatedAt): self
|
||||
{
|
||||
$this->updatedAt = $updatedAt;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getVerwalter(): User
|
||||
{
|
||||
return $this->verwalter;
|
||||
}
|
||||
|
||||
public function setVerwalter(User $verwalter): self
|
||||
{
|
||||
$this->verwalter = $verwalter;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Berechnet den Preis pro Quadratmeter
|
||||
*/
|
||||
public function getPreisProQm(): float
|
||||
{
|
||||
if ($this->flaeche > 0) {
|
||||
return round($this->preis / $this->flaeche, 2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Berechnet die Gesamtfläche inkl. Balkon und Keller
|
||||
*/
|
||||
public function getGesamtflaeche(): float
|
||||
{
|
||||
$gesamt = $this->flaeche;
|
||||
if ($this->balkonFlaeche) {
|
||||
$gesamt += $this->balkonFlaeche;
|
||||
}
|
||||
if ($this->kellerFlaeche) {
|
||||
$gesamt += $this->kellerFlaeche;
|
||||
}
|
||||
return $gesamt;
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,8 @@ use ApiPlatform\Metadata\Put;
|
||||
use ApiPlatform\Metadata\Delete;
|
||||
use App\Enum\UserRole;
|
||||
use App\Repository\UserRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
@@ -47,10 +49,14 @@ class User
|
||||
#[ORM\Column(type: 'datetime')]
|
||||
private \DateTimeInterface $createdAt;
|
||||
|
||||
#[ORM\OneToMany(targetEntity: Immobilie::class, mappedBy: 'verwalter', orphanRemoval: true)]
|
||||
private Collection $immobilien;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->createdAt = new \DateTime();
|
||||
$this->role = UserRole::USER;
|
||||
$this->immobilien = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
@@ -101,4 +107,28 @@ class User
|
||||
$this->createdAt = $createdAt;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, Immobilie>
|
||||
*/
|
||||
public function getImmobilien(): Collection
|
||||
{
|
||||
return $this->immobilien;
|
||||
}
|
||||
|
||||
public function addImmobilie(Immobilie $immobilie): self
|
||||
{
|
||||
if (!$this->immobilien->contains($immobilie)) {
|
||||
$this->immobilien->add($immobilie);
|
||||
$immobilie->setVerwalter($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeImmobilie(Immobilie $immobilie): self
|
||||
{
|
||||
$this->immobilien->removeElement($immobilie);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
23
src/Enum/ImmobilienTyp.php
Normal file
23
src/Enum/ImmobilienTyp.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enum;
|
||||
|
||||
enum ImmobilienTyp: string
|
||||
{
|
||||
case WOHNUNG = 'wohnung';
|
||||
case HAUS = 'haus';
|
||||
case GRUNDSTUECK = 'grundstueck';
|
||||
case GEWERBE = 'gewerbe';
|
||||
case BUERO = 'buero';
|
||||
|
||||
public function getLabel(): string
|
||||
{
|
||||
return match($this) {
|
||||
self::WOHNUNG => 'Wohnung',
|
||||
self::HAUS => 'Haus',
|
||||
self::GRUNDSTUECK => 'Grundstück',
|
||||
self::GEWERBE => 'Gewerbe',
|
||||
self::BUERO => 'Büro',
|
||||
};
|
||||
}
|
||||
}
|
||||
137
src/Repository/ImmobilieRepository.php
Normal file
137
src/Repository/ImmobilieRepository.php
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Immobilie;
|
||||
use App\Enum\ImmobilienTyp;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Immobilie>
|
||||
*/
|
||||
class ImmobilieRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Immobilie::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find available properties
|
||||
*/
|
||||
public function findVerfuegbare(): array
|
||||
{
|
||||
return $this->createQueryBuilder('i')
|
||||
->andWhere('i.verfuegbar = :verfuegbar')
|
||||
->setParameter('verfuegbar', true)
|
||||
->orderBy('i.createdAt', 'DESC')
|
||||
->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find properties by type
|
||||
*/
|
||||
public function findByTyp(ImmobilienTyp $typ): array
|
||||
{
|
||||
return $this->createQueryBuilder('i')
|
||||
->andWhere('i.typ = :typ')
|
||||
->setParameter('typ', $typ)
|
||||
->orderBy('i.preis', 'ASC')
|
||||
->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find properties within price range
|
||||
*/
|
||||
public function findByPreisRange(float $minPreis, float $maxPreis): array
|
||||
{
|
||||
return $this->createQueryBuilder('i')
|
||||
->andWhere('i.preis BETWEEN :minPreis AND :maxPreis')
|
||||
->andWhere('i.verfuegbar = :verfuegbar')
|
||||
->setParameter('minPreis', $minPreis)
|
||||
->setParameter('maxPreis', $maxPreis)
|
||||
->setParameter('verfuegbar', true)
|
||||
->orderBy('i.preis', 'ASC')
|
||||
->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find properties within area range
|
||||
*/
|
||||
public function findByFlaecheRange(float $minFlaeche, float $maxFlaeche): array
|
||||
{
|
||||
return $this->createQueryBuilder('i')
|
||||
->andWhere('i.flaeche BETWEEN :minFlaeche AND :maxFlaeche')
|
||||
->andWhere('i.verfuegbar = :verfuegbar')
|
||||
->setParameter('minFlaeche', $minFlaeche)
|
||||
->setParameter('maxFlaeche', $maxFlaeche)
|
||||
->setParameter('verfuegbar', true)
|
||||
->orderBy('i.flaeche', 'ASC')
|
||||
->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find properties with garage
|
||||
*/
|
||||
public function findMitGarage(): array
|
||||
{
|
||||
return $this->createQueryBuilder('i')
|
||||
->andWhere('i.garage = :garage')
|
||||
->andWhere('i.verfuegbar = :verfuegbar')
|
||||
->setParameter('garage', true)
|
||||
->setParameter('verfuegbar', true)
|
||||
->orderBy('i.preis', 'ASC')
|
||||
->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find properties by minimum number of rooms
|
||||
*/
|
||||
public function findByMinZimmer(int $minZimmer): array
|
||||
{
|
||||
return $this->createQueryBuilder('i')
|
||||
->andWhere('i.zimmer >= :minZimmer')
|
||||
->andWhere('i.verfuegbar = :verfuegbar')
|
||||
->setParameter('minZimmer', $minZimmer)
|
||||
->setParameter('verfuegbar', true)
|
||||
->orderBy('i.zimmer', 'ASC')
|
||||
->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get average price per sqm by type
|
||||
*/
|
||||
public function getAveragePreisProQmByTyp(ImmobilienTyp $typ): float
|
||||
{
|
||||
$result = $this->createQueryBuilder('i')
|
||||
->select('AVG(i.preis / i.flaeche) as avgPreisProQm')
|
||||
->andWhere('i.typ = :typ')
|
||||
->andWhere('i.verfuegbar = :verfuegbar')
|
||||
->setParameter('typ', $typ)
|
||||
->setParameter('verfuegbar', true)
|
||||
->getQuery()
|
||||
->getSingleScalarResult();
|
||||
|
||||
return round((float) $result, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search properties by address
|
||||
*/
|
||||
public function searchByAdresse(string $search): array
|
||||
{
|
||||
return $this->createQueryBuilder('i')
|
||||
->andWhere('i.adresse LIKE :search')
|
||||
->setParameter('search', '%' . $search . '%')
|
||||
->orderBy('i.createdAt', 'DESC')
|
||||
->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user