Merge remote-tracking branch 'origin/master' into rector/rules-symfony

This commit is contained in:
Julien Fastré 2023-09-27 15:25:29 +02:00
commit 65aa0a1588
Signed by: julienfastre
GPG Key ID: BDE2190974723FCB
106 changed files with 1259 additions and 506 deletions

View File

@ -1,6 +0,0 @@
kind: Feature
body: Add locations in Aside Activity. By default, suggest user location, otherwise
a select with all locations.
time: 2023-08-17T13:10:59.152278661+02:00
custom:
Issue: "133"

View File

@ -1,6 +0,0 @@
kind: Feature
body: 'Adapt Aside Activity exports: display location, filter by location, group by
location'
time: 2023-08-17T13:11:52.911356021+02:00
custom:
Issue: "133"

View File

@ -0,0 +1,7 @@
kind: Feature
body: "The regulation list load accompanying periods by exact postal code (address
associated with postal code), and not by the content of the postal code (postal
code with same code's string)"
time: 2023-09-26T16:44:41.414746336+02:00
custom:
Issue: "155"

View File

@ -1,5 +0,0 @@
kind: Fixed
body: Missing translation in Work Actions exports
time: 2023-08-17T13:12:39.159627128+02:00
custom:
Issue: ""

View File

@ -1,6 +0,0 @@
kind: Fixed
body: "Corrects a typing error in 2 filters, which caused an \nerror when trying to
reedit a saved export\n\n"
time: 2023-08-22T14:28:09.485466139+02:00
custom:
Issue: "135"

View File

@ -1,6 +0,0 @@
kind: Fixed
body: '[household] when moving a person to a sharing position to a not-sharing position
on the same household on the same date, remove the previous household membership on the same household. This fix duplicate member.'
time: 2023-08-29T18:13:32.799479781+02:00
custom:
Issue: "136"

View File

@ -1,6 +0,0 @@
kind: Fixed
body: |
Add missing translation for comment field placeholder in repositionning household editor.
time: 2023-08-29T18:18:37.691526331+02:00
custom:
Issue: ""

View File

@ -1,5 +0,0 @@
kind: Fixed
body: Do not send an email to creator twice when adding a comment to a notification
time: 2023-09-06T15:48:56.991246312+02:00
custom:
Issue: ""

View File

@ -0,0 +1,5 @@
kind: Fixed
body: Fix the label of filter ActivityTypeFilter to a more obvious one
time: 2023-09-13T11:59:54.948009297+02:00
custom:
Issue: "142"

View File

@ -0,0 +1,6 @@
kind: Fixed
body: '[export] Fix association of filter "filter location by type" which did not
appears on "list of activities"'
time: 2023-09-26T17:58:15.871908118+02:00
custom:
Issue: "140"

View File

@ -1,6 +0,0 @@
kind: UX
body: |
Uniformize badge-person in household banner (background, size)
time: 2023-08-29T18:17:33.190396543+02:00
custom:
Issue: ""

21
.changes/v2.6.0.md Normal file
View File

@ -0,0 +1,21 @@
## v2.6.0 - 2023-09-14
### Feature
* ([#133](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/133)) Add locations in Aside Activity. By default, suggest user location, otherwise a select with all locations.
* ([#133](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/133)) Adapt Aside Activity exports: display location, filter by location, group by location
* Use the CRUD controller for center entity + add the isActive property to be able to mask instances of Center that are no longer in use.
### Fixed
* ([#107](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/107)) reinstate the fusion of duplicate persons
* Missing translation in Work Actions exports
* Reimplement the mission type filter on tasks, only for instances that have a config parameter indicating true for this.
* ([#135](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/135)) Corrects a typing error in 2 filters, which caused an
error when trying to reedit a saved export
* ([#136](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/136)) [household] when moving a person to a sharing position to a not-sharing position on the same household on the same date, remove the previous household membership on the same household. This fix duplicate member.
* Add missing translation for comment field placeholder in repositionning household editor.
* Do not send an email to creator twice when adding a comment to a notification
* ([#107](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/107)) Fix gestion doublon functionality to work with chill bundles v2
### UX
* Uniformize badge-person in household banner (background, size)

3
.changes/v2.6.1.md Normal file
View File

@ -0,0 +1,3 @@
## v2.6.1 - 2023-09-14
### Fixed
* Filter out active centers in exports, which uses a different PickCenterType.

3
.changes/v2.6.2.md Normal file
View File

@ -0,0 +1,3 @@
## v2.6.2 - 2023-09-18
### Fixed
* Fix doctrine mapping of AbstractTaskPlaceEvent and SingleTaskPlaceEvent: id property moved.

4
.changes/v2.6.3.md Normal file
View File

@ -0,0 +1,4 @@
## v2.6.3 - 2023-09-19
### Fixed
* Remove id property from document
mappedsuperclass

View File

@ -6,6 +6,41 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
and is generated by [Changie](https://github.com/miniscruff/changie). and is generated by [Changie](https://github.com/miniscruff/changie).
## v2.6.3 - 2023-09-19
### Fixed
* Remove id property from document
mappedsuperclass
## v2.6.2 - 2023-09-18
### Fixed
* Fix doctrine mapping of AbstractTaskPlaceEvent and SingleTaskPlaceEvent: id property moved.
## v2.6.1 - 2023-09-14
### Fixed
* Filter out active centers in exports, which uses a different PickCenterType.
## v2.6.0 - 2023-09-14
### Feature
* ([#133](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/133)) Add locations in Aside Activity. By default, suggest user location, otherwise a select with all locations.
* ([#133](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/133)) Adapt Aside Activity exports: display location, filter by location, group by location
* Use the CRUD controller for center entity + add the isActive property to be able to mask instances of Center that are no longer in use.
### Fixed
* ([#107](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/107)) reinstate the fusion of duplicate persons
* Missing translation in Work Actions exports
* Reimplement the mission type filter on tasks, only for instances that have a config parameter indicating true for this.
* ([#135](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/135)) Corrects a typing error in 2 filters, which caused an
error when trying to reedit a saved export
* ([#136](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/136)) [household] when moving a person to a sharing position to a not-sharing position on the same household on the same date, remove the previous household membership on the same household. This fix duplicate member.
* Add missing translation for comment field placeholder in repositionning household editor.
* Do not send an email to creator twice when adding a comment to a notification
* ([#107](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/107)) Fix gestion doublon functionality to work with chill bundles v2
### UX
* Uniformize badge-person in household banner (background, size)
## v2.5.3 - 2023-07-20 ## v2.5.3 - 2023-07-20
### Fixed ### Fixed
* ([#132](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/132)) Rendez-vous documents created would appear in all documents lists of all persons with an accompanying period. Or statements are now added to the where clause to filter out documents that come from unrelated accompanying period/ or person rendez-vous. * ([#132](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/132)) Rendez-vous documents created would appear in all documents lists of all persons with an accompanying period. Or statements are now added to the where clause to filter out documents that come from unrelated accompanying period/ or person rendez-vous.

View File

@ -121,7 +121,8 @@
"ocramius/package-versions": true, "ocramius/package-versions": true,
"phpro/grumphp": true, "phpro/grumphp": true,
"phpstan/extension-installer": true, "phpstan/extension-installer": true,
"roave/you-are-using-it-wrong": true "roave/you-are-using-it-wrong": true,
"symfony/runtime": true
}, },
"bin-dir": "bin", "bin-dir": "bin",
"optimize-autoloader": true, "optimize-autoloader": true,

View File

@ -0,0 +1,36 @@
.. Copyright (C) 2014 Champs Libres Cooperative SCRLFS
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the section entitled "GNU
Free Documentation License".
.. _faq:
Frequently asked questions
####################
Continuous integration
***********
Pipeline fails, but php-cs-fixer doesn't alert me when running it locally ?
========================================
It is possible that you run php-cs-fixer on your local instance of chill and no fixes are made.
Everything seems fine, so you push. However once the pipeline is run in gitlab, you're notified that it failed due to php
cs errors.
In this case it's likely that you have to update your version of php-cs-fixer.
php-cs-fixer is installed when building the docker image: https://gitea.champs-libres.be/Chill-project/chill-skeleton-basic/src/branch/main/Dockerfile#L50
Consequently, to update php-cs-fixer we have to update the image by building it again.
For this the following commands can be used,
.. code-block:: php
docker compose build --pull php
# replace existing containers
docker compose up -d --force-recreate php

View File

@ -9,7 +9,7 @@
Development Development
########### ###########
As Chill rely on the `symfony <http://symfony.com>`_ framework, reading the framework's documentation should answer most of your questions. We are explaining here some tips to work with Chill, and things we provide to encounter our needs. As Chill relies on the `symfony <http://symfony.com>`_ framework, reading the framework's documentation should answer most of your questions. We are explaining here some tips to work with Chill, and help with things we've encountered.
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
@ -37,6 +37,7 @@ As Chill rely on the `symfony <http://symfony.com>`_ framework, reading the fram
Cron Jobs <cronjob.rst> Cron Jobs <cronjob.rst>
Info about entities <entity-info.rst> Info about entities <entity-info.rst>
Info about database (in French) <database-principles.rst> Info about database (in French) <database-principles.rst>
Developer FAQ <FAQ.rst>
Layout and UI Layout and UI
************** **************

View File

@ -9,7 +9,7 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Export\Aggregator\ACPAggregators; namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\AggregatorInterface; use Chill\MainBundle\Export\AggregatorInterface;
@ -35,7 +35,7 @@ class ByCreatorAggregator implements AggregatorInterface
public function applyOn(): string public function applyOn(): string
{ {
return Declarations::ACTIVITY_ACP; return Declarations::ACTIVITY;
} }
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder)

View File

@ -9,7 +9,7 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Export\Aggregator\ACPAggregators; namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\AggregatorInterface; use Chill\MainBundle\Export\AggregatorInterface;
@ -40,7 +40,7 @@ class ByThirdpartyAggregator implements AggregatorInterface
public function applyOn(): string public function applyOn(): string
{ {
return Declarations::ACTIVITY_ACP; return Declarations::ACTIVITY;
} }
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder)

View File

@ -9,7 +9,7 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Export\Aggregator\ACPAggregators; namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\AggregatorInterface; use Chill\MainBundle\Export\AggregatorInterface;
@ -40,7 +40,7 @@ class CreatorScopeAggregator implements AggregatorInterface
public function applyOn(): string public function applyOn(): string
{ {
return Declarations::ACTIVITY_ACP; return Declarations::ACTIVITY;
} }
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder)

View File

@ -9,7 +9,7 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Export\Aggregator\ACPAggregators; namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\AggregatorInterface; use Chill\MainBundle\Export\AggregatorInterface;
@ -66,7 +66,7 @@ class DateAggregator implements AggregatorInterface
public function applyOn(): string public function applyOn(): string
{ {
return Declarations::ACTIVITY_ACP; return Declarations::ACTIVITY;
} }
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder)

View File

@ -9,7 +9,7 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Export\Aggregator\ACPAggregators; namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\AggregatorInterface; use Chill\MainBundle\Export\AggregatorInterface;
@ -40,7 +40,7 @@ class LocationTypeAggregator implements AggregatorInterface
public function applyOn(): string public function applyOn(): string
{ {
return Declarations::ACTIVITY_ACP; return Declarations::ACTIVITY;
} }
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder)

View File

@ -12,6 +12,7 @@ declare(strict_types=1);
namespace Chill\ActivityBundle\Export\Export\LinkedToACP; namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Export\Export\ListActivityHelper; use Chill\ActivityBundle\Export\Export\ListActivityHelper;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter; use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\Scope;
@ -141,6 +142,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
return array_merge( return array_merge(
$this->helper->supportsModifiers(), $this->helper->supportsModifiers(),
[ [
Declarations::ACTIVITY,
\Chill\PersonBundle\Export\Declarations::ACP_TYPE, \Chill\PersonBundle\Export\Declarations::ACP_TYPE,
] ]
); );

View File

@ -281,7 +281,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
return [ return [
Declarations::ACTIVITY, Declarations::ACTIVITY,
Declarations::ACTIVITY_PERSON, Declarations::ACTIVITY_PERSON,
//PersonDeclarations::PERSON_TYPE, PersonDeclarations::PERSON_TYPE,
]; ];
} }
} }

View File

@ -148,7 +148,7 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
return [ return [
Declarations::ACTIVITY, Declarations::ACTIVITY,
Declarations::ACTIVITY_PERSON, Declarations::ACTIVITY_PERSON,
//PersonDeclarations::PERSON_TYPE, PersonDeclarations::PERSON_TYPE,
]; ];
} }
} }

View File

@ -23,7 +23,10 @@ use Symfony\Component\Form\FormBuilderInterface;
class ActivityTypeFilter implements FilterInterface class ActivityTypeFilter implements FilterInterface
{ {
public function __construct(private readonly ActivityTypeRepositoryInterface $activityTypeRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper) {} public function __construct(
private readonly ActivityTypeRepositoryInterface $activityTypeRepository,
private readonly TranslatableStringHelperInterface $translatableStringHelper
) {}
public function addRole(): ?string public function addRole(): ?string
{ {
@ -71,7 +74,7 @@ class ActivityTypeFilter implements FilterInterface
$types[] = $this->translatableStringHelper->localize($aty->getName()); $types[] = $this->translatableStringHelper->localize($aty->getName());
} }
return ['Filtered by activity types: only %activitytypes%', [ return ['export.filter.activity.acp_by_activity_type.acp_containing_at_least_one_%activitytypes%', [
'%activitytypes%' => implode(', ', $types), '%activitytypes%' => implode(', ', $types),
]]; ]];
} }

View File

@ -17,6 +17,9 @@ use Chill\PersonBundle\Export\Declarations;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
/**
* Filter accompanying periods to keep only the one without any activity
*/
class HasNoActivityFilter implements FilterInterface class HasNoActivityFilter implements FilterInterface
{ {
public function addRole(): ?string public function addRole(): ?string

View File

@ -9,7 +9,7 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Export\Filter\ACPFilters; namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Export\FilterInterface;
@ -38,7 +38,7 @@ class ByCreatorFilter implements FilterInterface
public function applyOn(): string public function applyOn(): string
{ {
return Declarations::ACTIVITY_ACP; return Declarations::ACTIVITY;
} }
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder)

View File

@ -9,7 +9,7 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Export\Filter\ACPFilters; namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Export\FilterInterface;
@ -53,7 +53,7 @@ class EmergencyFilter implements FilterInterface
public function applyOn(): string public function applyOn(): string
{ {
return Declarations::ACTIVITY_ACP; return Declarations::ACTIVITY;
} }
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder)

View File

@ -9,7 +9,7 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Export\Filter\ACPFilters; namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Export\FilterInterface;
@ -36,7 +36,7 @@ class LocationFilter implements FilterInterface
public function applyOn(): string public function applyOn(): string
{ {
return Declarations::ACTIVITY_ACP; return Declarations::ACTIVITY;
} }
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder)

View File

@ -9,7 +9,7 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Export\Filter\ACPFilters; namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Export\FilterInterface;
@ -50,7 +50,7 @@ class LocationTypeFilter implements FilterInterface
public function applyOn(): string public function applyOn(): string
{ {
return Declarations::ACTIVITY_ACP; return Declarations::ACTIVITY;
} }
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder)

View File

@ -9,7 +9,7 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Export\Filter\ACPFilters; namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
@ -54,7 +54,7 @@ class SentReceivedFilter implements FilterInterface
public function applyOn(): string public function applyOn(): string
{ {
return Declarations::ACTIVITY_ACP; return Declarations::ACTIVITY;
} }
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder)

View File

@ -9,7 +9,7 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Export\Filter\ACPFilters; namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Export\FilterInterface;
@ -46,7 +46,7 @@ class UserFilter implements FilterInterface
public function applyOn(): string public function applyOn(): string
{ {
return Declarations::ACTIVITY_ACP; return Declarations::ACTIVITY;
} }
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder)

View File

@ -9,7 +9,7 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Export\Filter\ACPFilters; namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Export\Declarations; use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\Scope;
@ -52,7 +52,7 @@ class UserScopeFilter implements FilterInterface
public function applyOn(): string public function applyOn(): string
{ {
return Declarations::ACTIVITY_ACP; return Declarations::ACTIVITY;
} }
public function buildForm(FormBuilderInterface $builder) public function buildForm(FormBuilderInterface $builder)

View File

@ -12,7 +12,7 @@ declare(strict_types=1);
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators; namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\BySocialActionAggregator; use Chill\ActivityBundle\Export\Aggregator\BySocialActionAggregator;
use Chill\MainBundle\Test\Export\AbstractAggregatorTest; use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;

View File

@ -12,7 +12,7 @@ declare(strict_types=1);
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators; namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\BySocialIssueAggregator; use Chill\ActivityBundle\Export\Aggregator\BySocialIssueAggregator;
use Chill\MainBundle\Test\Export\AbstractAggregatorTest; use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;

View File

@ -9,10 +9,10 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators; namespace Chill\ActivityBundle\Tests\Export\Aggregator;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\ByThirdpartyAggregator; use Chill\ActivityBundle\Export\Aggregator\ByThirdpartyAggregator;
use Chill\MainBundle\Test\Export\AbstractAggregatorTest; use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
@ -28,7 +28,7 @@ final class ByThirdpartyAggregatorTest extends AbstractAggregatorTest
{ {
self::bootKernel(); self::bootKernel();
$this->aggregator = self::$container->get('chill.activity.export.bythirdparty_aggregator'); $this->aggregator = self::$container->get(ByThirdpartyAggregator::class);
} }
public function getAggregator() public function getAggregator()

View File

@ -9,10 +9,10 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators; namespace Chill\ActivityBundle\Tests\Export\Aggregator;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\ByCreatorAggregator; use Chill\ActivityBundle\Export\Aggregator\ByCreatorAggregator;
use Chill\MainBundle\Test\Export\AbstractAggregatorTest; use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;

View File

@ -9,10 +9,10 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators; namespace Chill\ActivityBundle\Tests\Export\Aggregator;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\CreatorScopeAggregator; use Chill\ActivityBundle\Export\Aggregator\CreatorScopeAggregator;
use Chill\MainBundle\Test\Export\AbstractAggregatorTest; use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
@ -20,7 +20,7 @@ use Doctrine\ORM\EntityManagerInterface;
* @internal * @internal
* @coversNothing * @coversNothing
*/ */
final class UserScopeAggregatorTest extends AbstractAggregatorTest final class CreatorScopeAggregatorTest extends AbstractAggregatorTest
{ {
private CreatorScopeAggregator $aggregator; private CreatorScopeAggregator $aggregator;

View File

@ -9,10 +9,10 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators; namespace Chill\ActivityBundle\Tests\Export\Aggregator;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\DateAggregator; use Chill\ActivityBundle\Export\Aggregator\DateAggregator;
use Chill\MainBundle\Test\Export\AbstractAggregatorTest; use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
@ -28,7 +28,7 @@ final class DateAggregatorTest extends AbstractAggregatorTest
{ {
self::bootKernel(); self::bootKernel();
$this->aggregator = self::$container->get('chill.activity.export.date_aggregator'); $this->aggregator = self::$container->get(DateAggregator::class);
} }
public function getAggregator() public function getAggregator()

View File

@ -9,10 +9,10 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators; namespace Chill\ActivityBundle\Tests\Export\Aggregator;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\LocationTypeAggregator; use Chill\ActivityBundle\Export\Aggregator\LocationTypeAggregator;
use Chill\MainBundle\Test\Export\AbstractAggregatorTest; use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
@ -28,7 +28,7 @@ final class LocationTypeAggregatorTest extends AbstractAggregatorTest
{ {
self::bootKernel(); self::bootKernel();
$this->aggregator = self::$container->get('chill.activity.export.locationtype_aggregator'); $this->aggregator = self::$container->get(LocationTypeAggregator::class);
} }
public function getAggregator() public function getAggregator()

View File

@ -13,9 +13,10 @@ namespace Chill\ActivityBundle\Tests\Export\Filter\ACPFilters;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Entity\ActivityType; use Chill\ActivityBundle\Entity\ActivityType;
use Chill\ActivityBundle\Export\Filter\ACPFilters\ActivityTypeFilter; use Chill\ActivityBundle\Export\Filter\ActivityTypeFilter;
use Chill\MainBundle\Test\Export\AbstractFilterTest; use Chill\MainBundle\Test\Export\AbstractFilterTest;
use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query\Expr; use Doctrine\ORM\Query\Expr;
@ -25,13 +26,13 @@ use Doctrine\ORM\Query\Expr;
*/ */
final class ActivityTypeFilterTest extends AbstractFilterTest final class ActivityTypeFilterTest extends AbstractFilterTest
{ {
private ActivityTypeFilter $filter; private \Chill\ActivityBundle\Export\Filter\ACPFilters\ActivityTypeFilter $filter;
protected function setUp(): void protected function setUp(): void
{ {
self::bootKernel(); self::bootKernel();
$this->filter = self::$container->get('chill.activity.export.filter_activitytype'); $this->filter = self::$container->get(\Chill\ActivityBundle\Export\Filter\ACPFilters\ActivityTypeFilter::class);
} }
public function getFilter() public function getFilter()
@ -48,13 +49,14 @@ final class ActivityTypeFilterTest extends AbstractFilterTest
->from(ActivityType::class, 'at') ->from(ActivityType::class, 'at')
->select('at') ->select('at')
->getQuery() ->getQuery()
->setMaxResults(1)
->getResult(); ->getResult();
$data = []; $data = [];
foreach ($array as $a) { foreach ($array as $a) {
$data[] = [ $data[] = [
'accepted_activitytypes' => $a, 'accepted_activitytypes' => new ArrayCollection([$a]),
]; ];
} }

View File

@ -12,8 +12,7 @@ declare(strict_types=1);
namespace Chill\ActivityBundle\Tests\Export\Filter\ACPFilters; namespace Chill\ActivityBundle\Tests\Export\Filter\ACPFilters;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Filter\ACPFilters\ByCreatorFilter; use Chill\ActivityBundle\Export\Filter\ByCreatorFilter;
use Chill\ActivityBundle\Export\Filter\ACPFilters\UserFilter;
use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Test\Export\AbstractFilterTest; use Chill\MainBundle\Test\Export\AbstractFilterTest;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;

View File

@ -12,7 +12,6 @@ declare(strict_types=1);
namespace Chill\ActivityBundle\Tests\Export\Filter\ACPFilters; namespace Chill\ActivityBundle\Tests\Export\Filter\ACPFilters;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Filter\ACPFilters\BySocialActionFilter;
use Chill\MainBundle\Test\Export\AbstractFilterTest; use Chill\MainBundle\Test\Export\AbstractFilterTest;
use Chill\PersonBundle\Entity\SocialWork\SocialAction; use Chill\PersonBundle\Entity\SocialWork\SocialAction;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
@ -24,13 +23,13 @@ use Doctrine\ORM\EntityManagerInterface;
*/ */
final class BySocialActionFilterTest extends AbstractFilterTest final class BySocialActionFilterTest extends AbstractFilterTest
{ {
private BySocialActionFilter $filter; private \Chill\ActivityBundle\Export\Filter\ACPFilters\BySocialActionFilter $filter;
protected function setUp(): void protected function setUp(): void
{ {
self::bootKernel(); self::bootKernel();
$this->filter = self::$container->get('chill.activity.export.bysocialaction_filter'); $this->filter = self::$container->get(\Chill\ActivityBundle\Export\Filter\ACPFilters\BySocialActionFilter::class);
} }
public function getFilter() public function getFilter()
@ -48,7 +47,6 @@ final class BySocialActionFilterTest extends AbstractFilterTest
->from(SocialAction::class, 'sa') ->from(SocialAction::class, 'sa')
->select('sa') ->select('sa')
->getQuery() ->getQuery()
->setMaxResults(4)
->getResult(); ->getResult();
$data = []; $data = [];

View File

@ -15,6 +15,7 @@ use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Filter\ACPFilters\BySocialIssueFilter; use Chill\ActivityBundle\Export\Filter\ACPFilters\BySocialIssueFilter;
use Chill\MainBundle\Test\Export\AbstractFilterTest; use Chill\MainBundle\Test\Export\AbstractFilterTest;
use Chill\PersonBundle\Entity\SocialWork\SocialIssue; use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
/** /**
@ -29,7 +30,7 @@ final class BySocialIssueFilterTest extends AbstractFilterTest
{ {
self::bootKernel(); self::bootKernel();
$this->filter = self::$container->get('chill.activity.export.bysocialissue_filter'); $this->filter = self::$container->get(BySocialIssueFilter::class);
} }
public function getFilter() public function getFilter()
@ -39,19 +40,21 @@ final class BySocialIssueFilterTest extends AbstractFilterTest
public function getFormData(): array public function getFormData(): array
{ {
self::bootKernel();
$em = self::$container->get(EntityManagerInterface::class); $em = self::$container->get(EntityManagerInterface::class);
$array = $em->createQueryBuilder() $array = $em->createQueryBuilder()
->from(SocialIssue::class, 'si') ->from(SocialIssue::class, 'si')
->select('si') ->select('si')
->getQuery() ->getQuery()
->setMaxResults(2)
->getResult(); ->getResult();
$data = []; $data = [];
foreach ($array as $a) { foreach ($array as $a) {
$data[] = [ $data[] = [
'accepted_socialissues' => $a, 'accepted_socialissues' => new ArrayCollection([$a]),
]; ];
} }

View File

@ -30,7 +30,7 @@ final class ActivityDateFilterTest extends AbstractFilterTest
{ {
self::bootKernel(); self::bootKernel();
$this->filter = self::$container->get('chill.activity.export.date_filter'); $this->filter = self::$container->get(ActivityDateFilter::class);
} }
public function getFilter() public function getFilter()

View File

@ -0,0 +1,76 @@
<?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\Filter;
use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Filter\ByCreatorFilter;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Test\Export\AbstractFilterTest;
use Doctrine\ORM\EntityManagerInterface;
/**
* @internal
* @coversNothing
*/
final class ByCreatorFilterTest extends AbstractFilterTest
{
private ByCreatorFilter $filter;
protected function setUp(): void
{
self::bootKernel();
$this->filter = self::$container->get(ByCreatorFilter::class);
}
public function getFilter()
{
return $this->filter;
}
public function getFormData(): array
{
$em = self::$container->get(EntityManagerInterface::class);
$array = $em->createQueryBuilder()
->from(User::class, 'u')
->select('u')
->getQuery()
->getResult();
$data = [];
foreach ($array as $a) {
$data[] = [
'accepted_users' => $a,
];
}
return $data;
}
public function getQueryBuilders(): array
{
if (null === self::$kernel) {
self::bootKernel();
}
$em = self::$container->get(EntityManagerInterface::class);
return [
$em->createQueryBuilder()
->select('count(activity.id)')
->from(Activity::class, 'activity')
->join('activity.users', 'actusers'),
];
}
}

View File

@ -9,10 +9,10 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Tests\Export\Filter\ACPFilters; namespace Chill\ActivityBundle\Tests\Export\Filter;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Filter\ACPFilters\EmergencyFilter; use Chill\ActivityBundle\Export\Filter\EmergencyFilter;
use Chill\MainBundle\Test\Export\AbstractFilterTest; use Chill\MainBundle\Test\Export\AbstractFilterTest;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
@ -28,7 +28,7 @@ final class EmergencyFilterTest extends AbstractFilterTest
{ {
self::bootKernel(); self::bootKernel();
$this->filter = self::$container->get('chill.activity.export.emergency_filter'); $this->filter = self::$container->get(EmergencyFilter::class);
} }
public function getFilter() public function getFilter()

View File

@ -9,10 +9,10 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Tests\Export\Filter\ACPFilters; namespace Chill\ActivityBundle\Tests\Export\Filter;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Filter\ACPFilters\LocationTypeFilter; use Chill\ActivityBundle\Export\Filter\LocationTypeFilter;
use Chill\MainBundle\Entity\LocationType; use Chill\MainBundle\Entity\LocationType;
use Chill\MainBundle\Test\Export\AbstractFilterTest; use Chill\MainBundle\Test\Export\AbstractFilterTest;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
@ -29,7 +29,7 @@ final class LocationTypeFilterTest extends AbstractFilterTest
{ {
self::bootKernel(); self::bootKernel();
$this->filter = self::$container->get('chill.activity.export.locationtype_filter'); $this->filter = self::$container->get(LocationTypeFilter::class);
} }
public function getFilter() public function getFilter()

View File

@ -56,7 +56,7 @@ final class PersonHavingActivityBetweenDateFilterTest extends AbstractFilterTest
$data[] = [ $data[] = [
'date_from' => DateTime::createFromFormat('Y-m-d', '2021-07-01'), 'date_from' => DateTime::createFromFormat('Y-m-d', '2021-07-01'),
'date_to' => DateTime::createFromFormat('Y-m-d', '2022-07-01'), 'date_to' => DateTime::createFromFormat('Y-m-d', '2022-07-01'),
'reasons' => $a, 'reasons' => [$a],
]; ];
} }
@ -74,7 +74,9 @@ final class PersonHavingActivityBetweenDateFilterTest extends AbstractFilterTest
return [ return [
$em->createQueryBuilder() $em->createQueryBuilder()
->select('count(activity.id)') ->select('count(activity.id)')
->from(Activity::class, 'activity'), ->from(Activity::class, 'activity')
->join('activity.person', 'person')
,
]; ];
} }
} }

View File

@ -9,10 +9,10 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Tests\Export\Filter\ACPFilters; namespace Chill\ActivityBundle\Tests\Export\Filter;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Filter\ACPFilters\SentReceivedFilter; use Chill\ActivityBundle\Export\Filter\SentReceivedFilter;
use Chill\MainBundle\Test\Export\AbstractFilterTest; use Chill\MainBundle\Test\Export\AbstractFilterTest;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
@ -28,7 +28,7 @@ final class SentReceivedFilterTest extends AbstractFilterTest
{ {
self::bootKernel(); self::bootKernel();
$this->filter = self::$container->get('chill.activity.export.sentreceived_filter'); $this->filter = self::$container->get(SentReceivedFilter::class);
} }
public function getFilter() public function getFilter()

View File

@ -9,10 +9,10 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Tests\Export\Filter\ACPFilters; namespace Chill\ActivityBundle\Tests\Export\Filter;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Filter\ACPFilters\UserFilter; use Chill\ActivityBundle\Export\Filter\UserFilter;
use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Test\Export\AbstractFilterTest; use Chill\MainBundle\Test\Export\AbstractFilterTest;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
@ -29,7 +29,7 @@ final class UserFilterTest extends AbstractFilterTest
{ {
self::bootKernel(); self::bootKernel();
$this->filter = self::$container->get('chill.activity.export.user_filter'); $this->filter = self::$container->get(UserFilter::class);
} }
public function getFilter() public function getFilter()

View File

@ -9,10 +9,10 @@ declare(strict_types=1);
* the LICENSE file that was distributed with this source code. * the LICENSE file that was distributed with this source code.
*/ */
namespace Chill\ActivityBundle\Tests\Export\Filter\ACPFilters; namespace Chill\ActivityBundle\Tests\Export\Filter;
use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Filter\ACPFilters\UserScopeFilter; use Chill\ActivityBundle\Export\Filter\UserScopeFilter;
use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Test\Export\AbstractFilterTest; use Chill\MainBundle\Test\Export\AbstractFilterTest;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
@ -29,7 +29,7 @@ final class UserScopeFilterTest extends AbstractFilterTest
{ {
self::bootKernel(); self::bootKernel();
$this->filter = self::$container->get('chill.activity.export.userscope_filter'); $this->filter = self::$container->get(UserScopeFilter::class);
} }
public function getFilter() public function getFilter()

View File

@ -53,8 +53,7 @@ services:
tags: tags:
- { name: chill.export_filter, alias: 'activity_type_filter' } - { name: chill.export_filter, alias: 'activity_type_filter' }
chill.activity.export.date_filter: Chill\ActivityBundle\Export\Filter\ActivityDateFilter:
class: Chill\ActivityBundle\Export\Filter\ActivityDateFilter
tags: tags:
- { name: chill.export_filter, alias: 'activity_date_filter' } - { name: chill.export_filter, alias: 'activity_date_filter' }
@ -74,52 +73,43 @@ services:
name: chill.export_filter name: chill.export_filter
alias: 'activity_person_having_ac_bw_date_filter' alias: 'activity_person_having_ac_bw_date_filter'
chill.activity.export.filter_activitytype: Chill\ActivityBundle\Export\Filter\ACPFilters\ActivityTypeFilter:
class: Chill\ActivityBundle\Export\Filter\ACPFilters\ActivityTypeFilter
tags: tags:
- { name: chill.export_filter, alias: 'accompanyingcourse_activitytype_filter' } - { name: chill.export_filter, alias: 'accompanyingcourse_activitytype_filter' }
chill.activity.export.location_filter: Chill\ActivityBundle\Export\Filter\LocationFilter:
class: Chill\ActivityBundle\Export\Filter\ACPFilters\LocationFilter
tags: tags:
- { name: chill.export_filter, alias: 'activity_location_filter' } - { name: chill.export_filter, alias: 'activity_location_filter' }
chill.activity.export.locationtype_filter: Chill\ActivityBundle\Export\Filter\LocationTypeFilter:
class: Chill\ActivityBundle\Export\Filter\ACPFilters\LocationTypeFilter
tags: tags:
- { name: chill.export_filter, alias: 'activity_locationtype_filter' } - { name: chill.export_filter, alias: 'activity_locationtype_filter' }
Chill\ActivityBundle\Export\Filter\ACPFilters\ByCreatorFilter: Chill\ActivityBundle\Export\Filter\ByCreatorFilter:
tags: tags:
- { name: chill.export_filter, alias: 'activity_bycreator_filter' } - { name: chill.export_filter, alias: 'activity_bycreator_filter' }
chill.activity.export.emergency_filter: Chill\ActivityBundle\Export\Filter\EmergencyFilter:
class: Chill\ActivityBundle\Export\Filter\ACPFilters\EmergencyFilter
tags: tags:
- { name: chill.export_filter, alias: 'activity_emergency_filter' } - { name: chill.export_filter, alias: 'activity_emergency_filter' }
chill.activity.export.sentreceived_filter: Chill\ActivityBundle\Export\Filter\SentReceivedFilter:
class: Chill\ActivityBundle\Export\Filter\ACPFilters\SentReceivedFilter
tags: tags:
- { name: chill.export_filter, alias: 'activity_sentreceived_filter' } - { name: chill.export_filter, alias: 'activity_sentreceived_filter' }
chill.activity.export.bysocialaction_filter: Chill\ActivityBundle\Export\Filter\ACPFilters\BySocialActionFilter:
class: Chill\ActivityBundle\Export\Filter\ACPFilters\BySocialActionFilter
tags: tags:
- { name: chill.export_filter, alias: 'activity_bysocialaction_filter' } - { name: chill.export_filter, alias: 'activity_bysocialaction_filter' }
chill.activity.export.bysocialissue_filter: Chill\ActivityBundle\Export\Filter\ACPFilters\BySocialIssueFilter:
class: Chill\ActivityBundle\Export\Filter\ACPFilters\BySocialIssueFilter
tags: tags:
- { name: chill.export_filter, alias: 'activity_bysocialissue_filter' } - { name: chill.export_filter, alias: 'activity_bysocialissue_filter' }
chill.activity.export.user_filter: # Creator (M2O) Chill\ActivityBundle\Export\Filter\UserFilter:
class: Chill\ActivityBundle\Export\Filter\ACPFilters\UserFilter
tags: tags:
- { name: chill.export_filter, alias: 'activity_user_filter' } - { name: chill.export_filter, alias: 'activity_user_filter' }
chill.activity.export.userscope_filter: Chill\ActivityBundle\Export\Filter\UserScopeFilter:
class: Chill\ActivityBundle\Export\Filter\ACPFilters\UserScopeFilter
tags: tags:
- { name: chill.export_filter, alias: 'activity_userscope_filter' } - { name: chill.export_filter, alias: 'activity_userscope_filter' }
@ -157,22 +147,19 @@ services:
tags: tags:
- { name: chill.export_aggregator, alias: activity_user_aggregator } - { name: chill.export_aggregator, alias: activity_user_aggregator }
chill.activity.export.locationtype_aggregator: Chill\ActivityBundle\Export\Aggregator\LocationTypeAggregator:
class: Chill\ActivityBundle\Export\Aggregator\ACPAggregators\LocationTypeAggregator
tags: tags:
- { name: chill.export_aggregator, alias: activity_locationtype_aggregator } - { name: chill.export_aggregator, alias: activity_locationtype_aggregator }
chill.activity.export.date_aggregator: Chill\ActivityBundle\Export\Aggregator\DateAggregator:
class: Chill\ActivityBundle\Export\Aggregator\ACPAggregators\DateAggregator
tags: tags:
- { name: chill.export_aggregator, alias: activity_date_aggregator } - { name: chill.export_aggregator, alias: activity_date_aggregator }
Chill\ActivityBundle\Export\Aggregator\ACPAggregators\ByCreatorAggregator: Chill\ActivityBundle\Export\Aggregator\ByCreatorAggregator:
tags: tags:
- { name: chill.export_aggregator, alias: activity_by_creator_aggregator } - { name: chill.export_aggregator, alias: activity_by_creator_aggregator }
chill.activity.export.bythirdparty_aggregator: Chill\ActivityBundle\Export\Aggregator\ByThirdpartyAggregator:
class: Chill\ActivityBundle\Export\Aggregator\ACPAggregators\ByThirdpartyAggregator
tags: tags:
- { name: chill.export_aggregator, alias: activity_bythirdparty_aggregator } - { name: chill.export_aggregator, alias: activity_bythirdparty_aggregator }
@ -186,7 +173,7 @@ services:
tags: tags:
- { name: chill.export_aggregator, alias: activity_bysocialissue_aggregator } - { name: chill.export_aggregator, alias: activity_bysocialissue_aggregator }
Chill\ActivityBundle\Export\Aggregator\ACPAggregators\CreatorScopeAggregator: Chill\ActivityBundle\Export\Aggregator\CreatorScopeAggregator:
tags: tags:
- { name: chill.export_aggregator, alias: activity_creator_scope_aggregator } - { name: chill.export_aggregator, alias: activity_creator_scope_aggregator }

View File

@ -377,6 +377,8 @@ export:
Title: Filtre les parcours ayant reçu un échange entre deux dates Title: Filtre les parcours ayant reçu un échange entre deux dates
Receiving an activity after: Ayant reçu un échange après le Receiving an activity after: Ayant reçu un échange après le
Receiving an activity before: Ayant reçu un échange avant le Receiving an activity before: Ayant reçu un échange avant le
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%'
aggregator: aggregator:

View File

@ -26,6 +26,7 @@ class AvgAsideActivityDuration implements ExportInterface, GroupedExportInterfac
public function __construct(private readonly AsideActivityRepository $repository) {} public function __construct(private readonly AsideActivityRepository $repository) {}
public function buildForm(FormBuilderInterface $builder) {} public function buildForm(FormBuilderInterface $builder) {}
public function getFormDefaultData(): array public function getFormDefaultData(): array
{ {
return []; return [];

View File

@ -28,6 +28,13 @@ class AccompanyingCourseDocument extends Document implements HasScopesInterface,
*/ */
private ?AccompanyingPeriod $course = null; private ?AccompanyingPeriod $course = null;
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private ?int $id = null;
public function getCenters(): ?iterable public function getCenters(): ?iterable
{ {
return $this->course->getCenters(); return $this->course->getCenters();
@ -38,6 +45,11 @@ class AccompanyingCourseDocument extends Document implements HasScopesInterface,
return $this->course; return $this->course;
} }
public function getId()
{
return $this->id;
}
public function getScopes(): iterable public function getScopes(): iterable
{ {
if (null === $this->course) { if (null === $this->course) {
@ -53,4 +65,5 @@ class AccompanyingCourseDocument extends Document implements HasScopesInterface,
return $this; return $this;
} }
} }

View File

@ -49,13 +49,6 @@ class Document implements TrackCreationInterface, TrackUpdateInterface
*/ */
private string $description = ''; private string $description = '';
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private ?int $id = null;
/** /**
* @ORM\ManyToOne( * @ORM\ManyToOne(
* targetEntity="Chill\DocStoreBundle\Entity\StoredObject", * targetEntity="Chill\DocStoreBundle\Entity\StoredObject",
@ -101,11 +94,6 @@ class Document implements TrackCreationInterface, TrackUpdateInterface
return $this->description; return $this->description;
} }
public function getId()
{
return $this->id;
}
public function getObject(): ?StoredObject public function getObject(): ?StoredObject
{ {
return $this->object; return $this->object;

View File

@ -23,6 +23,13 @@ use Doctrine\ORM\Mapping as ORM;
*/ */
class PersonDocument extends Document implements HasCenterInterface, HasScopeInterface class PersonDocument extends Document implements HasCenterInterface, HasScopeInterface
{ {
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private ?int $id = null;
/** /**
* @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\Person") * @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\Person")
*/ */
@ -40,6 +47,11 @@ class PersonDocument extends Document implements HasCenterInterface, HasScopeInt
return $this->getPerson()->getCenter(); return $this->getPerson()->getCenter();
} }
public function getId()
{
return $this->id;
}
public function getPerson(): Person public function getPerson(): Person
{ {
return $this->person; return $this->person;

View File

@ -474,7 +474,7 @@ class CRUDController extends AbstractController
* 6. Launch rendering, the parameter is fetch using `getTemplateFor` * 6. Launch rendering, the parameter is fetch using `getTemplateFor`
* The parameters may be personnalized using `generateTemplateParameter`. * The parameters may be personnalized using `generateTemplateParameter`.
* *
* @param string $formClass * @param class-string $formClass
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
*/ */
protected function formEditAction(string $action, Request $request, mixed $id, ?string $formClass = null, array $formOptions = []): Response protected function formEditAction(string $action, Request $request, mixed $id, ?string $formClass = null, array $formOptions = []): Response

View File

@ -11,177 +11,19 @@ declare(strict_types=1);
namespace Chill\MainBundle\Controller; namespace Chill\MainBundle\Controller;
use Chill\MainBundle\Entity\Center; use Chill\MainBundle\CRUD\Controller\CRUDController;
use Chill\MainBundle\Form\CenterType; use Chill\MainBundle\Pagination\PaginatorInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
/** /**
* Class CenterController. * Class CenterController.
*/ */
class CenterController extends AbstractController class CenterController extends CRUDController
{ {
/** protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
* Creates a new Center entity.
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/center/create", name="admin_center_create", methods={"POST"})
*/
public function createAction(Request $request)
{ {
$center = new Center(); $query->addOrderBy('e.name', 'ASC');
$form = $this->createCreateForm($center);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { return parent::orderQuery($action, $query, $request, $paginator);
$em = $this->getDoctrine()->getManager();
$em->persist($center);
$em->flush();
return $this->redirectToRoute('admin_center');
}
return $this->render('@ChillMain/Center/new.html.twig', [
'entity' => $center,
'form' => $form->createView(),
]);
}
/**
* Displays a form to edit an existing Center entity.
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/center/{id}/edit", name="admin_center_edit")
*/
public function editAction(mixed $id)
{
$em = $this->getDoctrine()->getManager();
$center = $em->getRepository(\Chill\MainBundle\Entity\Center::class)->find($id);
if (!$center) {
throw $this->createNotFoundException('Unable to find Center entity.');
}
$editForm = $this->createEditForm($center);
return $this->render('@ChillMain/Center/edit.html.twig', [
'entity' => $center,
'edit_form' => $editForm->createView(),
]);
}
/**
* Lists all Center entities.
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/center/", name="admin_center")
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository(\Chill\MainBundle\Entity\Center::class)->findAll();
usort($entities, fn (Center $a, Center $b) => $a->getName() <=> $b->getName());
return $this->render('@ChillMain/Center/index.html.twig', [
'entities' => $entities,
]);
}
/**
* Displays a form to create a new Center entity.
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/center/new", name="admin_center_new")
*/
public function newAction()
{
$center = new Center();
$form = $this->createCreateForm($center);
return $this->render('@ChillMain/Center/new.html.twig', [
'entity' => $center,
'form' => $form->createView(),
]);
}
/**
* Finds and displays a Center entity.
*/
public function showAction(mixed $id)
{
$em = $this->getDoctrine()->getManager();
$center = $em->getRepository(\Chill\MainBundle\Entity\Center::class)->find($id);
if (!$center) {
throw $this->createNotFoundException('Unable to find Center entity.');
}
return $this->render('@ChillMain/Center/show.html.twig', [
'entity' => $center,
]);
}
/**
* Edits an existing Center entity.
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/center/{id}/update", name="admin_center_update", methods={"POST", "PUT"})
*/
public function updateAction(Request $request, mixed $id)
{
$em = $this->getDoctrine()->getManager();
$center = $em->getRepository(\Chill\MainBundle\Entity\Center::class)->find($id);
if (!$center) {
throw $this->createNotFoundException('Unable to find Center entity.');
}
$editForm = $this->createEditForm($center);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$em->flush();
return $this->redirectToRoute('admin_center_edit', ['id' => $id]);
}
return $this->render('@ChillMain/Center/edit.html.twig', [
'entity' => $center,
'edit_form' => $editForm->createView(),
]);
}
/**
* Creates a form to create a Center entity.
*
* @param Center $center The entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createCreateForm(Center $center)
{
$form = $this->createForm(CenterType::class, $center, [
'action' => $this->generateUrl('admin_center_create'),
'method' => 'POST',
]);
$form->add('submit', SubmitType::class, ['label' => 'Create']);
return $form;
}
/**
* Creates a form to edit a Center entity.
*
* @param Center $center The entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createEditForm(Center $center)
{
$form = $this->createForm(CenterType::class, $center, [
'action' => $this->generateUrl('admin_center_update', ['id' => $center->getId()]),
'method' => 'PUT',
]);
$form->add('submit', SubmitType::class, ['label' => 'Update']);
return $form;
} }
} }

View File

@ -12,6 +12,7 @@ declare(strict_types=1);
namespace Chill\MainBundle\DependencyInjection; namespace Chill\MainBundle\DependencyInjection;
use Chill\MainBundle\Controller\AddressApiController; use Chill\MainBundle\Controller\AddressApiController;
use Chill\MainBundle\Controller\CenterController;
use Chill\MainBundle\Controller\CivilityApiController; use Chill\MainBundle\Controller\CivilityApiController;
use Chill\MainBundle\Controller\CivilityController; use Chill\MainBundle\Controller\CivilityController;
use Chill\MainBundle\Controller\CountryController; use Chill\MainBundle\Controller\CountryController;
@ -44,6 +45,7 @@ use Chill\MainBundle\Doctrine\DQL\Unaccent;
use Chill\MainBundle\Doctrine\ORM\Hydration\FlatHierarchyEntityHydrator; use Chill\MainBundle\Doctrine\ORM\Hydration\FlatHierarchyEntityHydrator;
use Chill\MainBundle\Doctrine\Type\NativeDateIntervalType; use Chill\MainBundle\Doctrine\Type\NativeDateIntervalType;
use Chill\MainBundle\Doctrine\Type\PointType; use Chill\MainBundle\Doctrine\Type\PointType;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\Civility; use Chill\MainBundle\Entity\Civility;
use Chill\MainBundle\Entity\Country; use Chill\MainBundle\Entity\Country;
use Chill\MainBundle\Entity\GeographicalUnitLayer; use Chill\MainBundle\Entity\GeographicalUnitLayer;
@ -53,6 +55,7 @@ use Chill\MainBundle\Entity\LocationType;
use Chill\MainBundle\Entity\Regroupment; use Chill\MainBundle\Entity\Regroupment;
use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Entity\UserJob;
use Chill\MainBundle\Form\CenterType;
use Chill\MainBundle\Form\CivilityType; use Chill\MainBundle\Form\CivilityType;
use Chill\MainBundle\Form\CountryType; use Chill\MainBundle\Form\CountryType;
use Chill\MainBundle\Form\LanguageType; use Chill\MainBundle\Form\LanguageType;
@ -521,6 +524,27 @@ class ChillMainExtension extends Extension implements
], ],
], ],
], ],
[
'class' => Center::class,
'name' => 'center',
'base_path' => '/admin/center',
'form_class' => CenterType::class,
'controller' => CenterController::class,
'actions' => [
'index' => [
'role' => 'ROLE_ADMIN',
'template' => '@ChillMain/Admin/Center/index.html.twig',
],
'new' => [
'role' => 'ROLE_ADMIN',
'template' => '@ChillMain/Admin/Center/new.html.twig',
],
'edit' => [
'role' => 'ROLE_ADMIN',
'template' => '@ChillMain/Admin/Center/edit.html.twig',
],
],
],
], ],
'apis' => [ 'apis' => [
[ [

View File

@ -48,6 +48,11 @@ class Center implements HasCenterInterface, \Stringable
*/ */
private string $name = ''; private string $name = '';
/**
* @ORM\Column(type="boolean")
*/
private bool $isActive = true;
/** /**
* @var Collection<Regroupment> * @var Collection<Regroupment>
* @ORM\ManyToMany(targetEntity=Regroupment::class, mappedBy="centers") * @ORM\ManyToMany(targetEntity=Regroupment::class, mappedBy="centers")
@ -121,6 +126,11 @@ class Center implements HasCenterInterface, \Stringable
return $this->regroupments; return $this->regroupments;
} }
public function getIsActive(): bool
{
return $this->isActive;
}
/** /**
* @param $name * @param $name
* *
@ -132,4 +142,11 @@ class Center implements HasCenterInterface, \Stringable
return $this; return $this;
} }
public function setIsActive(bool $isActive): self
{
$this->isActive = $isActive;
return $this;
}
} }

View File

@ -11,7 +11,10 @@ declare(strict_types=1);
namespace Chill\MainBundle\Form; namespace Chill\MainBundle\Form;
use Chill\MainBundle\Entity\Center;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
@ -21,24 +24,18 @@ class CenterType extends AbstractType
public function buildForm(FormBuilderInterface $builder, array $options) public function buildForm(FormBuilderInterface $builder, array $options)
{ {
$builder $builder
->add('name', TextType::class); ->add('name', TextType::class, [
} 'label' => 'Nom',
])
/** ->add('isActive', CheckboxType::class, [
* @param OptionsResolverInterface $resolver 'label' => 'Actif ?',
*/ 'required' => false,
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => \Chill\MainBundle\Entity\Center::class,
]); ]);
} }
/** public function configureOptions(OptionsResolver $resolver)
* @return string
*/
public function getBlockPrefix()
{ {
return 'chill_mainbundle_center'; $resolver
->setDefault('class', Center::class);
} }
} }

View File

@ -47,12 +47,14 @@ final class PickCenterType extends AbstractType
$export->requiredRole() $export->requiredRole()
); );
$centersActive = array_filter($centers, fn (Center $c) => $c->getIsActive());
// order alphabetically // order alphabetically
usort($centers, fn (Center $a, Center $b) => $a->getCenter() <=> $b->getName()); usort($centersActive, fn (Center $a, Center $b) => $a->getCenter() <=> $b->getName());
$builder->add('center', EntityType::class, [ $builder->add('center', EntityType::class, [
'class' => Center::class, 'class' => Center::class,
'choices' => $centers, 'choices' => $centersActive,
'label' => 'center', 'label' => 'center',
'multiple' => true, 'multiple' => true,
'expanded' => true, 'expanded' => true,

View File

@ -47,6 +47,8 @@ class PickCenterType extends AbstractType
{ {
$centers = $this->getReachableCenters($options['role'], $options['scopes']); $centers = $this->getReachableCenters($options['role'], $options['scopes']);
$centersActive = array_filter($centers, fn (Center $c) => $c->getIsActive());
if (count($centers) <= 1) { if (count($centers) <= 1) {
$multiple = $options['choice_options']['multiple'] ?? false; $multiple = $options['choice_options']['multiple'] ?? false;
$builder->add('center', HiddenType::class); $builder->add('center', HiddenType::class);
@ -61,7 +63,7 @@ class PickCenterType extends AbstractType
$options['choice_options'], $options['choice_options'],
[ [
'class' => Center::class, 'class' => Center::class,
'choices' => $centers, 'choices' => $centersActive,
] ]
) )
); );

View File

@ -57,6 +57,7 @@ class UserType extends AbstractType
'class' => Center::class, 'class' => Center::class,
'query_builder' => static function (EntityRepository $er) { 'query_builder' => static function (EntityRepository $er) {
$qb = $er->createQueryBuilder('c'); $qb = $er->createQueryBuilder('c');
$qb->where($qb->expr()->eq('c.isActive', 'true'));
$qb->addOrderBy('c.name'); $qb->addOrderBy('c.name');
return $qb; return $qb;

View File

@ -29,9 +29,12 @@ final class CenterRepository implements CenterRepositoryInterface
return $this->repository->find($id, $lockMode, $lockVersion); return $this->repository->find($id, $lockMode, $lockVersion);
} }
/**
* @return Center[]
*/
public function findActive(): array public function findActive(): array
{ {
return $this->findAll(); return $this->repository->findBy(['isActive' => true], ['name' => 'ASC']);
} }
/** /**

View File

@ -0,0 +1,11 @@
{% extends '@ChillMain/CRUD/Admin/index.html.twig' %}
{% block title %}
{% include('@ChillMain/CRUD/_edit_title.html.twig') %}
{% endblock %}
{% block admin_content %}
{% embed '@ChillMain/CRUD/_edit_content.html.twig' %}
{% block content_form_actions_save_and_show %}{% endblock %}
{% endembed %}
{% endblock admin_content %}

View File

@ -0,0 +1,39 @@
{% extends '@ChillMain/CRUD/Admin/index.html.twig' %}
{% block admin_content %}
{% embed '@ChillMain/CRUD/_index.html.twig' %}
{% block table_entities_thead_tr %}
<th>{{ 'Label'|trans }}</th>
<th>{{ 'Active'|trans }}</th>
<th>&nbsp;</th>
{% endblock %}
{% block table_entities_tbody %}
{% for entity in entities %}
<tr>
<td>{{ entity.name }}</td>
<td style="text-align:center">
{% if entity.isActive %}
<i class="fa fa-check-square-o"></i>
{% else %}
<i class="fa fa-square-o"></i>
{% endif %}
</td>
<td>
<ul class="record_actions">
<li>
<a href="{{ chill_path_add_return_path('chill_crud_center_edit', { 'id': entity.id }) }}" class="btn btn-edit"></a>
</li>
</ul>
</td>
</tr>
{% endfor %}
{% endblock %}
{% block actions_before %}
<li class='cancel'>
<a href="{{ path('chill_main_admin_central') }}" class="btn btn-cancel">{{'Back to the admin'|trans}}</a>
</li>
{% endblock %}
{% endembed %}
{% endblock %}

View File

@ -0,0 +1,11 @@
{% extends '@ChillMain/CRUD/Admin/index.html.twig' %}
{% block title %}
{% include('@ChillMain/CRUD/_new_title.html.twig') %}
{% endblock %}
{% block admin_content %}
{% embed '@ChillMain/CRUD/_new_content.html.twig' %}
{% block content_form_actions_save_and_show %}{% endblock %}
{% endembed %}
{% endblock admin_content %}

View File

@ -1,23 +0,0 @@
{% extends '@ChillMain/Admin/layoutWithVerticalMenu.html.twig' %}
{% block title %}{{ 'Center edit'|trans }}{% endblock %}
{% block admin_content -%}
<h1>{{ 'Center edit'|trans }}</h1>
{{ form_start(edit_form) }}
{{ form_row(edit_form.name) }}
<ul class="record_actions sticky-form-buttons">
<li class='cancel'>
<a href="{{ path('admin_center') }}" class="btn btn-cancel">
{{ 'Back to the list'|trans }}
</a>
</li>
<li>
{{ form_widget(edit_form.submit, { 'attr' : { 'class' : 'btn btn-update' }}) }}
</li>
</ul>
{{ form_end(edit_form) }}
{% endblock %}

View File

@ -1,50 +0,0 @@
{% extends '@ChillMain/CRUD/Admin/index.html.twig' %}
{% block title %}{{ 'Center list'|trans }}{% endblock %}
{% block admin_content -%}
{% embed '@ChillMain/CRUD/_index.html.twig' %}
{% block index_header %}
<h1>{{ 'Center list'|trans }}</h1>
{% endblock %}
{% block filter_order %}{% endblock %}
{% block table_entities_thead_tr %}
<th>id</th>
<th>{{ 'Name'|trans }}</th>
<th>{{ 'Actions'|trans }}</th>
{% endblock %}
{% block table_entities_tbody %}
{% for entity in entities %}
<tr>
<td>{{ entity.id }}</td>
<td>{{ entity.name }}</td>
<td>
<ul class="record_actions">
<li>
<a href="{{ path('admin_center_edit', { 'id': entity.id }) }}" class="btn btn-edit">{{ 'edit'|trans }}</a>
</li>
</ul>
</td>
</tr>
{% endfor %}
{% endblock %}
{% block pagination %}{% endblock %}
{% block list_actions %}
<ul class="record_actions sticky-form-buttons">
<li class='cancel'>
<a href="{{ path('chill_main_admin_central') }}" class="btn btn-cancel">{{'Back to the admin'|trans}}</a>
</li>
<li>
<a href="{{ path('admin_center_new') }}" class="btn btn-create">{{ 'Create a new center'|trans }}</a>
</li>
</ul>
{% endblock list_actions %}
{% endembed %}
{% endblock %}

View File

@ -1,23 +0,0 @@
{% extends '@ChillMain/Admin/layoutWithVerticalMenu.html.twig' %}
{% block title %}{{ 'Center creation'|trans }}{% endblock %}
{% block admin_content -%}
<h1>{{ 'Center creation'|trans }}</h1>
{{ form_start(form) }}
{{ form_row(form.name) }}
<ul class="record_actions sticky-form-buttons">
<li class='cancel'>
<a href="{{ path('admin_center') }}" class="btn btn-cancel">
{{ 'Back to the list'|trans }}
</a>
</li>
<li>
{{ form_widget(form.submit, { 'attr' : { 'class' : 'btn btn-save' }}) }}
</li>
</ul>
{{ form_end(form) }}
{% endblock %}

View File

@ -46,7 +46,7 @@ class AdminUserMenuBuilder implements LocalMenuBuilderInterface
]); ]);
$menu->addChild('Center list', [ $menu->addChild('Center list', [
'route' => 'admin_center', 'route' => 'chill_crud_center_index',
])->setExtras(['order' => 1010]); ])->setExtras(['order' => 1010]);
$menu->addChild('Regroupements des centres', [ $menu->addChild('Regroupements des centres', [

View File

@ -58,6 +58,7 @@ class CenterNormalizer implements DenormalizerInterface, NormalizerInterface
'id' => $center->getId(), 'id' => $center->getId(),
'type' => 'center', 'type' => 'center',
'name' => $center->getName(), 'name' => $center->getName(),
'isActive' => $center->getIsActive()
]; ];
} }

View File

@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\Migrations\Main;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Add property to center
*/
final class Version20230906134410 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add the isActive property to the Center entity';
}
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE centers ADD isActive BOOLEAN DEFAULT true NOT NULL');
}
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE centers DROP isActive');
}
}

View File

@ -425,6 +425,12 @@ crud:
add_new: Ajouter un regroupement add_new: Ajouter un regroupement
title_new: Nouveau regroupement title_new: Nouveau regroupement
title_edit: Modifier un regroupement title_edit: Modifier un regroupement
center:
index:
title: Liste des centres
add_new: Ajouter un centre
title_new: Nouveau centre
title_edit: Modifier un centre
No entities: Aucun élément No entities: Aucun élément

View File

@ -0,0 +1,46 @@
<?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\Actions\Remove\Handler;
use Chill\PersonBundle\Actions\Remove\PersonMoveSqlHandlerInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
use Chill\PersonBundle\Entity\Person;
class PersonMoveAccompanyingPeriodParticipationHandler implements PersonMoveSqlHandlerInterface
{
public function supports(string $className, string $field): bool
{
return $className === AccompanyingPeriodParticipation::class;
}
public function getSqls(string $className, string $field, Person $from, Person $to): array
{
$insertSql = sprintf(<<<'SQL'
INSERT INTO chill_person_accompanying_period_participation (person_id, accompanyingperiod_id, id, startdate, enddate)
SELECT %d, accompanyingperiod_id, nextval('chill_person_accompanying_period_id_seq'), startdate, enddate
FROM chill_person_accompanying_period_participation cpapp
WHERE person_id = %d
AND NOT EXISTS (
SELECT 1 FROM chill_person_accompanying_period_participation cpapp2
WHERE
person_id = %d
AND (cpapp.startdate, COALESCE(cpapp.enddate, 'infinity'::date)) OVERLAPS (cpapp2.startdate, COALESCE(cpapp2.enddate, 'infinity'::date))
);
SQL, $to->getId(), $from->getId(), $to->getId());
$deleteSql = sprintf(<<<'SQL'
DELETE FROM chill_person_accompanying_period_participation WHERE person_id = %d;
SQL, $from->getId());
return [$insertSql, $deleteSql];
}
}

View File

@ -0,0 +1,73 @@
<?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\Actions\Remove\Handler;
use Chill\PersonBundle\Actions\Remove\PersonMoveSqlHandlerInterface;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Repository\Person\PersonCenterHistoryRepository;
class PersonMoveCenterHistoryHandler implements PersonMoveSqlHandlerInterface
{
public function __construct(
private PersonCenterHistoryRepository $centerHistoryRepository,
) {}
public function supports(string $className, string $field): bool
{
return $className === Person\PersonCenterHistory::class;
}
public function getSqls(string $className, string $field, Person $from, Person $to): array
{
$sqlStatements = [];
$oldestDateA = null;
$oldestDateB = null;
$oldestCenterHistoryB = null;
$oldestCenterHistoryA = null;
$centerHistoriesA = $this->centerHistoryRepository->findBy(['person' => $from]);
foreach ($centerHistoriesA as $ch) {
if ($oldestDateA === null || ($ch->getStartDate() < $oldestDateA)) {
$oldestDateA = $ch->getStartDate();
$oldestCenterHistoryA = $ch;
}
}
$centerHistoriesB = $this->centerHistoryRepository->findBy(['person' => $to]);
foreach ($centerHistoriesB as $ch) {
if ($oldestDateB === null || ($ch->getStartDate() < $oldestDateB)) {
$oldestDateB = $ch->getStartDate();
$oldestCenterHistoryB = $ch;
}
}
$sqlDelete = sprintf(<<<'SQL'
DELETE FROM chill_person_person_center_history WHERE person_id = %d;
SQL, $from->getId());
$sqlStatements = [$sqlDelete];
if ((null !== $oldestDateA && null !== $oldestDateB) && $oldestDateA <= $oldestDateB) {
$sqlInsert = sprintf(<<<'SQL'
UPDATE chill_person_person_center_history SET startDate = '%s' WHERE id = %d;
SQL, $oldestDateA->format('Y-m-d'), $oldestCenterHistoryB->getId());
$sqlStatements = [$sqlInsert, $sqlDelete];
}
return $sqlStatements;
}
}

View File

@ -0,0 +1,47 @@
<?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\Actions\Remove\Handler;
use Chill\PersonBundle\Actions\Remove\PersonMoveSqlHandlerInterface;
use Chill\PersonBundle\Entity\Household\HouseholdMember;
use Chill\PersonBundle\Entity\Person;
class PersonMoveHouseholdHandler implements PersonMoveSqlHandlerInterface
{
public function supports(string $className, string $field): bool
{
return $className === HouseholdMember::class;
}
public function getSqls(string $className, string $field, Person $from, Person $to): array
{
$sqlInsert = sprintf(<<<'SQL'
INSERT INTO chill_person_household_members (id, person_id, household_id, startdate, enddate, comment, sharedhousehold, position_id, holder)
SELECT nextval('chill_person_household_members_id_seq'), %d, household_id, startdate, enddate, comment, sharedhousehold, position_id, holder
FROM chill_person_household_members cphm
WHERE person_id = %d
AND NOT EXISTS (
SELECT 1 FROM chill_person_household_members cphm_inner
WHERE
person_id = %d
AND daterange(cphm.startdate, cphm.enddate) && daterange(cphm_inner.startdate, cphm_inner.enddate)
);
SQL, $to->getId(), $from->getId(), $to->getId());
$deleteSql = sprintf(<<<'SQL'
DELETE FROM chill_person_household_members WHERE person_id = %d;
SQL, $from->getId());
return [$sqlInsert, $deleteSql];
}
}

View File

@ -0,0 +1,47 @@
<?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\Actions\Remove\Handler;
use Chill\PersonBundle\Actions\Remove\PersonMoveSqlHandlerInterface;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\Relationships\Relationship;
class PersonMoveRelationHandler implements PersonMoveSqlHandlerInterface
{
public function supports(string $className, string $field): bool
{
return $className === Relationship::class;
}
public function getSqls(string $className, string $field, Person $from, Person $to): array
{
$insertSql = sprintf(<<<'SQL'
INSERT INTO chill_person_relationships (id, relation_id, reverse, fromperson_id, toperson_id)
SELECT nextval('chill_person_relationships_id_seq'), relation_id, reverse, fromperson_id, toperson_id
FROM chill_person_relationships cpr
WHERE fromperson_id = %d OR toperson_id = %d
AND NOT EXISTS (
SELECT 1 FROM chill_person_relationships cpr2
WHERE
cpr2.fromperson_id = %d AND cpr2.toperson_id = %d
OR cpr2.fromperson_id = %d AND cpr2.toperson_id = %d
);
SQL, $from->getId(), $from->getId(), $to->getId(), $from->getId(), $from->getId(), $to->getId());
$deleteSql = [
sprintf("DELETE FROM chill_person_relationships WHERE fromperson_id = %d", $from->getId()),
sprintf("DELETE FROM chill_person_relationships WHERE toperson_id = %d", $from->getId())
];
return [$insertSql, ...$deleteSql];
}
}

View File

@ -35,23 +35,11 @@ use function in_array;
*/ */
class PersonMove class PersonMove
{ {
/**
* @var EntityManagerInterface
*/
protected $em;
/**
* @var EventDispatcherInterface
*/
protected $eventDispatcher;
public function __construct( public function __construct(
EntityManagerInterface $em, private EntityManagerInterface $em,
EventDispatcherInterface $eventDispatcher private PersonMoveManager $personMoveManager,
) { private EventDispatcherInterface $eventDispatcher
$this->em = $em; ) {}
$this->eventDispatcher = $eventDispatcher;
}
/** /**
* Return the sql used to move or delete entities associated to a person to * Return the sql used to move or delete entities associated to a person to
@ -88,9 +76,16 @@ class PersonMove
} }
foreach ($metadata->getAssociationMappings() as $field => $mapping) { foreach ($metadata->getAssociationMappings() as $field => $mapping) {
if ($this->personMoveManager->hasHandler($metadata->getName(), $field)) {
$sqls = array_merge($sqls, $this->personMoveManager->getSqls($metadata->getName(), $field, $from, $to));
continue;
}
if (in_array($mapping['sourceEntity'], $this->getIgnoredEntities(), true)) { if (in_array($mapping['sourceEntity'], $this->getIgnoredEntities(), true)) {
continue; continue;
} }
if (Person::class === $mapping['targetEntity'] and true === $mapping['isOwningSide']) { if (Person::class === $mapping['targetEntity'] and true === $mapping['isOwningSide']) {
if (in_array($mapping['sourceEntity'], $toDelete, true)) { if (in_array($mapping['sourceEntity'], $toDelete, true)) {
$sql = $this->createDeleteSQL($metadata, $from, $field); $sql = $this->createDeleteSQL($metadata, $from, $field);
@ -100,26 +95,18 @@ class PersonMove
$sql, $sql,
['to' => $to->getId(), 'original_action' => 'move'] ['to' => $to->getId(), 'original_action' => 'move']
); );
$this->eventDispatcher->dispatch($event, ActionEvent::DELETE); $this->eventDispatcher->dispatch(ActionEvent::DELETE, $event);
} else {
$sql = $this->createMoveSQL($metadata, $from, $to, $field);
$event = new ActionEvent(
$from->getId(),
$metadata->getName(),
$sql,
['to' => $to->getId(), 'original_action' => 'move']
);
$this->eventDispatcher->dispatch($event, ActionEvent::MOVE);
}
$sqls = array_merge($sqls, $event->getPreSql(), [$event->getSqlStatement()], $event->getPostSql()); $sqls = array_merge($sqls, $event->getPreSql(), [$event->getSqlStatement()], $event->getPostSql());
} else {
$sqls = array_merge($sqls, $this->createMoveSQLs($metadata, $from, $to, $field));
}
} }
} }
} }
$personMetadata = $this->em->getClassMetadata(Person::class); $personMetadata = $this->em->getClassMetadata(Person::class);
$sqls[] = sprintf( $sqls[] = sprintf(
'DELETE FROM %s WHERE id = %d', 'DELETE FROM %s WHERE id = %d;',
$this->getTableName($personMetadata), $this->getTableName($personMetadata),
$from->getId() $from->getId()
); );
@ -133,18 +120,24 @@ class PersonMove
$conditions = []; $conditions = [];
if (array_key_exists('joinTable', $mapping)) {
foreach ($mapping['joinTable']['joinColumns'] as $columns) {
$conditions[] = sprintf('%s = %d', $columns['referencedColumnName'], $from->getId());
}
} elseif (array_key_exists('joinColumns', $mapping)) {
foreach ($mapping['joinColumns'] as $columns) { foreach ($mapping['joinColumns'] as $columns) {
$conditions[] = sprintf('%s = %d', $columns['name'], $from->getId()); $conditions[] = sprintf('%s = %d', $columns['name'], $from->getId());
} }
}
return sprintf( return sprintf(
'DELETE FROM %s WHERE %s', 'DELETE FROM %s WHERE %s;',
$this->getTableName($metadata), $this->getTableName($metadata),
implode(' AND ', $conditions) implode(' AND ', $conditions)
); );
} }
private function createMoveSQL(ClassMetadata $metadata, Person $from, Person $to, $field): string private function createMoveSQLs($metadata, Person $from, Person $to, $field): array
{ {
$mapping = $metadata->getAssociationMapping($field); $mapping = $metadata->getAssociationMapping($field);
@ -154,9 +147,29 @@ class PersonMove
$tableName = ''; $tableName = '';
if (array_key_exists('joinTable', $mapping)) { if (array_key_exists('joinTable', $mapping)) {
// there is a join_table: we have to find conflict
$tableName = (null !== ($mapping['joinTable']['schema'] ?? null) ? $mapping['joinTable']['schema'] . '.' : '') $tableName = (null !== ($mapping['joinTable']['schema'] ?? null) ? $mapping['joinTable']['schema'] . '.' : '')
. $mapping['joinTable']['name']; . $mapping['joinTable']['name'];
$sqlInsert = sprintf(
"INSERT INTO %s (%s, %s) SELECT %d, %s FROM %s WHERE %s = %d ON CONFLICT DO NOTHING;",
$tableName,
$mapping['joinTable']['inverseJoinColumns'][0]['name'], // person_id
$mapping['joinTable']['joinColumns'][0]['name'], // something_else_id
$to->getId(),
$mapping['joinTable']['joinColumns'][0]['name'], // something_else_id
$tableName,
$mapping['joinTable']['inverseJoinColumns'][0]['name'], // person_id
$from->getId()
);
$deleteSql = sprintf(
"DELETE FROM %s WHERE %s = %d;",
$tableName,
$mapping['joinTable']['inverseJoinColumns'][0]['name'], // person_id
$from->getId()
);
foreach ($mapping['joinTable']['inverseJoinColumns'] as $columns) { foreach ($mapping['joinTable']['inverseJoinColumns'] as $columns) {
$sets[] = sprintf('%s = %d', $columns['name'], $to->getId()); $sets[] = sprintf('%s = %d', $columns['name'], $to->getId());
} }
@ -164,24 +177,29 @@ class PersonMove
foreach ($mapping['joinTable']['inverseJoinColumns'] as $columns) { foreach ($mapping['joinTable']['inverseJoinColumns'] as $columns) {
$conditions[] = sprintf('%s = %d', $columns['name'], $from->getId()); $conditions[] = sprintf('%s = %d', $columns['name'], $from->getId());
} }
} elseif (array_key_exists('joinColumns', $mapping)) {
return [
$sqlInsert, $deleteSql
];
}
if (array_key_exists('joinColumns', $mapping)) {
$tableName = $this->getTableName($metadata); $tableName = $this->getTableName($metadata);
foreach ($mapping['joinColumns'] as $columns) { foreach ($mapping['joinColumns'] as $columns) {
$sets[] = sprintf('%s = %d', $columns['name'], $to->getId()); $sets[] = sprintf('%s = %d', $columns['name'], $to->getId());
} }
foreach ($mapping['joinColumns'] as $columns) { foreach ($mapping['joinColumns'] as $columns) {
$conditions[] = sprintf('%s = %d', $columns['name'], $from->getId()); $conditions[] = sprintf('%s = %d', $columns['name'], $from->getId());
} }
} }
return sprintf( return [sprintf(
'UPDATE %s SET %s WHERE %s', 'UPDATE %s SET %s WHERE %s;',
$tableName, $tableName,
implode(' ', $sets), implode(' ', $sets),
implode(' AND ', $conditions) implode(' AND ', $conditions)
); )];
} }
/** /**
@ -191,9 +209,6 @@ class PersonMove
private function getDeleteEntities(): array private function getDeleteEntities(): array
{ {
return [ return [
Person\PersonCenterHistory::class,
HouseholdMember::class,
AccompanyingPeriodParticipation::class,
AccompanyingPeriod\AccompanyingPeriodWork::class, AccompanyingPeriod\AccompanyingPeriodWork::class,
Relationship::class Relationship::class
]; ];

View File

@ -0,0 +1,55 @@
<?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\Actions\Remove;
use Chill\PersonBundle\Entity\Person;
class PersonMoveManager
{
public function __construct(
/**
* @var iterable<PersonMoveSqlHandlerInterface>
*/
private iterable $handlers,
) {}
/**
* @param class-string $className
* @param string $field
* @return bool
*/
public function hasHandler(string $className, string $field): bool
{
foreach ($this->handlers as $handler) {
if ($handler->supports($className, $field)) {
return true;
}
}
return false;
}
/**
* @param class-string $className
* @return array<string>
*/
public function getSqls(string $className, string $field, Person $from, Person $to): array
{
foreach ($this->handlers as $handler) {
if ($handler->supports($className, $field)) {
return $handler->getSqls($className, $field, $from, $to);
}
}
return [];
}
}

View File

@ -0,0 +1,28 @@
<?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\Actions\Remove;
use Chill\PersonBundle\Entity\Person;
interface PersonMoveSqlHandlerInterface
{
/**
* @param class-string $className
*/
public function supports(string $className, string $field): bool;
/**
* @param class-string $className
* @return array<string>
*/
public function getSqls(string $className, string $field, Person $from, Person $to): array;
}

View File

@ -11,6 +11,7 @@ declare(strict_types=1);
namespace Chill\PersonBundle; namespace Chill\PersonBundle;
use Chill\PersonBundle\Actions\Remove\PersonMoveSqlHandlerInterface;
use Chill\PersonBundle\DependencyInjection\CompilerPass\AccompanyingPeriodTimelineCompilerPass; use Chill\PersonBundle\DependencyInjection\CompilerPass\AccompanyingPeriodTimelineCompilerPass;
use Chill\PersonBundle\Service\EntityInfo\AccompanyingPeriodInfoUnionQueryPartInterface; use Chill\PersonBundle\Service\EntityInfo\AccompanyingPeriodInfoUnionQueryPartInterface;
use Chill\PersonBundle\Widget\PersonListWidgetFactory; use Chill\PersonBundle\Widget\PersonListWidgetFactory;
@ -29,5 +30,7 @@ class ChillPersonBundle extends Bundle
$container->addCompilerPass(new AccompanyingPeriodTimelineCompilerPass(), \Symfony\Component\DependencyInjection\Compiler\PassConfig::TYPE_BEFORE_OPTIMIZATION, 0); $container->addCompilerPass(new AccompanyingPeriodTimelineCompilerPass(), \Symfony\Component\DependencyInjection\Compiler\PassConfig::TYPE_BEFORE_OPTIMIZATION, 0);
$container->registerForAutoconfiguration(AccompanyingPeriodInfoUnionQueryPartInterface::class) $container->registerForAutoconfiguration(AccompanyingPeriodInfoUnionQueryPartInterface::class)
->addTag('chill_person.accompanying_period_info_part'); ->addTag('chill_person.accompanying_period_info_part');
$container->registerForAutoconfiguration(PersonMoveSqlHandlerInterface::class)
->addTag('chill_person.person_move_handler');
} }
} }

View File

@ -13,6 +13,7 @@ namespace Chill\PersonBundle\Controller;
use Chill\MainBundle\CRUD\Controller\ApiController; use Chill\MainBundle\CRUD\Controller\ApiController;
use Chill\MainBundle\Entity\Address; use Chill\MainBundle\Entity\Address;
use Chill\MainBundle\Entity\Center;
use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper; use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper;
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation; use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\Person;
@ -50,7 +51,7 @@ class PersonApiController extends ApiController
['showCenters' => $this->showCenters, 'centers' => $centers], ['showCenters' => $this->showCenters, 'centers' => $centers],
Response::HTTP_OK, Response::HTTP_OK,
[], [],
['gropus' => ['read']] ['groups' => ['read']]
); );
} }

