Merge branch '111_exports' into social_action_exports

This commit is contained in:
2022-08-11 14:08:33 +02:00
14 changed files with 869 additions and 4 deletions

View File

@@ -0,0 +1,98 @@
<?php
namespace Chill\PersonBundle\Export\Aggregator\EvaluationAggregators;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Repository\SocialWork\EvaluationRepository;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
class EvaluationTypeAggregator implements AggregatorInterface
{
private EvaluationRepository $evaluationRepository;
private TranslatableStringHelper $translatableStringHelper;
public function __construct(
EvaluationRepository $evaluationRepository,
TranslatableStringHelper $translatableStringHelper
) {
$this->evaluationRepository = $evaluationRepository;
$this->translatableStringHelper = $translatableStringHelper;
}
/**
* @inheritDoc
*/
public function getLabels($key, array $values, $data)
{
return function ($value): string {
if ($value === '_header') {
return 'Evaluation type';
}
$ev = $this->evaluationRepository->find($value);
return $this->translatableStringHelper->localize($ev->getTitle());
};
}
/**
* @inheritDoc
*/
public function getQueryKeys($data): array
{
return ['evaluationtype_aggregator'];
}
/**
* @inheritDoc
*/
public function buildForm(FormBuilderInterface $builder)
{
// no form
}
/**
* @inheritDoc
*/
public function getTitle(): string
{
return 'Group by evaluation type';
}
/**
* @inheritDoc
*/
public function addRole()
{
return null;
}
/**
* @inheritDoc
*/
public function alterQuery(QueryBuilder $qb, $data)
{
$qb->join('eval.evaluation', 'ev');
$qb->addSelect('ev.id AS evaluationtype_aggregator');
$groupBy = $qb->getDQLPart('groupBy');
if (!empty($groupBy)) {
$qb->addGroupBy('evaluationtype_aggregator');
} else {
$qb->groupBy('evaluationtype_aggregator');
}
}
/**
* @inheritDoc
*/
public function applyOn(): string
{
return Declarations::EVAL_TYPE;
}
}

View File

@@ -0,0 +1,108 @@
<?php
namespace Chill\PersonBundle\Export\Aggregator\HouseholdAggregators;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Form\Type\ChillDateType;
use Chill\PersonBundle\Export\Declarations;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
class ChildrenNumberAggregator implements AggregatorInterface
{
private TranslatorInterface $translator;
public function __construct(
TranslatorInterface $translator
) {
$this->translator = $translator;
}
/**
* @inheritDoc
*/
public function getLabels($key, array $values, $data)
{
return function ($value): string {
if ($value === '_header') {
return 'Number of children';
}
return $this->translator->trans(
'household_composition.numberOfChildren children in household', [
'numberOfChildren' => $value
]);
};
}
/**
* @inheritDoc
*/
public function getQueryKeys($data): array
{
return ['childrennumber_aggregator'];
}
/**
* @inheritDoc
*/
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('on_date', ChillDateType::class, [
'data' => new \DateTime('now'),
]);
}
/**
* @inheritDoc
*/
public function getTitle(): string
{
return 'Group by number of children';
}
/**
* @inheritDoc
*/
public function addRole()
{
return null;
}
/**
* @inheritDoc
*/
public function alterQuery(QueryBuilder $qb, $data)
{
$qb->addSelect('composition.numberOfChildren AS childrennumber_aggregator');
$groupBy = $qb->getDQLPart('groupBy');
if (!empty($groupBy)) {
$qb->addGroupBy('childrennumber_aggregator');
} else {
$qb->groupBy('childrennumber_aggregator');
}
// add date in where clause
$where = $qb->getDQLPart('where');
$clause = $qb->expr()->andX(
$qb->expr()->lte('composition.startDate', ':ondate'),
$qb->expr()->orX(
$qb->expr()->gt('composition.endDate', ':ondate'),
$qb->expr()->isNull('composition.endDate')
)
);
}
/**
* @inheritDoc
*/
public function applyOn(): string
{
return Declarations::HOUSEHOLD_TYPE;
}
}

