factory = $this->buildMembersEditorFactory(); } public function testAddingParticipationNotSharingHouseholdCloseTheOldOnes() { $person = new Person(); $position = (new Position())->setShareHousehold(false); $household = new Household(); // set a first time the person in position $factory = $this->buildMembersEditorFactory(); $editor = $factory->createEditor($household); $editor->addMovement($aMonthAgo = new DateTimeImmutable('1 month ago'), $person, $position); // set a second time the person in position $factory = $this->buildMembersEditorFactory(); $editor = $factory->createEditor($household); $editor->addMovement($yesterday = new DateTimeImmutable('yesterday'), $person, $position); $this->assertCount(2, $person->getHouseholdParticipationsNotShareHousehold()); $startDates = []; $endDates = []; foreach ($person->getHouseholdParticipationsNotShareHousehold() as $participation) { $startDates[] = $participation->getStartDate(); $endDates[] = $participation->getEndDate(); } $this->assertContains($aMonthAgo, $startDates); $this->assertContains($yesterday, $startDates); $this->assertContains($yesterday, $endDates); $this->assertContains(null, $endDates); } /** * We test that a leave move is possible when member startdate is same as current date * */ public function testLeaveMovementInSameHouseholdFromShareHouseholdToNotShareHouseholdOnSameDate() { $person = new Person(); $household = new Household(); $factory = $this->buildMembersEditorFactory(); $positionSharing = (new Position())->setShareHousehold(true); $positionNotSharing = (new Position())->setShareHousehold(false); // create add move $editor = $factory->createEditor($household); $editor->addMovement(new DateTimeImmutable('today'), $person, $positionSharing); $editor->postMove(); self::assertContains($person, $household->getCurrentPersons()); self::assertSame($household, $person->getCurrentHousehold()); self::assertCount(1, $household->getMembers()); // create leave move $eventDispatcher = $this->prophesize(EventDispatcherInterface::class); $eventDispatcher ->dispatch(Argument::type(PersonAddressMoveEvent::class)) ->shouldBeCalled(); $factory = $this->buildMembersEditorFactory( $eventDispatcher->reveal(), null ); $editor = $factory->createEditor($household); $editor->addMovement(new DateTimeImmutable('today'), $person, $positionNotSharing); $editor->postMove(); $participations = $household->getMembers(); self::assertCount(2, $participations); $sharing = $participations->filter(fn (HouseholdMember $hm) => $hm->getShareHousehold()); self::assertCount(1, $sharing); $notSharing = $participations->filter(fn (HouseholdMember $hm) => !$hm->getShareHousehold()); self::assertCount(1, $notSharing); self::assertNotNull($sharing[0]->getEndDate()); self::assertEquals(new DateTimeImmutable('today'), $sharing[0]->getEndDate()); } /** * We test here a move for a person:. * * * which was in a position "sharing household" * * which move to the another household, in a position "not sharing household" * * The person should stays in the two households */ public function testMoveFromSharingHouseholdToNotSharingHousehouldInDifferentHousehold() { $person = new Person(); $household = new Household(); $positionSharing = (new Position())->setShareHousehold(true); $positionNotSharing = (new Position())->setShareHousehold(false); $factory = $this->buildMembersEditorFactory(); $editor = $factory->createEditor($household); // we add the member to the household $editor->addMovement(new DateTimeImmutable('1 month ago'), $person, $positionSharing); // double check that the person is in the household $this->assertContains($person, $household->getCurrentPersons()); // we do the move to the position not sharing household $eventDispatcher = $this->prophesize(EventDispatcherInterface::class); $eventDispatcher ->dispatch(Argument::type(PersonAddressMoveEvent::class)) ->shouldNotBeCalled(); $factory = $this->buildMembersEditorFactory( $eventDispatcher->reveal(), null ); $editor = $factory->createEditor($household2 = new Household()); $editor->addMovement(new DateTimeImmutable('yesterday'), $person, $positionNotSharing); $editor->postMove(); $sharings = $household->getCurrentMembers()->filter(static fn (HouseholdMember $m) => $m->getShareHousehold()); $notSharing = $household2->getCurrentMembers()->filter(static fn (HouseholdMember $m) => !$m->getShareHousehold()); $this->assertCount(1, $notSharing); $this->assertCount(1, $sharings); $getPerson = static fn (HouseholdMember $m) => $m->getPerson(); $this->assertContains($person, $notSharing->map($getPerson)); } /** * We test here a move for a person:. * * * which was in a position "sharing household" * * which move to the same household, in a position "not sharing household" */ public function testMoveFromSharingHouseholdToNotSharingHousehouldInSamehouseholdOnDifferentDate() { $person = new Person(); $household = new Household(); $positionSharing = (new Position())->setShareHousehold(true); $positionNotSharing = (new Position())->setShareHousehold(false); $factory = $this->buildMembersEditorFactory(); $editor = $factory->createEditor($household); // we add the member to the household $editor->addMovement(new DateTimeImmutable('1 month ago'), $person, $positionSharing); // double check that the person is in the household $this->assertContains($person, $household->getCurrentPersons()); // we do the move to the position not sharing household $eventDispatcher = $this->prophesize(EventDispatcherInterface::class); $eventDispatcher ->dispatch(Argument::type(PersonAddressMoveEvent::class)) ->shouldBeCalled(); $factory = $this->buildMembersEditorFactory( $eventDispatcher->reveal(), null ); $editor = $factory->createEditor($household); $editor->addMovement(new DateTimeImmutable('yesterday'), $person, $positionNotSharing); $editor->postMove(); $sharings = $household->getCurrentMembers()->filter(static fn (HouseholdMember $m) => $m->getShareHousehold()); $notSharing = $household->getCurrentMembers()->filter(static fn (HouseholdMember $m) => !$m->getShareHousehold()); $this->assertCount(1, $notSharing); $this->assertCount(0, $sharings); $getPerson = static fn (HouseholdMember $m) => $m->getPerson(); $this->assertContains($person, $notSharing->map($getPerson)); } /** * We test here a move for a person:. * * * which was in a position "not sharing household" * * which move to the same household, in a position "sharing household" */ public function testMoveFromNotSharingHouseholdToSharingHousehouldInSamehousehold() { $person = new Person(); $household = new Household(); $positionSharing = (new Position())->setShareHousehold(true); $positionNotSharing = (new Position())->setShareHousehold(false); $factory = $this->buildMembersEditorFactory(); $editor = $factory->createEditor($household); // we add the member to the household, at the position "not sharing" $editor->addMovement(new DateTimeImmutable('1 month ago'), $person, $positionNotSharing); // double check that the person is in the household $this->assertContains($person, $household->getCurrentPersons()); // we do the move to the position sharing household $editor = $factory->createEditor($household); $editor->addMovement(new DateTimeImmutable('yesterday'), $person, $positionSharing); self::assertCount(2, $household->getMembers()); $sharings = $household->getCurrentMembers()->filter(static fn (HouseholdMember $m) => $m->getShareHousehold()); $notSharing = $household->getCurrentMembers()->filter(static fn (HouseholdMember $m) => !$m->getShareHousehold()); $this->assertCount(0, $notSharing); $this->assertCount(1, $sharings); $getPerson = static fn (HouseholdMember $m) => $m->getPerson(); $this->assertContains($person, $sharings->map($getPerson)); $this->assertNotContains($person, $notSharing->map($getPerson)); } /** * We test here a move for a person:. * * * which was in a position "not sharing household" * * which move to the same household, in a position "sharing household" */ public function testMoveFromNotSharingHouseholdToSharingHousehouldInSamehouseholdOnSameDate() { $person = new Person(); $household = new Household(); $positionSharing = (new Position())->setShareHousehold(true); $positionNotSharing = (new Position())->setShareHousehold(false); $factory = $this->buildMembersEditorFactory(); $editor = $factory->createEditor($household); // we add the member to the household, at the position "not sharing" $editor->addMovement(new DateTimeImmutable('today'), $person, $positionNotSharing); // double check that the person is in the household $this->assertContains($person, $household->getCurrentPersons()); // we do the move to the position sharing household $editor = $factory->createEditor($household); $editor->addMovement(new DateTimeImmutable('today'), $person, $positionSharing); self::assertCount(2, $household->getMembers()); $sharings = $household->getCurrentMembers()->filter(static fn (HouseholdMember $m) => $m->getShareHousehold()); $notSharing = $household->getCurrentMembers()->filter(static fn (HouseholdMember $m) => !$m->getShareHousehold()); $this->assertCount(0, $notSharing); $this->assertCount(1, $sharings); $getPerson = static fn (HouseholdMember $m) => $m->getPerson(); $this->assertContains($person, $sharings->map($getPerson)); $this->assertNotContains($person, $notSharing->map($getPerson)); } public function testMovePersonWithoutSharedHousehold() { $person = new Person(); $position = (new Position()) ->setShareHousehold(false); $household1 = new Household(); $household2 = new Household(); $editor = $this->factory->createEditor($household1); $editor->addMovement( DateTimeImmutable::createFromFormat('Y-m-d', '2020-01-01'), $person, $position ); $persistables = $editor->getPersistable(); $this->assertEquals(1, count($persistables)); $membership1 = $person->getHouseholdParticipations()->first(); $this->assertSame($household1, $membership1->getHousehold()); $this->assertNull($membership1->getEndDate()); // move to another household $date = DateTimeImmutable::createFromFormat('Y-m-d', '2021-01-01'); $editor = $this->factory->createEditor($household2); $editor->addMovement( $date, $person, $position ); $persistables = $editor->getPersistable(); $this->assertEquals(1, count($persistables)); $membership2 = $person->getHouseholdParticipations()->last(); $this->assertNull($membership2->getEndDate()); $this->assertSame($household2, $membership2->getHousehold()); $this->assertNull( $membership1->getEndDate(), 'assert that the membership1 is not closed' ); } public function testMovePersonWithSharedHousehold() { $person = new Person(); $position = (new Position()) ->setShareHousehold(true); $household1 = new Household(); $household2 = new Household(); $editor = $this->factory->createEditor($household1); $editor->addMovement( DateTimeImmutable::createFromFormat('Y-m-d', '2020-01-01'), $person, $position ); $persistables = $editor->getPersistable(); $this->assertEquals(count($persistables), 1); $membership1 = $persistables[0]; $this->assertSame($household1, $membership1->getHousehold()); $this->assertNull($membership1->getEndDate()); // move to another household $date = DateTimeImmutable::createFromFormat('Y-m-d', '2021-01-01'); $editor = $this->factory->createEditor($household2); $editor->addMovement( $date, $person, $position ); $persistables = $editor->getPersistable(); $this->assertEquals(1, count($persistables)); $membership2 = $persistables[0]; $this->assertSame($household2, $membership2->getHousehold()); $this->assertNull($membership2->getEndDate()); $this->assertNotNull( $membership1->getEndDate(), 'assert that the membership1 is closed' ); $this->assertEquals($date, $membership1->getEndDate()); } public function testPostMoveToAPositionNotSharingHouseholdOnSameDay() { $person = new Person(); $positionNotSharing = (new Position()) ->setShareHousehold(false); $positionSharing = (new Position())->setShareHousehold(true); $household1 = new Household(); $household2 = new Household(); $factory = $this->buildMembersEditorFactory(); $editor = $factory->createEditor($household1); $editor->addMovement(new DateTimeImmutable('today'), $person, $positionSharing); $editor->postMove(); self::assertContains($person, $household1->getCurrentPersons()); self::assertContains($person, $household1->getCurrentMembers() ->filter(fn (HouseholdMember $m) => $m->getShareHousehold()) ->map(fn (HouseholdMember $m) => $m->getPerson())); self::assertSame($household1, $person->getCurrentHousehold()); $eventDispatcher = $this->prophesize(EventDispatcherInterface::class); $eventDispatcher ->dispatch(Argument::type(PersonAddressMoveEvent::class)) ->shouldNotBeCalled(); $factory = $this->buildMembersEditorFactory( $eventDispatcher->reveal(), null ); $editor = $factory->createEditor($household2); $editor->addMovement(new DateTimeImmutable('today'), $person, $positionNotSharing); $editor->postMove(); // $household1 still contains $person self::assertContains($person, $household1->getCurrentPersons()); self::assertContains($person, $household1->getCurrentMembers() ->filter(fn (HouseholdMember $m) => $m->getShareHousehold()) ->map(fn (HouseholdMember $m) => $m->getPerson())); self::assertSame($household1, $person->getCurrentHousehold()); // $household2 contains $person at non-sharing position self::assertContains($person, $household2->getCurrentMembers() ->filter(fn (HouseholdMember $m) => !$m->getShareHousehold()) ->map(fn (HouseholdMember $m) => $m->getPerson())); self::assertContains( $household2, $person->getHouseholdParticipationsNotShareHousehold() ->map(fn (HouseholdMember $hm) => $hm->getHousehold()) ); } public function testPostMoveToAPositionNotSharingHouseholdOnDifferentDays() { $person = new Person(); $positionNotSharing = (new Position()) ->setShareHousehold(false); $positionSharing = (new Position())->setShareHousehold(true); $household1 = new Household(); $household2 = new Household(); $factory = $this->buildMembersEditorFactory(); $editor = $factory->createEditor($household1); $editor->addMovement(new DateTimeImmutable('1 year ago'), $person, $positionSharing); $editor->postMove(); self::assertContains($person, $household1->getCurrentPersons()); self::assertContains($person, $household1->getCurrentMembers() ->filter(fn (HouseholdMember $m) => $m->getShareHousehold()) ->map(fn (HouseholdMember $m) => $m->getPerson())); self::assertSame($household1, $person->getCurrentHousehold()); $eventDispatcher = $this->prophesize(EventDispatcherInterface::class); $eventDispatcher ->dispatch(Argument::type(PersonAddressMoveEvent::class)) ->shouldNotBeCalled(); $factory = $this->buildMembersEditorFactory( $eventDispatcher->reveal(), null ); $editor = $factory->createEditor($household2); $editor->addMovement(new DateTimeImmutable('yesterday'), $person, $positionNotSharing); $editor->postMove(); // $household1 still contains $person self::assertContains($person, $household1->getCurrentPersons()); self::assertContains($person, $household1->getCurrentMembers() ->filter(fn (HouseholdMember $m) => $m->getShareHousehold()) ->map(fn (HouseholdMember $m) => $m->getPerson())); self::assertSame($household1, $person->getCurrentHousehold()); // $household2 contains $person at non-sharing position self::assertContains($person, $household2->getCurrentMembers() ->filter(fn (HouseholdMember $m) => !$m->getShareHousehold()) ->map(fn (HouseholdMember $m) => $m->getPerson())); self::assertContains( $household2, $person->getHouseholdParticipationsNotShareHousehold() ->map(fn (HouseholdMember $hm) => $hm->getHousehold()) ); } public function testPostMoveToAPositionSharingHouseholdAndSameHousehold() { $person = new Person(); $position = (new Position()) ->setShareHousehold(true); $position2 = (new Position()) ->setShareHousehold(true); $household1 = new Household(); // set into the first household $editor = $this->buildMembersEditorFactory() ->createEditor($household1); $editor->addMovement(new DateTimeImmutable('1 year ago'), $person, $position); // prepare for next move $eventDispatcher = $this->prophesize(EventDispatcherInterface::class); $eventDispatcher ->dispatch(Argument::type(PersonAddressMoveEvent::class)) ->shouldNotBeCalled(); $factory = $this->buildMembersEditorFactory( $eventDispatcher->reveal(), null ); $editor = $factory->createEditor($household1); $editor->addMovement(new DateTimeImmutable('now'), $person, $position2); $editor->postMove(); } public function testPostMoveToAPositionSharingHouseholdFromDifferentHousehold() { $person = new Person(); $position = (new Position()) ->setShareHousehold(true); $household1 = new Household(); $household2 = new Household(); // set into the first household $editor = $this->buildMembersEditorFactory() ->createEditor($household1); $editor->addMovement(new DateTimeImmutable('1 year ago'), $person, $position); // perform now the movement $eventDispatcher = $this->prophesize(EventDispatcherInterface::class); $eventDispatcher ->dispatch(Argument::type(PersonAddressMoveEvent::class)) ->shouldBeCalled(); $factory = $this->buildMembersEditorFactory( $eventDispatcher->reveal(), null ); $editor = $factory->createEditor($household2); $editor->addMovement(new DateTimeImmutable('now'), $person, $position); $editor->postMove(); } public function testPostMoveToAPositionSharingHouseholdFromNoHousehold() { $person = new Person(); $position = (new Position()) ->setShareHousehold(true); $household1 = new Household(); $eventDispatcher = $this->prophesize(EventDispatcherInterface::class); $eventDispatcher ->dispatch(Argument::type(PersonAddressMoveEvent::class)) ->shouldBeCalled(); $factory = $this->buildMembersEditorFactory( $eventDispatcher->reveal(), null ); $editor = $factory->createEditor($household1); $editor->addMovement(new DateTimeImmutable('now'), $person, $position); $editor->postMove(); } private function buildMembersEditorFactory( ?EventDispatcherInterface $eventDispatcher = null, ?ValidatorInterface $validator = null ) { if (null === $eventDispatcher) { $double = $this->getProphet()->prophesize(); $double->willImplement(EventDispatcherInterface::class); $double->dispatch(Argument::type(PersonAddressMoveEvent::class)); $eventDispatcher = $double->reveal(); } if (null === $validator) { $double = $this->getProphet()->prophesize(); $double->willImplement(ValidatorInterface::class); $validator = $double->reveal(); } return new MembersEditorFactory( $eventDispatcher, $validator ); } }