diff --git a/src/Bundle/ChillMainBundle/migrations/Version20210528090000.php b/src/Bundle/ChillMainBundle/migrations/Version20210528090000.php new file mode 100644 index 000000000..d2a33230f --- /dev/null +++ b/src/Bundle/ChillMainBundle/migrations/Version20210528090000.php @@ -0,0 +1,29 @@ +addSql('CREATE EXTENSION IF NOT EXISTS btree_gist'); + } + + public function down(Schema $schema): void + { + $this->addSql('DROP EXTENSION btree_gist'); + } +} diff --git a/src/Bundle/ChillPersonBundle/Controller/HouseholdMemberController.php b/src/Bundle/ChillPersonBundle/Controller/HouseholdMemberController.php new file mode 100644 index 000000000..c6fd4dd59 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Controller/HouseholdMemberController.php @@ -0,0 +1,50 @@ +getSerializer() + ->deserialize($request->getContent(), MembersEditor::class, + $_format, ['groups' => [ "read" ]]); + } catch (Exception\InvalidArgumentException | Exception\UnexpectedValueException $e) { + throw new BadRequestException("Deserialization error: {$e->getMessage()}", 45896, $e); + } + dump($editor); + // TODO ACL + // + // TODO validation + // + $em = $this->getDoctrine()->getManager(); + + // to ensure closing membership before creating one, we must manually open a transaction + $em->beginTransaction(); + + foreach ($editor->getPersistable() as $el) { + $em->persist($el); + } + + $em->flush(); + $em->commit(); + + + return $this->json($editor->getHousehold(), Response::HTTP_OK, ["groups" => ["read"]]); + } +} diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadHousehold.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadHousehold.php new file mode 100644 index 000000000..8dfca71f6 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadHousehold.php @@ -0,0 +1,126 @@ +editorFactory = $editorFactory; + $this->em = $em; + } + + public function load(ObjectManager $manager) + { + // generate two times the participation. This will lead to + // some movement in participation (same people in two differents + // households) + + $this->preparePersonIds(); + + $this->generateHousehold( + $manager, + \DateTimeImmutable::createFromFormat('Y-m-d', '2010-01-01') + ); + + $this->preparePersonIds(); + + $this->generateHousehold( + $manager, + \DateTimeImmutable::createFromFormat('Y-m-d', '2015-01-01') + ); + + $manager->flush(); + } + + private function generateHousehold(ObjectManager $manager, \DateTimeImmutable $startDate) + { + for ($i=0; $i < self::NUMBER_OF_HOUSEHOLD; $i++) { + $household = new Household(); + $manager->persist($household); + + $movement = $this->editorFactory->createEditor($household); + + // load adults + $k = 0; + foreach ($this->getRandomPersons(1, 3) as $person) { + $date = $startDate->add(new \DateInterval('P'.\random_int(1, 200).'W')); + $position = $this->getReference(LoadHouseholdPosition::ADULT); + + $movement->addMovement($date, $person, $position, $k === 0, "self generated"); + $k++; + } + + // load children + foreach ($this->getRandomPersons(0, 3) as $person) { + $date = $startDate->add(new \DateInterval('P'.\random_int(1, 200).'W')); + $position = $this->getReference(LoadHouseholdPosition::CHILD); + + $movement->addMovement($date, $person, $position, $k === 0, "self generated"); + $k++; + } + + // load children out + foreach ($this->getRandomPersons(0, 2) as $person) { + $date = $startDate->add(new \DateInterval('P'.\random_int(1, 200).'W')); + $position = $this->getReference(LoadHouseholdPosition::CHILD_OUT); + + $movement->addMovement($date, $person, $position, $k === 0, "self generated"); + $k++; + } + + foreach ($movement->getPersistable() as $obj) { + $manager->persist($obj); + } + } + } + + private function preparePersonIds() + { + $this->personIds = $this->em + ->createQuery('SELECT p.id FROM '.Person::class.' p '. + 'JOIN p.center c '. + 'WHERE c.name = :center ' + ) + ->setParameter('center', 'Center A') + ->getScalarResult() + ; + \shuffle($this->personIds); + } + + private function getRandomPersons(int $min, int $max) + { + $nb = \random_int($min, $max); + + for ($i=0; $i < $nb; $i++) { + $personId = \array_pop($this->personIds)['id']; + $persons[] = $this->em->getRepository(Person::class) + ->find($personId) + ; + } + + return $persons ?? []; + } + + public function getDependencies() + { + return [ + LoadPeople::class, + LoadHouseholdPosition::class + ]; + } +} diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadHouseholdPosition.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadHouseholdPosition.php new file mode 100644 index 000000000..cf0bf3de1 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadHouseholdPosition.php @@ -0,0 +1,38 @@ +setLabel([ "fr" => $name ]) + ->setAllowHolder($allowHolder) + ->setShareHousehold($share) + ->setOrdering($ordering) + ; + + $manager->persist($position); + $this->addReference($ref, $position); + } + + $manager->flush(); + } +} diff --git a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php index 27721012d..a28887c68 100644 --- a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php +++ b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php @@ -74,6 +74,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac $loader->load('services/form.yaml'); $loader->load('services/templating.yaml'); $loader->load('services/alt_names.yaml'); + $loader->load('services/household.yaml'); // We can get rid of this file when the service 'chill.person.repository.person' is no more used. // We should use the PersonRepository service instead of a custom service name. $loader->load('services/repository.yaml'); diff --git a/src/Bundle/ChillPersonBundle/Entity/Household/Household.php b/src/Bundle/ChillPersonBundle/Entity/Household/Household.php index 4e8787a96..ac22b6e8b 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Household/Household.php +++ b/src/Bundle/ChillPersonBundle/Entity/Household/Household.php @@ -5,9 +5,16 @@ namespace Chill\PersonBundle\Entity\Household; use Doctrine\ORM\Mapping as ORM; use Doctrine\Common\Collections\Collection; use Chill\MainBundle\Entity\Address; +use Symfony\Component\Serializer\Annotation as Serializer; /** * @ORM\Entity + * @ORM\Table( + * name="chill_person_household" + * ) + * @Serializer\DiscriminatorMap(typeProperty="type", mapping={ + * "household"=Household::class + * }) */ class Household { @@ -15,6 +22,7 @@ class Household * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") + * @Serializer\Groups({"read"}) */ private $id; diff --git a/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdMember.php b/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdMember.php new file mode 100644 index 000000000..52bd969fc --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdMember.php @@ -0,0 +1,186 @@ +id; + } + + public function getPosition(): ?Position + { + return $this->position; + } + + public function setPosition(Position $position): self + { + if ($this->position instanceof Position) { + throw new \LogicException("The position is already set. You cannot change ". + "a position of a membership"); + } + + $this->position = $position; + $this->sharedHousehold = $position->getShareHousehold(); + + return $this; + } + + public function getStartDate(): ?\DateTimeImmutable + { + return $this->startDate; + } + + public function setStartDate(\DateTimeImmutable $startDate): self + { + $this->startDate = $startDate; + + return $this; + } + + public function getEndDate(): ?\DateTimeImmutable + { + return $this->endDate; + } + + public function setEndDate(\DateTimeImmutable $endDate): self + { + $this->endDate = $endDate; + + return $this; + } + + public function getComment(): ?string + { + return $this->comment; + } + + public function setComment(?string $comment): self + { + $this->comment = $comment; + + return $this; + } + + public function getShareHousehold(): ?bool + { + return $this->sharedHousehold; + } + + + public function getPerson(): ?Person + { + return $this->person; + } + + public function setPerson(?Person $person): self + { + if ($this->person instanceof Person) { + throw new \LogicException("You cannot change person ". + "on a membership"); + } + + $this->person = $person; + $this->person->addHouseholdParticipation($this); + + return $this; + } + + public function getHousehold(): ?Household + { + return $this->household; + } + + public function setHousehold(?Household $household): self + { + if ($this->household instanceof Household) { + throw new \LogicException("You cannot change household ". + "on a membership"); + } + + $this->household = $household; + + return $this; + } + + public function setHolder(bool $holder): self + { + $this->holder = $holder; + + return $this; + } + + public function isHolder(): bool + { + return $this->holder; + } +} diff --git a/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdMembers.php b/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdMembers.php deleted file mode 100644 index 5d16649a8..000000000 --- a/src/Bundle/ChillPersonBundle/Entity/Household/HouseholdMembers.php +++ /dev/null @@ -1,152 +0,0 @@ -id; - } - - public function getPosition(): ?string - { - return $this->position; - } - - public function setPosition(?string $position): self - { - $this->position = $position; - - return $this; - } - - public function getStartDate(): ?\DateTimeInterface - { - return $this->startDate; - } - - public function setStartDate(\DateTimeInterface $startDate): self - { - $this->startDate = $startDate; - - return $this; - } - - public function getEndDate(): ?\DateTimeInterface - { - return $this->endDate; - } - - public function setEndDate(\DateTimeInterface $endDate): self - { - $this->endDate = $endDate; - - return $this; - } - - public function getComment(): ?string - { - return $this->comment; - } - - public function setComment(?string $comment): self - { - $this->comment = $comment; - - return $this; - } - - public function getSharedHousehold(): ?bool - { - return $this->sharedHousehold; - } - - public function setSharedHousehold(bool $sharedHousehold): self - { - $this->sharedHousehold = $sharedHousehold; - - return $this; - } - - public function getPerson(): ?Person - { - return $this->person; - } - - public function setPerson(?Person $person): self - { - $this->person = $person; - - return $this; - } - - public function getHousehold(): ?Household - { - return $this->household; - } - - public function setHousehold(?Household $household): self - { - $this->household = $household; - - return $this; - } -} diff --git a/src/Bundle/ChillPersonBundle/Entity/Household/Position.php b/src/Bundle/ChillPersonBundle/Entity/Household/Position.php new file mode 100644 index 000000000..156631b63 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Entity/Household/Position.php @@ -0,0 +1,98 @@ +id; + } + + public function getLabel(): ?array + { + return $this->label; + } + + public function setLabel(array $label): self + { + $this->label = $label; + + return $this; + } + + public function getShareHousehold(): ?bool + { + return $this->shareHouseHold; + } + + public function setShareHousehold(bool $shareHouseHold): self + { + $this->shareHouseHold = $shareHouseHold; + + return $this; + } + + public function getAllowHolder(): ?bool + { + return $this->allowHolder; + } + + public function setAllowHolder(bool $allowHolder): self + { + $this->allowHolder = $allowHolder; + + return $this; + } + + public function getOrdering(): ?float + { + return $this->ordering; + } + + public function setOrdering(float $ordering): self + { + $this->ordering = $ordering; + + return $this; + } +} diff --git a/src/Bundle/ChillPersonBundle/Entity/Person.php b/src/Bundle/ChillPersonBundle/Entity/Person.php index a4fb185fb..0d9bb7cf6 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person.php @@ -26,6 +26,7 @@ use ArrayIterator; use Chill\MainBundle\Entity\Center; use Chill\MainBundle\Entity\Country; use Chill\PersonBundle\Entity\MaritalStatus; +use Chill\PersonBundle\Entity\Household\HouseholdMember; use Chill\MainBundle\Entity\HasCenterInterface; use Chill\MainBundle\Entity\Address; use DateTime; @@ -272,6 +273,14 @@ class Person implements HasCenterInterface */ private $fullnameCanonical; + /** + * @ORM\OneToMany( + * targetEntity=HouseholdMember::class, + * mappedBy="person" + * ) + */ + private Collection $householdParticipations; + /** * Person constructor. * @@ -284,6 +293,7 @@ class Person implements HasCenterInterface $this->addresses = new ArrayCollection(); $this->altNames = new ArrayCollection(); $this->otherPhoneNumbers = new ArrayCollection(); + $this->householdParticipations = new ArrayCollection(); if ($opening === null) { $opening = new \DateTime(); @@ -1180,4 +1190,16 @@ class Person implements HasCenterInterface $this->fullnameCanonical = $fullnameCanonical; return $this; } + + public function addHouseholdParticipation(HouseholdMember $member): self + { + $this->householdParticipations[] = $member; + + return $this; + } + + public function getHouseholdParticipations(): Collection + { + return $this->householdParticipations; + } } diff --git a/src/Bundle/ChillPersonBundle/Household/MembersEditor.php b/src/Bundle/ChillPersonBundle/Household/MembersEditor.php new file mode 100644 index 000000000..527404c75 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Household/MembersEditor.php @@ -0,0 +1,79 @@ +validation = $validator; + $this->household = $household; + } + + public function addMovement(\DateTimeImmutable $date, Person $person, Position $position, ?bool $holder = false, ?string $comment = null): self + { + if (NULL === $this->household) { + throw new \LogicException("You must define a household first"); + } + + $membership = (new HouseholdMember()) + ->setStartDate($date) + ->setPerson($person) + ->setPosition($position) + ->setHolder($holder) + ->setHousehold($this->household) + ->setComment($comment) + ; + + if ($position->getShareHousehold()) { + foreach ($person->getHouseholdParticipations() as $participation) { + if (FALSE === $participation->getShareHousehold()) { + continue; + } + + if ($participation === $membership) { + continue; + } + + if ($participation->getEndDate() === NULL || $participation->getEndDate() > $date) { + $participation->setEndDate($date); + $this->membershipsAffected[] = $participation; + } + } + } + + $this->membershipsAffected[] = $membership; + $this->persistables[] = $membership; + + return $this; + } + + public function validate(): ConstraintViolationListInterface + { + + } + + public function getPersistable(): array + { + return $this->persistables; + } + + public function getHousehold(): Household + { + return $this->household; + } +} diff --git a/src/Bundle/ChillPersonBundle/Household/MembersEditorFactory.php b/src/Bundle/ChillPersonBundle/Household/MembersEditorFactory.php new file mode 100644 index 000000000..611308b19 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Household/MembersEditorFactory.php @@ -0,0 +1,21 @@ +validator = $validator; + } + + public function createEditor(Household $household): MembersEditor + { + return new MembersEditor($this->validator, $household); + } +} diff --git a/src/Bundle/ChillPersonBundle/Repository/Household/PositionRepository.php b/src/Bundle/ChillPersonBundle/Repository/Household/PositionRepository.php new file mode 100644 index 000000000..6d07f791e --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Repository/Household/PositionRepository.php @@ -0,0 +1,22 @@ +factory = $factory; + } + + public function denormalize($data, string $type, string $format = null, array $context = []) + { + $household = $this->denormalizer->denormalize($data['destination'], Household::class, + $format, $context); + + if (NULL === $household) { + throw new Exception\InvalidArgumentException("household could not be denormalized. Impossible to process"); + } + + $editor = $this->factory->createEditor($household); + + if (NULL == $data['concerned'] ?? [] + && FALSE === ·\is_array('concerned')) { + throw new Exception\UnexpectedValueException("The schema does not have any key 'concerned'"); + } + + foreach ($data['concerned'] as $key => $concerned) { + $person = $this->denormalizer->denormalize($concerned['person'] ?? null, Person::class, + $format, $context); + $position = $this->denormalizer->denormalize($concerned['position'] ?? null, Position::class, + $format, $context); + $startDate = $this->denormalizer->denormalize($concerned['start_date'] ?? null, \DateTimeImmutable::class, + $format, $context); + + $holder = (bool) $concerned['holder'] ?? false; + $comment = (string) $concerned['comment'] ?? false; + + if ( + NULL === $person + && NULL === $position + && NULL === $startDate + ) { + throw new Exception\InvalidArgumentException("position with ". + "key $key could not be denormalized: missing ". + "person, position or start_date."); + } + + $editor->addMovement($startDate, $person, $position, $holder, + $comment); + + return $editor; + } + } + + public function supportsDenormalization($data, string $type, string $format = null) + { + return $type === MembersEditor::class; + } + +} diff --git a/src/Bundle/ChillPersonBundle/Tests/Controller/HouseholdMemberControllerTest.php b/src/Bundle/ChillPersonBundle/Tests/Controller/HouseholdMemberControllerTest.php new file mode 100644 index 000000000..96cb81382 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Controller/HouseholdMemberControllerTest.php @@ -0,0 +1,98 @@ +getClientAuthenticated(); + + $client->request( + Request::METHOD_POST, + '/api/1.0/person/household/members/move.json', + [], // parameters + [], // files + [], // server + \json_encode( + [ + 'concerned' => + [ + [ + 'person' => + [ + 'type' => 'person', + 'id' => $personId + ], + 'start_date' => + [ + 'datetime' => $date->format(\DateTimeInterface::RFC3339) + ], + 'position' => + [ + 'type' => 'household_position', + 'id' => $positionId + ], + 'holder' => false, + 'comment' => "Introduced by automated test", + ], + ], + 'destination' => + [ + 'type' => 'household', + 'id' => $householdId + ] + ], + true) + ); + + $this->assertEquals(Response::HTTP_OK, + $client->getResponse()->getStatusCode() + ); + } + + public function provideValidData(): \Iterator + { + self::bootKernel(); + $em = self::$container->get(EntityManagerInterface::class); + + $personIds = $em->createQuery("SELECT p.id FROM ".Person::class." p ". + "JOIN p.center c WHERE c.name = :center") + ->setParameter('center', "Center A") + ->setMaxResults(100) + ->getScalarResult() + ; + \shuffle($personIds); + + $household = new Household(); + $em->persist($household); + $em->flush(); + + $positions = $em->createQuery("SELECT pos.id FROM ".Position::class." pos ". + "WHERE pos.shareHouseHold = TRUE") + ->getResult() + ; + + yield [ + \array_pop($personIds)['id'], + $household->getId(), + $positions[\random_int(0, count($positions) - 1)]['id'], + new \DateTimeImmutable('today') + ]; + } +} diff --git a/src/Bundle/ChillPersonBundle/Tests/Entity/Household/HouseholdMemberTest.php b/src/Bundle/ChillPersonBundle/Tests/Entity/Household/HouseholdMemberTest.php new file mode 100644 index 000000000..f18a62781 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Entity/Household/HouseholdMemberTest.php @@ -0,0 +1,34 @@ +setShareHousehold(true) + ; + $membership = (new HouseholdMember()) + ->setPosition($position) + ; + + $this->assertTrue($membership->getShareHousehold()); + } + + public function testPositionDoNotSharehousehold() + { + $position = (new Position()) + ->setShareHousehold(false) + ; + $membership = (new HouseholdMember()) + ->setPosition($position) + ; + + $this->assertFalse($membership->getShareHousehold()); + } +} diff --git a/src/Bundle/ChillPersonBundle/Tests/Household/MembersEditorTest.php b/src/Bundle/ChillPersonBundle/Tests/Household/MembersEditorTest.php new file mode 100644 index 000000000..8ef409296 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Household/MembersEditorTest.php @@ -0,0 +1,105 @@ +createMock(ValidatorInterface::class); + + $this->factory = new MembersEditorFactory($validator); + } + + 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 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"); + } +} diff --git a/src/Bundle/ChillPersonBundle/chill.api.specs.yaml b/src/Bundle/ChillPersonBundle/chill.api.specs.yaml index c3067be55..0fac8e6ce 100644 --- a/src/Bundle/ChillPersonBundle/chill.api.specs.yaml +++ b/src/Bundle/ChillPersonBundle/chill.api.specs.yaml @@ -192,6 +192,25 @@ components: text: type: string readOnly: true + Household: + type: object + properties: + id: + type: integer + type: + type: string + enum: + - 'household' + HouseholdPosition: + type: object + properties: + id: + type: integer + type: + type: string + enum: + - 'household_position' + paths: /1.0/person/person/{id}.json: @@ -764,3 +783,46 @@ paths: description: "OK" 400: description: "transition cannot be applyed" + + /1.0/person/household/members/move.json: + post: + tags: + - household + summary: move one or multiple person from a household to another + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + concerned: + type: array + items: + type: object + properties: + person: + $ref: '#/components/schemas/PersonById' + start_date: + $ref: '#/components/schemas/Date' + position: + $ref: '#/components/schemas/HouseholdPosition' + holder: + type: boolean + comment: + type: string + destination: + oneOf: + - $ref: '#/components/schemas/Household' + responses: + 401: + description: "Unauthorized" + 404: + description: "Not found" + 200: + description: "OK" + 422: + description: "Unprocessable entity (validation errors)" + 400: + description: "transition cannot be applyed" + diff --git a/src/Bundle/ChillPersonBundle/config/services/fixtures.yaml b/src/Bundle/ChillPersonBundle/config/services/fixtures.yaml index a6becd555..72bf899f4 100644 --- a/src/Bundle/ChillPersonBundle/config/services/fixtures.yaml +++ b/src/Bundle/ChillPersonBundle/config/services/fixtures.yaml @@ -1,5 +1,6 @@ services: Chill\PersonBundle\DataFixtures\ORM\: + autowire: true resource: ../../DataFixtures/ORM tags: [ 'doctrine.fixture.orm' ] diff --git a/src/Bundle/ChillPersonBundle/config/services/household.yaml b/src/Bundle/ChillPersonBundle/config/services/household.yaml new file mode 100644 index 000000000..300928c49 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/config/services/household.yaml @@ -0,0 +1,3 @@ +services: + Chill\PersonBundle\Household\MembersEditorFactory: + autowire: true diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20210528092625.php b/src/Bundle/ChillPersonBundle/migrations/Version20210528092625.php new file mode 100644 index 000000000..1ce855140 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/migrations/Version20210528092625.php @@ -0,0 +1,63 @@ +addSql('ALTER TABLE householdmembers DROP CONSTRAINT fk_4d1fb288e79ff843'); + $this->addSql('ALTER TABLE householdmembers DROP CONSTRAINT fk_4d1fb288217bbb47'); + + // rename tables + $this->addSql('ALTER TABLE householdmembers RENAME TO chill_person_household_members'); + $this->addSql('ALTER TABLE household RENAME TO chill_person_household'); + + // rename sequences + $this->addSql('ALTER SEQUENCE household_id_seq RENAME TO chill_person_household_id_seq'); + $this->addSql('ALTER SEQUENCE householdmembers_id_seq RENAME TO chill_person_household_members_id_seq'); + + // recreate constraints + $this->addSql('ALTER TABLE chill_person_household_members ADD CONSTRAINT FK_EEF5DED7217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_household_members ADD CONSTRAINT FK_EEF5DED7E79FF843 FOREIGN KEY (household_id) REFERENCES chill_person_household (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + + // create constraint 'householdmembers not overlaps' + $this->addSql('ALTER TABLE chill_person_household_members ADD CHECK (startdate < enddate)'); + $this->addSql('ALTER TABLE chill_person_household_members ADD CONSTRAINT '. + "household_members_not_overlaps EXCLUDE USING GIST( + -- extension btree_gist required to include comparaison with integer + person_id WITH =, + daterange(startdate, enddate) WITH && + ) WHERE (sharedhousehold IS TRUE) + INITIALLY DEFERRED"); + + // rename constraints + $this->addSql('ALTER TABLE public.chill_person_household_to_addresses DROP CONSTRAINT fk_7109483e79ff843'); + $this->addSql('ALTER TABLE chill_person_household_to_addresses ADD CONSTRAINT FK_C28AF063E79FF843 FOREIGN KEY (household_id) REFERENCES chill_person_household (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + + // rename indexes + $this->addSql('ALTER INDEX idx_7109483e79ff843 RENAME TO IDX_C28AF063E79FF843'); + $this->addSql('ALTER INDEX idx_7109483f5b7af75 RENAME TO IDX_C28AF063F5B7AF75'); + $this->addSql('ALTER INDEX idx_4d1fb288e79ff843 RENAME TO IDX_EEF5DED7E79FF843'); + $this->addSql('ALTER INDEX idx_4d1fb288217bbb47 RENAME TO IDX_EEF5DED7217BBB47'); + } + + public function down(Schema $schema): void + { + $this->throwIrreversibleMigrationException("the down method is not implemented"); + } +} diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20210528111624.php b/src/Bundle/ChillPersonBundle/migrations/Version20210528111624.php new file mode 100644 index 000000000..2228d42c3 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/migrations/Version20210528111624.php @@ -0,0 +1,39 @@ +addSql('CREATE SEQUENCE chill_person_household_position_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE TABLE chill_person_household_position (id INT NOT NULL, label JSON NOT NULL, shareHouseHold BOOLEAN NOT NULL, allowHolder BOOLEAN NOT NULL, ordering DOUBLE PRECISION NOT NULL, PRIMARY KEY(id))'); + + $this->addSql('ALTER TABLE chill_person_household_members ADD position_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_person_household_members DROP "position"'); + $this->addSql('ALTER TABLE chill_person_household_members ADD CONSTRAINT FK_EEF5DED7DD842E46 FOREIGN KEY (position_id) REFERENCES chill_person_household_position (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('CREATE INDEX IDX_EEF5DED7DD842E46 ON chill_person_household_members (position_id)'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_person_household_members DROP CONSTRAINT FK_EEF5DED7DD842E46'); + $this->addSql('DROP SEQUENCE chill_person_household_position_id_seq CASCADE'); + $this->addSql('DROP TABLE chill_person_household_position'); + $this->addSql('ALTER TABLE chill_person_household_members ADD "position" VARCHAR(255) DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_person_household_members DROP position_id'); + } +} diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20210528132405.php b/src/Bundle/ChillPersonBundle/migrations/Version20210528132405.php new file mode 100644 index 000000000..f9e94532a --- /dev/null +++ b/src/Bundle/ChillPersonBundle/migrations/Version20210528132405.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE chill_person_household_members ALTER startdate DROP NOT NULL'); + $this->addSql('ALTER TABLE chill_person_household_members ALTER enddate DROP NOT NULL'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_person_household_members ALTER startDate SET NOT NULL'); + $this->addSql('ALTER TABLE chill_person_household_members ALTER endDate SET NOT NULL'); + } +} diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20210528142121.php b/src/Bundle/ChillPersonBundle/migrations/Version20210528142121.php new file mode 100644 index 000000000..4eaf149af --- /dev/null +++ b/src/Bundle/ChillPersonBundle/migrations/Version20210528142121.php @@ -0,0 +1,29 @@ +addSql('ALTER TABLE chill_person_household_members ADD holder BOOLEAN DEFAULT FALSE NOT NULL'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_person_household_members DROP COLUMN holder'); + } +}