<?php
namespace App\Entity;
use App\Entity\Enum\RegistrationStatus;
use App\Entity\Traits\Identifiable;
use App\Repository\FamilyRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: FamilyRepository::class)]
class Family
{
//TODO: ajouter un listener pour définir le responsable automatiquement à la création
use Identifiable;
#[ORM\Column(type: 'string', length: 150)]
private $lastName;
#[ORM\OneToMany(mappedBy: 'family', targetEntity: Person::class, cascade: ['remove'])]
private $persons;
#[ORM\OneToOne(targetEntity: Person::class)]
private $responsiblePerson;
#[ORM\Embedded(class: Address::class)]
private $address;
#[ORM\Column(type: 'integer', nullable: true)]
private $oldId;
#[ORM\OneToMany(mappedBy: 'family', targetEntity: LegalPerson::class)]
private Collection $legalPersons;
public function __construct()
{
$this->persons = new ArrayCollection();
$this->legalPersons = new ArrayCollection();
}
public function __toString(): string
{
return $this->getLastName(true);
}
public function getId(): ?int
{
return $this->id;
}
public function getLastName(?bool $uppercase = false): ?string
{
return $uppercase ? mb_strtoupper($this->lastName) : $this->lastName;
}
public function setLastName(string $lastName): self
{
$this->lastName = $lastName;
return $this;
}
/**
* @return Collection<int, Person>
*/
public function getPersons(): Collection
{
return $this->persons;
}
public function addPerson(Person $person): self
{
if (!$this->persons->contains($person)) {
$this->persons[] = $person;
$person->setFamily($this);
}
return $this;
}
public function removePerson(Person $person): self
{
if ($this->persons->removeElement($person)) {
// set the owning side to null (unless already changed)
if ($person->getFamily() === $this) {
$person->setFamily(null);
}
}
return $this;
}
/**
* @param array|Person[] $persons
* @return $this
*/
public function setPersons(array $persons): self
{
$collection = new ArrayCollection();
foreach ($persons as $person) {
if (!$collection->contains($person)) {
$collection->add($person);
}
}
$this->persons = $collection;
return $this;
}
/**
* @return Collection<int, Person>
*/
public function getAdults(): Collection
{
$maxBirthDate = new \DateTimeImmutable('-18 years');
$collection = new ArrayCollection();
$responsiblePerson = $this->getResponsiblePerson();
if ($responsiblePerson) {
$collection->add($responsiblePerson);
}
foreach ($this->getPersons() as $person) {
if ($collection->contains($person)) {
continue;
}
$birthDate = $person->getBirthDate();
if ($birthDate && $birthDate < $maxBirthDate) {
$collection->add($person);
continue;
}
if ($person->getWards()->count() > 0) {
$collection->add($person);
}
}
return $collection;
}
public function getResponsiblePerson(): ?Person
{
return $this->responsiblePerson;
}
public function setResponsiblePerson(?Person $responsiblePerson): self
{
$this->responsiblePerson = $responsiblePerson;
return $this;
}
public function getAddress(): ?Address
{
return $this->address;
}
public function setAddress(?Address $address)
{
$this->address = $address;
return $this;
}
/**
* @param Section|null $section
* @return Collection<int, Registration>
*/
public function getRegistrations(?Section $section = null): Collection
{
$registrations = new ArrayCollection();
foreach ($this->getPersons() as $person) {
foreach ($person->getRegistrations($section) as $registration) {
$registrations->add($registration);
}
}
return $registrations;
}
/**
* @param Section|null $section
* @return Collection<int, Registration>
*/
public function getActiveRegistrations(?Section $section = null): Collection
{
$registrations = new ArrayCollection();
foreach ($this->getPersons() as $person) {
foreach ($person->getActiveRegistrations($section) as $activeRegistration) {
$registrations->add($activeRegistration);
}
}
return $registrations;
}
public function getOldId(): ?int
{
return $this->oldId;
}
public function setOldId(?int $oldId): self
{
$this->oldId = $oldId;
return $this;
}
public function remainingToPay(?Section $section = null, $validStatusesOnly = false): float
{
$remaining = 0;
foreach ($this->getPersons() as $person) {
foreach ($person->getActiveRegistrations($section) as $activeRegistration) {
if ($validStatusesOnly && !in_array(
$activeRegistration->getStatus(),
RegistrationStatus::VALID_VALUES,
true
)) {
continue;
}
$remaining += $activeRegistration->getOrder()->getRemainingAmount(false);
}
}
return $remaining;
}
public function getTotalToPay(?Section $section = null): float
{
$total = 0;
foreach ($this->getPersons() as $person) {
foreach ($person->getActiveRegistrations() as $activeRegistration) {
if ($section === null || $section === $activeRegistration->getSeason()->getSection()) {
if (in_array($activeRegistration->getStatus(), RegistrationStatus::VALID_VALUES, true)) {
$total += $activeRegistration->getOrder()?->getAmount() ?? 0.0;
}
}
}
}
return $total;
}
/**
* @return Collection<int, Debt>
*/
public function getDebts(): Collection
{
$collection = new ArrayCollection();
foreach ($this->getPersons() as $person) {
foreach ($person->getDebts() as $debt) {
$collection->add($debt);
}
}
return $collection;
}
/**
* @return Collection<int, Debt>
*/
public function getUnpaidDebts(): Collection
{
return $this->getDebts()->filter(fn(Debt $debt) => $debt->getAmountPayed() < $debt->getAmount());
}
/**
* @return Collection<int, LegalPerson>
*/
public function getLegalPersons(): Collection
{
return $this->legalPersons;
}
public function addLegalPerson(LegalPerson $legalPerson): self
{
if (!$this->legalPersons->contains($legalPerson)) {
$this->legalPersons->add($legalPerson);
$legalPerson->setFamily($this);
}
return $this;
}
public function removeLegalPerson(LegalPerson $legalPerson): self
{
if ($this->legalPersons->removeElement($legalPerson)) {
// set the owning side to null (unless already changed)
if ($legalPerson->getFamily() === $this) {
$legalPerson->setFamily(null);
}
}
return $this;
}
/**
* @return Collection<int, Donation>
*/
public function getDonations(?Section $section = null): Collection
{
$donations = new ArrayCollection();
foreach ($this->getPersons() as $person) {
foreach ($person->getDonations() as $donation) {
if ($section === null || $donation->getSection() === $section) {
$donations->add($donation);
}
}
}
foreach ($this->getLegalPersons() as $person) {
foreach ($person->getDonations() as $donation) {
if ($section === null || $donation->getSection() === $section) {
$donations->add($donation);
}
}
}
return $donations;
}
}