mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-14 14:24:24 +00:00
Merge branch 'features/sql-vue-from-household-address-to-person' into 'master'
Features/sql vue from household address to person See merge request Chill-Projet/chill-bundles!86
This commit is contained in:
commit
1b1a25edc4
@ -196,6 +196,8 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
|
|||||||
'doctrine',
|
'doctrine',
|
||||||
[
|
[
|
||||||
'dbal' => [
|
'dbal' => [
|
||||||
|
// ignore views:
|
||||||
|
'schema_filter' => '~^(?!view_)~',
|
||||||
// This is mandatory since we are using postgis as database.
|
// This is mandatory since we are using postgis as database.
|
||||||
'mapping_types' => [
|
'mapping_types' => [
|
||||||
'geometry' => 'string',
|
'geometry' => 'string',
|
||||||
|
@ -116,7 +116,7 @@ class Address
|
|||||||
* @ORM\Column(type="date")
|
* @ORM\Column(type="date")
|
||||||
* @groups({"write"})
|
* @groups({"write"})
|
||||||
*/
|
*/
|
||||||
private $validFrom;
|
private \DateTime $validFrom;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates when the address ends. Used to build an history
|
* Indicates when the address ends. Used to build an history
|
||||||
@ -127,7 +127,7 @@ class Address
|
|||||||
* @ORM\Column(type="date", nullable=true)
|
* @ORM\Column(type="date", nullable=true)
|
||||||
* @groups({"write"})
|
* @groups({"write"})
|
||||||
*/
|
*/
|
||||||
private $validTo;
|
private ?\DateTime $validTo = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if the address is a "no address", aka homeless person, ...
|
* True if the address is a "no address", aka homeless person, ...
|
||||||
|
@ -4,11 +4,15 @@ namespace Chill\PersonBundle\DataFixtures\ORM;
|
|||||||
|
|
||||||
use Chill\PersonBundle\Entity\Person;
|
use Chill\PersonBundle\Entity\Person;
|
||||||
use Chill\PersonBundle\Entity\Household\Household;
|
use Chill\PersonBundle\Entity\Household\Household;
|
||||||
|
use Chill\MainBundle\Entity\PostalCode;
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
use Chill\PersonBundle\Household\MembersEditorFactory;
|
use Chill\PersonBundle\Household\MembersEditorFactory;
|
||||||
use Doctrine\Bundle\FixturesBundle\Fixture;
|
use Doctrine\Bundle\FixturesBundle\Fixture;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Doctrine\Persistence\ObjectManager;
|
use Doctrine\Persistence\ObjectManager;
|
||||||
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
|
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
|
||||||
|
use Nelmio\Alice\Loader\NativeLoader;
|
||||||
|
use Chill\MainBundle\DataFixtures\ORM\LoadPostalCodes;
|
||||||
|
|
||||||
class LoadHousehold extends Fixture implements DependentFixtureInterface
|
class LoadHousehold extends Fixture implements DependentFixtureInterface
|
||||||
{
|
{
|
||||||
@ -16,12 +20,15 @@ class LoadHousehold extends Fixture implements DependentFixtureInterface
|
|||||||
|
|
||||||
private EntityManagerInterface $em;
|
private EntityManagerInterface $em;
|
||||||
|
|
||||||
|
private NativeLoader $loader;
|
||||||
|
|
||||||
private CONST NUMBER_OF_HOUSEHOLD = 10;
|
private CONST NUMBER_OF_HOUSEHOLD = 10;
|
||||||
|
|
||||||
public function __construct(MembersEditorFactory $editorFactory, EntityManagerInterface $em)
|
public function __construct(MembersEditorFactory $editorFactory, EntityManagerInterface $em)
|
||||||
{
|
{
|
||||||
$this->editorFactory = $editorFactory;
|
$this->editorFactory = $editorFactory;
|
||||||
$this->em = $em;
|
$this->em = $em;
|
||||||
|
$this->loader = new NativeLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function load(ObjectManager $manager)
|
public function load(ObjectManager $manager)
|
||||||
@ -53,6 +60,8 @@ class LoadHousehold extends Fixture implements DependentFixtureInterface
|
|||||||
$household = new Household();
|
$household = new Household();
|
||||||
$manager->persist($household);
|
$manager->persist($household);
|
||||||
|
|
||||||
|
$this->addAddressToHousehold($household, clone $startDate, $manager);
|
||||||
|
|
||||||
$movement = $this->editorFactory->createEditor($household);
|
$movement = $this->editorFactory->createEditor($household);
|
||||||
|
|
||||||
// load adults
|
// load adults
|
||||||
@ -89,6 +98,55 @@ class LoadHousehold extends Fixture implements DependentFixtureInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function addAddressToHousehold(Household $household, \DateTimeImmutable $date, ObjectManager $manager)
|
||||||
|
{
|
||||||
|
if (\random_int(0, 10) > 8) {
|
||||||
|
// 20% of household without address
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$nb = \random_int(1, 6);
|
||||||
|
|
||||||
|
$i = 0;
|
||||||
|
while ($i < $nb) {
|
||||||
|
$address = $this->createAddress();
|
||||||
|
$address->setValidFrom(\DateTime::createFromImmutable($date));
|
||||||
|
|
||||||
|
if (\random_int(0, 20) < 1) {
|
||||||
|
$date = $date->add(new \DateInterval('P'.\random_int(8, 52).'W'));
|
||||||
|
$address->setValidTo(\DateTime::createFromImmutable($date));
|
||||||
|
}
|
||||||
|
|
||||||
|
$household->addAddress($address);
|
||||||
|
$manager->persist($address);
|
||||||
|
|
||||||
|
$date = $date->add(new \DateInterval('P'.\random_int(8, 52).'W'));
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createAddress(): Address
|
||||||
|
{
|
||||||
|
$objectSet = $this->loader->loadData([
|
||||||
|
Address::class => [
|
||||||
|
'address1' => [
|
||||||
|
'street' => '<fr_FR:streetName()>',
|
||||||
|
'streetNumber' => '<fr_FR:buildingNumber()>',
|
||||||
|
'postCode' => $this->getPostalCode()
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $objectSet->getObjects()['address1'];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getPostalCode(): PostalCode
|
||||||
|
{
|
||||||
|
$ref = LoadPostalCodes::$refs[\array_rand(LoadPostalCodes::$refs)];
|
||||||
|
|
||||||
|
return $this->getReference($ref);
|
||||||
|
}
|
||||||
|
|
||||||
private function preparePersonIds()
|
private function preparePersonIds()
|
||||||
{
|
{
|
||||||
$this->personIds = $this->em
|
$this->personIds = $this->em
|
||||||
|
@ -51,7 +51,7 @@ class Household
|
|||||||
* targetEntity=HouseholdMember::class,
|
* targetEntity=HouseholdMember::class,
|
||||||
* mappedBy="household"
|
* mappedBy="household"
|
||||||
* )
|
* )
|
||||||
* @Serializer\Groups({"write"})
|
* @Serializer\Groups({"write", "read"})
|
||||||
*/
|
*/
|
||||||
private Collection $members;
|
private Collection $members;
|
||||||
|
|
||||||
@ -88,13 +88,14 @@ class Household
|
|||||||
*/
|
*/
|
||||||
public function addAddress(Address $address)
|
public function addAddress(Address $address)
|
||||||
{
|
{
|
||||||
$this->addresses[] = $address;
|
|
||||||
|
|
||||||
foreach ($this->getAddresses() as $a) {
|
foreach ($this->getAddresses() as $a) {
|
||||||
if ($a->getValidFrom() < $address->getValidFrom() && $a->getValidTo() === NULL) {
|
if ($a->getValidFrom() < $address->getValidFrom() && $a->getValidTo() === NULL) {
|
||||||
$a->setValidTo($address->getValidFrom());
|
$a->setValidTo($address->getValidFrom());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->addresses[] = $address;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,6 +119,27 @@ class Household
|
|||||||
return $this->addresses;
|
return $this->addresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Serializer\Groups({ "read" })
|
||||||
|
* @Serializer\SerializedName("current_address")
|
||||||
|
*/
|
||||||
|
public function getCurrentAddress(\DateTime $at = null): ?Address
|
||||||
|
{
|
||||||
|
$at = $at === null ? new \DateTime('today') : $at;
|
||||||
|
|
||||||
|
$addrs = $this->getAddresses()->filter(function (Address $a) use ($at) {
|
||||||
|
return $a->getValidFrom() < $at && (
|
||||||
|
NULL === $a->getValidTo() || $at < $a->getValidTo()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($addrs->count() > 0) {
|
||||||
|
return $addrs->first();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Collection|HouseholdMember[]
|
* @return Collection|HouseholdMember[]
|
||||||
*/
|
*/
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Entity\Household;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
|
use Chill\PersonBundle\Entity\Household\Household;
|
||||||
|
use Chill\PersonBundle\Entity\Person;
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Entity(readOnly=true)
|
||||||
|
* @ORM\Table(name="view_chill_person_household_address")
|
||||||
|
*/
|
||||||
|
class PersonHouseholdAddress
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="date_immutable")
|
||||||
|
*/
|
||||||
|
private $validFrom;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="date_immutable", nullable=true)
|
||||||
|
*/
|
||||||
|
private $validTo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Id
|
||||||
|
* @ORM\ManyToOne(targetEntity=Person::class)
|
||||||
|
* @ORM\JoinColumn(nullable=false)
|
||||||
|
*/
|
||||||
|
private $person;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Id
|
||||||
|
* @ORM\ManyToOne(targetEntity=Household::class)
|
||||||
|
* @ORM\JoinColumn(nullable=false)
|
||||||
|
*/
|
||||||
|
private $household;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Id
|
||||||
|
* @ORM\ManyToOne(targetEntity=Address::class)
|
||||||
|
* @ORM\JoinColumn(nullable=false)
|
||||||
|
*/
|
||||||
|
private $address;
|
||||||
|
|
||||||
|
public function getValidFrom(): ?\DateTimeInterface
|
||||||
|
{
|
||||||
|
return $this->validFrom;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getValidTo(): ?\DateTimeImmutable
|
||||||
|
{
|
||||||
|
return $this->validTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPerson(): ?Person
|
||||||
|
{
|
||||||
|
return $this->person;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHousehold(): ?Household
|
||||||
|
{
|
||||||
|
return $this->relation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAddress(): ?Address
|
||||||
|
{
|
||||||
|
return $this->address;
|
||||||
|
}
|
||||||
|
}
|
@ -37,6 +37,7 @@ use Doctrine\Common\Collections\ArrayCollection;
|
|||||||
use Doctrine\Common\Collections\Criteria;
|
use Doctrine\Common\Collections\Criteria;
|
||||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||||
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||||
|
use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Person Class
|
* Person Class
|
||||||
@ -287,6 +288,14 @@ class Person implements HasCenterInterface
|
|||||||
*/
|
*/
|
||||||
private array $currentHouseholdAt = [];
|
private array $currentHouseholdAt = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\OneToMany(
|
||||||
|
* targetEntity=PersonHouseholdAddress::class,
|
||||||
|
* mappedBy="person"
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
private Collection $householdAddresses;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Person constructor.
|
* Person constructor.
|
||||||
*
|
*
|
||||||
@ -300,6 +309,7 @@ class Person implements HasCenterInterface
|
|||||||
$this->altNames = new ArrayCollection();
|
$this->altNames = new ArrayCollection();
|
||||||
$this->otherPhoneNumbers = new ArrayCollection();
|
$this->otherPhoneNumbers = new ArrayCollection();
|
||||||
$this->householdParticipations = new ArrayCollection();
|
$this->householdParticipations = new ArrayCollection();
|
||||||
|
$this->householdAddresses = new ArrayCollection();
|
||||||
|
|
||||||
if ($opening === null) {
|
if ($opening === null) {
|
||||||
$opening = new \DateTime();
|
$opening = new \DateTime();
|
||||||
@ -1291,4 +1301,36 @@ class Person implements HasCenterInterface
|
|||||||
{
|
{
|
||||||
return NULL !== $this->getCurrentHousehold($at);
|
return NULL !== $this->getCurrentHousehold($at);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getHouseholdAddresses(): Collection
|
||||||
|
{
|
||||||
|
return $this->householdAddresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCurrentHouseholdAddress(?\DateTimeImmutable $at = null): ?Address
|
||||||
|
{
|
||||||
|
$at = $at === null ? new \DateTimeImmutable('today') : $at;
|
||||||
|
$criteria = new Criteria();
|
||||||
|
$expr = Criteria::expr();
|
||||||
|
|
||||||
|
$criteria->where(
|
||||||
|
$expr->lte('validFrom', $at)
|
||||||
|
)
|
||||||
|
->andWhere(
|
||||||
|
$expr->orX(
|
||||||
|
$expr->isNull('validTo'),
|
||||||
|
$expr->gte('validTo', $at)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$addrs = $this->getHouseholdAddresses()
|
||||||
|
->matching($criteria)
|
||||||
|
;
|
||||||
|
|
||||||
|
if ($addrs->count() > 0) {
|
||||||
|
return $addrs->first()->getAddress();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Repository\Household;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
use Doctrine\Persistence\ObjectRepository;
|
||||||
|
|
||||||
|
final class PersonHouseholdAddressRepository implements ObjectRepository
|
||||||
|
{
|
||||||
|
private EntityRepository $repository;
|
||||||
|
|
||||||
|
public function __construct(EntityManagerInterface $em)
|
||||||
|
{
|
||||||
|
$this->repository = $em->getRepository(PersonHouseholdAddress::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function find($id, $lockMode = null, $lockVersion = null): ?PersonHouseholdAddress
|
||||||
|
{
|
||||||
|
return $this->repository->find($id, $lockMode, $lockVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findOneBy(array $criteria, array $orderBy = null): ?PersonHouseholdAddress
|
||||||
|
{
|
||||||
|
return $this->repository->findOneBy($criteria, $orderBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return PersonHouseholdAddress[]
|
||||||
|
*/
|
||||||
|
public function findAll(): array
|
||||||
|
{
|
||||||
|
return $this->repository->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return PersonHouseholdAddress[]
|
||||||
|
*/
|
||||||
|
public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null): array
|
||||||
|
{
|
||||||
|
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getClassName() {
|
||||||
|
return PersonHouseholdAddress::class;
|
||||||
|
}
|
||||||
|
}
|
@ -75,6 +75,7 @@ class PersonNormalizer implements
|
|||||||
'altNames' => $this->normalizeAltNames($person->getAltNames()),
|
'altNames' => $this->normalizeAltNames($person->getAltNames()),
|
||||||
'gender' => $person->getGender(),
|
'gender' => $person->getGender(),
|
||||||
'gender_numeric' => $person->getGenderNumeric(),
|
'gender_numeric' => $person->getGenderNumeric(),
|
||||||
|
'current_household_address' => $this->normalizer->normalize($person->getCurrentHouseholdAddress()),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,8 +9,8 @@ module.exports = function(encore, entries)
|
|||||||
});
|
});
|
||||||
|
|
||||||
encore.addEntry('accompanying_course', __dirname + '/Resources/public/vuejs/AccompanyingCourse/index.js');
|
encore.addEntry('accompanying_course', __dirname + '/Resources/public/vuejs/AccompanyingCourse/index.js');
|
||||||
|
encore.addEntry('household_address', __dirname + '/Resources/public/vuejs/HouseholdAddress/index.js');
|
||||||
encore.addEntry('household_members_editor', __dirname + '/Resources/public/vuejs/HouseholdMembersEditor/index.js');
|
encore.addEntry('household_members_editor', __dirname + '/Resources/public/vuejs/HouseholdMembersEditor/index.js');
|
||||||
encore.addEntry('vue_accourse', __dirname + '/Resources/public/vuejs/AccompanyingCourse/index.js');
|
encore.addEntry('vue_accourse', __dirname + '/Resources/public/vuejs/AccompanyingCourse/index.js');
|
||||||
encore.addEntry('household_edit_metadata', __dirname + '/Resources/public/modules/household_edit_metadata/index.js');
|
encore.addEntry('household_edit_metadata', __dirname + '/Resources/public/modules/household_edit_metadata/index.js');
|
||||||
encore.addEntry('household_address', __dirname + '/Resources/public/vuejs/HouseholdAddress/index.js');
|
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\Migrations\Person;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a view for assembling household, person and addresses
|
||||||
|
*/
|
||||||
|
final class Version20210616102900 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'Create a view for assembling household, person and addresses';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql("CREATE VIEW view_chill_person_household_address AS ".
|
||||||
|
"SELECT ".
|
||||||
|
"members.person_id AS person_id, ".
|
||||||
|
"members.household_id AS household_id, ".
|
||||||
|
"members.id AS member_id, ".
|
||||||
|
"address.id AS address_id, ".
|
||||||
|
"CASE WHEN address.validFrom < members.startDate THEN members.startDate ELSE address.validFrom END AS validFrom, ".
|
||||||
|
"CASE WHEN COALESCE(address.validTo, 'infinity') < COALESCE(members.endDate, 'infinity') THEN address.validTo ELSE members.endDate END AS validTo ".
|
||||||
|
"FROM chill_person_household_members AS members ".
|
||||||
|
"JOIN chill_person_household_to_addresses AS household_to_addr ON household_to_addr.household_id = members.household_id ".
|
||||||
|
"JOIN chill_main_address AS address ON household_to_addr.address_id = address.id ".
|
||||||
|
"AND daterange(address.validFrom, address.validTo) && daterange(members.startDate, members.endDate) ".
|
||||||
|
"WHERE members.sharedhousehold IS TRUE "
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql("DROP VIEW view_chill_person_household_address");
|
||||||
|
}
|
||||||
|
}
|
@ -88,17 +88,8 @@ class LoadThirdParty extends Fixture Implements DependentFixtureInterface
|
|||||||
private function getPostalCode(): PostalCode
|
private function getPostalCode(): PostalCode
|
||||||
{
|
{
|
||||||
$ref = LoadPostalCodes::$refs[\array_rand(LoadPostalCodes::$refs)];
|
$ref = LoadPostalCodes::$refs[\array_rand(LoadPostalCodes::$refs)];
|
||||||
|
|
||||||
return $this->getReference($ref);
|
return $this->getReference($ref);
|
||||||
if (count($this->postalCodesIds) === 0) {
|
|
||||||
// fill the postal codes
|
|
||||||
$this->em->createQuery('SELECT p.id FROM '.PostalCode::class)
|
|
||||||
->getScalarResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
$id = $this->postalCodesIds[\array_rand($this->postalCodesIds)];
|
|
||||||
|
|
||||||
return $this->em->getRepository(PostalCode::class)
|
|
||||||
->find($id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createAddress(): ObjectSet
|
private function createAddress(): ObjectSet
|
||||||
|
Loading…
x
Reference in New Issue
Block a user