View File

@@ -0,0 +1,124 @@
<?php
namespace Chill\PersonBundle\Export\Aggregator\HouseholdAggregators;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Form\Type\ChillDateType;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Repository\Household\HouseholdCompositionTypeRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Query\Expr\Andx;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
class CompositionAggregator implements AggregatorInterface
{
private HouseholdCompositionTypeRepository $typeRepository;
private TranslatableStringHelper $translatableStringHelper;
public function __construct(
HouseholdCompositionTypeRepository $typeRepository,
TranslatableStringHelper $translatableStringHelper
) {
$this->typeRepository = $typeRepository;
$this->translatableStringHelper = $translatableStringHelper;
}
/**
* @inheritDoc
*/
public function getLabels($key, array $values, $data)
{
return function ($value): string {
if ($value === '_header') {
return 'Composition';
}
$c = $this->typeRepository->find($value);
return $this->translatableStringHelper->localize(
$c->getLabel()
);
};
}
/**
* @inheritDoc
*/
public function getQueryKeys($data): array
{
return ['composition_aggregator'];
}
/**
* @inheritDoc
*/
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('on_date', ChillDateType::class, [
'data' => new \DateTime('now'),
]);
}
/**
* @inheritDoc
*/
public function getTitle(): string
{
return 'Group by composition';
}
/**
* @inheritDoc
*/
public function addRole()
{
return null;
}
/**
* @inheritDoc
*/
public function alterQuery(QueryBuilder $qb, $data)
{
$qb->addSelect('IDENTITY(composition.householdCompositionType) AS composition_aggregator');
$groupBy = $qb->getDQLPart('groupBy');
if (!empty($groupBy)) {
$qb->addGroupBy('composition_aggregator');
} else {
$qb->groupBy('composition_aggregator');
}
// add date in where clause
$where = $qb->getDQLPart('where');
$clause = $qb->expr()->andX(
$qb->expr()->lte('composition.startDate', ':ondate'),
$qb->expr()->orX(
$qb->expr()->gt('composition.endDate', ':ondate'),
$qb->expr()->isNull('composition.endDate')
)
);
if ($where instanceof Andx) {
$where->add($clause);
} else {
$where = $qb->expr()->andX($clause);
}
$qb->add('where', $where);
$qb->setParameter('ondate', $data['on_date'], Types::DATE_MUTABLE);
}
/**
* @inheritDoc
*/
public function applyOn(): string
{
return Declarations::HOUSEHOLD_TYPE;
}
}

View File

@@ -27,4 +27,6 @@ abstract class Declarations
public const SOCIAL_WORK_ACTION_TYPE = 'social_actions';
public const EVAL_TYPE = 'evaluation';
public const HOUSEHOLD_TYPE = 'household';
}

View File

