mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-24 19:16:15 +00:00
[export][person] Feature: add filter and aggregator by geographical unit on person
This commit is contained in:
parent
fc567868c1
commit
432acc0ace
@ -53,6 +53,13 @@ class GeographicalUnit
|
|||||||
return $this->id;
|
return $this->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function setId(int $id): self
|
||||||
|
{
|
||||||
|
$this->id = $id;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function getUnitName(): ?string
|
public function getUnitName(): ?string
|
||||||
{
|
{
|
||||||
return $this->unitName;
|
return $this->unitName;
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
namespace Chill\MainBundle\Repository;
|
namespace Chill\MainBundle\Repository;
|
||||||
|
|
||||||
use Chill\MainBundle\Entity\GeographicalUnit;
|
use Chill\MainBundle\Entity\GeographicalUnit;
|
||||||
|
use Chill\MainBundle\Entity\GeographicalUnitDTO;
|
||||||
|
use Chill\MainBundle\Entity\GeographicalUnitLayer;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Doctrine\ORM\EntityRepository;
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
|
||||||
@ -33,7 +35,7 @@ class GeographicalUnitRepository implements GeographicalUnitRepositoryInterface
|
|||||||
{
|
{
|
||||||
return $this->repository
|
return $this->repository
|
||||||
->createQueryBuilder('gu')
|
->createQueryBuilder('gu')
|
||||||
->addSelect('PARTIAL gu.{id,unitName,unitRefId,layer}')
|
->select('PARTIAL gu.{id,unitName,unitRefId,layer}')
|
||||||
->addOrderBy('IDENTITY(gu.layer)')
|
->addOrderBy('IDENTITY(gu.layer)')
|
||||||
->addOrderBy(('gu.unitName'))
|
->addOrderBy(('gu.unitName'))
|
||||||
->getQuery()
|
->getQuery()
|
||||||
|
@ -0,0 +1,163 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Export\Aggregator\PersonAggregators;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\GeographicalUnit;
|
||||||
|
use Chill\MainBundle\Entity\GeographicalUnitLayer;
|
||||||
|
use Chill\MainBundle\Export\AggregatorInterface;
|
||||||
|
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||||
|
use Chill\MainBundle\Repository\GeographicalUnitLayerRepositoryInterface;
|
||||||
|
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||||
|
use Chill\PersonBundle\Export\Declarations;
|
||||||
|
use Doctrine\ORM\Query\Expr\Join;
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
|
||||||
|
class GeographicalUnitAggregator implements AggregatorInterface
|
||||||
|
{
|
||||||
|
private GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository;
|
||||||
|
|
||||||
|
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository,
|
||||||
|
TranslatableStringHelperInterface $translatableStringHelper
|
||||||
|
) {
|
||||||
|
$this->geographicalUnitLayerRepository = $geographicalUnitLayerRepository;
|
||||||
|
$this->translatableStringHelper = $translatableStringHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function getLabels($key, array $values, $data)
|
||||||
|
{
|
||||||
|
switch ($key) {
|
||||||
|
case 'geog_unit_name':
|
||||||
|
return function ($value): string {
|
||||||
|
if ('_header' === $value) {
|
||||||
|
return 'acp_geog_agg_unitname';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $value) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
};
|
||||||
|
|
||||||
|
case 'geog_unit_key':
|
||||||
|
return function ($value): string {
|
||||||
|
if ('_header' === $value) {
|
||||||
|
return 'acp_geog_agg_unitrefid';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $value) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
};
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new \LogicException('key not supported');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function getQueryKeys($data)
|
||||||
|
{
|
||||||
|
return ['geog_unit_name', 'geog_unit_key'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function buildForm(FormBuilderInterface $builder)
|
||||||
|
{
|
||||||
|
$builder
|
||||||
|
->add('date_calc', ChillDateType::class, [
|
||||||
|
'label' => 'Address valid at this date',
|
||||||
|
'required' => true,
|
||||||
|
'data' => new \DateTimeImmutable('today'),
|
||||||
|
'input' => 'datetime_immutable',
|
||||||
|
])
|
||||||
|
->add('level', EntityType::class, [
|
||||||
|
'label' => 'Geographical layer',
|
||||||
|
'placeholder' => 'Select a geographical layer',
|
||||||
|
'class' => GeographicalUnitLayer::class,
|
||||||
|
'choices' => $this->geographicalUnitLayerRepository->findAllHavingUnits(),
|
||||||
|
'choice_label' => function(GeographicalUnitLayer $item) {
|
||||||
|
return $this->translatableStringHelper->localize($item->getName());
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function getTitle()
|
||||||
|
{
|
||||||
|
return 'Group people by geographical unit based on his address';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function addRole(): ?string
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function alterQuery(QueryBuilder $qb, $data): void
|
||||||
|
{
|
||||||
|
$qb
|
||||||
|
->leftJoin('person.householdAddresses', 'person_geog_agg_current_household_address')
|
||||||
|
->leftJoin('person_geog_agg_current_household_address.address', 'person_geog_agg_address')
|
||||||
|
->leftJoin(GeographicalUnit::class, 'person_geog_agg_geog_unit', Join::WITH, 'ST_CONTAINS(person_geog_agg_geog_unit.geom, person_geog_agg_address.point) = TRUE')
|
||||||
|
->andWhere(
|
||||||
|
$qb->expr()->orX(
|
||||||
|
$qb->expr()->isNull('person_geog_agg_current_household_address'),
|
||||||
|
$qb->expr()->andX(
|
||||||
|
$qb->expr()->lte('person_geog_agg_current_household_address.validFrom', ':person_geog_agg_date'),
|
||||||
|
$qb->expr()->orX(
|
||||||
|
$qb->expr()->isNull('person_geog_agg_current_household_address.validTo'),
|
||||||
|
$qb->expr()->gt('person_geog_agg_current_household_address.validTo', ':person_geog_agg_date')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
->andWhere(
|
||||||
|
$qb->expr()->orX(
|
||||||
|
$qb->expr()->isNull('person_geog_agg_geog_unit'),
|
||||||
|
$qb->expr()->in('person_geog_agg_geog_unit.layer', ':person_geog_agg_layers')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
->setParameter('person_geog_agg_date', $data['date_calc'])
|
||||||
|
->setParameter('person_geog_agg_layers', $data['level'])
|
||||||
|
->addSelect('person_geog_agg_geog_unit.unitName AS geog_unit_name')
|
||||||
|
->addSelect('person_geog_agg_geog_unit.unitRefId AS geog_unit_key')
|
||||||
|
->addGroupBy('geog_unit_name')
|
||||||
|
->addGroupBy('geog_unit_key')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function applyOn()
|
||||||
|
{
|
||||||
|
return Declarations::PERSON_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getDefaultAlias(): string
|
||||||
|
{
|
||||||
|
return 'person_geog_agg';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,134 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Export\Filter\PersonFilters;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
|
use Chill\MainBundle\Entity\GeographicalUnit;
|
||||||
|
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||||
|
use Chill\MainBundle\Repository\GeographicalUnitLayerRepositoryInterface;
|
||||||
|
use Chill\MainBundle\Repository\GeographicalUnitRepositoryInterface;
|
||||||
|
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||||
|
use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress;
|
||||||
|
use Chill\PersonBundle\Export\Declarations;
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
|
||||||
|
class GeographicalUnitFilter implements \Chill\MainBundle\Export\FilterInterface
|
||||||
|
{
|
||||||
|
private GeographicalUnitRepositoryInterface $geographicalUnitRepository;
|
||||||
|
|
||||||
|
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
GeographicalUnitRepositoryInterface $geographicalUnitRepository,
|
||||||
|
TranslatableStringHelperInterface $translatableStringHelper
|
||||||
|
) {
|
||||||
|
$this->geographicalUnitRepository = $geographicalUnitRepository;
|
||||||
|
$this->translatableStringHelper = $translatableStringHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function buildForm(FormBuilderInterface $builder)
|
||||||
|
{
|
||||||
|
$builder
|
||||||
|
->add('date_calc', ChillDateType::class, [
|
||||||
|
'label' => 'Compute geographical location at date',
|
||||||
|
'required' => true,
|
||||||
|
'data' => new \DateTimeImmutable('today'),
|
||||||
|
'input' => 'datetime_immutable',
|
||||||
|
])
|
||||||
|
->add('units', EntityType::class, [
|
||||||
|
'label' => 'Geographical unit',
|
||||||
|
'placeholder' => 'Select a geographical unit',
|
||||||
|
'class' => GeographicalUnit::class,
|
||||||
|
'choices' => $this->geographicalUnitRepository->findAll(),
|
||||||
|
'choice_label' => function(GeographicalUnit $item) {
|
||||||
|
return $this->translatableStringHelper->localize($item->getLayer()->getName()) . ' > ' . $item->getUnitName();
|
||||||
|
},
|
||||||
|
'attr' => [
|
||||||
|
'class' => 'select2',
|
||||||
|
],
|
||||||
|
'multiple' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function getTitle(): string
|
||||||
|
{
|
||||||
|
return 'Filter by person\'s geographical unit (based on address)';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function describeAction($data, $format = 'string')
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'exports.by_person.Filtered by person\'s geographical unit (based on address) computed at datecalc, only units',
|
||||||
|
[
|
||||||
|
'datecalc' => $data['date_calc']->format('Y-m-d'),
|
||||||
|
'units' => implode(
|
||||||
|
', ',
|
||||||
|
array_map(
|
||||||
|
function (GeographicalUnit $item) {
|
||||||
|
return $this->translatableStringHelper->localize($item->getLayer()->getName()) . ' > ' . $item->getUnitName();
|
||||||
|
},
|
||||||
|
$data['units']->toArray()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function addRole(): ?string
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
|
{
|
||||||
|
$subQuery =
|
||||||
|
'SELECT 1
|
||||||
|
FROM '.PersonHouseholdAddress::class.' person_filter_geog_person_household_address
|
||||||
|
JOIN person_filter_geog_person_household_address.address person_filter_geog_address
|
||||||
|
JOIN '.GeographicalUnit::class.' person_filter_geog_unit
|
||||||
|
WITH ST_CONTAINS(person_filter_geog_unit.geom, person_filter_geog_address.point) = TRUE
|
||||||
|
WHERE
|
||||||
|
person_filter_geog_person_household_address.validFrom <= :person_filter_geog_date
|
||||||
|
AND
|
||||||
|
(person_filter_geog_person_household_address.validTo IS NULL
|
||||||
|
OR person_filter_geog_person_household_address.validTo > :person_filter_geog_date)
|
||||||
|
AND
|
||||||
|
person_filter_geog_unit IN (:person_filter_geog_units)
|
||||||
|
AND
|
||||||
|
person_filter_geog_person_household_address.person = person
|
||||||
|
';
|
||||||
|
|
||||||
|
$qb
|
||||||
|
->andWhere(
|
||||||
|
$qb->expr()->exists($subQuery)
|
||||||
|
)
|
||||||
|
->setParameter('person_filter_geog_date', $data['date_calc'])
|
||||||
|
->setParameter('person_filter_geog_units', $data['units'])
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function applyOn()
|
||||||
|
{
|
||||||
|
return Declarations::PERSON_TYPE;
|
||||||
|
}
|
||||||
|
}
|
@ -90,6 +90,12 @@ services:
|
|||||||
tags:
|
tags:
|
||||||
- { name: chill.export_filter, alias: person_marital_status_filter }
|
- { name: chill.export_filter, alias: person_marital_status_filter }
|
||||||
|
|
||||||
|
Chill\PersonBundle\Export\Filter\PersonFilters\GeographicalUnitFilter:
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
|
tags:
|
||||||
|
- { name: chill.export_filter, alias: person_geog_filter }
|
||||||
|
|
||||||
## Aggregators
|
## Aggregators
|
||||||
chill.person.export.aggregator_nationality:
|
chill.person.export.aggregator_nationality:
|
||||||
class: Chill\PersonBundle\Export\Aggregator\PersonAggregators\NationalityAggregator
|
class: Chill\PersonBundle\Export\Aggregator\PersonAggregators\NationalityAggregator
|
||||||
@ -132,3 +138,10 @@ services:
|
|||||||
autoconfigure: true
|
autoconfigure: true
|
||||||
tags:
|
tags:
|
||||||
- { name: chill.export_aggregator, alias: person_household_position_aggregator }
|
- { name: chill.export_aggregator, alias: person_household_position_aggregator }
|
||||||
|
|
||||||
|
Chill\PersonBundle\Export\Aggregator\PersonAggregators\GeographicalUnitAggregator:
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
|
tags:
|
||||||
|
- { name: chill.export_aggregator, alias: person_geog_aggregator }
|
||||||
|
|
||||||
|
@ -130,3 +130,8 @@ periods:
|
|||||||
many {Masquer # parcours clôturés ou anciens parcours}
|
many {Masquer # parcours clôturés ou anciens parcours}
|
||||||
other {Masquer # parcours clôturés ou anciens parcours}
|
other {Masquer # parcours clôturés ou anciens parcours}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports:
|
||||||
|
by_person:
|
||||||
|
Filtered by person\'s geographical unit (based on address) computed at date, only units:
|
||||||
|
"Filtré par zone géographique sur base de l'adresse, calculé à {datecalc, date, short}, seulement les zones suivantes: {units}"
|
||||||
|
@ -462,6 +462,8 @@ acp_geog_agg_unitname: Zone géographique
|
|||||||
acp_geog_agg_unitrefid: Clé de la zone géographique
|
acp_geog_agg_unitrefid: Clé de la zone géographique
|
||||||
Geographical layer: Couche géographique
|
Geographical layer: Couche géographique
|
||||||
Select a geographical layer: Choisir une couche géographique
|
Select a geographical layer: Choisir une couche géographique
|
||||||
|
Group people by geographical unit based on his address: Grouper les personnes par zone géographique (sur base de l'adresse)
|
||||||
|
Filter by person's geographical unit (based on address): Filter les personnes par zone géographique (sur base de l'adresse)
|
||||||
|
|
||||||
Filter by socialaction: Filtrer les parcours par action d'accompagnement
|
Filter by socialaction: Filtrer les parcours par action d'accompagnement
|
||||||
Accepted socialactions: Actions d'accompagnement
|
Accepted socialactions: Actions d'accompagnement
|
||||||
|
Loading…
x
Reference in New Issue
Block a user