api for grouping centers, select centers as group in "pick centers" step

for exports
This commit is contained in:
Julien Fastré 2019-01-28 15:21:31 +01:00
parent cf354cbccd
commit 722274964c
8 changed files with 179 additions and 5 deletions

View File

@ -31,3 +31,7 @@ Master branch
- add margin of 0.5rem beyond buttons ;
- add a spreadsheet formatter (format xlsx, ods, csv) for lists
- add possibility to generate DirectExport: exports without formatters, filters and aggregators ;
- add api for grouping centers ;
- select centers as grouped on step "pick centers" in exports ;

View File

@ -0,0 +1,27 @@
<?php
/*
*
*/
namespace Chill\MainBundle\Center;
/**
* Interface to declare a groups of centers.
*
* This interface is used to declare a groups of centers in
* `Chill\MainBundle\Form\Export\PickCenterType`.
*
*/
interface GroupingCenterInterface
{
/**
* @return string[]
*/
public function getGroups($authorizedCenters = null): array;
/**
*
* @param string $group
* @return \Chill\MainBundle\Entity\Center[]
*/
public function getCentersForGroup($group);
}

View File

@ -13,6 +13,7 @@ use Chill\MainBundle\DependencyInjection\CompilerPass\WidgetsCompilerPass;
use Chill\MainBundle\DependencyInjection\CompilerPass\NotificationCounterCompilerPass;
use Chill\MainBundle\DependencyInjection\CompilerPass\MenuCompilerPass;
use Chill\MainBundle\DependencyInjection\CompilerPass\ACLFlagsCompilerPass;
use Chill\MainBundle\DependencyInjection\CompilerPass\GroupingCenterCompilerPass;
class ChillMainBundle extends Bundle
@ -29,5 +30,6 @@ class ChillMainBundle extends Bundle
$container->addCompilerPass(new NotificationCounterCompilerPass());
$container->addCompilerPass(new MenuCompilerPass());
$container->addCompilerPass(new ACLFlagsCompilerPass());
$container->addCompilerPass(new GroupingCenterCompilerPass());
}
}

View File

@ -0,0 +1,46 @@
<?php
/*
* Copyright (C) 2019 Champs-Libres <info@champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Chill\MainBundle\DependencyInjection\CompilerPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Reference;
use Chill\MainBundle\Form\Type\Export\PickCenterType;
/**
*
*
*
*/
class GroupingCenterCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if (FALSE === $container->hasDefinition('chill.main.form.pick_centers_type')) {
throw new \LogicException("The service chill.main.form.pick_centers_type does "
. "not exists in container");
}
$pickCenterType = $container->getDefinition('chill.main.form.pick_centers_type');
foreach ($container->findTaggedServiceIds('chill.grouping_center') as $serviceId => $tagged) {
$pickCenterType->addMethodCall('addGroupingCenter',
[ new Reference($serviceId) ]);
}
}
}

View File

@ -563,7 +563,7 @@ class ExportManager
*/
public function getPickedCenters(array $data)
{
return $data[PickCenterType::CENTERS_IDENTIFIERS];
return $data;
}
/**

View File

@ -28,12 +28,14 @@ use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Center\GroupingCenterInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\CallbackTransformer;
use Doctrine\Common\Collections\Collection;
/**
* Pick centers amongst available centers for the user
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @author Champs Libres <info@champs-libres.coop>
*/
class PickCenterType extends AbstractType
{
@ -49,6 +51,12 @@ class PickCenterType extends AbstractType
*/
protected $exportManager;
/**
*
* @var GroupingCenterInterface[]
*/
protected $groupingCenters = [];
const CENTERS_IDENTIFIERS = 'c';
/**
@ -87,10 +95,87 @@ class PickCenterType extends AbstractType
return $qb->where($qb->expr()->in('c.id', $ids));
},
'multiple' => true,
'expanded' => false,
'expanded' => true,
'choice_label' => function(Center $c) { return $c->getName(); },
'data' => $centers
'data' => count($this->groupingCenters) > 0 ? null : $centers
));
if (count($this->groupingCenters) > 0) {
$groupingBuilder = $builder->create('g', null, [
'compound' => true
]);
foreach ($this->groupingCenters as $key => $gc) {
$choices = $this->buildChoices($centers, $gc);
if (count($choices) > 0) {
$groupingBuilder->add($key, ChoiceType::class, [
'choices' => $choices,
'multiple' => true,
'expanded' => true,
'label' => $gc->getName()
]);
}
}
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 addGroupingCenter(GroupingCenterInterface $grouping)
{
$this->groupingCenters[md5($grouping->getName())] = $grouping;
}
protected function buildChoices($reachablesCenters, GroupingCenterInterface $gc)
{
$result = [];
foreach ($gc->getGroups() as $group) {
foreach ($gc->getCentersForGroup($group) as $center) {
if (\in_array($center, $reachablesCenters)) {
$result[$group] = $group;
}
}
}
return $result;
}
protected function transform($data, $centers)
{
return $data;
}
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);
}
}

View File

@ -152,6 +152,7 @@ Pick centers: Choisir les centres
The export will contains only data from the picked centers.: L'export ne contiendra que les données des centres choisis.
This will eventually restrict your possibilities in filtering the data.: Les possibilités de filtrages seront adaptées aux droits de consultation pour les centres choisis.
Go to export options: Vers la préparation de l'export
Pick aggregated centers: Regroupement de centres
# export creation step 'export' : choose aggregators, filtering and formatter
Formatter: Mise en forme
Choose the formatter: Choisissez le format d'export voulu.

View File

@ -35,6 +35,15 @@
{{ form_widget(form.centers.c) }}
{% if form.centers.children.g is defined %}
<h3>{{ 'Pick aggregated centers'|trans }}</h3>
{% for f in form.centers.children.g.children %}
{{ form_row(f) }}
{% endfor %}
{% endif %}
<p>{{ form_widget(form.submit, { 'attr' : { 'class' : 'sc-button btn-action bt-create' }, 'label' : 'Go to export options' } ) }}</p>
{{ form_end(form) }}