@@ -5,7 +5,7 @@ namespace Chill\PersonBundle\Export\Export;
use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface;
use Chill\PersonBundle\Entity\SocialWork\Evaluation;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
use Doctrine\ORM\EntityManagerInterface;
@@ -22,7 +22,7 @@ class CountEvaluation implements ExportInterface, GroupedExportInterface
public function __construct(
EntityManagerInterface $em
) {
$this->evaluationRepository = $em->getRepository(Evaluation::class);
$this->evaluationRepository = $em->getRepository(AccompanyingPeriodWorkEvaluation::class);
}
/**

View File

@@ -0,0 +1,141 @@
<?php
namespace Chill\PersonBundle\Export\Export;
use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
class CountHousehold implements ExportInterface, GroupedExportInterface
{
private EntityRepository $acpRepository;
public function __construct(
EntityManagerInterface $em
) {
$this->acpRepository = $em->getRepository(AccompanyingPeriod::class);
}
/**
* @inheritDoc
*/
public function buildForm(FormBuilderInterface $builder)
{
// TODO: Implement buildForm() method.
}
/**
* @inheritDoc
*/
public function getTitle(): string
{
return 'Count households';
}
/**
* @inheritDoc
*/
public function getAllowedFormattersTypes(): array
{
return [FormatterInterface::TYPE_TABULAR];
}
/**
* @inheritDoc
*/
public function getDescription(): string
{
return 'Count household by various parameters.';
}
/**
* @inheritDoc
*/
public function getLabels($key, array $values, $data)
{
if ('export_result' !== $key) {
throw new LogicException("the key {$key} is not used by this export");
}
$labels = array_combine($values, $values);
$labels['_header'] = $this->getTitle();
return static function ($value) use ($labels) {
return $labels[$value];
};
}
/**
* @inheritDoc
*/
public function getQueryKeys($data): array
{
return ['export_result'];
}
/**
* @inheritDoc
*/
public function getResult($qb, $data)
{
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
/**
* @inheritDoc
*/
public function getType(): string
{
return Declarations::HOUSEHOLD_TYPE;
}
/**
* @inheritDoc
*/
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$qb = $this->acpRepository->createQueryBuilder('acp')
->join('acp.participations', 'acppart')
->join('acppart.person', 'person')
->join('person.householdParticipations', 'householdmember')
->join('householdmember.household', 'household')
->join('household.compositions', 'composition')
;
$qb->select('COUNT(DISTINCT householdmember.household) AS export_result');
return $qb;
}
/**
* @inheritDoc
*/
public function requiredRole()
{
// TODO HouseholdVoter::STATS !??
return new Role(AccompanyingPeriodVoter::STATS);
}
/**
* @inheritDoc
*/
public function supportsModifiers(): array
{
return [
Declarations::HOUSEHOLD_TYPE,
];
}
public function getGroup(): string
{
return 'Exports of households';
}
}

View File

@@ -11,7 +11,6 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters;
use Chill\CustomFieldsBundle\Form\Type\ChoicesType;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Export\FilterInterface;

View File

@@ -0,0 +1,96 @@
<?php
namespace Chill\PersonBundle\Export\Filter\EvaluationFilters;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\PersonBundle\Entity\SocialWork\Evaluation;
use Chill\PersonBundle\Export\Declarations;
use Doctrine\ORM\Query\Expr\Andx;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
final class EvaluationTypeFilter implements FilterInterface
{
private TranslatableStringHelper $translatableStringHelper;
public function __construct(
TranslatableStringHelper $translatableStringHelper
) {
$this->translatableStringHelper = $translatableStringHelper;
}
/**
* @inheritDoc
*/
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('accepted_evaluationtype', EntityType::class, [
'class' => Evaluation::class,
'choice_label' => function (Evaluation $ev): string {
return $this->translatableStringHelper->localize($ev->getTitle());
},
'multiple' => true,
'expanded' => true
]);
}
/**
* @inheritDoc
*/
public function getTitle(): string
{
return 'Filter by evaluation type';
}
/**
* @inheritDoc
*/
public function describeAction($data, $format = 'string'): array
{
$evals = [];
foreach ($data['accepted_evaluationtype'] as $ev) {
$evals[] = $this->translatableStringHelper->localize($ev->getTitle());
}
return ['Filtered by evaluation type: only %evals%', [
'%evals%' => implode(", ou ", $evals)
]];
}
/**
* @inheritDoc
*/
public function addRole()
{
return null;
}
/**
* @inheritDoc
*/
public function alterQuery(QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
$clause = $qb->expr()->in('eval.evaluation', ':evaluationtype');
if ($where instanceof Andx) {
$where->add($clause);
} else {
$where = $qb->expr()->andX($clause);
}
$qb->add('where', $where);
$qb->setParameter('evaluationtype', $data['accepted_evaluationtype']);
}
/**
* @inheritDoc
*/
public function applyOn(): string
{
return Declarations::EVAL_TYPE;
}
}

View File

