mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-12 13:24:25 +00:00
Merge branch 'integrate_regroupment_entity' into 'master'
Feature: ask for center regroupment in exports See merge request Chill-Projet/chill-bundles!486
This commit is contained in:
commit
88ccbd450a
@ -298,6 +298,8 @@ class ExportController extends AbstractController
|
|||||||
'csrf_protection' => $isGenerate ? false : true,
|
'csrf_protection' => $isGenerate ? false : true,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// TODO: add a condition to be able to select a regroupment of centers?
|
||||||
|
|
||||||
if ('centers' === $step || 'generate_centers' === $step) {
|
if ('centers' === $step || 'generate_centers' === $step) {
|
||||||
$builder->add('centers', PickCenterType::class, [
|
$builder->add('centers', PickCenterType::class, [
|
||||||
'export_alias' => $alias,
|
'export_alias' => $alias,
|
||||||
|
@ -24,7 +24,7 @@ class Regroupment
|
|||||||
/**
|
/**
|
||||||
* @var Center
|
* @var Center
|
||||||
* @ORM\ManyToMany(
|
* @ORM\ManyToMany(
|
||||||
* targetEntity="Chill\MainBundle\Entity\Center"
|
* targetEntity=Center::class
|
||||||
* )
|
* )
|
||||||
* @ORM\Id
|
* @ORM\Id
|
||||||
*/
|
*/
|
||||||
@ -43,7 +43,7 @@ class Regroupment
|
|||||||
private bool $isActive = true;
|
private bool $isActive = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="string", length=15, options={"default": ""}, nullable=false)
|
* @ORM\Column(type="text", options={"default": ""}, nullable=false)
|
||||||
*/
|
*/
|
||||||
private string $name = '';
|
private string $name = '';
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ class Regroupment
|
|||||||
$this->centers = new ArrayCollection();
|
$this->centers = new ArrayCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCenters(): ?Collection
|
public function getCenters(): Collection
|
||||||
{
|
{
|
||||||
return $this->centers;
|
return $this->centers;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
<?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\MainBundle\Form\DataMapper;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Center;
|
||||||
|
use Chill\MainBundle\Entity\Regroupment;
|
||||||
|
use Chill\MainBundle\Repository\RegroupmentRepository;
|
||||||
|
use Exception;
|
||||||
|
use Symfony\Component\Form\DataMapperInterface;
|
||||||
|
use Symfony\Component\Form\FormInterface;
|
||||||
|
use function count;
|
||||||
|
|
||||||
|
class ExportPickCenterDataMapper implements DataMapperInterface
|
||||||
|
{
|
||||||
|
protected RegroupmentRepository $regroupmentRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array|Center[] $data
|
||||||
|
* @param $forms
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function mapDataToForms($data, $forms)
|
||||||
|
{
|
||||||
|
if (null === $data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var array<string, FormInterface> $form */
|
||||||
|
$form = iterator_to_array($forms);
|
||||||
|
|
||||||
|
$pickedRegroupment = [];
|
||||||
|
|
||||||
|
foreach ($this->regroupmentRepository->findAll() as $regroupment) {
|
||||||
|
[$contained, $notContained] = $regroupment->getCenters()->partition(static function (Center $center) {
|
||||||
|
});
|
||||||
|
|
||||||
|
if (0 === count($notContained)) {
|
||||||
|
$pickedRegroupment[] = $regroupment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$form['regroupment']->setData($pickedRegroupment);
|
||||||
|
$form['centers']->setData($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param iterable $forms
|
||||||
|
* @param array $data
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function mapFormsToData($forms, &$data)
|
||||||
|
{
|
||||||
|
/** @var array<string, FormInterface> $forms */
|
||||||
|
$forms = iterator_to_array($forms);
|
||||||
|
|
||||||
|
$centers = [];
|
||||||
|
|
||||||
|
foreach ($forms['center']->getData() as $center) {
|
||||||
|
$centers[spl_object_hash($center)] = $center;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($forms['regroupment']->getData() as $regroupment) {
|
||||||
|
/** @var Regroupment $regroupment */
|
||||||
|
foreach ($regroupment->getCenters() as $center) {
|
||||||
|
$centers[spl_object_hash($center)] = $center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = array_values($centers);
|
||||||
|
}
|
||||||
|
}
|
@ -13,55 +13,45 @@ namespace Chill\MainBundle\Form\Type\Export;
|
|||||||
|
|
||||||
use Chill\MainBundle\Center\GroupingCenterInterface;
|
use Chill\MainBundle\Center\GroupingCenterInterface;
|
||||||
use Chill\MainBundle\Entity\Center;
|
use Chill\MainBundle\Entity\Center;
|
||||||
|
use Chill\MainBundle\Entity\Regroupment;
|
||||||
use Chill\MainBundle\Export\ExportManager;
|
use Chill\MainBundle\Export\ExportManager;
|
||||||
|
use Chill\MainBundle\Form\DataMapper\ExportPickCenterDataMapper;
|
||||||
|
use Chill\MainBundle\Repository\RegroupmentRepository;
|
||||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface;
|
use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface;
|
||||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
use Symfony\Component\Form\CallbackTransformer;
|
|
||||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||||
|
|
||||||
use Symfony\Component\Security\Core\User\UserInterface;
|
use Symfony\Component\Security\Core\User\UserInterface;
|
||||||
use function array_intersect;
|
|
||||||
use function array_key_exists;
|
|
||||||
use function array_merge;
|
|
||||||
use function array_unique;
|
|
||||||
use function count;
|
use function count;
|
||||||
use function in_array;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pick centers amongst available centers for the user.
|
* Pick centers amongst available centers for the user.
|
||||||
*/
|
*/
|
||||||
class PickCenterType extends AbstractType
|
final class PickCenterType extends AbstractType
|
||||||
{
|
{
|
||||||
public const CENTERS_IDENTIFIERS = 'c';
|
public const CENTERS_IDENTIFIERS = 'c';
|
||||||
|
|
||||||
protected AuthorizationHelperInterface $authorizationHelper;
|
private AuthorizationHelperInterface $authorizationHelper;
|
||||||
|
|
||||||
protected ExportManager $exportManager;
|
private ExportManager $exportManager;
|
||||||
|
|
||||||
/**
|
private RegroupmentRepository $regroupmentRepository;
|
||||||
* @var array|GroupingCenterInterface[]
|
|
||||||
*/
|
|
||||||
protected array $groupingCenters = [];
|
|
||||||
|
|
||||||
protected UserInterface $user;
|
private UserInterface $user;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
TokenStorageInterface $tokenStorage,
|
TokenStorageInterface $tokenStorage,
|
||||||
ExportManager $exportManager,
|
ExportManager $exportManager,
|
||||||
|
RegroupmentRepository $regroupmentRepository,
|
||||||
AuthorizationHelperInterface $authorizationHelper
|
AuthorizationHelperInterface $authorizationHelper
|
||||||
) {
|
) {
|
||||||
$this->exportManager = $exportManager;
|
$this->exportManager = $exportManager;
|
||||||
$this->user = $tokenStorage->getToken()->getUser();
|
$this->user = $tokenStorage->getToken()->getUser();
|
||||||
$this->authorizationHelper = $authorizationHelper;
|
$this->authorizationHelper = $authorizationHelper;
|
||||||
}
|
$this->regroupmentRepository = $regroupmentRepository;
|
||||||
|
|
||||||
public function addGroupingCenter(GroupingCenterInterface $grouping)
|
|
||||||
{
|
|
||||||
$this->groupingCenters[md5($grouping->getName())] = $grouping;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
@ -72,97 +62,33 @@ class PickCenterType extends AbstractType
|
|||||||
$export->requiredRole()
|
$export->requiredRole()
|
||||||
);
|
);
|
||||||
|
|
||||||
$builder->add(self::CENTERS_IDENTIFIERS, EntityType::class, [
|
$builder->add('center', EntityType::class, [
|
||||||
'class' => Center::class,
|
'class' => Center::class,
|
||||||
|
'label' => 'center',
|
||||||
'choices' => $centers,
|
'choices' => $centers,
|
||||||
'multiple' => true,
|
'multiple' => true,
|
||||||
'expanded' => true,
|
'expanded' => true,
|
||||||
'choice_label' => static function (Center $c) {
|
'choice_label' => static function (Center $c) {
|
||||||
return $c->getName();
|
return $c->getName();
|
||||||
},
|
},
|
||||||
'data' => count($this->groupingCenters) > 0 ? null : $centers,
|
'data' => $centers,
|
||||||
]);
|
])
|
||||||
|
->add('regroupment', EntityType::class, [
|
||||||
if (count($this->groupingCenters) > 0) {
|
'class' => Regroupment::class,
|
||||||
$groupingBuilder = $builder->create('g', null, [
|
'label' => 'regroupment',
|
||||||
'compound' => true,
|
'multiple' => true,
|
||||||
|
'expanded' => true,
|
||||||
|
'choices' => $this->regroupmentRepository->findAllActive(),
|
||||||
|
'choice_label' => static function (Regroupment $r) {
|
||||||
|
return $r->getName();
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
foreach ($this->groupingCenters as $key => $gc) {
|
$builder->setDataMapper(new ExportPickCenterDataMapper());
|
||||||
$choices = $this->buildChoices($centers, $gc);
|
|
||||||
|
|
||||||
if (count($choices) > 0) {
|
|
||||||
$groupingBuilder->add($key, ChoiceType::class, [
|
|
||||||
'choices' => $choices,
|
|
||||||
'multiple' => true,
|
|
||||||
'expanded' => true,
|
|
||||||
'label' => $gc->getName(),
|
|
||||||
'required' => false,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($groupingBuilder->count() > 0) {
|
|
||||||
$builder->add($groupingBuilder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$builder->addModelTransformer(new CallbackTransformer(
|
|
||||||
function ($data) use ($centers) {
|
|
||||||
return $this->transform($data, $centers);
|
|
||||||
},
|
|
||||||
function ($data) use ($centers) {
|
|
||||||
return $this->reverseTransform($data, $centers);
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function configureOptions(OptionsResolver $resolver)
|
public function configureOptions(OptionsResolver $resolver)
|
||||||
{
|
{
|
||||||
$resolver->setRequired('export_alias');
|
$resolver->setRequired('export_alias');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildChoices($reachablesCenters, GroupingCenterInterface $gc)
|
|
||||||
{
|
|
||||||
$result = [];
|
|
||||||
|
|
||||||
foreach ($gc->getGroups() as $group) {
|
|
||||||
foreach ($gc->getCentersForGroup($group) as $center) {
|
|
||||||
if (in_array($center, $reachablesCenters, true)) {
|
|
||||||
$result[$group] = $group;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function reverseTransform($data, $centers)
|
|
||||||
{
|
|
||||||
$picked = $data[self::CENTERS_IDENTIFIERS]
|
|
||||||
instanceof \Doctrine\Common\Collections\Collection ?
|
|
||||||
$data[self::CENTERS_IDENTIFIERS]->toArray()
|
|
||||||
:
|
|
||||||
$data[self::CENTERS_IDENTIFIERS];
|
|
||||||
|
|
||||||
if (array_key_exists('g', $data)) {
|
|
||||||
foreach ($data['g'] as $gcid => $group) {
|
|
||||||
$picked =
|
|
||||||
array_merge(
|
|
||||||
array_intersect(
|
|
||||||
$this->groupingCenters[$gcid]->getCentersForGroup($group),
|
|
||||||
$centers
|
|
||||||
),
|
|
||||||
$picked
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return array_unique($picked);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function transform($data, $centers)
|
|
||||||
{
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
<?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\MainBundle\Repository;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Regroupment;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
use Doctrine\Persistence\ObjectRepository;
|
||||||
|
|
||||||
|
final class RegroupmentRepository implements ObjectRepository
|
||||||
|
{
|
||||||
|
private EntityRepository $repository;
|
||||||
|
|
||||||
|
public function __construct(EntityManagerInterface $entityManager)
|
||||||
|
{
|
||||||
|
$this->repository = $entityManager->getRepository(Regroupment::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function find($id, $lockMode = null, $lockVersion = null): ?Regroupment
|
||||||
|
{
|
||||||
|
return $this->repository->find($id, $lockMode, $lockVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Regroupment[]
|
||||||
|
*/
|
||||||
|
public function findAll(): array
|
||||||
|
{
|
||||||
|
return $this->repository->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findAllActive(): array
|
||||||
|
{
|
||||||
|
return $this->repository->findBy(['isActive' => true], ['name' => 'ASC']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed|null $limit
|
||||||
|
* @param mixed|null $offset
|
||||||
|
*
|
||||||
|
* @return Regroupment[]
|
||||||
|
*/
|
||||||
|
public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array
|
||||||
|
{
|
||||||
|
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findOneBy(array $criteria, ?array $orderBy = null): ?Regroupment
|
||||||
|
{
|
||||||
|
return $this->repository->findOneBy($criteria, $orderBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getClassName()
|
||||||
|
{
|
||||||
|
return Regroupment::class;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
{#
|
{#
|
||||||
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
|
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
|
||||||
<info@champs-libres.coop> / <http://www.champs-libres.coop>
|
<info@champs-libres.coop> / <http://www.champs-libres.coop>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@ -22,39 +22,33 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="col-md-10">
|
<div class="col-md-10">
|
||||||
|
|
||||||
{{ include('@ChillMain/Export/_breadcrumb.html.twig') }}
|
{{ include('@ChillMain/Export/_breadcrumb.html.twig') }}
|
||||||
|
|
||||||
<h1>{{ export.title|trans }}</h1>
|
<h1>{{ export.title|trans }}</h1>
|
||||||
|
|
||||||
<p>{{ export.description|trans }}</p>
|
<p>{{ export.description|trans }}</p>
|
||||||
|
|
||||||
{{ form_start(form) }}
|
{{ form_start(form) }}
|
||||||
|
|
||||||
<section class="center mb-4">
|
<section class="center mb-4">
|
||||||
|
|
||||||
<h2>{{ 'Pick centers'|trans }}</h2>
|
<h2>{{ 'Pick centers'|trans }}</h2>
|
||||||
|
|
||||||
<p>{{ 'The export will contains only data from the picked centers.'|trans }}
|
<p>{{ 'The export will contains only data from the picked centers.'|trans }}
|
||||||
{{ 'This will eventually restrict your possibilities in filtering the data.'|trans }}</p>
|
{{ 'This will eventually restrict your possibilities in filtering the data.'|trans }}</p>
|
||||||
|
|
||||||
{{ form_widget(form.centers.c) }}
|
<h3 class="m-3">{{ 'Center'|trans }}</h3>
|
||||||
|
{{ form_widget(form.centers.center) }}
|
||||||
{% if form.centers.children.g is defined %}
|
|
||||||
|
<h3 class="m-3">{{ 'Pick aggregated centers'|trans }}</h3>
|
||||||
<h3>{{ 'Pick aggregated centers'|trans }}</h3>
|
{{ form_widget(form.centers.regroupment) }}
|
||||||
|
|
||||||
{% for f in form.centers.children.g.children %}
|
|
||||||
{{ form_row(f) }}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<p>{{ form_widget(form.submit, { 'attr' : { 'class' : 'btn btn-action btn-create' }, 'label' : 'Go to export options' } ) }}</p>
|
<p>{{ form_widget(form.submit, { 'attr' : { 'class' : 'btn btn-action btn-create' }, 'label' : 'Go to export options' } ) }}</p>
|
||||||
|
|
||||||
{{ form_end(form) }}
|
{{ form_end(form) }}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
@ -139,6 +139,7 @@ services:
|
|||||||
autoconfigure: true
|
autoconfigure: true
|
||||||
|
|
||||||
Chill\MainBundle\Form\AbsenceType: ~
|
Chill\MainBundle\Form\AbsenceType: ~
|
||||||
|
Chill\MainBundle\Form\DataMapper\RegroupmentDataMapper: ~
|
||||||
Chill\MainBundle\Form\RegroupmentType: ~
|
Chill\MainBundle\Form\RegroupmentType: ~
|
||||||
|
|
||||||
Chill\MainBundle\Form\DataTransformer\IdToLocationDataTransformer: ~
|
Chill\MainBundle\Form\DataTransformer\IdToLocationDataTransformer: ~
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\Migrations\Main;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
final class Version20230301155213 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'Alter type to TEXT for regroupment.name';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('ALTER TABLE regroupment ALTER name TYPE TEXT');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('ALTER TABLE regroupment ALTER name TYPE VARCHAR(15)');
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user