View File

@ -86,6 +86,7 @@ class PersonDuplicateController extends \Symfony\Bundle\FrameworkBundle\Controll
$connection->beginTransaction(); $connection->beginTransaction();
foreach ($sqls as $sql) { foreach ($sqls as $sql) {
dump($sql);
$connection->executeQuery($sql); $connection->executeQuery($sql);
} }
$connection->commit(); $connection->commit();

View File

@ -1595,6 +1595,15 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
return $this; return $this;
} }
public function addCenterHistory(PersonCenterHistory $newCenterHistory): self
{
if (!$this->centerHistory->contains($newCenterHistory)) {
$this->centerHistory[] = $newCenterHistory;
$newCenterHistory->setPerson($this);
}
return $this;
}
public function setCFData(?array $cFData): self public function setCFData(?array $cFData): self
{ {
$this->cFData = $cFData; $this->cFData = $cFData;

View File

@ -225,7 +225,7 @@ class SocialIssue
/** /**
* @param array|SocialIssue[] $socialIssues * @param array|SocialIssue[] $socialIssues
*/ */
public static function getDescendantsWithThisForIssues(array $socialIssues): Collection public static function getDescendantsWithThisForIssues(array|Collection $socialIssues): Collection
{ {
$unique = []; $unique = [];

View File

@ -11,7 +11,7 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Form; namespace Chill\PersonBundle\Form;
use Chill\PersonBundle\Form\Type\PickPersonType; use Chill\PersonBundle\Form\Type\PickPersonDynamicType;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
@ -21,7 +21,7 @@ class PersonFindManuallyDuplicateType extends AbstractType
public function buildForm(FormBuilderInterface $builder, array $options) public function buildForm(FormBuilderInterface $builder, array $options)
{ {
$builder $builder
->add('person', PickPersonType::class, [ ->add('person', PickPersonDynamicType::class, [
'label' => 'Find duplicate', 'label' => 'Find duplicate',
'mapped' => false, 'mapped' => false,
]) ])

View File

@ -66,11 +66,10 @@ final readonly class AccompanyingPeriodACLAwareRepository implements Accompanyin
Join::WITH, Join::WITH,
'COALESCE(IDENTITY(person_address.address), IDENTITY(location_history.addressLocation)) = address.id' 'COALESCE(IDENTITY(person_address.address), IDENTITY(location_history.addressLocation)) = address.id'
) )
->join('address.postcode', 'postcode')
->andWhere( ->andWhere(
$qb->expr()->in('postcode.code', ':postal_codes') $qb->expr()->in('address.postcode', ':postal_codes')
) )
->setParameter('postal_codes', array_map(fn (PostalCode $postalCode) => $postalCode->getCode(), $postalCodes)); ->setParameter('postal_codes', $postalCodes);
} }
return $qb; return $qb;

View File

@ -329,12 +329,13 @@ export default {
if (this.action !== 'create') { if (this.action !== 'create') {
this.loadData(); this.loadData();
} else { } else {
console.log('show centers', this.showCenters); // console.log('show centers', this.showCenters);
getCentersForPersonCreation() getCentersForPersonCreation()
.then(params => { .then(params => {
this.config.centers = params.centers; this.config.centers = params.centers.filter(c => c.isActive);
this.showCenters = params.showCenters; this.showCenters = params.showCenters;
console.log('show centers inside', this.showCenters); // console.log('centers', this.config.centers)
// console.log('show centers inside', this.showCenters);
if (this.showCenters && this.config.centers.length === 1) { if (this.showCenters && this.config.centers.length === 1) {
this.person.center = this.config.centers[0]; this.person.center = this.config.centers[0];
} }

View File

@ -4,7 +4,7 @@
<li><b>{{ 'gender'|trans }}</b>: <li><b>{{ 'gender'|trans }}</b>:
{{ person.gender|trans }}</li> {{ person.gender|trans }}</li>
<li><b>{{ 'maritalStatus'|trans }}</b>: <li><b>{{ 'maritalStatus'|trans }}</b>:
{% if person.maritalStatus.name %}{{ person.maritalStatus.name|localize_translatable_string }}{% endif %}</li> {% if person.maritalStatus %}{{ person.maritalStatus.name|localize_translatable_string }}{% endif %}</li>
<li><b>{{ 'birthdate'|trans }}</b>: <li><b>{{ 'birthdate'|trans }}</b>:
{% if person.birthdate is not null %}{{ person.birthdate|format_date('short') }}{% endif %}</li> {% if person.birthdate is not null %}{{ person.birthdate|format_date('short') }}{% endif %}</li>
<li><b>{{ 'placeOfBirth'|trans }}</b>: <li><b>{{ 'placeOfBirth'|trans }}</b>:

View File

@ -29,3 +29,11 @@
</div> </div>
{% endblock %} {% endblock %}
{% block js %}
{{ encore_entry_script_tags('mod_pickentity_type') }}
{% endblock %}
{% block css %}
{{ encore_entry_link_tags('mod_pickentity_type') }}
{% endblock %}

View File

@ -0,0 +1,275 @@
<?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 Action\Remove;
use Chill\ActivityBundle\Entity\Activity;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Repository\CenterRepositoryInterface;
use Chill\PersonBundle\Actions\Remove\PersonMove;
use Chill\PersonBundle\Actions\Remove\PersonMoveManager;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
use Chill\PersonBundle\Entity\Household\Household;
use Chill\PersonBundle\Entity\Household\HouseholdMember;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\Relationships\Relation;
use Chill\PersonBundle\Entity\Relationships\Relationship;
use Chill\PersonBundle\Repository\PersonRepository;
use Doctrine\DBAL\Connection;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* @internal
* @coversNothing
*/
class PersonMoveTest extends KernelTestCase
{
private EntityManagerInterface $em;
private PersonMoveManager $personMoveManager;
private EventDispatcherInterface $eventDispatcher;
private CenterRepositoryInterface $centerRepository;
/**
* @var list<array{0: class-string, 1: int}>
*/
private static $entitiesToDelete = [];
public function setUp(): void
{
self::bootKernel();
$this->em = self::$container->get(EntityManagerInterface::class);
$this->personMoveManager = self::$container->get(PersonMoveManager::class);
$this->eventDispatcher = self::$container->get(EventDispatcherInterface::class);
$this->centerRepository = self::$container->get(CenterRepositoryInterface::class);
}
public static function tearDownAfterClass(): void
{
self::bootKernel();
$em = self::$container->get(EntityManagerInterface::class);
foreach (self::$entitiesToDelete as [$class, $id]) {
$entity = $em->find($class, $id);
if (null !== $entity) {
$em->remove($entity);
}
}
$em->flush();
}
/**
* @dataProvider dataProviderMovePerson
*/
public function testMovePersonSimple(Person $personA, Person $personB, string $message): void
{
$move = new PersonMove($this->em, $this->personMoveManager, $this->eventDispatcher);
$sqls = $move->getSQL($personA, $personB);
$this->em->getConnection()->transactional(function (Connection $conn) use ($personA, $personB, $sqls) {
foreach ($sqls as $sql) {
$conn->executeStatement($sql);
}
});
$personsByIdOfA = $this->em->createQuery("SELECT p FROM " . Person::class . " p WHERE p.id = :id")
->setParameter('id', $personA->getId())
->getResult();
$personB = $this->em->find(Person::class, $personB->getId());
self::assertCount(0, $personsByIdOfA);
self::assertNotNull($personB?->getId(), $message);
}
public function testMovePersonCenterHistory(): void
{
$personA = new Person();
$personB = new Person();
[$centerA, $centerB] = $this->centerRepository->findAll();
$this->em->persist($personA);
$this->em->persist($personB);
$personCenterHistoryAFirst = (new Person\PersonCenterHistory())->setCenter($centerA)
->setStartDate(new \DateTimeImmutable('2023-01-01'))
->setEndDate(new \DateTimeImmutable('2023-06-30'));
$personCenterHistoryASecond = (new Person\PersonCenterHistory())->setCenter($centerB)
->setStartDate(new \DateTimeImmutable('2023-06-30'))
->setEndDate(new \DateTimeImmutable('2023-09-30'));
$personCenterHistoryBFirst = (new Person\PersonCenterHistory())->setCenter($centerA)
->setStartDate(new \DateTimeImmutable('2023-03-01'))
->setEndDate(new \DateTimeImmutable('2023-07-15'));
$personCenterHistoryBSecond = (new Person\PersonCenterHistory())->setCenter($centerB)
->setStartDate(new \DateTimeImmutable('2023-07-15'))
->setEndDate(new \DateTimeImmutable('2023-09-30'));
$this->em->persist($personCenterHistoryAFirst);
$this->em->persist($personCenterHistoryASecond);
$this->em->persist($personCenterHistoryBFirst);
$this->em->persist($personCenterHistoryBSecond);
$personA->addCenterHistory($personCenterHistoryAFirst);
$personA->addCenterHistory($personCenterHistoryASecond);
$personB->addCenterHistory($personCenterHistoryBFirst);
$personB->addCenterHistory($personCenterHistoryBSecond);
$this->em->flush();
$this->em->clear();
$move = new PersonMove($this->em, $this->personMoveManager, $this->eventDispatcher);
$sqls = $move->getSQL($personA, $personB);
$this->em->getConnection()->transactional(function (Connection $conn) use ($personA, $personB, $sqls) {
foreach ($sqls as $sql) {
$conn->executeStatement($sql);
}
});
$personsByIdOfA = $this->em->createQuery("SELECT p FROM " . Person::class . " p WHERE p.id = :id")
->setParameter('id', $personA->getId())
->getResult();
/** @var Person $personB */
$personB = $this->em->find(Person::class, $personB->getId());
$message = 'Move persons with overlapping center histories';
$this->em->refresh($personB);
self::assertCount(0, $personsByIdOfA);
self::assertNotNull($personB?->getId(), $message);
$centerHistoriesB = $personB->getCenterHistory();
$oldestDate = new \DateTimeImmutable('2023-01-01');
$this->em->refresh($centerHistoriesB->first());
self::assertCount(2, $centerHistoriesB);
self::assertEquals($oldestDate, $centerHistoriesB->first()->getStartDate());
self::$entitiesToDelete[] = [Person::class, $personA];
self::$entitiesToDelete[] = [Person::class, $personB];
self::$entitiesToDelete[] = [Person\PersonCenterHistory::class, $personCenterHistoryAFirst];
self::$entitiesToDelete[] = [Person\PersonCenterHistory::class, $personCenterHistoryASecond];
self::$entitiesToDelete[] = [Person\PersonCenterHistory::class, $personCenterHistoryBFirst];
self::$entitiesToDelete[] = [Person\PersonCenterHistory::class, $personCenterHistoryBSecond];
}
public function dataProviderMovePerson(): iterable
{
$this->setUp();
$personA = new Person();
$personB = new Person();
$this->em->persist($personA);
$this->em->persist($personB);
self::$entitiesToDelete[] = [Person::class, $personA];
self::$entitiesToDelete[] = [Person::class, $personB];
yield [$personA, $personB, "move 2 people without any associated data"];
$personA = new Person();
$personB = new Person();
$activity = new Activity();
$activity->setDate(new \DateTime('today'));
$activity->addPerson($personA);
$activity->addPerson($personB);
$this->em->persist($personA);
$this->em->persist($personB);
$this->em->persist($activity);
self::$entitiesToDelete[] = [Person::class, $personA];
self::$entitiesToDelete[] = [Person::class, $personB];
self::$entitiesToDelete[] = [Activity::class, $activity];
yield [$personA, $personB, "move 2 people having an activity"];
$personA = new Person();
$personB = new Person();
$household = new Household();
$household->addMember(
$memberA = (new HouseholdMember())->setPerson($personA)->setShareHousehold(true)
->setStartDate(new \DateTimeImmutable('2023-01-01'))
);
$household->addMember(
$memberB = (new HouseholdMember())->setPerson($personB)->setShareHousehold(true)
->setStartDate(new \DateTimeImmutable('2023-01-01'))
);
$this->em->persist($personA);
$this->em->persist($personB);
$this->em->persist($household);
$this->em->persist($memberA);
$this->em->persist($memberB);
self::$entitiesToDelete[] = [Person::class, $personA];
self::$entitiesToDelete[] = [Person::class, $personB];
self::$entitiesToDelete[] = [HouseholdMember::class, $memberA];
self::$entitiesToDelete[] = [HouseholdMember::class, $memberB];
self::$entitiesToDelete[] = [Household::class, $household];
yield [$personA, $personB, "move 2 people having the same household at the same time"];
$personA = new Person();
$personB = new Person();
$parcours = new AccompanyingPeriod();
$parcours->addPerson($personA);
$parcours->addPerson($personB);
$this->em->persist($personA);
$this->em->persist($personB);
$this->em->persist($parcours);
self::$entitiesToDelete[] = [Person::class, $personA];
self::$entitiesToDelete[] = [Person::class, $personB];
self::$entitiesToDelete[] = [AccompanyingPeriod::class, $parcours];
yield [$personA, $personB, "move 2 people participating to the same parcours"];
$personA = new Person();
$personB = new Person();
$relationship = new Relationship();
$relation = new Relation();
$user = (new User())->setUsername(uniqid())->setEmail(uniqid() . '@foo.com');
$relationship->setRelation($relation);
$relationship->setToPerson($personA);
$relationship->setFromPerson($personB);
$relationship->setReverse(false);
$relationship->setCreatedBy($user);
$this->em->persist($personA);
$this->em->persist($personB);
$this->em->persist($relation);
$this->em->persist($user);
$this->em->persist($relationship);
self::$entitiesToDelete[] = [Person::class, $personA];
self::$entitiesToDelete[] = [Person::class, $personB];
self::$entitiesToDelete[] = [Relation::class, $relation];
self::$entitiesToDelete[] = [User::class, $user];
self::$entitiesToDelete[] = [Relationship::class, $relationship];
yield [$personA, $personB, "move 2 people with a relationship"];
$this->em->flush();
$this->em->clear();
}
}

Some files were not shown because too many files have changed in this diff Show More