@@ -0,0 +1,103 @@
<?php
namespace Chill\PersonBundle\Export\Filter\EvaluationFilters;
use Chill\MainBundle\Export\FilterInterface;
use Chill\PersonBundle\Export\Declarations;
use Doctrine\ORM\Query\Expr\Andx;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
class MaxDateFilter implements FilterInterface
{
private const MAXDATE_CHOICES = [
'is specified' => true,
'is not specified' => false,
];
private TranslatorInterface $translator;
public function __construct(TranslatorInterface $translator)
{
$this->translator = $translator;
}
/**
* @inheritDoc
*/
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('maxdate', ChoiceType::class, [
'choices' => self::MAXDATE_CHOICES,
'multiple' => false,
'expanded' => true
]);
}
/**
* @inheritDoc
*/
public function getTitle(): string
{
return 'Filter by maxdate';
}
/**
* @inheritDoc
*/
public function describeAction($data, $format = 'string'): array
{
foreach (self::MAXDATE_CHOICES as $k => $v) {
if ($v === $data['maxdate']) {
$choice = $k;
}
}
return ['Filtered by maxdate: only %choice%', [
'%choice%' => $this->translator->trans($choice)
]];
}
/**
* @inheritDoc
*/
public function addRole()
{
return null;
}
/**
* @inheritDoc
*/
public function alterQuery(QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
if ($data['maxdate'] === true) {
$clause = $qb->expr()->isNotNull('eval.maxDate');
} else {
$clause = $qb->expr()->isNull('eval.maxDate');
}
if ($where instanceof Andx) {
$where->add($clause);
} else {
$where = $qb->expr()->andX($clause);
}
$qb->add('where', $where);
dump($data['maxdate']);
}
/**
* @inheritDoc
*/
public function applyOn(): string
{
return Declarations::EVAL_TYPE;
}
}

View File

@@ -0,0 +1,119 @@
<?php
namespace Chill\PersonBundle\Export\Filter\HouseholdFilters;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Form\Type\ChillDateType;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\PersonBundle\Entity\Household\HouseholdCompositionType;
use Chill\PersonBundle\Export\Declarations;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Query\Expr\Andx;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
class CompositionFilter implements FilterInterface
{
private TranslatableStringHelper $translatableStringHelper;
public function __construct(
TranslatableStringHelper $translatableStringHelper
) {
$this->translatableStringHelper = $translatableStringHelper;
}
/**
* @inheritDoc
*/
public function buildForm(FormBuilderInterface $builder)
{
$builder
->add('accepted_composition', EntityType::class, [
'class' => HouseholdCompositionType::class,
'choice_label' => function (HouseholdCompositionType $type) {
return $this->translatableStringHelper->localize(
$type->getLabel()
);
},
'multiple' => true,
'expanded' => true,
])
->add('on_date', ChillDateType::class, [
'data' => new \DateTime('now'),
])
;
}
/**
* @inheritDoc
*/
public function getTitle(): string
{
return 'Filter by composition';
}
/**
* @inheritDoc
*/
public function describeAction($data, $format = 'string'): array
{
$compositions = [];
foreach ($data['accepted_composition'] as $c) {
$compositions[] = $this->translatableStringHelper->localize(
$c->getLabel()
);
}
return ['Filtered by composition: only %compositions% on %ondate%', [
'%compositions%' => implode(", ou ", $compositions),
'%ondate%' => $data['on_date']->format('d-m-Y')
]];
}
/**
* @inheritDoc
*/
public function addRole()
{
return null;
}
/**
* @inheritDoc
*/
public function alterQuery(QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
$clause = $qb->expr()->andX(
$qb->expr()->in('composition.householdCompositionType', ':compositions'),
$qb->expr()->andX(
$qb->expr()->lte('composition.startDate', ':ondate'),
$qb->expr()->orX(
$qb->expr()->gt('composition.endDate', ':ondate'),
$qb->expr()->isNull('composition.endDate')
)
)
);
if ($where instanceof Andx) {
$where->add($clause);
} else {
$where = $qb->expr()->andX($clause);
}
$qb->add('where', $where);
$qb->setParameter('compositions', $data['accepted_composition']);
$qb->setParameter('ondate', $data['on_date'], Types::DATE_MUTABLE);
}
/**
* @inheritDoc
*/
public function applyOn(): string
{
return Declarations::HOUSEHOLD_TYPE;
}
}