Compare commits

..

1 Commits

Author SHA1 Message Date
b19a1ba53b Update bootstrap to version 5.3.0 2023-11-29 10:22:43 +01:00
49 changed files with 317 additions and 1084 deletions

View File

@@ -0,0 +1,5 @@
kind: Fixed
body: 'Export: fix list person with custom fields'
time: 2023-11-27T21:01:38.260730706+01:00
custom:
Issue: ""

View File

@@ -1,5 +0,0 @@
## v2.14.1 - 2023-11-29
### Fixed
* Export: fix list person with custom fields
* ([#100](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/100)) Add a paginator to budget elements (resource and charge types) in the admin
* Fix error in ListEvaluation when "handling agents" are alone

View File

@@ -1,11 +0,0 @@
## v2.15.0 - 2023-12-11
### Feature
* ([#191](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/191)) Add export "number of household associate with an exchange"
* ([#235](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/235)) Export: add dates on the filter "filter course by activity type"
### Fixed
* ([#214](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/214)) Fix error when posting an empty comment on an accompanying period.
* ([#233](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/233)) Fix "filter evaluation by evaluation type" (and add select2 to the list of evaluation types to pick)
* ([#234](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/234)) Fix "filter aside activity by date"
* ([#228](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/228)) Fix export of activity for people created before the introduction of the createdAt column on person (during v1)
* ([#246](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/246)) Do not show activities, evaluations and social work when associated to a confidential accompanying period, except for the users which are allowed to see them

View File

@@ -1,5 +0,0 @@
## v2.15.1 - 2023-12-20
### Fixed
* Fix the household export query to exclude accompanying periods that are in draft state.
### DX
* ([#167](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/167)) Fixed readthedocs compilation by updating readthedocs config file and requirements for Sphinx

View File

@@ -1,14 +1,10 @@
---
version: 2
build:
os: ubuntu-22.04
tools:
python: "3.7"
sphinx:
configuration: docs/source/conf.py
python:
version: 3.7
install:
- requirements: docs/requirements.txt

View File

@@ -6,30 +6,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
and is generated by [Changie](https://github.com/miniscruff/changie).
## v2.15.1 - 2023-12-20
### Fixed
* Fix the household export query to exclude accompanying periods that are in draft state.
### DX
* ([#167](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/167)) Fixed readthedocs compilation by updating readthedocs config file and requirements for Sphinx
## v2.15.0 - 2023-12-11
### Feature
* ([#191](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/191)) Add export "number of household associate with an exchange"
* ([#235](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/235)) Export: add dates on the filter "filter course by activity type"
### Fixed
* ([#214](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/214)) Fix error when posting an empty comment on an accompanying period.
* ([#233](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/233)) Fix "filter evaluation by evaluation type" (and add select2 to the list of evaluation types to pick)
* ([#234](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/234)) Fix "filter aside activity by date"
* ([#228](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/228)) Fix export of activity for people created before the introduction of the createdAt column on person (during v1)
* ([#246](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/246)) Do not show activities, evaluations and social work when associated to a confidential accompanying period, except for the users which are allowed to see them
## v2.14.1 - 2023-11-29
### Fixed
* Export: fix list person with custom fields
* ([#100](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/100)) Add a paginator to budget elements (resource and charge types) in the admin
* Fix error in ListEvaluation when "handling agents" are alone
## v2.14.0 - 2023-11-24
### Feature
* ([#161](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/161)) Export: in filter "Filter accompanying period work (social action) by type, goal and result", order the items alphabetically or with the defined order

View File

@@ -27,7 +27,7 @@ To compile this documentation :
Contribute
===========
Issue tracker : https://gitlab.com/Chill-Projet/chill-bundles/-/issues
Issue tracker : https://git.framasoft.org/groups/Chill-project/issues
Licence
=======

View File

@@ -1,7 +1,6 @@
docutils==0.13.1
Pygments==2.2.0
sphinx==1.8.5
Jinja2<3.1
git+https://github.com/fabpot/sphinx-php.git@v2.0.2#egg_name=sphinx-php
jsx-lexer===0.0.8
sphinx_rtd_theme==0.5.0

View File

@@ -49,7 +49,7 @@ Clone or download the chill-skeleton project and `cd` into the main directory.
.. code-block:: bash
git clone https://gitlab.com/Chill-Projet/chill-skeleton-basic.git
cd chill-skeleton-basic
cd chill-app
As a developer, the code will stay on your computer and will be executed in docker container. To avoid permission problem, the code should be run with the same uid/gid from your current user. This is why we get your current user id with the command ``id -u`` in each following scripts.

View File

@@ -15,7 +15,7 @@
"@symfony/webpack-encore": "^4.1.0",
"@tsconfig/node14": "^1.0.1",
"bindings": "^1.5.0",
"bootstrap": "^5.0.1",
"bootstrap": "^5.3.0",
"chokidar": "^3.5.1",
"fork-awesome": "^1.1.7",
"jquery": "^3.6.0",

View File

@@ -1,147 +0,0 @@
<?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\ActivityBundle\Export\Export\LinkedToACP;
use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
use Chill\PersonBundle\Entity\Household\HouseholdMember;
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\FormBuilderInterface;
final readonly class CountHouseholdOnActivity implements ExportInterface, GroupedExportInterface
{
private EntityRepository $repository;
private bool $filterStatsByCenters;
public function __construct(
EntityManagerInterface $em,
ParameterBagInterface $parameterBag,
) {
$this->repository = $em->getRepository(Activity::class);
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
}
public function buildForm(FormBuilderInterface $builder) {}
public function getFormDefaultData(): array
{
return [];
}
public function getAllowedFormattersTypes(): array
{
return [FormatterInterface::TYPE_TABULAR];
}
public function getDescription(): string
{
return 'export.export.count_household_on_activity.description';
}
public function getGroup(): string
{
return 'Exports of activities linked to an accompanying period';
}
public function getLabels($key, array $values, $data)
{
if ('export_count_activity' !== $key) {
throw new \LogicException("the key {$key} is not used by this export");
}
return static fn ($value) => '_header' === $value ? 'export.export.count_household_on_activity.header' : $value;
}
public function getQueryKeys($data): array
{
return ['export_count_activity'];
}
public function getResult($query, $data)
{
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
public function getTitle(): string
{
return 'export.export.count_household_on_activity.title';
}
public function getType(): string
{
return Declarations::ACTIVITY;
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$centers = array_map(static fn ($el) => $el['center'], $acl);
$qb = $this->repository
->createQueryBuilder('activity')
->join('activity.persons', 'person')
->join('activity.accompanyingPeriod', 'acp')
->join(
HouseholdMember::class,
'householdmember',
Query\Expr\Join::WITH,
'person.id = IDENTITY(householdmember.person) AND householdmember.startDate <= activity.date AND (householdmember.endDate IS NULL OR householdmember.endDate > activity.date)'
)
->join('householdmember.household', 'household');
if ($this->filterStatsByCenters) {
$qb
->andWhere(
$qb->expr()->exists(
'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part
JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
'
)
)
->setParameter('authorized_centers', $centers);
}
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
$qb->select('COUNT(DISTINCT household.id) as export_count_activity');
return $qb;
}
public function requiredRole(): string
{
return ActivityStatsVoter::STATS;
}
public function supportsModifiers(): array
{
return [
Declarations::ACTIVITY,
Declarations::ACTIVITY_ACP,
PersonDeclarations::ACP_TYPE,
PersonDeclarations::PERSON_TYPE,
PersonDeclarations::HOUSEHOLD_TYPE,
];
}
}

View File

@@ -20,18 +20,23 @@ use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
use Chill\MainBundle\Export\GroupedExportInterface;
use Chill\MainBundle\Export\Helper\TranslatableStringExportLabelHelper;
use Chill\MainBundle\Export\ListInterface;
use Chill\PersonBundle\Export\Helper\FilterListAccompanyingPeriodHelperInterface;
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\FormBuilderInterface;
final readonly class ListActivity implements ListInterface, GroupedExportInterface
class ListActivity implements ListInterface, GroupedExportInterface
{
private readonly bool $filterStatsByCenters;
public function __construct(
private ListActivityHelper $helper,
private EntityManagerInterface $entityManager,
private TranslatableStringExportLabelHelper $translatableStringExportLabelHelper,
private FilterListAccompanyingPeriodHelperInterface $filterListAccompanyingPeriodHelper,
) {}
private readonly ListActivityHelper $helper,
private readonly EntityManagerInterface $entityManager,
private readonly TranslatableStringExportLabelHelper $translatableStringExportLabelHelper,
ParameterBagInterface $parameterBag,
) {
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
}
public function buildForm(FormBuilderInterface $builder)
{
@@ -114,7 +119,19 @@ final readonly class ListActivity implements ListInterface, GroupedExportInterfa
->leftJoin('acppart.person', 'person')
->andWhere('acppart.startDate != acppart.endDate OR acppart.endDate IS NULL');
$this->filterListAccompanyingPeriodHelper->addFilterAccompanyingPeriods($qb, $requiredModifiers, $acl, $data);
if ($this->filterStatsByCenters) {
$qb
->andWhere(
$qb->expr()->exists(
'SELECT 1
FROM '.PersonCenterHistory::class.' acl_count_person_history
WHERE acl_count_person_history.person = person
AND acl_count_person_history.center IN (:authorized_centers)
'
)
)
->setParameter('authorized_centers', $centers);
}
$qb
// some grouping are necessary

View File

@@ -1,138 +0,0 @@
<?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\ActivityBundle\Export\Export\LinkedToPerson;
use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Repository\ActivityRepository;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface;
use Chill\PersonBundle\Entity\Household\HouseholdMember;
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
use Doctrine\ORM\Query;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\FormBuilderInterface;
final readonly class CountHouseholdOnActivity implements ExportInterface, GroupedExportInterface
{
private bool $filterStatsByCenters;
public function __construct(
private ActivityRepository $activityRepository,
ParameterBagInterface $parameterBag,
) {
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
}
public function buildForm(FormBuilderInterface $builder) {}
public function getFormDefaultData(): array
{
return [];
}
public function getAllowedFormattersTypes()
{
return [FormatterInterface::TYPE_TABULAR];
}
public function getDescription()
{
return 'export.export.count_household_on_activity_person.description';
}
public function getGroup(): string
{
return 'Exports of activities linked to a person';
}
public function getLabels($key, array $values, $data)
{
if ('export_count_activity' !== $key) {
throw new \LogicException("the key {$key} is not used by this export");
}
return static fn ($value) => '_header' === $value ? 'export.export.count_household_on_activity_person.header' : $value;
}
public function getQueryKeys($data)
{
return ['export_count_activity'];
}
public function getResult($query, $data)
{
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
public function getTitle()
{
return 'export.export.count_household_on_activity_person.title';
}
public function getType(): string
{
return Declarations::ACTIVITY;
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$centers = array_map(static fn ($el) => $el['center'], $acl);
$qb = $this->activityRepository
->createQueryBuilder('activity')
->join('activity.person', 'person')
->join(
HouseholdMember::class,
'householdmember',
Query\Expr\Join::WITH,
'person = householdmember.person AND householdmember.startDate <= activity.date AND (householdmember.endDate IS NULL OR householdmember.endDate > activity.date)'
)
->join('householdmember.household', 'household');
$qb->select('COUNT(DISTINCT household.id) as export_count_activity');
if ($this->filterStatsByCenters) {
$qb
->join('person.centerHistory', 'centerHistory')
->where(
$qb->expr()->andX(
$qb->expr()->lte('centerHistory.startDate', 'activity.date'),
$qb->expr()->orX(
$qb->expr()->isNull('centerHistory.endDate'),
$qb->expr()->gt('centerHistory.endDate', 'activity.date')
)
)
)
->andWhere($qb->expr()->in('centerHistory.center', ':centers'))
->setParameter('centers', $centers);
}
return $qb;
}
public function requiredRole(): string
{
return ActivityStatsVoter::STATS;
}
public function supportsModifiers()
{
return [
Declarations::ACTIVITY,
Declarations::ACTIVITY_PERSON,
PersonDeclarations::PERSON_TYPE,
PersonDeclarations::HOUSEHOLD_TYPE,
];
}
}

View File

@@ -15,22 +15,17 @@ use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Entity\ActivityType;
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Export\Declarations;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
final readonly class ActivityTypeFilter implements FilterInterface
class ActivityTypeFilter implements FilterInterface
{
private const BASE_EXISTS = 'SELECT 1 FROM '.Activity::class.' act_type_filter_activity WHERE act_type_filter_activity.accompanyingPeriod = acp';
public function __construct(
private ActivityTypeRepositoryInterface $activityTypeRepository,
private TranslatableStringHelperInterface $translatableStringHelper,
private RollingDateConverterInterface $rollingDateConverter,
private readonly ActivityTypeRepositoryInterface $activityTypeRepository,
private readonly TranslatableStringHelperInterface $translatableStringHelper
) {}
public function addRole(): ?string
@@ -40,28 +35,15 @@ final readonly class ActivityTypeFilter implements FilterInterface
public function alterQuery(QueryBuilder $qb, $data)
{
$exists = self::BASE_EXISTS;
if (count($data['accepted_activitytypes']) > 0) {
$exists .= ' AND act_type_filter_activity.activityType IN (:act_type_filter_activity_types)';
$qb->andWhere(
$qb->expr()->exists(
'SELECT 1 FROM '.Activity::class.' act_type_filter_activity
WHERE act_type_filter_activity.activityType IN (:act_type_filter_activity_types) AND act_type_filter_activity.accompanyingPeriod = acp'
)
);
$qb->setParameter('act_type_filter_activity_types', $data['accepted_activitytypes']);
}
if (null !== $data['date_after']) {
$exists .= ' AND act_type_filter_activity.date >= :act_type_filter_activity_date_after';
$qb->setParameter('act_type_filter_activity_date_after', $this->rollingDateConverter->convert($data['date_after']));
}
if (null !== $data['date_before']) {
$exists .= ' AND act_type_filter_activity.date >= :act_type_filter_activity_date_before';
$qb->setParameter('act_type_filter_activity_date_before', $this->rollingDateConverter->convert($data['date_before']));
}
if (self::BASE_EXISTS !== $exists) {
$qb->andWhere($qb->expr()->exists($exists));
}
}
public function applyOn()
{
return Declarations::ACP_TYPE;
@@ -78,27 +60,11 @@ final readonly class ActivityTypeFilter implements FilterInterface
'multiple' => true,
'expanded' => true,
]);
$builder->add('date_after', PickRollingDateType::class, [
'label' => 'export.filter.activity.acp_by_activity_type.activity after',
'help' => 'export.filter.activity.acp_by_activity_type.activity after help',
'required' => false,
]);
$builder->add('date_before', PickRollingDateType::class, [
'label' => 'export.filter.activity.acp_by_activity_type.activity before',
'help' => 'export.filter.activity.acp_by_activity_type.activity before help',
'required' => false,
]);
}
public function getFormDefaultData(): array
{
return [
'accepted_activitytypes' => [],
'date_after' => null,
'date_before' => null,
];
return [];
}
public function describeAction($data, $format = 'string'): array
@@ -109,12 +75,8 @@ final readonly class ActivityTypeFilter implements FilterInterface
$types[] = $this->translatableStringHelper->localize($aty->getName());
}
return ['export.filter.activity.acp_by_activity_type.acp_containing_at_least_one_activitytypes', [
'activitytypes' => implode(', ', $types),
'has_date_after' => null !== $data['date_after'] ? 1 : 0,
'date_after' => $this->rollingDateConverter->convert($data['date_after']),
'has_date_before' => null !== $data['date_before'] ? 1 : 0,
'date_before' => $this->rollingDateConverter->convert($data['date_before']),
return ['export.filter.activity.acp_by_activity_type.acp_containing_at_least_one_%activitytypes%', [
'%activitytypes%' => implode(', ', $types),
]];
}

View File

@@ -1,60 +0,0 @@
<?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\ActivityBundle\Tests\Export\Export\LinkedToACP;
use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Export\Export\LinkedToACP\CountHouseholdOnActivity;
use Chill\MainBundle\Test\Export\AbstractExportTest;
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
use Doctrine\ORM\EntityManagerInterface;
/**
* @internal
*
* @coversNothing
*/
class CountHouseholdOnActivityTest extends AbstractExportTest
{
private EntityManagerInterface $entityManager;
protected function setUp(): void
{
self::bootKernel();
$this->entityManager = self::$container->get(EntityManagerInterface::class);
}
public function getExport()
{
yield new CountHouseholdOnActivity($this->entityManager, $this->getParameters(true));
yield new CountHouseholdOnActivity($this->entityManager, $this->getParameters(false));
}
public function getFormData()
{
return [
[],
];
}
public function getModifiersCombination()
{
return [
[
Declarations::ACTIVITY,
Declarations::ACTIVITY_ACP,
PersonDeclarations::ACP_TYPE,
PersonDeclarations::PERSON_TYPE,
PersonDeclarations::HOUSEHOLD_TYPE,
],
];
}
}

View File

@@ -1,59 +0,0 @@
<?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\ActivityBundle\Tests\Export\Export\LinkedToPerson;
use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Export\Export\LinkedToPerson\CountHouseholdOnActivity;
use Chill\ActivityBundle\Repository\ActivityRepository;
use Chill\MainBundle\Test\Export\AbstractExportTest;
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
/**
* @internal
*
* @coversNothing
*/
class CountHouseholdOnActivityTest extends AbstractExportTest
{
private ActivityRepository $activityRepository;
protected function setUp(): void
{
self::bootKernel();
$this->activityRepository = self::$container->get(ActivityRepository::class);
}
public function getExport()
{
yield new CountHouseholdOnActivity($this->activityRepository, $this->getParameters(true));
yield new CountHouseholdOnActivity($this->activityRepository, $this->getParameters(false));
}
public function getFormData()
{
return [
[],
];
}
public function getModifiersCombination()
{
return [
[
Declarations::ACTIVITY,
Declarations::ACTIVITY_PERSON,
PersonDeclarations::PERSON_TYPE,
PersonDeclarations::HOUSEHOLD_TYPE,
],
];
}
}

View File

@@ -13,7 +13,6 @@ namespace Chill\ActivityBundle\Tests\Export\Filter\ACPFilters;
use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Entity\ActivityType;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Test\Export\AbstractFilterTest;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Doctrine\Common\Collections\ArrayCollection;
@@ -56,30 +55,8 @@ final class ActivityTypeFilterTest extends AbstractFilterTest
$data = [];
foreach ($array as $a) {
$data[] = [
'accepted_activitytypes' => [],
'date_after' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START),
'date_before' => new RollingDate(RollingDate::T_TODAY),
];
$data[] = [
'accepted_activitytypes' => new ArrayCollection([$a]),
'date_after' => null,
'date_before' => null,
];
$data[] = [
'accepted_activitytypes' => [$a],
'date_after' => null,
'date_before' => null,
];
$data[] = [
'accepted_activitytypes' => [$a],
'date_after' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START),
'date_before' => new RollingDate(RollingDate::T_TODAY),
];
$data[] = [
'accepted_activitytypes' => [],
'date_after' => null,
'date_before' => null,
];
}

View File

@@ -20,14 +20,6 @@ services:
tags:
- { name: chill.export, alias: 'count_person_on_activity' }
Chill\ActivityBundle\Export\Export\LinkedToACP\CountHouseholdOnActivity:
tags:
- { name: chill.export, alias: 'count_household_on_activity_acp' }
Chill\ActivityBundle\Export\Export\LinkedToPerson\CountHouseholdOnActivity:
tags:
- { name: chill.export, alias: 'count_household_on_activity_person' }
chill.activity.export.count_activity_linked_to_acp:
class: Chill\ActivityBundle\Export\Export\LinkedToACP\CountActivity
tags:

View File

@@ -3,12 +3,7 @@ export:
activity:
course_having_activity_between_date:
Only course having an activity between from and to: Seulement les parcours ayant reçu au moins un échange entre le {from, date, short} et le {to, date, short}
acp_by_activity_type:
'acp_containing_at_least_one_activitytypes': >-
Parcours filtrés: uniquement ceux qui contiennent au moins un échange d'un des types suivants: {activitytypes}
{has_date_after, select, 1 {, après le {date_after, date}} other {}}
{has_date_before, select, 1 {, avant le {date_before, date}} other {}}
person_between_dates:
describe_action_with_no_subject: >-
Filtré par personne ayant eu un échange entre le {date_from, date} et le {date_to, date}
describe_action_with_subject: >-

View File

@@ -337,14 +337,6 @@ export:
title: Nombre d'usagers concernés par les échanges
description: Compte le nombre d'usagers concernés par les échanges. Si un usager est présent dans plusieurs échanges, il n'est comptabilisé qu'une seule fois.
header: Nombre d'usagers concernés par des échanges
count_household_on_activity:
title: Nombre de ménages concernés par les échanges
description: Compte le nombre de ménages concernés par les échanges. Si un ménage est présent dans plusieurs échanges, il n'est comptabilisé qu'une seule fois. Les usagers sans ménages ne sont pas comptabilisés.
header: Nombre de ménage concernés par des échanges
count_household_on_activity_person:
title: Nombre de ménages concernés par les échanges
description: Compte le nombre de ménages concernés par les échanges. Si un ménage est présent dans plusieurs échanges, il n'est comptabilisé qu'une seule fois. Les usagers sans ménages ne sont pas comptabilisés. Lorsqu'un usager change de ménage, chaque ménage est comptabilisé une fois.
header: Nombre de ménage concernés par des échanges
list:
activity:
users name: Nom des utilisateurs
@@ -379,10 +371,7 @@ export:
Receiving an activity after: Ayant reçu un échange après le
Receiving an activity before: Ayant reçu un échange avant le
acp_by_activity_type:
'activity after': Échanges après le
activity after help: Si laissé vide, ne sera pas pris en compte
activity before: Echanges avant le
activity before help: Si laissé vide, ne sera pas pris en compte
'acp_containing_at_least_one_%activitytypes%': 'Parcours filtrés: uniquement ceux qui contiennent au moins un échange d''un des types suivants: %activitytypes%'
person_between_dates:
Implied in an activity after this date: Impliqué dans un échange après cette date
Implied in an activity before this date: Impliqué dans un échange avant cette date

View File

@@ -13,11 +13,15 @@ namespace Chill\AsideActivityBundle\Export\Filter;
use Chill\AsideActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Form\Type\Export\FilterType;
use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Contracts\Translation\TranslatorInterface;
class ByDateFilter implements FilterInterface
@@ -62,14 +66,51 @@ class ByDateFilter implements FilterInterface
->add('date_to', PickRollingDateType::class, [
'label' => 'export.filter.Aside activities before this date',
]);
$builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
/** @var \Symfony\Component\Form\FormInterface $filterForm */
$filterForm = $event->getForm()->getParent();
$enabled = $filterForm->get(FilterType::ENABLED_FIELD)->getData();
if (true === $enabled) {
// if the filter is enabled, add some validation
$form = $event->getForm();
$date_from = $form->get('date_from')->getData();
$date_to = $form->get('date_to')->getData();
// check that fields are not empty
if (null === $date_from) {
$form->get('date_from')->addError(new FormError(
$this->translator->trans('This field '
.'should not be empty')
));
}
if (null === $date_to) {
$form->get('date_to')->addError(new FormError(
$this->translator->trans('This field '
.'should not be empty')
));
}
// check that date_from is before date_to
if (
(null !== $date_from && null !== $date_to)
&& $date_from >= $date_to
) {
$form->get('date_to')->addError(new FormError(
$this->translator->trans('export.filter.This date should be after '
.'the date given in "Implied in an aside activity after '
.'this date" field')
));
}
}
});
}
public function getFormDefaultData(): array
{
return [
'date_from' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START),
'date_to' => new RollingDate(RollingDate::T_TODAY),
];
return ['date_from' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START), 'date_to' => new RollingDate(RollingDate::T_TODAY)];
}
public function describeAction($data, $format = 'string'): array

View File

@@ -23,6 +23,6 @@ class ChargeKindController extends CRUDController
/* @var QueryBuilder $query */
$query->addOrderBy('e.ordering', 'ASC');
return parent::orderQuery($action, $query, $request, $paginator);
return $query;
}
}

View File

@@ -23,6 +23,6 @@ class ResourceKindController extends CRUDController
/* @var QueryBuilder $query */
$query->addOrderBy('e.ordering', 'ASC');
return parent::orderQuery($action, $query, $request, $paginator);
return $query;
}
}

View File

@@ -92,11 +92,6 @@ class UserHelper
}
$asStrings = [];
if (array_key_exists('uid', $decoded) || is_numeric($decoded)) {
// this is a single value. We have to wrap it into an array
$decoded = [$decoded];
}
foreach ($decoded as $userId) {
if (is_array($userId)) {
$uid = $userId['uid'];

View File

@@ -11,6 +11,7 @@
// 3. Include remainder of required Bootstrap stylesheets
@import "bootstrap/scss/variables";
@import "bootstrap/scss/variables-dark";
// 4. Include any default map overrides here
@import "custom/_maps";

View File

@@ -58,7 +58,7 @@ class AddressReferenceFromBano
foreach ($stmt as $record) {
$this->baseImporter->importAddress(
$record['refId'],
substr((string) $record['refId'], 0, 5), // extract insee from reference
substr($record['refId'], 0, 5), // extract insee from reference
$record['postcode'],
$record['street'],
$record['streetNumber'],

View File

@@ -23,7 +23,7 @@ use Symfony\Contracts\HttpClient\HttpClientInterface;
*/
class PostalCodeFRFromOpenData
{
private const CSV = 'https://datanova.laposte.fr/data-fair/api/v1/datasets/laposte-hexasmal/data-files/019HexaSmal.csv';
private const CSV = 'https://datanova.legroupe.laposte.fr/explore/dataset/laposte_hexasmal/download/?format=csv&timezone=Europe/Berlin&lang=fr&use_labels_for_header=true&csv_separator=%3B';
public function __construct(private readonly PostalCodeBaseImporter $baseImporter, private readonly HttpClientInterface $client, private readonly LoggerInterface $logger) {}

View File

@@ -41,7 +41,7 @@ class Comment implements TrackCreationInterface, TrackUpdateInterface
private ?AccompanyingPeriod $accompanyingPeriod = null;
/**
* @ORM\Column(type="text", nullable=false, options={"default":""})
* @ORM\Column(type="text")
*
* @Groups({"read", "write", "docgen:read"})
*

View File

@@ -17,7 +17,6 @@ use Chill\MainBundle\Export\GroupedExportInterface;
use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Household\Household;
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
use Chill\PersonBundle\Export\Declarations;
@@ -122,9 +121,7 @@ class CountHouseholdInPeriod implements ExportInterface, GroupedExportInterface
->join('acppart.accompanyingPeriod', 'acp')
->andWhere('acppart.startDate != acppart.endDate OR acppart.endDate IS NULL')
->andWhere('hmember.startDate <= :count_household_at_date AND (hmember.endDate IS NULL OR hmember.endDate > :count_household_at_date)')
->andWhere('acp.step != :count_acp_step')
->setParameter('count_household_at_date', $this->rollingDateConverter->convert($data['calc_date']))
->setParameter('count_acp_step', AccompanyingPeriod::STEP_DRAFT);
->setParameter('count_household_at_date', $this->rollingDateConverter->convert($data['calc_date']));
$qb
->select('COUNT(DISTINCT household.id) AS household_export_result')

View File

@@ -19,22 +19,28 @@ use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Export\Helper\FilterListAccompanyingPeriodHelperInterface;
use Chill\PersonBundle\Export\Helper\ListAccompanyingPeriodHelper;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\FormBuilderInterface;
final readonly class ListAccompanyingPeriod implements ListInterface, GroupedExportInterface
{
private bool $filterStatsByCenters;
public function __construct(
private EntityManagerInterface $entityManager,
private RollingDateConverterInterface $rollingDateConverter,
private ListAccompanyingPeriodHelper $listAccompanyingPeriodHelper,
private FilterListAccompanyingPeriodHelperInterface $filterListAccompanyingPeriodHelper,
) {}
ParameterBagInterface $parameterBag,
) {
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
}
public function buildForm(FormBuilderInterface $builder)
{
@@ -95,6 +101,8 @@ final readonly class ListAccompanyingPeriod implements ListInterface, GroupedExp
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$centers = array_map(static fn ($el) => $el['center'], $acl);
$qb = $this->entityManager->createQueryBuilder();
$qb
@@ -102,7 +110,18 @@ final readonly class ListAccompanyingPeriod implements ListInterface, GroupedExp
->andWhere('acp.step != :list_acp_step')
->setParameter('list_acp_step', AccompanyingPeriod::STEP_DRAFT);
$this->filterListAccompanyingPeriodHelper->addFilterAccompanyingPeriods($qb, $requiredModifiers, $acl, $data);
if ($this->filterStatsByCenters) {
$qb
->andWhere(
$qb->expr()->exists(
'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part
JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
'
)
)
->setParameter('authorized_centers', $centers);
}
$this->listAccompanyingPeriodHelper->addSelectClauses($qb, $this->rollingDateConverter->convert($data['calc_date']));

View File

@@ -28,11 +28,11 @@ use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkGoal;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkReferrerHistory;
use Chill\PersonBundle\Entity\AccompanyingPeriod\UserHistory;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
use Chill\PersonBundle\Entity\SocialWork\Evaluation;
use Chill\PersonBundle\Entity\SocialWork\Goal;
use Chill\PersonBundle\Entity\SocialWork\Result;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Export\Helper\FilterListAccompanyingPeriodHelperInterface;
use Chill\PersonBundle\Export\Helper\LabelPersonHelper;
use Chill\PersonBundle\Repository\SocialWork\SocialActionRepository;
use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
@@ -44,9 +44,10 @@ use Chill\ThirdPartyBundle\Export\Helper\LabelThirdPartyHelper;
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\FormBuilderInterface;
final readonly class ListAccompanyingPeriodWorkAssociatePersonOnAccompanyingPeriod implements ListInterface, GroupedExportInterface
class ListAccompanyingPeriodWorkAssociatePersonOnAccompanyingPeriod implements ListInterface, GroupedExportInterface
{
private const FIELDS = [
'id',
@@ -78,6 +79,8 @@ final readonly class ListAccompanyingPeriodWorkAssociatePersonOnAccompanyingPeri
'updatedBy',
];
private readonly bool $filterStatsByCenters;
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly DateTimeHelper $dateTimeHelper,
@@ -91,8 +94,10 @@ final readonly class ListAccompanyingPeriodWorkAssociatePersonOnAccompanyingPeri
private readonly RollingDateConverterInterface $rollingDateConverter,
private readonly AggregateStringHelper $aggregateStringHelper,
private readonly SocialActionRepository $socialActionRepository,
private readonly FilterListAccompanyingPeriodHelperInterface $filterListAccompanyingPeriodHelper,
) {}
ParameterBagInterface $parameterBag,
) {
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
}
public function buildForm(FormBuilderInterface $builder)
{
@@ -218,7 +223,17 @@ final readonly class ListAccompanyingPeriodWorkAssociatePersonOnAccompanyingPeri
->andWhere('acppart.startDate <= :calc_date AND (acppart.endDate > :calc_date OR acppart.endDate IS NULL)')
->setParameter('calc_date', $this->rollingDateConverter->convert($calcDate));
$this->filterListAccompanyingPeriodHelper->addFilterAccompanyingPeriods($qb, $requiredModifiers, $acl, $data);
if ($this->filterStatsByCenters) {
$qb
->andWhere(
$qb->expr()->exists(
'SELECT 1 FROM '.PersonCenterHistory::class.' acl_count_person_history WHERE acl_count_person_history.person = person
AND acl_count_person_history.center IN (:authorized_centers)
'
)
)
->setParameter('authorized_centers', $centers);
}
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);

View File

@@ -28,11 +28,11 @@ use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkGoal;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkReferrerHistory;
use Chill\PersonBundle\Entity\AccompanyingPeriod\UserHistory;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
use Chill\PersonBundle\Entity\SocialWork\Evaluation;
use Chill\PersonBundle\Entity\SocialWork\Goal;
use Chill\PersonBundle\Entity\SocialWork\Result;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Export\Helper\FilterListAccompanyingPeriodHelperInterface;
use Chill\PersonBundle\Export\Helper\LabelPersonHelper;
use Chill\PersonBundle\Repository\SocialWork\SocialActionRepository;
use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
@@ -44,9 +44,10 @@ use Chill\ThirdPartyBundle\Export\Helper\LabelThirdPartyHelper;
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\FormBuilderInterface;
final readonly class ListAccompanyingPeriodWorkAssociatePersonOnWork implements ListInterface, GroupedExportInterface
class ListAccompanyingPeriodWorkAssociatePersonOnWork implements ListInterface, GroupedExportInterface
{
private const FIELDS = [
'id',
@@ -78,6 +79,8 @@ final readonly class ListAccompanyingPeriodWorkAssociatePersonOnWork implements
'updatedBy',
];
private readonly bool $filterStatsByCenters;
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly DateTimeHelper $dateTimeHelper,
@@ -91,8 +94,10 @@ final readonly class ListAccompanyingPeriodWorkAssociatePersonOnWork implements
private readonly RollingDateConverterInterface $rollingDateConverter,
private readonly AggregateStringHelper $aggregateStringHelper,
private readonly SocialActionRepository $socialActionRepository,
private FilterListAccompanyingPeriodHelperInterface $filterListAccompanyingPeriodHelper,
) {}
ParameterBagInterface $parameterBag,
) {
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
}
public function buildForm(FormBuilderInterface $builder)
{
@@ -213,7 +218,17 @@ final readonly class ListAccompanyingPeriodWorkAssociatePersonOnWork implements
->join('acpw.persons', 'person')
;
$this->filterListAccompanyingPeriodHelper->addFilterAccompanyingPeriods($qb, $requiredModifiers, $acl, $data);
if ($this->filterStatsByCenters) {
$qb
->andWhere(
$qb->expr()->exists(
'SELECT 1 FROM '.PersonCenterHistory::class.' acl_count_person_history WHERE acl_count_person_history.person = person
AND acl_count_person_history.center IN (:authorized_centers)
'
)
)
->setParameter('authorized_centers', $centers);
}
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);

View File

@@ -26,8 +26,8 @@ use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
use Chill\PersonBundle\Entity\AccompanyingPeriod\UserHistory;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Export\Helper\FilterListAccompanyingPeriodHelperInterface;
use Chill\PersonBundle\Export\Helper\LabelPersonHelper;
use Chill\PersonBundle\Repository\SocialWork\SocialActionRepository;
use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
@@ -37,9 +37,10 @@ use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\FormBuilderInterface;
final readonly class ListEvaluation implements ListInterface, GroupedExportInterface
class ListEvaluation implements ListInterface, GroupedExportInterface
{
private const FIELDS = [
'id',
@@ -68,6 +69,8 @@ final readonly class ListEvaluation implements ListInterface, GroupedExportInter
'updatedBy',
];
private readonly bool $filterStatsByCenters;
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly SocialIssueRender $socialIssueRender,
@@ -80,8 +83,10 @@ final readonly class ListEvaluation implements ListInterface, GroupedExportInter
private readonly TranslatableStringExportLabelHelper $translatableStringExportLabelHelper,
private readonly AggregateStringHelper $aggregateStringHelper,
private readonly RollingDateConverterInterface $rollingDateConverter,
private FilterListAccompanyingPeriodHelperInterface $filterListAccompanyingPeriodHelper,
) {}
ParameterBagInterface $parameterBag,
) {
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
}
public function buildForm(FormBuilderInterface $builder)
{
@@ -188,7 +193,6 @@ final readonly class ListEvaluation implements ListInterface, GroupedExportInter
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$centers = array_map(static fn ($el) => $el['center'], $acl);
$calcDate = $data['calc_date'] ?? new RollingDate(RollingDate::T_TODAY);
$qb = $this->entityManager->createQueryBuilder();
@@ -204,13 +208,23 @@ final readonly class ListEvaluation implements ListInterface, GroupedExportInter
->andWhere('acppart.startDate != acppart.endDate OR acppart.endDate IS NULL')
// get participants at the given date
->andWhere('acppart.startDate <= :calc_date AND (acppart.endDate > :calc_date OR acppart.endDate IS NULL)')
->setParameter('calc_date', $this->rollingDateConverter->convert($calcDate));
->setParameter('calc_date', $this->rollingDateConverter->convert($data['calc_date']));
$this->filterListAccompanyingPeriodHelper->addFilterAccompanyingPeriods($qb, $requiredModifiers, $acl, $data);
if ($this->filterStatsByCenters) {
$qb
->andWhere(
$qb->expr()->exists(
'SELECT 1 FROM '.PersonCenterHistory::class.' acl_count_person_history WHERE acl_count_person_history.person = person
AND acl_count_person_history.center IN (:authorized_centers)
'
)
)
->setParameter('authorized_centers', $centers);
}
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
$this->addSelectClauses($qb, $this->rollingDateConverter->convert($calcDate));
$this->addSelectClauses($qb, $this->rollingDateConverter->convert($data['calc_date']));
return $qb;
}
@@ -264,7 +278,7 @@ final readonly class ListEvaluation implements ListInterface, GroupedExportInter
// referrers => at date XXXX
$qb
->addSelect('(SELECT JSON_BUILD_OBJECT(\'uid\', IDENTITY(history.user), \'d\', history.startDate) FROM '.UserHistory::class.' history '.
'WHERE history.accompanyingPeriod = acp AND history.startDate <= :calc_date AND (history.endDate IS NULL OR history.endDate > :calc_date)) AS acpw_referrers');
'WHERE history.accompanyingPeriod = acp AND history.startDate <= :calc_date AND (history.endDate IS NULL OR history.endDate > :calc_date)) AS referrers');
// persons
$qb

View File

@@ -20,7 +20,6 @@ use Chill\MainBundle\Export\ListInterface;
use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Household\Household;
use Chill\PersonBundle\Entity\Household\HouseholdComposition;
use Chill\PersonBundle\Entity\Household\HouseholdMember;
@@ -145,9 +144,7 @@ class ListHouseholdInPeriod implements ListInterface, GroupedExportInterface
->join('acppart.accompanyingPeriod', 'acp')
->andWhere('acppart.startDate != acppart.endDate OR acppart.endDate IS NULL')
->andWhere('hmember.startDate <= :count_household_at_date AND (hmember.endDate IS NULL OR hmember.endDate > :count_household_at_date)')
->andWhere('acp.step != :list_acp_step')
->setParameter('count_household_at_date', $this->rollingDateConverter->convert($data['calc_date']))
->setParameter('list_acp_step', AccompanyingPeriod::STEP_DRAFT);
->setParameter('count_household_at_date', $this->rollingDateConverter->convert($data['calc_date']));
if ($this->filterStatsByCenters) {
$qb

View File

@@ -20,14 +20,15 @@ use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Export\Helper\FilterListAccompanyingPeriodHelperInterface;
use Chill\PersonBundle\Export\Helper\ListAccompanyingPeriodHelper;
use Chill\PersonBundle\Export\Helper\ListPersonHelper;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use DateTimeImmutable;
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\FormBuilderInterface;
/**
@@ -35,13 +36,17 @@ use Symfony\Component\Form\FormBuilderInterface;
*/
final readonly class ListPersonWithAccompanyingPeriodDetails implements ListInterface, GroupedExportInterface
{
private bool $filterStatsByCenters;
public function __construct(
private ListPersonHelper $listPersonHelper,
private ListAccompanyingPeriodHelper $listAccompanyingPeriodHelper,
private EntityManagerInterface $entityManager,
private RollingDateConverterInterface $rollingDateConverter,
private FilterListAccompanyingPeriodHelperInterface $filterListAccompanyingPeriodHelper,
) {}
ParameterBagInterface $parameterBag,
) {
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
}
public function buildForm(FormBuilderInterface $builder)
{
@@ -117,7 +122,14 @@ final readonly class ListPersonWithAccompanyingPeriodDetails implements ListInte
->join('acppart.accompanyingPeriod', 'acp')
->andWhere($qb->expr()->neq('acp.step', "'".AccompanyingPeriod::STEP_DRAFT."'"));
$this->filterListAccompanyingPeriodHelper->addFilterAccompanyingPeriods($qb, $requiredModifiers, $acl, $data);
if ($this->filterStatsByCenters) {
$qb
->andWhere(
$qb->expr()->exists(
'SELECT 1 FROM '.PersonCenterHistory::class.' pch WHERE pch.person = person.id AND pch.center IN (:authorized_centers)'
)
)->setParameter('authorized_centers', $centers);
}
$this->listPersonHelper->addSelect($qb, ListPersonHelper::FIELDS, $this->rollingDateConverter->convert($data['address_date']));
$this->listAccompanyingPeriodHelper->addSelectClauses($qb, $this->rollingDateConverter->convert($data['address_date']));

View File

@@ -15,14 +15,14 @@ use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\PersonBundle\Entity\SocialWork\Evaluation;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Repository\SocialWork\EvaluationRepositoryInterface;
use Doctrine\ORM\Query\Expr\Andx;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
final readonly class EvaluationTypeFilter implements FilterInterface
{
public function __construct(private TranslatableStringHelper $translatableStringHelper, private EvaluationRepositoryInterface $evaluationRepository) {}
public function __construct(private TranslatableStringHelper $translatableStringHelper) {}
public function addRole(): ?string
{
@@ -31,9 +31,16 @@ final readonly class EvaluationTypeFilter implements FilterInterface
public function alterQuery(QueryBuilder $qb, $data)
{
$qb->andWhere(
$qb->expr()->in('workeval.evaluation', ':evaluationtype')
);
$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']);
}
@@ -44,17 +51,11 @@ final readonly class EvaluationTypeFilter implements FilterInterface
public function buildForm(FormBuilderInterface $builder)
{
$evaluations = $this->evaluationRepository->findAllActive();
usort($evaluations, fn (Evaluation $a, Evaluation $b) => $this->translatableStringHelper->localize($a->getTitle()) <=> $this->translatableStringHelper->localize($b->getTitle()));
$builder->add('accepted_evaluationtype', EntityType::class, [
'class' => Evaluation::class,
'choices' => $evaluations,
'choice_label' => fn (Evaluation $ev): string => $this->translatableStringHelper->localize($ev->getTitle()),
'multiple' => true,
'expanded' => false,
'attr' => ['class' => 'select2'],
'expanded' => true,
]);
}

View File

@@ -1,105 +0,0 @@
<?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 Chill\MainBundle\Entity\User;
use Chill\MainBundle\Repository\CenterRepositoryInterface;
use Chill\MainBundle\Security\Authorization\AuthorizationHelperForCurrentUserInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Security\Core\Security;
/**
* Filter accompanying period list and related, removing confidential ones
* based on ACL rules.
*/
final readonly class FilterListAccompanyingPeriodHelper implements FilterListAccompanyingPeriodHelperInterface
{
private bool $filterStatsByCenters;
public function __construct(
private Security $security,
private CenterRepositoryInterface $centerRepository,
private AuthorizationHelperForCurrentUserInterface $authorizationHelperForCurrentUser,
ParameterBagInterface $parameterBag,
) {
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
}
public function addFilterAccompanyingPeriods(QueryBuilder &$qb, array $requiredModifiers, array $acl, array $data = []): void
{
$centers = match ($this->filterStatsByCenters) {
true => array_map(static fn ($el) => $el['center'], $acl),
false => $this->centerRepository->findAll(),
};
$user = $this->security->getUser();
if (!$user instanceof User) {
throw new \RuntimeException('only a regular user can run this export');
}
// add filtering on confidential accompanying period. The confidential is applyed on the current status of
// the accompanying period (we do not use the 'calc_date' here
$aclConditionsOrX = $qb->expr()->orX(
// either the current user is the refferer for the course
'acp.user = :list_acp_current_user',
);
$qb->setParameter('list_acp_current_user', $user);
$i = 0;
foreach ($centers as $center) {
$scopes = $this->authorizationHelperForCurrentUser->getReachableScopes(AccompanyingPeriodVoter::SEE_DETAILS, $center);
$scopesConfidential =
$this->authorizationHelperForCurrentUser->getReachableScopes(AccompanyingPeriodVoter::SEE_CONFIDENTIAL_ALL, $center);
$orScopes = $qb->expr()->orX();
foreach ($scopes as $scope) {
$scopeCondition = match (in_array($scope, $scopesConfidential, true)) {
true => ":scope_{$i} MEMBER OF acp.scopes",
false => $qb->expr()->andX(
'acp.confidential = FALSE',
":scope_{$i} MEMBER OF acp.scopes",
),
};
$orScopes->add($scopeCondition);
$qb->setParameter("scope_{$i}", $scope);
++$i;
}
if ($this->filterStatsByCenters) {
$andX = $qb->expr()->andX(
$qb->expr()->exists(
'SELECT 1 FROM '.AccompanyingPeriodParticipation::class." acl_count_part_{$i}
JOIN ".PersonCenterHistory::class." acl_count_person_history_{$i} WITH IDENTITY(acl_count_person_history_{$i}.person) = IDENTITY(acl_count_part_{$i}.person)
WHERE acl_count_part_{$i}.accompanyingPeriod = acp.id AND acl_count_person_history_{$i}.center IN (:authorized_center_{$i})
AND acl_count_person_history_{$i}.startDate <= CURRENT_DATE() AND (acl_count_person_history_{$i}.endDate IS NULL or acl_count_person_history_{$i}.endDate > CURRENT_DATE())
"
),
$orScopes,
);
$qb->setParameter('authorized_center_'.$i, $center);
$aclConditionsOrX->add($andX);
} else {
$aclConditionsOrX->add($orScopes);
}
++$i;
}
$qb->andWhere($aclConditionsOrX);
}
}

View File

@@ -1,23 +0,0 @@
<?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;
/**
* Filter accompanying period list and related, removing confidential ones
* based on ACL rules.
*/
interface FilterListAccompanyingPeriodHelperInterface
{
public function addFilterAccompanyingPeriods(QueryBuilder &$qb, array $requiredModifiers, array $acl, array $data = []): void;
}

View File

@@ -26,7 +26,6 @@ class AccompanyingCourseCommentType extends AbstractType
{
$builder->add('content', ChillTextareaType::class, [
'required' => false,
'empty_data' => '',
]);
}

View File

@@ -14,7 +14,6 @@ namespace Chill\PersonBundle\Tests\Controller;
use Chill\MainBundle\Test\PrepareClientTrait;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\Relationships\Relation;
use Chill\PersonBundle\Entity\Relationships\Relationship;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\HttpFoundation\Request;
@@ -44,34 +43,31 @@ final class RelationshipApiControllerTest extends WebTestCase
{
self::bootKernel();
$em = self::$container->get(EntityManagerInterface::class);
$personIdHavingRelation = $em->createQueryBuilder()
->select('p.id')
$countPersons = $em->createQueryBuilder()
->select('count(p)')
->from(Person::class, 'p')
->join('p.centerCurrent', 'center_current')
->join('center_current.center', 'c')
->where('c.name LIKE :name')
->andWhere('EXISTS (SELECT 1 FROM '.Relationship::class.' r WHERE r.fromPerson = p OR r.toPerson = p)')
->setParameter('name', 'Center A')
->getQuery()
->setMaxResults(1)
->getSingleScalarResult();
$personIdWithoutRelation = $em->createQueryBuilder()
->select('p.id')
$person = $em->createQueryBuilder()
->select('p')
->from(Person::class, 'p')
->join('p.centerCurrent', 'center_current')
->join('center_current.center', 'c')
->where('c.name LIKE :name')
->andWhere('NOT EXISTS (SELECT 1 FROM '.Relationship::class.' r WHERE r.fromPerson = p OR r.toPerson = p)')
->setParameter('name', 'Center A')
->getQuery()
->setMaxResults(1)
->getSingleScalarResult();
->setFirstResult(\random_int(0, $countPersons - 1))
->getSingleResult();
self::ensureKernelShutdown();
return [
[$personIdHavingRelation, $personIdWithoutRelation],
[$person->getId()],
];
}
@@ -79,29 +75,39 @@ final class RelationshipApiControllerTest extends WebTestCase
{
self::bootKernel();
$em = self::$container->get(EntityManagerInterface::class);
$personIdWithoutRelations = $em->createQueryBuilder()
->select('p.id')
$countPersons = $em->createQueryBuilder()
->select('count(DISTINCT p)')
->from(Person::class, 'p')
->join('p.centerCurrent', 'center_current')
->join('center_current.center', 'c')
->where('c.name LIKE :name')
->setParameter('name', 'Center A')
->getQuery()
->getSingleScalarResult();
$persons = $em->createQueryBuilder()
->select('p')
->from(Person::class, 'p')
->join('p.centerCurrent', 'center_current')
->join('center_current.center', 'c')
->where('c.name LIKE :name')
->andWhere('NOT EXISTS (SELECT 1 FROM '.Relationship::class.' r WHERE r.fromPerson = p OR r.toPerson = p)')
->setParameter('name', 'Center A')
->getQuery()
->setMaxResults(2)
->setFirstResult(\random_int(0, $countPersons - 1))
->getResult();
self::ensureKernelShutdown();
return [
[$personIdWithoutRelations[0]['id'], $personIdWithoutRelations[1]['id'], $this->getRandomRelation($em)->getId(), true],
[$persons[0]->getId(), $persons[1]->getId(), $this->getRandomRelation($em)->getId(), true],
];
}
/**
* @dataProvider personProvider
*/
public function testGetRelationshipByPerson(int $personId)
public function testGetRelationshipByPerson(mixed $personId)
{
self::ensureKernelShutdown();
$client = $this->getClientAuthenticated();

View File

@@ -11,23 +11,14 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Tests\Export\Export;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Repository\CenterRepositoryInterface;
use Chill\MainBundle\Repository\ScopeRepositoryInterface;
use Chill\MainBundle\Security\Authorization\AuthorizationHelperForCurrentUserInterface;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\MainBundle\Test\Export\AbstractExportTest;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Export\Export\ListAccompanyingPeriod;
use Chill\PersonBundle\Export\Helper\FilterListAccompanyingPeriodHelper;
use Chill\PersonBundle\Export\Helper\ListAccompanyingPeriodHelper;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
use Doctrine\ORM\EntityManagerInterface;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Symfony\Component\Security\Core\Security;
/**
* @internal
@@ -36,8 +27,6 @@ use Symfony\Component\Security\Core\Security;
*/
class ListAccompanyingPeriodTest extends AbstractExportTest
{
use ProphecyTrait;
private readonly ListAccompanyingPeriod $listAccompanyingPeriod;
private readonly CenterRepositoryInterface $centerRepository;
@@ -50,54 +39,12 @@ class ListAccompanyingPeriodTest extends AbstractExportTest
public function getExport()
{
/** @var EntityManagerInterface::class $em */
$em = self::$container->get(EntityManagerInterface::class);
$rollingDateConverter = self::$container->get(RollingDateConverterInterface::class);
$listAccompanyingPeriodHelper = self::$container->get(ListAccompanyingPeriodHelper::class);
$centerRepository = self::$container->get(CenterRepositoryInterface::class);
$scopeRepository = self::$container->get(ScopeRepositoryInterface::class);
// mock security
$user = $em->createQuery('SELECT u FROM '.User::class.' u')
->setMaxResults(1)->getSingleResult();
if (null === $user) {
throw new \RuntimeException('no user found');
}
$security = $this->prophesize(Security::class);
$security->getUser()->willReturn($user);
// mock authorization helper
$scopes = $scopeRepository->findAll();
$scopesConfidentials = [] !== $scopes ? [$scopes[0]] : [];
$authorizationHelper = $this->prophesize(AuthorizationHelperForCurrentUserInterface::class);
$authorizationHelper->getReachableScopes(AccompanyingPeriodVoter::SEE_DETAILS, Argument::type(Center::class))
->willReturn($scopes);
$authorizationHelper->getReachableScopes(AccompanyingPeriodVoter::SEE_CONFIDENTIAL_ALL, Argument::type(Center::class))
->willReturn($scopesConfidentials);
yield new ListAccompanyingPeriod(
$em,
$rollingDateConverter,
$listAccompanyingPeriodHelper,
new FilterListAccompanyingPeriodHelper(
$security->reveal(),
$centerRepository,
$authorizationHelper->reveal(),
$this->getParameters(true)
)
);
yield new ListAccompanyingPeriod(
$em,
$rollingDateConverter,
$listAccompanyingPeriodHelper,
new FilterListAccompanyingPeriodHelper(
$security->reveal(),
$centerRepository,
$authorizationHelper->reveal(),
$this->getParameters(false)
)
);
yield new ListAccompanyingPeriod($em, $rollingDateConverter, $listAccompanyingPeriodHelper, $this->getParameters(true));
yield new ListAccompanyingPeriod($em, $rollingDateConverter, $listAccompanyingPeriodHelper, $this->getParameters(false));
}
public function getFormData()

View File

@@ -20,7 +20,6 @@ use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\MainBundle\Test\Export\AbstractExportTest;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Export\Export\ListAccompanyingPeriodWorkAssociatePersonOnAccompanyingPeriod;
use Chill\PersonBundle\Export\Helper\FilterListAccompanyingPeriodHelperInterface;
use Chill\PersonBundle\Export\Helper\LabelPersonHelper;
use Chill\PersonBundle\Repository\SocialWork\SocialActionRepository;
use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
@@ -28,7 +27,6 @@ use Chill\PersonBundle\Templating\Entity\SocialActionRender;
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
use Chill\ThirdPartyBundle\Export\Helper\LabelThirdPartyHelper;
use Doctrine\ORM\EntityManagerInterface;
use Prophecy\PhpUnit\ProphecyTrait;
/**
* @internal
@@ -37,8 +35,6 @@ use Prophecy\PhpUnit\ProphecyTrait;
*/
class ListAccompanyingPeriodWorkAssociatePersonOnAccompanyingPeriodTest extends AbstractExportTest
{
use ProphecyTrait;
protected function setUp(): void
{
parent::setUp();
@@ -59,7 +55,6 @@ class ListAccompanyingPeriodWorkAssociatePersonOnAccompanyingPeriodTest extends
$rollingDateConverter = self::$container->get(RollingDateConverterInterface::class);
$aggregateStringHelper = self::$container->get(AggregateStringHelper::class);
$socialActionRepository = self::$container->get(SocialActionRepository::class);
$filterListAccompanyingPeriodHelper = $this->prophesize(FilterListAccompanyingPeriodHelperInterface::class);
yield new ListAccompanyingPeriodWorkAssociatePersonOnAccompanyingPeriod(
$entityManager,
@@ -74,7 +69,23 @@ class ListAccompanyingPeriodWorkAssociatePersonOnAccompanyingPeriodTest extends
$rollingDateConverter,
$aggregateStringHelper,
$socialActionRepository,
$filterListAccompanyingPeriodHelper->reveal(),
$this->getParameters(true),
);
yield new ListAccompanyingPeriodWorkAssociatePersonOnAccompanyingPeriod(
$entityManager,
$dateTimeHelper,
$userHelper,
$personHelper,
$thirdPartyHelper,
$translatableStringExportLabelHelper,
$socialIssueRender,
$socialIssueRepository,
$socialActionRender,
$rollingDateConverter,
$aggregateStringHelper,
$socialActionRepository,
$this->getParameters(false),
);
}

View File

@@ -20,7 +20,6 @@ use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\MainBundle\Test\Export\AbstractExportTest;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Export\Export\ListAccompanyingPeriodWorkAssociatePersonOnWork;
use Chill\PersonBundle\Export\Helper\FilterListAccompanyingPeriodHelperInterface;
use Chill\PersonBundle\Export\Helper\LabelPersonHelper;
use Chill\PersonBundle\Repository\SocialWork\SocialActionRepository;
use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
@@ -28,7 +27,6 @@ use Chill\PersonBundle\Templating\Entity\SocialActionRender;
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
use Chill\ThirdPartyBundle\Export\Helper\LabelThirdPartyHelper;
use Doctrine\ORM\EntityManagerInterface;
use Prophecy\PhpUnit\ProphecyTrait;
/**
* @internal
@@ -37,8 +35,6 @@ use Prophecy\PhpUnit\ProphecyTrait;
*/
class ListAccompanyingPeriodWorkAssociatePersonOnWorkTest extends AbstractExportTest
{
use ProphecyTrait;
protected function setUp(): void
{
parent::setUp();
@@ -59,7 +55,6 @@ class ListAccompanyingPeriodWorkAssociatePersonOnWorkTest extends AbstractExport
$rollingDateConverter = self::$container->get(RollingDateConverterInterface::class);
$aggregateStringHelper = self::$container->get(AggregateStringHelper::class);
$socialActionRepository = self::$container->get(SocialActionRepository::class);
$filterHelper = $this->prophesize(FilterListAccompanyingPeriodHelperInterface::class);
yield new ListAccompanyingPeriodWorkAssociatePersonOnWork(
$entityManager,
@@ -74,7 +69,23 @@ class ListAccompanyingPeriodWorkAssociatePersonOnWorkTest extends AbstractExport
$rollingDateConverter,
$aggregateStringHelper,
$socialActionRepository,
$filterHelper->reveal(),
$this->getParameters(true),
);
yield new ListAccompanyingPeriodWorkAssociatePersonOnWork(
$entityManager,
$dateTimeHelper,
$userHelper,
$personHelper,
$thirdPartyHelper,
$translatableStringExportLabelHelper,
$socialIssueRender,
$socialIssueRepository,
$socialActionRender,
$rollingDateConverter,
$aggregateStringHelper,
$socialActionRepository,
$this->getParameters(false),
);
}

View File

@@ -11,6 +11,7 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Tests\Export\Export;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Export\Helper\AggregateStringHelper;
use Chill\MainBundle\Export\Helper\DateTimeHelper;
use Chill\MainBundle\Export\Helper\TranslatableStringExportLabelHelper;
@@ -21,14 +22,13 @@ use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\MainBundle\Test\Export\AbstractExportTest;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Export\Export\ListEvaluation;
use Chill\PersonBundle\Export\Helper\FilterListAccompanyingPeriodHelperInterface;
use Chill\PersonBundle\Export\Helper\LabelPersonHelper;
use Chill\PersonBundle\Repository\SocialWork\SocialActionRepository;
use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\EntityManagerInterface;
use Prophecy\PhpUnit\ProphecyTrait;
/**
* @internal
@@ -37,7 +37,7 @@ use Prophecy\PhpUnit\ProphecyTrait;
*/
class ListEvaluationTest extends AbstractExportTest
{
use ProphecyTrait;
private ListEvaluation $listEvaluation;
private CenterRepositoryInterface $centerRepository;
@@ -46,6 +46,7 @@ class ListEvaluationTest extends AbstractExportTest
parent::setUp();
self::bootKernel();
$this->listEvaluation = self::$container->get(ListEvaluation::class);
$this->centerRepository = self::$container->get(CenterRepositoryInterface::class);
}
@@ -62,7 +63,6 @@ class ListEvaluationTest extends AbstractExportTest
$rollingDateConverter = self::$container->get(RollingDateConverterInterface::class);
$aggregateStringHelper = self::$container->get(AggregateStringHelper::class);
$socialActionRepository = self::$container->get(SocialActionRepository::class);
$filterListHelper = $this->prophesize(FilterListAccompanyingPeriodHelperInterface::class);
yield new ListEvaluation(
$entityManager,
@@ -76,7 +76,22 @@ class ListEvaluationTest extends AbstractExportTest
$translatableStringExportLabelHelper,
$aggregateStringHelper,
$rollingDateConverter,
$filterListHelper->reveal(),
$this->getParameters(true),
);
yield new ListEvaluation(
$entityManager,
$socialIssueRender,
$socialIssueRepository,
$socialActionRender,
$socialActionRepository,
$userHelper,
$personHelper,
$dateTimeHelper,
$translatableStringExportLabelHelper,
$aggregateStringHelper,
$rollingDateConverter,
$this->getParameters(false),
);
}
@@ -89,4 +104,14 @@ class ListEvaluationTest extends AbstractExportTest
{
return [[Declarations::ACP_TYPE]];
}
public function testQuery(): void
{
$centers = $this->centerRepository->findAll();
$query = $this->listEvaluation->initiateQuery([], array_map(fn (Center $c) => ['center' => $c], $centers), ['calc_date' => new RollingDate(RollingDate::T_TODAY)]);
$query->setMaxResults(1);
self::assertIsArray($query->getQuery()->getResult(AbstractQuery::HYDRATE_ARRAY));
}
}

View File

@@ -16,11 +16,9 @@ use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\MainBundle\Test\Export\AbstractExportTest;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Export\Export\ListPersonWithAccompanyingPeriodDetails;
use Chill\PersonBundle\Export\Helper\FilterListAccompanyingPeriodHelperInterface;
use Chill\PersonBundle\Export\Helper\ListAccompanyingPeriodHelper;
use Chill\PersonBundle\Export\Helper\ListPersonHelper;
use Doctrine\ORM\EntityManagerInterface;
use Prophecy\PhpUnit\ProphecyTrait;
/**
* @internal
@@ -29,8 +27,6 @@ use Prophecy\PhpUnit\ProphecyTrait;
*/
class ListPersonWithAccompanyingPeriodDetailsTest extends AbstractExportTest
{
use ProphecyTrait;
protected function setUp(): void
{
parent::setUp();
@@ -43,14 +39,21 @@ class ListPersonWithAccompanyingPeriodDetailsTest extends AbstractExportTest
$listAccompanyingPeriodHelper = self::$container->get(ListAccompanyingPeriodHelper::class);
$entityManager = self::$container->get(EntityManagerInterface::class);
$rollingDateConverter = self::$container->get(RollingDateConverterInterface::class);
$filterHelper = $this->prophesize(FilterListAccompanyingPeriodHelperInterface::class);
yield new ListPersonWithAccompanyingPeriodDetails(
$listPersonHelper,
$listAccompanyingPeriodHelper,
$entityManager,
$rollingDateConverter,
$filterHelper->reveal()
$this->getParameters(true),
);
yield new ListPersonWithAccompanyingPeriodDetails(
$listPersonHelper,
$listAccompanyingPeriodHelper,
$entityManager,
$rollingDateConverter,
$this->getParameters(false),
);
}

View File

@@ -69,10 +69,10 @@ final class EvaluationTypeFilterTest extends AbstractFilterTest
return [
$em->createQueryBuilder()
->select('workeval.id')
->select('eval.id')
->from(AccompanyingPeriod::class, 'acp')
->join('acp.works', 'acpw')
->join('acpw.accompanyingPeriodWorkEvaluations', 'workeval'),
->join('acpw.accompanyingPeriodWorkEvaluations', 'eval'),
];
}
}

View File

@@ -1,137 +0,0 @@
<?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\Tests\Export\Helper;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Repository\CenterRepositoryInterface;
use Chill\MainBundle\Repository\ScopeRepositoryInterface;
use Chill\MainBundle\Security\Authorization\AuthorizationHelperForCurrentUserInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Export\Helper\FilterListAccompanyingPeriodHelper;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Security\Core\Security;
/**
* @internal
*
* @coversNothing
*/
final class FilterListAccompanyingPeriodHelperTest extends KernelTestCase
{
use ProphecyTrait;
private CenterRepositoryInterface $centerRepository;
private ScopeRepositoryInterface $scopeRepository;
private EntityManagerInterface $entityManager;
protected function setUp(): void
{
parent::setUp();
self::bootKernel();
$this->centerRepository = self::$container->get(CenterRepositoryInterface::class);
$this->scopeRepository = self::$container->get(ScopeRepositoryInterface::class);
$this->entityManager = self::$container->get(EntityManagerInterface::class);
}
/**
* @dataProvider dataProviderTestAddFilterAccompanyingPeriod
*/
public function testAddFilterAccompanyingPeriod(QueryBuilder $qb, ParameterBagInterface $parameterBag): void
{
// mock security
$user = $this->entityManager->createQuery('SELECT u FROM '.User::class.' u')
->setMaxResults(1)->getSingleResult();
if (null === $user) {
throw new \RuntimeException('no user found');
}
$security = $this->prophesize(Security::class);
$security->getUser()->willReturn($user);
// mock authorization helper
$scopes = $this->scopeRepository->findAll();
$scopesConfidentials = [] !== $scopes ? [$scopes[0]] : [];
$authorizationHelper = $this->prophesize(AuthorizationHelperForCurrentUserInterface::class);
$authorizationHelper->getReachableScopes(AccompanyingPeriodVoter::SEE_DETAILS, Argument::type(Center::class))
->willReturn($scopes);
$authorizationHelper->getReachableScopes(AccompanyingPeriodVoter::SEE_CONFIDENTIAL_ALL, Argument::type(Center::class))
->willReturn($scopesConfidentials);
$filter = new FilterListAccompanyingPeriodHelper(
$security->reveal(),
$this->centerRepository,
$authorizationHelper->reveal(),
$parameterBag
);
$filter->addFilterAccompanyingPeriods($qb, [], $this->getACL(), []);
$qb->setMaxResults(1);
$result = $qb->getQuery()->getResult();
self::assertIsArray($result);
}
public function dataProviderTestAddFilterAccompanyingPeriod(): iterable
{
self::setUp();
$qb = $this->entityManager->createQueryBuilder();
$qb
->select('acp.id')
->from(AccompanyingPeriod::class, 'acp');
yield [
$qb,
new ParameterBag(['chill_main' => ['acl' => ['filter_stats_by_center' => true]]]),
];
yield [
$qb,
new ParameterBag(['chill_main' => ['acl' => ['filter_stats_by_center' => false]]]),
];
}
/**
* @return list<array{center: Center, circles: list<Scope>}> the ACL, structured as an array
*
* @throws \RuntimeException when no center or circle is found
*/
private function getACL(): array
{
$centers = $this->centerRepository->findAll();
$circles = $this->scopeRepository->findAll();
if (0 === \count($centers)) {
throw new \RuntimeException('No center found. Did you forget to run `doctrine:fixtures:load` command before ?');
}
if (0 === \count($circles)) {
throw new \RuntimeException('No circle found. Did you forget to run `doctrine:fixtures:load` command before ?');
}
return [[
'center' => $centers[0],
'circles' => [
$circles,
], ]];
}
}

View File

@@ -1,36 +0,0 @@
<?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\Migrations\Person;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Version20231128143534 extends AbstractMigration
{
public function getDescription(): string
{
return 'Set a default for the content column of accompanying_period_comment';
}
public function up(Schema $schema): void
{
$this->addSql("UPDATE chill_person_accompanying_period_comment SET content='' WHERE content IS NULL");
$this->addSql('ALTER TABLE chill_person_accompanying_period_comment ALTER COLUMN content SET NOT NULL');
$this->addSql('ALTER TABLE chill_person_accompanying_period_comment ALTER COLUMN content SET DEFAULT \'\'');
}
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE chill_person_accompanying_period_comment ALTER COLUMN content DROP DEFAULT');
$this->addSql('ALTER TABLE chill_person_accompanying_period_comment ALTER COLUMN content DROP NOT NULL');
}
}

View File

@@ -1,58 +0,0 @@
<?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\Migrations\Person;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Fix lines in chill_person_person_center_history for people created before the introduction of the createdAt column.
*
* This class represents a migration for fixing lines in the 'chill_person_person_center_history' table.
*
* It updates the 'startdate' column for people created before the introduction
* of the 'createdAt' column, and set it at the first activity date. This migration is irreversible.
*/
final class Version20231207221700 extends AbstractMigration
{
public function getDescription(): string
{
return 'Fix lines in chill_person_person_center_history for people created before the introduction of the createdAt column';
}
public function up(Schema $schema): void
{
$this->addSql('WITH first_history_line AS (SELECT *
FROM (SELECT id,
person_id,
startdate,
rank() OVER (PARTITION BY person_id ORDER BY startdate ASC, id ASC) AS r
FROM chill_person_person_center_history) AS sk
WHERE sk.r = 1),
first_activity AS (SELECT *
FROM (SELECT id, date, person_id, rank() OVER (PARTITION BY person_id ORDER BY date ASC, id ASC) AS r
FROM activity
WHERE person_id IS NOT NULL) sq
WHERE sq.r = 1)
UPDATE chill_person_person_center_history cppch SET startdate=first_activity.date
FROM first_history_line, first_activity
WHERE
first_history_line.id = cppch.id
AND first_activity.person_id = cppch.person_id
AND first_activity.date < first_history_line.startDate');
}
public function down(Schema $schema): void
{
$this->throwIrreversibleMigrationException();
}
}