addresses = new ArrayCollection(); $this->members = new ArrayCollection(); $this->commentMembers = new CommentEmbeddable(); } /** * @return $this */ public function addAddress(Address $address) { foreach ($this->getAddresses() as $a) { if ($a->getValidFrom() <= $address->getValidFrom() && $a->getValidTo() === null) { $a->setValidTo($address->getValidFrom()); } } $this->addresses[] = $address; return $this; } public function addMember(HouseholdMember $member): self { if (!$this->members->contains($member)) { $this->members[] = $member; $member->setHousehold($this); } return $this; } /** * By default, the addresses are ordered by date, descending (the most * recent first). * * @Assert\Callback(methods={"validate"}) * * @return \Chill\MainBundle\Entity\Address[] */ public function getAddresses() { return $this->addresses; } public function getCommentMembers(): CommentEmbeddable { return $this->commentMembers; } /** * @Serializer\Groups({"read", "docgen:read"}) * @Serializer\SerializedName("current_address") */ public function getCurrentAddress(?DateTime $at = null): ?Address { $at = null === $at ? new DateTime('today') : $at; $addrs = $this->getAddresses()->filter(static function (Address $a) use ($at) { return $a->getValidFrom() <= $at && ( null === $a->getValidTo() || $a->getValidTo() > $at ); }); if ($addrs->count() > 0) { return $addrs->first(); } return null; } /** * @Serializer\Groups({"docgen:read"}) */ public function getCurrentMembers(?DateTimeImmutable $now = null): Collection { return $this->getMembers()->matching($this->buildCriteriaCurrentMembers($now)); } public function getCurrentMembersByPosition(Position $position, ?DateTimeInterface $now = null) { $criteria = new Criteria(); $expr = Criteria::expr(); $criteria->where($expr->eq('position', $position)); return $this->getCurrentMembers($now)->matching($criteria); } /** * get current members ids. * * Used in serialization * * @Serializer\Groups({"read"}) * @Serializer\SerializedName("current_members_id") */ public function getCurrentMembersIds(?DateTimeImmutable $now = null): Collection { return $this->getCurrentMembers($now)->map( static fn (HouseholdMember $m) => $m->getId() ); } /** * @return HouseholdMember[] */ public function getCurrentMembersOrdered(?DateTimeImmutable $now = null): Collection { $members = $this->getCurrentMembers($now); $members->getIterator() ->uasort( static function (HouseholdMember $a, HouseholdMember $b) { if ($a->getPosition() === null) { if ($b->getPosition() === null) { return 0; } return -1; } if ($b->getPosition() === null) { return 1; } if ($a->getPosition()->getOrdering() < $b->getPosition()->getOrdering()) { return -1; } if ($a->getPosition()->getOrdering() > $b->getPosition()->getOrdering()) { return 1; } if ($a->isHolder() && !$b->isHolder()) { return 1; } if (!$a->isHolder() && $b->isHolder()) { return -1; } return 0; } ); return $members; } public function getCurrentMembersWithoutPosition(?DateTimeInterface $now = null) { $criteria = new Criteria(); $expr = Criteria::expr(); $criteria->where($expr->isNull('position')); return $this->getCurrentMembers($now)->matching($criteria); } /** * Get the persons currently associated to the household. * * Return a list of Person, instead of a list of HouseholdMembers * * @return Person[] */ public function getCurrentPersons(?DateTimeImmutable $now = null): Collection { return $this->getCurrentMembers($now) ->map(static function (HouseholdMember $m) { return $m->getPerson(); }); } public function getId(): ?int { return $this->id; } /** * @return Collection|HouseholdMember[] */ public function getMembers(): Collection { return $this->members; } public function getMembersDuringMembership(HouseholdMember $membership) { return $this->getMembersOnRange( $membership->getStartDate(), $membership->getEndDate() )->filter( static function (HouseholdMember $m) use ($membership) { return $m !== $membership; } ); } public function getMembersHolder(): Collection { $criteria = new Criteria(); $expr = Criteria::expr(); $criteria->where( $expr->eq('holder', true) ); return $this->getMembers()->matching($criteria); } public function getMembersOnRange(DateTimeImmutable $from, ?DateTimeImmutable $to): Collection { $criteria = new Criteria(); $expr = Criteria::expr(); $criteria->where( $expr->gte('startDate', $from) ); if (null !== $to) { $criteria->andWhere( $expr->orX( $expr->lte('endDate', $to), $expr->eq('endDate', null) ), ); } return $this->getMembers() ->matching($criteria); } public function getNonCurrentMembers(?DateTimeImmutable $now = null): Collection { $criteria = new Criteria(); $expr = Criteria::expr(); $date = null === $now ? (new DateTimeImmutable('today')) : $now; $criteria ->where( $expr->gt('startDate', $date) ) ->orWhere( $expr->andX( $expr->lte('endDate', $date), $expr->neq('endDate', null) ) ); return $this->getMembers()->matching($criteria); } public function getNonCurrentMembersByPosition(Position $position, ?DateTimeInterface $now = null) { $criteria = new Criteria(); $expr = Criteria::expr(); $criteria->where($expr->eq('position', $position)); return $this->getNonCurrentMembers($now)->matching($criteria); } public function getNonCurrentMembersWithoutPosition(?DateTimeInterface $now = null) { $criteria = new Criteria(); $expr = Criteria::expr(); $criteria->where($expr->isNull('position')); return $this->getNonCurrentMembers($now)->matching($criteria); } public function getWaitingForBirth(): bool { return $this->waitingForBirth; } public function getWaitingForBirthDate(): ?DateTimeImmutable { return $this->waitingForBirthDate; } public function removeAddress(Address $address) { $this->addresses->removeElement($address); } public function removeMember(HouseholdMember $member): self { if ($this->members->removeElement($member)) { // set the owning side to null (unless already changed) if ($member->getHousehold() === $this) { $member->setHousehold(null); } } return $this; } public function setCommentMembers(CommentEmbeddable $commentMembers): self { $this->commentMembers = $commentMembers; return $this; } /** * Force an address starting at the current day * on the Household. * * This will force the startDate's address on today. * * Used on household creation. * * @Serializer\Groups({"create"}) */ public function setForceAddress(Address $address) { $address->setValidFrom(new DateTime('today')); $this->addAddress($address); } public function setWaitingForBirth(bool $waitingForBirth): self { $this->waitingForBirth = $waitingForBirth; return $this; } public function setWaitingForBirthDate(?DateTimeImmutable $waitingForBirthDate): self { $this->waitingForBirthDate = $waitingForBirthDate; return $this; } public function validate(ExecutionContextInterface $context, $payload) { $addresses = $this->getAddresses(); $cond = true; for ($i = 0; count($addresses) - 1 > $i; ++$i) { if ($addresses[$i]->getValidFrom() !== $addresses[$i + 1]->getValidTo()) { $cond = false; $context->buildViolation('The address are not sequentials. The validFrom date of one address should be equal to the validTo date of the previous address.') ->atPath('addresses') ->addViolation(); } } } private function buildCriteriaCurrentMembers(?DateTimeImmutable $now = null): Criteria { $criteria = new Criteria(); $expr = Criteria::expr(); $date = null === $now ? (new DateTimeImmutable('today')) : $now; $criteria ->where($expr->orX( $expr->isNull('startDate'), $expr->lte('startDate', $date) )) ->andWhere($expr->orX( $expr->isNull('endDate'), $expr->gt('endDate', $date) )); return $criteria; } }