diff --git a/src/Bundle/ChillPersonBundle/Entity/Household/Household.php b/src/Bundle/ChillPersonBundle/Entity/Household/Household.php index db7ef2c2b..fb0c2b110 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Household/Household.php +++ b/src/Bundle/ChillPersonBundle/Entity/Household/Household.php @@ -98,6 +98,18 @@ class Household return $this->members; } + public function getMembersHolder(): Collection + { + $criteria = new Criteria(); + $expr = Criteria::expr(); + + $criteria->where( + $expr->eq('holder', true) + ); + + return $this->getMembers()->matching($criteria); + } + public function getCurrentMembers(?\DateTimeImmutable $now = null): Collection { $criteria = new Criteria(); diff --git a/src/Bundle/ChillPersonBundle/Tests/Validator/Household/MaxHolderValidatorTest.php b/src/Bundle/ChillPersonBundle/Tests/Validator/Household/MaxHolderValidatorTest.php new file mode 100644 index 000000000..9210926ce --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Validator/Household/MaxHolderValidatorTest.php @@ -0,0 +1,76 @@ +getConstraint(); + + $this->validator->validate($household, $constraint); + + $this->buildViolation('msg') + ->setParameters($parameters) + ->assertRaised() + ; + } + + protected function getConstraint() + { + return new MaxHolder([ + 'message' => 'msg', + 'messageInfinity' => 'msgInfinity' + ]); + } + + public function provideInvalidHousehold() + { + $household = new Household(); + $position = (new Position()) + ->setAllowHolder(true); + $household + ->addMember( + (new HouseholdMember()) + ->setHolder(true) + ->setStartDate(new \DateTimeImmutable('2010-01-01')) + ->setEndDate(new \DateTimeImmutable('2010-12-01')) + ) + ->addMember( + (new HouseholdMember()) + ->setHolder(true) + ->setStartDate(new \DateTimeImmutable('2010-06-01')) + ->setEndDate(new \DateTimeImmutable('2010-07-01')) + ) + ->addMember( + (new HouseholdMember()) + ->setHolder(true) + ->setStartDate(new \DateTimeImmutable('2010-01-01')) + ->setEndDate(new \DateTimeImmutable('2010-12-01')) + ) + ; + + yield [ + $household, + [ + 'start' => '01-06-2010', + 'end' => '01-07-2010' + ] + ]; + } + + protected function createValidator() + { + return new MaxHolderValidator(); + } +} diff --git a/src/Bundle/ChillPersonBundle/Validator/Constraints/Household/MaxHolder.php b/src/Bundle/ChillPersonBundle/Validator/Constraints/Household/MaxHolder.php new file mode 100644 index 000000000..2c89b90cf --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Validator/Constraints/Household/MaxHolder.php @@ -0,0 +1,13 @@ +getMembersHolder(); + + if ($holders->count() <= self::MAX_HOLDERS) { + return; + } + + $covers = new DateRangeCovering(self::MAX_HOLDERS, + $holders[0]->getStartDate()->getTimezone()); + + foreach ($holders as $key => $member) { + $covers->add($member->getStartDate(), $member->getEndDate(), $key); + } + + $covers->compute(); + + if ($covers->hasIntersections()) { + foreach ($covers->getIntersections() as list($start, $end, $ids)) { + $msg = $end === null ? $constraint->messageEndInfinite : + $constraint->message; + + $this->context->buildViolation($msg) + ->setParameters([ + 'start' => $start->format('d-m-Y'), // TODO fix when MessageParameter works with timezone + 'end' => $end === null ? null : $end->format('d-m-Y') + ]) + ->addViolation(); + } + } + + } }