first impl of person Mover + add fixtures

This commit is contained in:
Julien Fastré 2021-05-28 16:41:37 +02:00
parent 94bcbac06a
commit 87ba68971c
13 changed files with 384 additions and 21 deletions

View File

@ -0,0 +1,101 @@
<?php
namespace Chill\PersonBundle\DataFixtures\ORM;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\Household\Household;
use Chill\PersonBundle\Household\MoveMembersFactory;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ObjectManager;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
class LoadHousehold extends Fixture implements DependentFixtureInterface
{
private MoveMembersFactory $movementFactory;
private EntityManagerInterface $em;
private CONST NUMBER_OF_HOUSEHOLD = 10;
public function __construct(MoveMembersFactory $movementFactory, EntityManagerInterface $em)
{
$this->movementFactory = $movementFactory;
$this->em = $em;
}
public function load(ObjectManager $manager)
{
$this->preparePersonIds();
for ($i=0; $i < self::NUMBER_OF_HOUSEHOLD; $i++) {
$household = new Household();
$manager->persist($household);
$movement = $this->movementFactory->createMovement($household);
// load adults
$k = 0;
foreach ($this->getRandomPersons(1, 3) as $person) {
$date = \DateTimeImmutable::createFromFormat('Y-m-d', '2010-01-01')
->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 = \DateTimeImmutable::createFromFormat('Y-m-d', '2010-01-01')
->add(new \DateInterval('P'.\random_int(1, 200).'W'));
$position = $this->getReference(LoadHouseholdPosition::CHILD);
$movement->addMovement($date, $person, $position, $k === 0, "self generated");
$k++;
}
foreach ($movement->getPersistable() as $obj) {
print($obj->getStartDate()->format('Y-m-d'));
$manager->persist($obj);
}
}
$manager->flush();
}
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
];
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace Chill\PersonBundle\DataFixtures\ORM;
use Chill\PersonBundle\Entity\Household\Position;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
class LoadHouseholdPosition extends Fixture
{
const POSITIONS_DATA = [
["Adulte", true, true, 1.0, self::ADULT ],
["Enfants", true, false, 2.0, self::CHILD ],
["Enfants hors ménage", false, false, 3.0, self::CHILD_OUT ]
];
const ADULT = "position_adulte";
const CHILD = "position_enfant";
const CHILD_OUT = "position_enfant_hors";
public function load(ObjectManager $manager)
{
foreach (self::POSITIONS_DATA as list($name, $share, $allowHolder,
$ordering, $ref)) {
$position = (new Position())
->setLabel([ "fr" => $name ])
->setAllowHolder($allowHolder)
->setShareHousehold($share)
->setOrdering($ordering)
;
$manager->persist($position);
$this->addReference($ref, $position);
}
$manager->flush();
}
}

View File

@ -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');

View File

