mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Merge branch '238-custom-column-export-person' into 'master'
Liste des usagers: permettre d'ajouter des colonnes custom Closes #238 See merge request Chill-Projet/chill-bundles!668
This commit is contained in:
commit
9ac43ecf5b
5
.changes/unreleased/Feature-20240319-172100.yaml
Normal file
5
.changes/unreleased/Feature-20240319-172100.yaml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
kind: Feature
|
||||||
|
body: Allow to customize list person with new fields
|
||||||
|
time: 2024-03-19T17:21:00.873293991+01:00
|
||||||
|
custom:
|
||||||
|
Issue: "238"
|
@ -13,6 +13,7 @@ namespace Chill\PersonBundle;
|
|||||||
|
|
||||||
use Chill\PersonBundle\Actions\Remove\PersonMoveSqlHandlerInterface;
|
use Chill\PersonBundle\Actions\Remove\PersonMoveSqlHandlerInterface;
|
||||||
use Chill\PersonBundle\DependencyInjection\CompilerPass\AccompanyingPeriodTimelineCompilerPass;
|
use Chill\PersonBundle\DependencyInjection\CompilerPass\AccompanyingPeriodTimelineCompilerPass;
|
||||||
|
use Chill\PersonBundle\Export\Helper\CustomizeListPersonHelperInterface;
|
||||||
use Chill\PersonBundle\Service\EntityInfo\AccompanyingPeriodInfoUnionQueryPartInterface;
|
use Chill\PersonBundle\Service\EntityInfo\AccompanyingPeriodInfoUnionQueryPartInterface;
|
||||||
use Chill\PersonBundle\Widget\PersonListWidgetFactory;
|
use Chill\PersonBundle\Widget\PersonListWidgetFactory;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
@ -32,5 +33,7 @@ class ChillPersonBundle extends Bundle
|
|||||||
->addTag('chill_person.accompanying_period_info_part');
|
->addTag('chill_person.accompanying_period_info_part');
|
||||||
$container->registerForAutoconfiguration(PersonMoveSqlHandlerInterface::class)
|
$container->registerForAutoconfiguration(PersonMoveSqlHandlerInterface::class)
|
||||||
->addTag('chill_person.person_move_handler');
|
->addTag('chill_person.person_move_handler');
|
||||||
|
$container->registerForAutoconfiguration(CustomizeListPersonHelperInterface::class)
|
||||||
|
->addTag('chill_person.list_person_customizer');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,8 @@ namespace Chill\PersonBundle\Export\Export;
|
|||||||
use Chill\CustomFieldsBundle\CustomFields\CustomFieldChoice;
|
use Chill\CustomFieldsBundle\CustomFields\CustomFieldChoice;
|
||||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||||
use Chill\CustomFieldsBundle\Service\CustomFieldProvider;
|
use Chill\CustomFieldsBundle\Service\CustomFieldProvider;
|
||||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
|
||||||
use Chill\MainBundle\Export\FormatterInterface;
|
use Chill\MainBundle\Export\FormatterInterface;
|
||||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||||
use Chill\MainBundle\Export\Helper\ExportAddressHelper;
|
|
||||||
use Chill\MainBundle\Export\ListInterface;
|
use Chill\MainBundle\Export\ListInterface;
|
||||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||||
@ -30,21 +28,17 @@ use Doctrine\ORM\EntityManagerInterface;
|
|||||||
use Doctrine\ORM\Query;
|
use Doctrine\ORM\Query;
|
||||||
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
||||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\Validator\Constraints\Callback;
|
|
||||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render a list of people.
|
* Render a list of people.
|
||||||
*/
|
*/
|
||||||
class ListPerson implements ExportElementValidatedInterface, ListInterface, GroupedExportInterface
|
class ListPerson implements ListInterface, GroupedExportInterface
|
||||||
{
|
{
|
||||||
private array $slugs = [];
|
private array $slugs = [];
|
||||||
private readonly bool $filterStatsByCenters;
|
private readonly bool $filterStatsByCenters;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly ExportAddressHelper $addressHelper,
|
|
||||||
private readonly CustomFieldProvider $customFieldProvider,
|
private readonly CustomFieldProvider $customFieldProvider,
|
||||||
private readonly ListPersonHelper $listPersonHelper,
|
private readonly ListPersonHelper $listPersonHelper,
|
||||||
private readonly EntityManagerInterface $entityManager,
|
private readonly EntityManagerInterface $entityManager,
|
||||||
@ -56,39 +50,6 @@ class ListPerson implements ExportElementValidatedInterface, ListInterface, Grou
|
|||||||
|
|
||||||
public function buildForm(FormBuilderInterface $builder)
|
public function buildForm(FormBuilderInterface $builder)
|
||||||
{
|
{
|
||||||
$choices = array_combine(ListPersonHelper::FIELDS, ListPersonHelper::FIELDS);
|
|
||||||
|
|
||||||
foreach ($this->getCustomFields() as $cf) {
|
|
||||||
$choices[$this->translatableStringHelper->localize($cf->getName())]
|
|
||||||
=
|
|
||||||
$cf->getSlug();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a checkbox to select fields
|
|
||||||
$builder->add('fields', ChoiceType::class, [
|
|
||||||
'multiple' => true,
|
|
||||||
'expanded' => true,
|
|
||||||
'choices' => $choices,
|
|
||||||
'label' => 'Fields to include in export',
|
|
||||||
'choice_attr' => static function (string $val): array {
|
|
||||||
// add a 'data-display-target' for address fields
|
|
||||||
if (str_starts_with($val, 'address') || 'center' === $val || 'household' === $val) {
|
|
||||||
return ['data-display-target' => 'address_date'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
},
|
|
||||||
'constraints' => [new Callback([
|
|
||||||
'callback' => static function ($selected, ExecutionContextInterface $context) {
|
|
||||||
if (0 === \count($selected)) {
|
|
||||||
$context->buildViolation('You must select at least one element')
|
|
||||||
->atPath('fields')
|
|
||||||
->addViolation();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
])],
|
|
||||||
]);
|
|
||||||
|
|
||||||
// add a date field for addresses
|
// add a date field for addresses
|
||||||
$builder->add('address_date', ChillDateType::class, [
|
$builder->add('address_date', ChillDateType::class, [
|
||||||
'label' => 'Data valid at this date',
|
'label' => 'Data valid at this date',
|
||||||
@ -99,15 +60,7 @@ class ListPerson implements ExportElementValidatedInterface, ListInterface, Grou
|
|||||||
|
|
||||||
public function getFormDefaultData(): array
|
public function getFormDefaultData(): array
|
||||||
{
|
{
|
||||||
$choices = array_combine(ListPersonHelper::FIELDS, ListPersonHelper::FIELDS);
|
return ['address_date' => new \DateTimeImmutable()];
|
||||||
|
|
||||||
foreach ($this->getCustomFields() as $cf) {
|
|
||||||
$choices[$this->translatableStringHelper->localize($cf->getName())]
|
|
||||||
=
|
|
||||||
$cf->getSlug();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ['fields' => array_values($choices), 'address_date' => new \DateTimeImmutable()];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAllowedFormattersTypes()
|
public function getAllowedFormattersTypes()
|
||||||
@ -127,7 +80,7 @@ class ListPerson implements ExportElementValidatedInterface, ListInterface, Grou
|
|||||||
|
|
||||||
public function getLabels($key, array $values, $data)
|
public function getLabels($key, array $values, $data)
|
||||||
{
|
{
|
||||||
if (\in_array($key, $this->listPersonHelper->getAllPossibleFields(), true)) {
|
if (\in_array($key, $this->listPersonHelper->getAllKeys(), true)) {
|
||||||
return $this->listPersonHelper->getLabels($key, $values, $data);
|
return $this->listPersonHelper->getLabels($key, $values, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,28 +91,12 @@ class ListPerson implements ExportElementValidatedInterface, ListInterface, Grou
|
|||||||
{
|
{
|
||||||
$fields = [];
|
$fields = [];
|
||||||
|
|
||||||
foreach (ListPersonHelper::FIELDS as $key) {
|
foreach ($this->listPersonHelper->getAllKeys() as $key) {
|
||||||
if (!\in_array($key, $data['fields'], true)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str_starts_with($key, 'address_fields')) {
|
|
||||||
$fields = \array_merge($fields, $this->addressHelper->getKeys(ExportAddressHelper::F_ALL, 'address_fields'));
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('lifecycleUpdate' === $key) {
|
|
||||||
$fields = \array_merge($fields, ['createdAt', 'createdBy', 'updatedAt', 'updatedBy']);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$fields[] = $key;
|
$fields[] = $key;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the key from slugs and return
|
// add the key from slugs and return
|
||||||
return \array_merge($fields, \array_keys($this->slugs));
|
return [...$fields, ...\array_keys($this->slugs)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getResult($query, $data)
|
public function getResult($query, $data)
|
||||||
@ -184,11 +121,6 @@ class ListPerson implements ExportElementValidatedInterface, ListInterface, Grou
|
|||||||
{
|
{
|
||||||
$centers = array_map(static fn ($el) => $el['center'], $acl);
|
$centers = array_map(static fn ($el) => $el['center'], $acl);
|
||||||
|
|
||||||
// throw an error if any fields are present
|
|
||||||
if (!\array_key_exists('fields', $data)) {
|
|
||||||
throw new \Doctrine\DBAL\Exception\InvalidArgumentException('any fields have been checked');
|
|
||||||
}
|
|
||||||
|
|
||||||
$qb = $this->entityManager->createQueryBuilder()
|
$qb = $this->entityManager->createQueryBuilder()
|
||||||
->from(Person::class, 'person');
|
->from(Person::class, 'person');
|
||||||
|
|
||||||
@ -202,15 +134,9 @@ class ListPerson implements ExportElementValidatedInterface, ListInterface, Grou
|
|||||||
->setParameter('authorized_centers', $centers);
|
->setParameter('authorized_centers', $centers);
|
||||||
}
|
}
|
||||||
|
|
||||||
$fields = $data['fields'];
|
$this->listPersonHelper->addSelect($qb, $data['address_date']);
|
||||||
|
|
||||||
$this->listPersonHelper->addSelect($qb, $fields, $data['address_date']);
|
|
||||||
|
|
||||||
foreach ($this->getCustomFields() as $cf) {
|
foreach ($this->getCustomFields() as $cf) {
|
||||||
if (!\in_array($cf->getSlug(), $fields, true)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$cfType = $this->customFieldProvider->getCustomFieldByType($cf->getType());
|
$cfType = $this->customFieldProvider->getCustomFieldByType($cf->getType());
|
||||||
|
|
||||||
if ($cfType instanceof CustomFieldChoice && $cfType->isMultiple($cf)) {
|
if ($cfType instanceof CustomFieldChoice && $cfType->isMultiple($cf)) {
|
||||||
@ -251,26 +177,6 @@ class ListPerson implements ExportElementValidatedInterface, ListInterface, Grou
|
|||||||
return [Declarations::PERSON_TYPE];
|
return [Declarations::PERSON_TYPE];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function validateForm($data, ExecutionContextInterface $context)
|
|
||||||
{
|
|
||||||
// get the field starting with address_
|
|
||||||
$addressFields = array_filter(
|
|
||||||
ListPersonHelper::FIELDS,
|
|
||||||
static fn (string $el): bool => str_starts_with($el, 'address_')
|
|
||||||
);
|
|
||||||
|
|
||||||
// check if there is one field starting with address in data
|
|
||||||
if (\count(array_intersect($data['fields'], $addressFields)) > 0) {
|
|
||||||
// if a field address is checked, the date must not be empty
|
|
||||||
if (!$data['address_date'] instanceof \DateTimeImmutable) {
|
|
||||||
$context
|
|
||||||
->buildViolation('You must set this date if an address is checked')
|
|
||||||
->atPath('address_date')
|
|
||||||
->addViolation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function DQLToSlug($cleanedSlug)
|
private function DQLToSlug($cleanedSlug)
|
||||||
{
|
{
|
||||||
return $this->slugs[$cleanedSlug]['slug'];
|
return $this->slugs[$cleanedSlug]['slug'];
|
||||||
@ -293,9 +199,9 @@ class ListPerson implements ExportElementValidatedInterface, ListInterface, Grou
|
|||||||
{
|
{
|
||||||
return $this->entityManager
|
return $this->entityManager
|
||||||
->createQuery('SELECT cf '
|
->createQuery('SELECT cf '
|
||||||
.'FROM ChillCustomFieldsBundle:CustomField cf '
|
.'FROM '.CustomField::class.' cf '
|
||||||
.'JOIN cf.customFieldGroup g '
|
.'JOIN cf.customFieldGroup g '
|
||||||
.'WHERE cf.type != :title AND g.entity LIKE :entity')
|
.'WHERE cf.type != :title AND g.entity LIKE :entity AND cf.active = TRUE')
|
||||||
->setParameters([
|
->setParameters([
|
||||||
'title' => 'title',
|
'title' => 'title',
|
||||||
'entity' => \addcslashes(Person::class, '\\'),
|
'entity' => \addcslashes(Person::class, '\\'),
|
||||||
|
@ -12,10 +12,8 @@ declare(strict_types=1);
|
|||||||
namespace Chill\PersonBundle\Export\Export;
|
namespace Chill\PersonBundle\Export\Export;
|
||||||
|
|
||||||
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
|
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
|
||||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
|
||||||
use Chill\MainBundle\Export\FormatterInterface;
|
use Chill\MainBundle\Export\FormatterInterface;
|
||||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||||
use Chill\MainBundle\Export\Helper\ExportAddressHelper;
|
|
||||||
use Chill\MainBundle\Export\ListInterface;
|
use Chill\MainBundle\Export\ListInterface;
|
||||||
use Chill\MainBundle\Form\Type\PickRollingDateType;
|
use Chill\MainBundle\Form\Type\PickRollingDateType;
|
||||||
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
||||||
@ -30,22 +28,18 @@ use DateTimeImmutable;
|
|||||||
use Doctrine\ORM\AbstractQuery;
|
use Doctrine\ORM\AbstractQuery;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\Validator\Constraints\Callback;
|
|
||||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List the persons, having an accompanying period.
|
* List the persons, having an accompanying period.
|
||||||
*
|
*
|
||||||
* Details of the accompanying period are not included
|
* Details of the accompanying period are not included
|
||||||
*/
|
*/
|
||||||
final readonly class ListPersonHavingAccompanyingPeriod implements ExportElementValidatedInterface, ListInterface, GroupedExportInterface
|
final readonly class ListPersonHavingAccompanyingPeriod implements ListInterface, GroupedExportInterface
|
||||||
{
|
{
|
||||||
private bool $filterStatsByCenters;
|
private bool $filterStatsByCenters;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private ExportAddressHelper $addressHelper,
|
|
||||||
private ListPersonHelper $listPersonHelper,
|
private ListPersonHelper $listPersonHelper,
|
||||||
private EntityManagerInterface $entityManager,
|
private EntityManagerInterface $entityManager,
|
||||||
private RollingDateConverterInterface $rollingDateConverter,
|
private RollingDateConverterInterface $rollingDateConverter,
|
||||||
@ -56,32 +50,6 @@ final readonly class ListPersonHavingAccompanyingPeriod implements ExportElement
|
|||||||
|
|
||||||
public function buildForm(FormBuilderInterface $builder)
|
public function buildForm(FormBuilderInterface $builder)
|
||||||
{
|
{
|
||||||
$choices = array_combine(ListPersonHelper::FIELDS, ListPersonHelper::FIELDS);
|
|
||||||
|
|
||||||
$builder->add('fields', ChoiceType::class, [
|
|
||||||
'multiple' => true,
|
|
||||||
'expanded' => true,
|
|
||||||
'choices' => $choices,
|
|
||||||
'label' => 'Fields to include in export',
|
|
||||||
'choice_attr' => static function (string $val): array {
|
|
||||||
// add a 'data-display-target' for address fields
|
|
||||||
if (str_starts_with($val, 'address') || 'center' === $val || 'household' === $val) {
|
|
||||||
return ['data-display-target' => 'address_date'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
},
|
|
||||||
'constraints' => [new Callback([
|
|
||||||
'callback' => static function ($selected, ExecutionContextInterface $context) {
|
|
||||||
if (0 === \count($selected)) {
|
|
||||||
$context->buildViolation('You must select at least one element')
|
|
||||||
->atPath('fields')
|
|
||||||
->addViolation();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
])],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$builder->add('address_date_rolling', PickRollingDateType::class, [
|
$builder->add('address_date_rolling', PickRollingDateType::class, [
|
||||||
'label' => 'Data valid at this date',
|
'label' => 'Data valid at this date',
|
||||||
'help' => 'Data regarding center, addresses, and so on will be computed at this date',
|
'help' => 'Data regarding center, addresses, and so on will be computed at this date',
|
||||||
@ -90,9 +58,7 @@ final readonly class ListPersonHavingAccompanyingPeriod implements ExportElement
|
|||||||
|
|
||||||
public function getFormDefaultData(): array
|
public function getFormDefaultData(): array
|
||||||
{
|
{
|
||||||
$choices = array_combine(ListPersonHelper::FIELDS, ListPersonHelper::FIELDS);
|
return ['address_date_rolling' => new RollingDate(RollingDate::T_TODAY)];
|
||||||
|
|
||||||
return ['fields' => array_values($choices), 'address_date_rolling' => new RollingDate(RollingDate::T_TODAY)];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAllowedFormattersTypes()
|
public function getAllowedFormattersTypes()
|
||||||
@ -117,29 +83,7 @@ final readonly class ListPersonHavingAccompanyingPeriod implements ExportElement
|
|||||||
|
|
||||||
public function getQueryKeys($data)
|
public function getQueryKeys($data)
|
||||||
{
|
{
|
||||||
$fields = [];
|
return $this->listPersonHelper->getAllKeys();
|
||||||
|
|
||||||
foreach (ListPersonHelper::FIELDS as $key) {
|
|
||||||
if (!\in_array($key, $data['fields'], true)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str_starts_with($key, 'address_fields')) {
|
|
||||||
$fields = array_merge($fields, $this->addressHelper->getKeys(ExportAddressHelper::F_ALL, 'address_fields'));
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('lifecycleUpdate' === $key) {
|
|
||||||
$fields = array_merge($fields, ['createdAt', 'createdBy', 'updatedAt', 'updatedBy']);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$fields[] = $key;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $fields;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getResult($query, $data)
|
public function getResult($query, $data)
|
||||||
@ -164,11 +108,6 @@ final readonly class ListPersonHavingAccompanyingPeriod implements ExportElement
|
|||||||
{
|
{
|
||||||
$centers = array_map(static fn ($el) => $el['center'], $acl);
|
$centers = array_map(static fn ($el) => $el['center'], $acl);
|
||||||
|
|
||||||
// throw an error if any fields are present
|
|
||||||
if (!\array_key_exists('fields', $data)) {
|
|
||||||
throw new \Doctrine\DBAL\Exception\InvalidArgumentException('any fields have been checked');
|
|
||||||
}
|
|
||||||
|
|
||||||
$qb = $this->entityManager->createQueryBuilder();
|
$qb = $this->entityManager->createQueryBuilder();
|
||||||
|
|
||||||
$qb->from(Person::class, 'person')
|
$qb->from(Person::class, 'person')
|
||||||
@ -185,9 +124,7 @@ final readonly class ListPersonHavingAccompanyingPeriod implements ExportElement
|
|||||||
)->setParameter('authorized_centers', $centers);
|
)->setParameter('authorized_centers', $centers);
|
||||||
}
|
}
|
||||||
|
|
||||||
$fields = $data['fields'];
|
$this->listPersonHelper->addSelect($qb, $this->rollingDateConverter->convert($data['address_date_rolling']));
|
||||||
|
|
||||||
$this->listPersonHelper->addSelect($qb, $fields, $this->rollingDateConverter->convert($data['address_date_rolling']));
|
|
||||||
|
|
||||||
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
|
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
|
||||||
|
|
||||||
@ -208,24 +145,4 @@ final readonly class ListPersonHavingAccompanyingPeriod implements ExportElement
|
|||||||
{
|
{
|
||||||
return [Declarations::PERSON_TYPE, Declarations::ACP_TYPE];
|
return [Declarations::PERSON_TYPE, Declarations::ACP_TYPE];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function validateForm($data, ExecutionContextInterface $context)
|
|
||||||
{
|
|
||||||
// get the field starting with address_
|
|
||||||
$addressFields = array_filter(
|
|
||||||
ListPersonHelper::FIELDS,
|
|
||||||
static fn (string $el): bool => str_starts_with($el, 'address_')
|
|
||||||
);
|
|
||||||
|
|
||||||
// check if there is one field starting with address in data
|
|
||||||
if (\count(array_intersect($data['fields'], $addressFields)) > 0) {
|
|
||||||
// if a field address is checked, the date must not be empty
|
|
||||||
if (!$data['address_date'] instanceof \DateTimeImmutable) {
|
|
||||||
$context
|
|
||||||
->buildViolation('You must set this date if an address is checked')
|
|
||||||
->atPath('address_date')
|
|
||||||
->addViolation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ final readonly class ListPersonWithAccompanyingPeriodDetails implements ListInte
|
|||||||
|
|
||||||
$this->filterListAccompanyingPeriodHelper->addFilterAccompanyingPeriods($qb, $requiredModifiers, $acl, $data);
|
$this->filterListAccompanyingPeriodHelper->addFilterAccompanyingPeriods($qb, $requiredModifiers, $acl, $data);
|
||||||
|
|
||||||
$this->listPersonHelper->addSelect($qb, ListPersonHelper::FIELDS, $this->rollingDateConverter->convert($data['address_date']));
|
$this->listPersonHelper->addSelect($qb, $this->rollingDateConverter->convert($data['address_date']));
|
||||||
$this->listAccompanyingPeriodHelper->addSelectClauses($qb, $this->rollingDateConverter->convert($data['address_date']));
|
$this->listAccompanyingPeriodHelper->addSelectClauses($qb, $this->rollingDateConverter->convert($data['address_date']));
|
||||||
|
|
||||||
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
|
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Export\Helper;
|
||||||
|
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface provides methods for customizing the list of person.
|
||||||
|
*/
|
||||||
|
interface CustomizeListPersonHelperInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Alter the keys possibles (column header) for the list.
|
||||||
|
*/
|
||||||
|
public function alterKeys(array $existing): array;
|
||||||
|
|
||||||
|
public function alterSelect(QueryBuilder $qb, \DateTimeImmutable $computedDate): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the callable which transform the doctrine result representation.
|
||||||
|
*
|
||||||
|
* If the key is not managed by the current implementation, this method must return null.
|
||||||
|
*
|
||||||
|
* @return callable|null return null if the key is not managed by the current implementation
|
||||||
|
*/
|
||||||
|
public function getLabels(string $key, array $values, array $data): ?callable;
|
||||||
|
}
|
@ -35,9 +35,9 @@ use Symfony\Contracts\Translation\TranslatorInterface;
|
|||||||
*
|
*
|
||||||
* for some fields
|
* for some fields
|
||||||
*/
|
*/
|
||||||
class ListPersonHelper
|
final readonly class ListPersonHelper
|
||||||
{
|
{
|
||||||
final public const FIELDS = [
|
private const FIELDS = [
|
||||||
'personId',
|
'personId',
|
||||||
'civility',
|
'civility',
|
||||||
'firstName',
|
'firstName',
|
||||||
@ -60,17 +60,31 @@ class ListPersonHelper
|
|||||||
'countryOfBirth',
|
'countryOfBirth',
|
||||||
'nationality',
|
'nationality',
|
||||||
// add full addresses
|
// add full addresses
|
||||||
'address_fields',
|
// 'address_fields',
|
||||||
// add a list of spoken languages
|
// add a list of spoken languages
|
||||||
'spokenLanguages',
|
'spokenLanguages',
|
||||||
// add household id
|
// add household id
|
||||||
'household_id',
|
'household_id',
|
||||||
// add created at, created by, updated at, and updated by
|
// add created at, created by, updated at, and updated by
|
||||||
'lifecycleUpdate',
|
// 'lifecycleUpdate',
|
||||||
|
'createdAt', 'createdBy', 'updatedAt', 'updatedBy',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function __construct(private readonly ExportAddressHelper $addressHelper, private readonly CenterRepositoryInterface $centerRepository, private readonly CivilityRepositoryInterface $civilityRepository, private readonly CountryRepository $countryRepository, private readonly LanguageRepositoryInterface $languageRepository, private readonly MaritalStatusRepositoryInterface $maritalStatusRepository, private readonly TranslatableStringHelper $translatableStringHelper, private readonly TranslatorInterface $translator, private readonly UserRepositoryInterface $userRepository)
|
public function __construct(
|
||||||
{
|
private ExportAddressHelper $addressHelper,
|
||||||
|
private CenterRepositoryInterface $centerRepository,
|
||||||
|
private CivilityRepositoryInterface $civilityRepository,
|
||||||
|
private CountryRepository $countryRepository,
|
||||||
|
private LanguageRepositoryInterface $languageRepository,
|
||||||
|
private MaritalStatusRepositoryInterface $maritalStatusRepository,
|
||||||
|
private TranslatableStringHelper $translatableStringHelper,
|
||||||
|
private TranslatorInterface $translator,
|
||||||
|
private UserRepositoryInterface $userRepository,
|
||||||
|
/**
|
||||||
|
* @var iterable<CustomizeListPersonHelperInterface>
|
||||||
|
*/
|
||||||
|
private iterable $customPersonHelpers,
|
||||||
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,26 +96,34 @@ class ListPersonHelper
|
|||||||
*/
|
*/
|
||||||
public function getAllKeys(): array
|
public function getAllKeys(): array
|
||||||
{
|
{
|
||||||
return [
|
$keys = [
|
||||||
...array_filter(
|
...ListPersonHelper::FIELDS,
|
||||||
ListPersonHelper::FIELDS,
|
|
||||||
fn (string $key) => !\in_array($key, ['address_fields', 'lifecycleUpdate'], true)
|
|
||||||
),
|
|
||||||
...$this->addressHelper->getKeys(ExportAddressHelper::F_ALL, 'address_fields'),
|
...$this->addressHelper->getKeys(ExportAddressHelper::F_ALL, 'address_fields'),
|
||||||
...['createdAt', 'createdBy', 'updatedAt', 'updatedBy'],
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
foreach ($this->customPersonHelpers as $customize) {
|
||||||
|
$keys = $customize->alterKeys($keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
return $keys;
|
||||||
* @param array<value-of<self::FIELDS>> $fields
|
}
|
||||||
*/
|
|
||||||
public function addSelect(QueryBuilder $qb, array $fields, \DateTimeImmutable $computedDate): void
|
public function addSelect(QueryBuilder $qb, \DateTimeImmutable $computedDate): void
|
||||||
{
|
{
|
||||||
foreach (ListPersonHelper::FIELDS as $f) {
|
// we first add all the fields which are handled by the
|
||||||
if (!\in_array($f, $fields, true)) {
|
$focusedFieldKeys = [
|
||||||
continue;
|
'personId', 'countryOfBirth', 'nationality', // 'address_fields',
|
||||||
}
|
'spokenLanguages', 'household_id', 'center', // 'lifecycleUpdate',
|
||||||
|
'genderComment', 'maritalStatus', 'maritalStatusComment', 'civility',
|
||||||
|
'createdAt', 'createdBy', 'updatedAt', 'updatedBy',
|
||||||
|
];
|
||||||
|
|
||||||
|
$filteredFields = array_filter(
|
||||||
|
ListPersonHelper::FIELDS,
|
||||||
|
fn ($field) => !in_array($field, $focusedFieldKeys, true)
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($this->getAllKeys() as $f) {
|
||||||
switch ($f) {
|
switch ($f) {
|
||||||
case 'personId':
|
case 'personId':
|
||||||
$qb->addSelect('person.id AS personId');
|
$qb->addSelect('person.id AS personId');
|
||||||
@ -114,13 +136,6 @@ class ListPersonHelper
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'address_fields':
|
|
||||||
$this->addCurrentAddressAt($qb, $computedDate);
|
|
||||||
$qb->leftJoin('personHouseholdAddress.address', 'personAddress');
|
|
||||||
$this->addressHelper->addSelectClauses(ExportAddressHelper::F_ALL, $qb, 'personAddress', 'address_fields');
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'spokenLanguages':
|
case 'spokenLanguages':
|
||||||
$qb->addSelect('(SELECT AGGREGATE(language.id) FROM '.Language::class.' language WHERE language MEMBER OF person.spokenLanguages) AS spokenLanguages');
|
$qb->addSelect('(SELECT AGGREGATE(language.id) FROM '.Language::class.' language WHERE language MEMBER OF person.spokenLanguages) AS spokenLanguages');
|
||||||
|
|
||||||
@ -154,15 +169,6 @@ class ListPersonHelper
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'lifecycleUpdate':
|
|
||||||
$qb
|
|
||||||
->addSelect('person.createdAt AS createdAt')
|
|
||||||
->addSelect('IDENTITY(person.createdBy) AS createdBy')
|
|
||||||
->addSelect('person.updatedAt AS updatedAt')
|
|
||||||
->addSelect('IDENTITY(person.updatedBy) AS updatedBy');
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'genderComment':
|
case 'genderComment':
|
||||||
$qb->addSelect('person.genderComment.comment AS genderComment');
|
$qb->addSelect('person.genderComment.comment AS genderComment');
|
||||||
|
|
||||||
@ -184,25 +190,47 @@ class ListPersonHelper
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
if (in_array($f, $filteredFields, true)) {
|
||||||
$qb->addSelect(sprintf('person.%s as %s', $f, $f));
|
$qb->addSelect(sprintf('person.%s as %s', $f, $f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// address
|
||||||
|
$this->addCurrentAddressAt($qb, $computedDate);
|
||||||
|
$qb->leftJoin('personHouseholdAddress.address', 'personAddress');
|
||||||
|
$this->addressHelper->addSelectClauses(ExportAddressHelper::F_ALL, $qb, 'personAddress', 'address_fields');
|
||||||
|
|
||||||
|
// lifecycle update
|
||||||
|
$qb
|
||||||
|
->addSelect('person.createdAt AS createdAt')
|
||||||
|
->addSelect('IDENTITY(person.createdBy) AS createdBy')
|
||||||
|
->addSelect('person.updatedAt AS updatedAt')
|
||||||
|
->addSelect('IDENTITY(person.updatedBy) AS updatedBy');
|
||||||
|
|
||||||
|
foreach ($this->customPersonHelpers as $customPersonHelper) {
|
||||||
|
$customPersonHelper->alterSelect($qb, $computedDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array|string[]
|
* @return array|string[]
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
public function getAllPossibleFields(): array
|
public function getAllPossibleFields(): array
|
||||||
{
|
{
|
||||||
return array_merge(
|
return $this->getAllKeys();
|
||||||
self::FIELDS,
|
|
||||||
['createdAt', 'createdBy', 'updatedAt', 'updatedBy'],
|
|
||||||
$this->addressHelper->getKeys(ExportAddressHelper::F_ALL, 'address_fields')
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLabels($key, array $values, $data): callable
|
public function getLabels($key, array $values, $data): callable
|
||||||
{
|
{
|
||||||
|
foreach ($this->customPersonHelpers as $customPersonHelper) {
|
||||||
|
if (null !== $callable = $customPersonHelper->getLabels($key, $values, $data)) {
|
||||||
|
return $callable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (str_starts_with((string) $key, 'address_fields')) {
|
if (str_starts_with((string) $key, 'address_fields')) {
|
||||||
return $this->addressHelper->getLabel($key, $values, $data, 'address_fields');
|
return $this->addressHelper->getLabel($key, $values, $data, 'address_fields');
|
||||||
}
|
}
|
||||||
@ -366,7 +394,7 @@ class ListPersonHelper
|
|||||||
};
|
};
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (!\in_array($key, self::getAllPossibleFields(), true)) {
|
if (!\in_array($key, self::getAllKeys(), true)) {
|
||||||
throw new \RuntimeException("this key is not supported by this helper: {$key}");
|
throw new \RuntimeException("this key is not supported by this helper: {$key}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\PersonBundle\Tests\Export\Export;
|
namespace Chill\PersonBundle\Tests\Export\Export;
|
||||||
|
|
||||||
use Chill\MainBundle\Export\Helper\ExportAddressHelper;
|
|
||||||
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
||||||
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
||||||
use Chill\MainBundle\Test\Export\AbstractExportTest;
|
use Chill\MainBundle\Test\Export\AbstractExportTest;
|
||||||
@ -35,13 +34,11 @@ class ListPersonHavingAccompanyingPeriodTest extends AbstractExportTest
|
|||||||
|
|
||||||
public function getExport()
|
public function getExport()
|
||||||
{
|
{
|
||||||
$addressHelper = self::$container->get(ExportAddressHelper::class);
|
|
||||||
$listPersonHelper = self::$container->get(ListPersonHelper::class);
|
$listPersonHelper = self::$container->get(ListPersonHelper::class);
|
||||||
$entityManager = self::$container->get(EntityManagerInterface::class);
|
$entityManager = self::$container->get(EntityManagerInterface::class);
|
||||||
$rollingDateconverter = self::$container->get(RollingDateConverterInterface::class);
|
$rollingDateconverter = self::$container->get(RollingDateConverterInterface::class);
|
||||||
|
|
||||||
yield new ListPersonHavingAccompanyingPeriod(
|
yield new ListPersonHavingAccompanyingPeriod(
|
||||||
$addressHelper,
|
|
||||||
$listPersonHelper,
|
$listPersonHelper,
|
||||||
$entityManager,
|
$entityManager,
|
||||||
$rollingDateconverter,
|
$rollingDateconverter,
|
||||||
@ -49,7 +46,6 @@ class ListPersonHavingAccompanyingPeriodTest extends AbstractExportTest
|
|||||||
);
|
);
|
||||||
|
|
||||||
yield new ListPersonHavingAccompanyingPeriod(
|
yield new ListPersonHavingAccompanyingPeriod(
|
||||||
$addressHelper,
|
|
||||||
$listPersonHelper,
|
$listPersonHelper,
|
||||||
$entityManager,
|
$entityManager,
|
||||||
$rollingDateconverter,
|
$rollingDateconverter,
|
||||||
@ -59,7 +55,7 @@ class ListPersonHavingAccompanyingPeriodTest extends AbstractExportTest
|
|||||||
|
|
||||||
public function getFormData()
|
public function getFormData()
|
||||||
{
|
{
|
||||||
return [['address_date_rolling' => new RollingDate(RollingDate::T_TODAY), 'fields' => ListPersonHelper::FIELDS]];
|
return [['address_date_rolling' => new RollingDate(RollingDate::T_TODAY)]];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getModifiersCombination()
|
public function getModifiersCombination()
|
||||||
|
@ -12,7 +12,6 @@ declare(strict_types=1);
|
|||||||
namespace Chill\PersonBundle\Tests\Export\Export;
|
namespace Chill\PersonBundle\Tests\Export\Export;
|
||||||
|
|
||||||
use Chill\CustomFieldsBundle\Service\CustomFieldProvider;
|
use Chill\CustomFieldsBundle\Service\CustomFieldProvider;
|
||||||
use Chill\MainBundle\Export\Helper\ExportAddressHelper;
|
|
||||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||||
use Chill\MainBundle\Test\Export\AbstractExportTest;
|
use Chill\MainBundle\Test\Export\AbstractExportTest;
|
||||||
use Chill\PersonBundle\Export\Export\ListPerson;
|
use Chill\PersonBundle\Export\Export\ListPerson;
|
||||||
@ -50,14 +49,12 @@ final class ListPersonTest extends AbstractExportTest
|
|||||||
|
|
||||||
public function getExport()
|
public function getExport()
|
||||||
{
|
{
|
||||||
$addressHelper = self::$container->get(ExportAddressHelper::class);
|
|
||||||
$customFieldProvider = self::$container->get(CustomFieldProvider::class);
|
$customFieldProvider = self::$container->get(CustomFieldProvider::class);
|
||||||
$listPersonHelper = self::$container->get(ListPersonHelper::class);
|
$listPersonHelper = self::$container->get(ListPersonHelper::class);
|
||||||
$entityManager = self::$container->get(EntityManagerInterface::class);
|
$entityManager = self::$container->get(EntityManagerInterface::class);
|
||||||
$translatableStringHelper = self::$container->get(TranslatableStringHelper::class);
|
$translatableStringHelper = self::$container->get(TranslatableStringHelper::class);
|
||||||
|
|
||||||
yield new ListPerson(
|
yield new ListPerson(
|
||||||
$addressHelper,
|
|
||||||
$customFieldProvider,
|
$customFieldProvider,
|
||||||
$listPersonHelper,
|
$listPersonHelper,
|
||||||
$entityManager,
|
$entityManager,
|
||||||
@ -66,7 +63,6 @@ final class ListPersonTest extends AbstractExportTest
|
|||||||
);
|
);
|
||||||
|
|
||||||
yield new ListPerson(
|
yield new ListPerson(
|
||||||
$addressHelper,
|
|
||||||
$customFieldProvider,
|
$customFieldProvider,
|
||||||
$listPersonHelper,
|
$listPersonHelper,
|
||||||
$entityManager,
|
$entityManager,
|
||||||
@ -77,15 +73,7 @@ final class ListPersonTest extends AbstractExportTest
|
|||||||
|
|
||||||
public function getFormData(): iterable
|
public function getFormData(): iterable
|
||||||
{
|
{
|
||||||
foreach ([
|
yield ['address_date' => new \DateTimeImmutable('today')];
|
||||||
['fields' => ['id', 'firstName', 'lastName']],
|
|
||||||
['fields' => ['id', 'birthdate', 'gender', 'memo', 'email', 'phonenumber']],
|
|
||||||
['fields' => ['firstName', 'lastName', 'phonenumber']],
|
|
||||||
['fields' => ['id', 'nationality']],
|
|
||||||
['fields' => ['id', 'countryOfBirth']],
|
|
||||||
] as $base) {
|
|
||||||
yield [...$base, 'address_date' => new \DateTimeImmutable('today')];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getModifiersCombination(): array
|
public function getModifiersCombination(): array
|
||||||
|
@ -16,6 +16,10 @@ services:
|
|||||||
tags:
|
tags:
|
||||||
- { name: chill.export, alias: list_person }
|
- { name: chill.export, alias: list_person }
|
||||||
|
|
||||||
|
Chill\PersonBundle\Export\Helper\ListPersonHelper:
|
||||||
|
arguments:
|
||||||
|
$customPersonHelpers: !tagged_iterator chill_person.list_person_customizer
|
||||||
|
|
||||||
Chill\PersonBundle\Export\Export\ListPersonHavingAccompanyingPeriod:
|
Chill\PersonBundle\Export\Export\ListPersonHavingAccompanyingPeriod:
|
||||||
tags:
|
tags:
|
||||||
- { name: chill.export, alias: list_person_with_acp }
|
- { name: chill.export, alias: list_person_with_acp }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user