@ -14,7 +14,7 @@ use Chill\PersonBundle\Entity\Household\Position;
* name="chill_person_household_members"
* )
*/
class HouseholdMembers
class HouseholdMember
{
/**
* @ORM\Id
@ -26,27 +26,32 @@ class HouseholdMembers
/**
* @ORM\ManyToOne(targetEntity=Position::class)
*/
private $position;
private ?Position $position = null;
/**
* @ORM\Column(type="date")
* @ORM\Column(type="date", nullable=true, options={"default": null})
*/
private $startDate;
private ?\DateTimeImmutable $startDate = null;
/**
* @ORM\Column(type="date")
* @ORM\Column(type="date", nullable= true, options={"default": null})
*/
private $endDate;
private ?\DateTimeImmutable $endDate = null;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $comment;
private ?string $comment = NULL;
/**
* @ORM\Column(type="boolean")
*/
private $sharedHousehold;
private bool $sharedHousehold = false;
/**
* @ORM\Column(type="boolean", options={"default": false})
*/
private bool $holder = false;
/**
*
@ -55,7 +60,7 @@ class HouseholdMembers
* targetEntity="\Chill\PersonBundle\Entity\Person"
* )
*/
private $person;
private ?Person $person = null;
/**
*
@ -64,21 +69,28 @@ class HouseholdMembers
* targetEntity="\Chill\PersonBundle\Entity\Household\Household"
* )
*/
private $household;
private ?Household $household = null;
public function getId(): ?int
{
return $this->id;
}
public function getPosition(): ?string
public function getPosition(): ?Position
{
return $this->position;
}
public function setPosition(?string $position): self
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;
}
@ -119,17 +131,11 @@ class HouseholdMembers
return $this;
}
public function getSharedHousehold(): ?bool
public function getShareHousehold(): ?bool
{
return $this->sharedHousehold;
}
public function setSharedHousehold(bool $sharedHousehold): self
{
$this->sharedHousehold = $sharedHousehold;
return $this;
}
public function getPerson(): ?Person
{
@ -138,8 +144,15 @@ class HouseholdMembers
public function setPerson(?Person $person): self
{
if ($this->person instanceof Person) {
throw new \LogicException("You cannot change person ".
"on a membership");
}
$this->person = $person;
$person->addHouseholdParticipation($this);
return $this;
}
@ -150,8 +163,25 @@ class HouseholdMembers
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;
}
}

View File

@ -55,12 +55,12 @@ class Position
return $this;
}
public function getShareHouseHold(): ?bool
public function getShareHousehold(): ?bool
{
return $this->shareHouseHold;
}
public function setShareHouseHold(bool $shareHouseHold): self
public function setShareHousehold(bool $shareHouseHold): self
{
$this->shareHouseHold = $shareHouseHold;

View File

@ -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;
}
}

View File

@ -0,0 +1,80 @@
<?php
namespace Chill\PersonBundle\Household;
use Symfony\Component\Validator\ConstraintViolationListInterface;
use Chill\PersonBundle\Entity\Household\HouseholdMember;
use Chill\PersonBundle\Entity\Household\Position;
use Chill\PersonBundle\Entity\Household\Household;
use Chill\PersonBundle\Entity\Person;
use Symfony\Component\Validator\Validator\ValidatorInterface;
class MoveMembers
{
private ValidatorInterface $validator;
private Household $household;
private array $persistables = [];
private array $memershipsAffected = [];
public function __construct(ValidatorInterface $validator)
{
$this->validation = $validator;
}
public function toHousehold(Household $household): self
{
$this->household = $household;
return $this;
}
public function addMovement(\DateTimeInterface $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;
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace Chill\PersonBundle\Household;
use Chill\PersonBundle\Household\MoveMembers;
use Chill\PersonBundle\Entity\Household\Household;
use Symfony\Component\Validator\Validator\ValidatorInterface;
class MoveMembersFactory
{
public function __construct(ValidatorInterface $validator)
{
$this->validator = $validator;
}
public function createMovement(?Household $household): MoveMembers
{
$movement = new MoveMembers($this->validator);
if ($household) {
$movement->toHousehold($household);
}
return $movement;
}
}

View File

@ -1,5 +1,6 @@
services:
Chill\PersonBundle\DataFixtures\ORM\:
autowire: true
resource: ../../DataFixtures/ORM
tags: [ 'doctrine.fixture.orm' ]

View File

@ -0,0 +1,3 @@
services:
Chill\PersonBundle\Household\MoveMembersFactory:
autowire: true

View File

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace Chill\Migrations\Person;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Household members: allow startdate and enddate to be null
*/
final class Version20210528132405 extends AbstractMigration
{
public function getDescription(): string
{
return 'Household members: allow startdate and enddate to be null';
}
public function up(Schema $schema): void
{
$this->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');
}
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Chill\Migrations\Person;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Add house holder on membership
*/
final class Version20210528142121 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add house holder on membership';
}
public function up(Schema $schema): void
{
$this->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');
}
}