mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-14 14:24:24 +00:00
Merge branch '111_exports_suite' into 111_export_GeographicalUnit
This commit is contained in:
commit
e1fda324a4
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
.composer/*
|
.composer/*
|
||||||
|
composer
|
||||||
composer.phar
|
composer.phar
|
||||||
composer.lock
|
composer.lock
|
||||||
docs/build/
|
docs/build/
|
||||||
|
18
CHANGELOG.md
18
CHANGELOG.md
@ -11,6 +11,22 @@ and this project adheres to
|
|||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
<!-- write down unreleased development here -->
|
<!-- write down unreleased development here -->
|
||||||
|
* [person][export] Fixed: rename the alias for `accompanying_period` to `acp` in filter associated with person
|
||||||
|
* [activity][export] Feature: improve label for aliases in "Filter by activity type"
|
||||||
|
* [activity][export] DX/Feature: use of an `ActivityTypeRepositoryInterface` instead of the old-style EntityRepository
|
||||||
|
* [person][export] Fixed: some inconsistency with date filter on accompanying courses
|
||||||
|
* [person][export] Fixed: use left join for related entities in accompanying course aggregators
|
||||||
|
|
||||||
|
## Test releases
|
||||||
|
|
||||||
|
### 2.0.0-beta2
|
||||||
|
|
||||||
|
* [workflow]: Fixed: the notification is sent when the user is added to the first step.
|
||||||
|
* [budget] Feature: allow to desactivate some charges and resources, adding an `active` key in the configuration
|
||||||
|
* [person] Feature: on Evaluation, allow to configure an URL from the admin
|
||||||
|
|
||||||
|
### 2022-06
|
||||||
|
|
||||||
* [workflow]: added pagination to workflow list page
|
* [workflow]: added pagination to workflow list page
|
||||||
* [homepage_widget]: null error on tasks widget fixed
|
* [homepage_widget]: null error on tasks widget fixed
|
||||||
* [person-thirdparty]: fix quick-add of names that consist of multiple parts (eg. De Vlieger) within onthefly modal person/thirdparty
|
* [person-thirdparty]: fix quick-add of names that consist of multiple parts (eg. De Vlieger) within onthefly modal person/thirdparty
|
||||||
@ -19,8 +35,6 @@ and this project adheres to
|
|||||||
* [household]: Reposition and cut button for enfant hors menage have been deleted (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/620)
|
* [household]: Reposition and cut button for enfant hors menage have been deleted (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/620)
|
||||||
* [admin]: Add crud for composition type in admin (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/611)
|
* [admin]: Add crud for composition type in admin (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/611)
|
||||||
|
|
||||||
## Test releases
|
|
||||||
|
|
||||||
### 2022-05-30
|
### 2022-05-30
|
||||||
|
|
||||||
* fix creating a new AccompanyingPeriodWorkEvaluationDocument when replacing the document (the workflow was lost)
|
* fix creating a new AccompanyingPeriodWorkEvaluationDocument when replacing the document (the workflow was lost)
|
||||||
|
@ -104,6 +104,29 @@ The password is always ``password``.
|
|||||||
|
|
||||||
Now, read `Operations` below.
|
Now, read `Operations` below.
|
||||||
|
|
||||||
|
Prepare for development
|
||||||
|
***********************
|
||||||
|
|
||||||
|
Add a Gitlab token to ensure that you get always the source code:
|
||||||
|
|
||||||
|
1. generate a gitlab token there: https://gitlab.com/oauth/token
|
||||||
|
2. run this command (in php container, at the app's root): :code:`composer config gitlab-token.gitlab.com <your token>`
|
||||||
|
|
||||||
|
The auth token should appears now in the directory :code:`.composer`:
|
||||||
|
|
||||||
|
.. code-block: bash
|
||||||
|
|
||||||
|
$ cat .composer/auth.json
|
||||||
|
{
|
||||||
|
"gitlab-token": {
|
||||||
|
"gitlab.com": "<your token>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
See also "how to switch branch and get new dependencies".
|
||||||
|
|
||||||
|
|
||||||
Operations
|
Operations
|
||||||
**********
|
**********
|
||||||
|
|
||||||
@ -211,6 +234,25 @@ How to run webpack interactively
|
|||||||
|
|
||||||
Executing :code:`bash docker-node.sh` will open a terminal in a node container, with volumes mounted.
|
Executing :code:`bash docker-node.sh` will open a terminal in a node container, with volumes mounted.
|
||||||
|
|
||||||
|
How to switch the branch for chill-bundles, and get new dependencies
|
||||||
|
====================================================================
|
||||||
|
|
||||||
|
During development, you will switch to new branches for chill-bundles. As long as the dependencies are equals, this does not cause any problem. But sometimes, a new branch introduces a new dependency, and you must download it.
|
||||||
|
|
||||||
|
In order to do that without pain, use those steps:
|
||||||
|
|
||||||
|
0. Ensuire you have a token, set
|
||||||
|
1. at the app's root, update the `composer.json` to your current branch:
|
||||||
|
|
||||||
|
.. code-block:: json
|
||||||
|
|
||||||
|
{
|
||||||
|
"require": {
|
||||||
|
"chill-bundles": "dev-<my-branch>@dev"
|
||||||
|
}
|
||||||
|
|
||||||
|
2. mount into the php container, and run `composer update`
|
||||||
|
|
||||||
Build the documentation API
|
Build the documentation API
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ Household::class,,,household
|
|||||||
,HouseholdComposition::class,household.compositions,composition
|
,HouseholdComposition::class,household.compositions,composition
|
||||||
Activity::class,,,activity
|
Activity::class,,,activity
|
||||||
,Person::class,activity.person,actperson
|
,Person::class,activity.person,actperson
|
||||||
,AccompanyingPeriod::class,activity.accompanyingPeriod,actacp
|
,AccompanyingPeriod::class,activity.accompanyingPeriod,acp
|
||||||
,Person::class,activity_person_having_activity.person,person_person_having_activity
|
,Person::class,activity_person_having_activity.person,person_person_having_activity
|
||||||
,ActivityReason::class,activity_person_having_activity.reasons,reasons_person_having_activity
|
,ActivityReason::class,activity_person_having_activity.reasons,reasons_person_having_activity
|
||||||
,ActivityType::class,activity.activityType,acttype
|
,ActivityType::class,activity.activityType,acttype
|
||||||
|
|
@ -47,7 +47,7 @@ These are alias conventions :
|
|||||||
| | HouseholdComposition::class | household.compositions | composition |
|
| | HouseholdComposition::class | household.compositions | composition |
|
||||||
| Activity::class | | | activity |
|
| Activity::class | | | activity |
|
||||||
| | Person::class | activity.person | actperson |
|
| | Person::class | activity.person | actperson |
|
||||||
| | AccompanyingPeriod::class | activity.accompanyingPeriod | actacp |
|
| | AccompanyingPeriod::class | activity.accompanyingPeriod | acp |
|
||||||
| | Person::class | activity\_person\_having\_activity.person | person\_person\_having\_activity |
|
| | Person::class | activity\_person\_having\_activity.person | person\_person\_having\_activity |
|
||||||
| | ActivityReason::class | activity\_person\_having\_activity.reasons | reasons\_person\_having\_activity |
|
| | ActivityReason::class | activity\_person\_having\_activity.reasons | reasons\_person\_having\_activity |
|
||||||
| | ActivityType::class | activity.activityType | acttype |
|
| | ActivityType::class | activity.activityType | acttype |
|
||||||
|
@ -17,7 +17,7 @@ use Chill\ActivityBundle\Form\ActivityType;
|
|||||||
use Chill\ActivityBundle\Repository\ActivityACLAwareRepositoryInterface;
|
use Chill\ActivityBundle\Repository\ActivityACLAwareRepositoryInterface;
|
||||||
use Chill\ActivityBundle\Repository\ActivityRepository;
|
use Chill\ActivityBundle\Repository\ActivityRepository;
|
||||||
use Chill\ActivityBundle\Repository\ActivityTypeCategoryRepository;
|
use Chill\ActivityBundle\Repository\ActivityTypeCategoryRepository;
|
||||||
use Chill\ActivityBundle\Repository\ActivityTypeRepository;
|
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
|
||||||
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
|
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
|
||||||
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
|
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
|
||||||
use Chill\MainBundle\Repository\LocationRepository;
|
use Chill\MainBundle\Repository\LocationRepository;
|
||||||
@ -55,7 +55,7 @@ final class ActivityController extends AbstractController
|
|||||||
|
|
||||||
private ActivityTypeCategoryRepository $activityTypeCategoryRepository;
|
private ActivityTypeCategoryRepository $activityTypeCategoryRepository;
|
||||||
|
|
||||||
private ActivityTypeRepository $activityTypeRepository;
|
private ActivityTypeRepositoryInterface $activityTypeRepository;
|
||||||
|
|
||||||
private CenterResolverManagerInterface $centerResolver;
|
private CenterResolverManagerInterface $centerResolver;
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ final class ActivityController extends AbstractController
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
ActivityACLAwareRepositoryInterface $activityACLAwareRepository,
|
ActivityACLAwareRepositoryInterface $activityACLAwareRepository,
|
||||||
ActivityTypeRepository $activityTypeRepository,
|
ActivityTypeRepositoryInterface $activityTypeRepository,
|
||||||
ActivityTypeCategoryRepository $activityTypeCategoryRepository,
|
ActivityTypeCategoryRepository $activityTypeCategoryRepository,
|
||||||
PersonRepository $personRepository,
|
PersonRepository $personRepository,
|
||||||
ThirdPartyRepository $thirdPartyRepository,
|
ThirdPartyRepository $thirdPartyRepository,
|
||||||
|
@ -516,6 +516,11 @@ class ActivityType
|
|||||||
return $this->userVisible;
|
return $this->userVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function hasCategory(): bool
|
||||||
|
{
|
||||||
|
return null !== $this->getCategory();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is active
|
* Is active
|
||||||
* return true if the type is active.
|
* return true if the type is active.
|
||||||
|
@ -41,18 +41,11 @@ class BySocialActionAggregator implements AggregatorInterface
|
|||||||
public function alterQuery(QueryBuilder $qb, $data)
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
{
|
{
|
||||||
if (!in_array('actsocialaction', $qb->getAllAliases(), true)) {
|
if (!in_array('actsocialaction', $qb->getAllAliases(), true)) {
|
||||||
$qb->join('activity.socialActions', 'actsocialaction');
|
$qb->leftJoin('activity.socialActions', 'actsocialaction');
|
||||||
}
|
}
|
||||||
|
|
||||||
$qb->addSelect('actsocialaction.id AS socialaction_aggregator');
|
$qb->addSelect('actsocialaction.id AS socialaction_aggregator');
|
||||||
|
$qb->addGroupBy('socialaction_aggregator');
|
||||||
$groupBy = $qb->getDQLPart('groupBy');
|
|
||||||
|
|
||||||
if (!empty($groupBy)) {
|
|
||||||
$qb->addGroupBy('socialaction_aggregator');
|
|
||||||
} else {
|
|
||||||
$qb->groupBy('socialaction_aggregator');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function applyOn(): string
|
public function applyOn(): string
|
||||||
@ -72,6 +65,10 @@ class BySocialActionAggregator implements AggregatorInterface
|
|||||||
return 'Social action';
|
return 'Social action';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (null === $value) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
$sa = $this->actionRepository->find($value);
|
$sa = $this->actionRepository->find($value);
|
||||||
|
|
||||||
return $this->actionRender->renderString($sa, []);
|
return $this->actionRender->renderString($sa, []);
|
||||||
|
@ -41,18 +41,11 @@ class BySocialIssueAggregator implements AggregatorInterface
|
|||||||
public function alterQuery(QueryBuilder $qb, $data)
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
{
|
{
|
||||||
if (!in_array('actsocialissue', $qb->getAllAliases(), true)) {
|
if (!in_array('actsocialissue', $qb->getAllAliases(), true)) {
|
||||||
$qb->join('activity.socialIssues', 'actsocialissue');
|
$qb->leftJoin('activity.socialIssues', 'actsocialissue');
|
||||||
}
|
}
|
||||||
|
|
||||||
$qb->addSelect('actsocialissue.id AS socialissue_aggregator');
|
$qb->addSelect('actsocialissue.id AS socialissue_aggregator');
|
||||||
|
$qb->addGroupBy('socialissue_aggregator');
|
||||||
$groupBy = $qb->getDQLPart('groupBy');
|
|
||||||
|
|
||||||
if (!empty($groupBy)) {
|
|
||||||
$qb->addGroupBy('socialissue_aggregator');
|
|
||||||
} else {
|
|
||||||
$qb->groupBy('socialissue_aggregator');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function applyOn(): string
|
public function applyOn(): string
|
||||||
@ -72,6 +65,10 @@ class BySocialIssueAggregator implements AggregatorInterface
|
|||||||
return 'Social issues';
|
return 'Social issues';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (null === $value) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
$i = $this->issueRepository->find($value);
|
$i = $this->issueRepository->find($value);
|
||||||
|
|
||||||
return $this->issueRender->renderString($i, []);
|
return $this->issueRender->renderString($i, []);
|
||||||
|
@ -41,18 +41,11 @@ class ByThirdpartyAggregator implements AggregatorInterface
|
|||||||
public function alterQuery(QueryBuilder $qb, $data)
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
{
|
{
|
||||||
if (!in_array('acttparty', $qb->getAllAliases(), true)) {
|
if (!in_array('acttparty', $qb->getAllAliases(), true)) {
|
||||||
$qb->join('activity.thirdParties', 'acttparty');
|
$qb->leftJoin('activity.thirdParties', 'acttparty');
|
||||||
}
|
}
|
||||||
|
|
||||||
$qb->addSelect('acttparty.id AS thirdparty_aggregator');
|
$qb->addSelect('acttparty.id AS thirdparty_aggregator');
|
||||||
|
$qb->addGroupBy('thirdparty_aggregator');
|
||||||
$groupBy = $qb->getDQLPart('groupBy');
|
|
||||||
|
|
||||||
if (!empty($groupBy)) {
|
|
||||||
$qb->addGroupBy('thirdparty_aggregator');
|
|
||||||
} else {
|
|
||||||
$qb->groupBy('thirdparty_aggregator');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function applyOn(): string
|
public function applyOn(): string
|
||||||
@ -72,6 +65,10 @@ class ByThirdpartyAggregator implements AggregatorInterface
|
|||||||
return 'Accepted thirdparty';
|
return 'Accepted thirdparty';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (null === $value) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
$tp = $this->thirdPartyRepository->find($value);
|
$tp = $this->thirdPartyRepository->find($value);
|
||||||
|
|
||||||
return $this->thirdPartyRender->renderString($tp, []);
|
return $this->thirdPartyRender->renderString($tp, []);
|
||||||
|
@ -41,18 +41,11 @@ class ByUserAggregator implements AggregatorInterface
|
|||||||
public function alterQuery(QueryBuilder $qb, $data)
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
{
|
{
|
||||||
if (!in_array('actusers', $qb->getAllAliases(), true)) {
|
if (!in_array('actusers', $qb->getAllAliases(), true)) {
|
||||||
$qb->join('activity.users', 'actusers');
|
$qb->leftJoin('activity.users', 'actusers');
|
||||||
}
|
}
|
||||||
|
|
||||||
$qb->addSelect('actusers.id AS users_aggregator');
|
$qb->addSelect('actusers.id AS users_aggregator');
|
||||||
|
$qb->addGroupBy('users_aggregator');
|
||||||
$groupBy = $qb->getDQLPart('groupBy');
|
|
||||||
|
|
||||||
if (!empty($groupBy)) {
|
|
||||||
$qb->addGroupBy('users_aggregator');
|
|
||||||
} else {
|
|
||||||
$qb->groupBy('users_aggregator');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function applyOn(): string
|
public function applyOn(): string
|
||||||
@ -72,6 +65,10 @@ class ByUserAggregator implements AggregatorInterface
|
|||||||
return 'Accepted users';
|
return 'Accepted users';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (null === $value) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
$u = $this->userRepository->find($value);
|
$u = $this->userRepository->find($value);
|
||||||
|
|
||||||
return $this->userRender->renderString($u, []);
|
return $this->userRender->renderString($u, []);
|
||||||
|
@ -49,41 +49,24 @@ class DateAggregator implements AggregatorInterface
|
|||||||
|
|
||||||
switch ($data['frequency']) {
|
switch ($data['frequency']) {
|
||||||
case 'month':
|
case 'month':
|
||||||
$fmt = 'MM';
|
$fmt = 'YYYY-MM';
|
||||||
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case 'week':
|
case 'week':
|
||||||
$fmt = 'IW';
|
$fmt = 'YYYY-IW';
|
||||||
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case 'year':
|
case 'year':
|
||||||
$fmt = 'YYYY'; $order = 'DESC';
|
$fmt = 'YYYY'; $order = 'DESC';
|
||||||
|
break; // order DESC does not works !
|
||||||
break; // order DESC does not works !
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new RuntimeException(sprintf("The frequency data '%s' is invalid.", $data['frequency']));
|
throw new RuntimeException(sprintf("The frequency data '%s' is invalid.", $data['frequency']));
|
||||||
}
|
}
|
||||||
|
|
||||||
$qb->addSelect(sprintf("TO_CHAR(activity.date, '%s') AS date_aggregator", $fmt));
|
$qb->addSelect(sprintf("TO_CHAR(activity.date, '%s') AS date_aggregator", $fmt));
|
||||||
|
$qb->addGroupBy('date_aggregator');
|
||||||
$groupBy = $qb->getDQLPart('groupBy');
|
$qb->addOrderBy('date_aggregator', $order);
|
||||||
|
|
||||||
if (!empty($groupBy)) {
|
|
||||||
$qb->addGroupBy('date_aggregator');
|
|
||||||
} else {
|
|
||||||
$qb->groupBy('date_aggregator');
|
|
||||||
}
|
|
||||||
|
|
||||||
$orderBy = $qb->getDQLPart('orderBy');
|
|
||||||
|
|
||||||
if (!empty($orderBy)) {
|
|
||||||
$qb->addOrderBy('date_aggregator', $order);
|
|
||||||
} else {
|
|
||||||
$qb->orderBy('date_aggregator', $order);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function applyOn(): string
|
public function applyOn(): string
|
||||||
@ -109,15 +92,12 @@ break; // order DESC does not works !
|
|||||||
return 'by ' . $data['frequency'];
|
return 'by ' . $data['frequency'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (null === $value) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
switch ($data['frequency']) {
|
switch ($data['frequency']) {
|
||||||
case 'month':
|
case 'month':
|
||||||
$month = DateTime::createFromFormat('!m', $value);
|
|
||||||
|
|
||||||
return sprintf(
|
|
||||||
'%02d (%s)',
|
|
||||||
$value,
|
|
||||||
$month->format('M')
|
|
||||||
);
|
|
||||||
|
|
||||||
case 'week':
|
case 'week':
|
||||||
//return $this->translator->trans('for week') .' '. $value ;
|
//return $this->translator->trans('for week') .' '. $value ;
|
||||||
|
@ -41,18 +41,11 @@ class LocationTypeAggregator implements AggregatorInterface
|
|||||||
public function alterQuery(QueryBuilder $qb, $data)
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
{
|
{
|
||||||
if (!in_array('actloc', $qb->getAllAliases(), true)) {
|
if (!in_array('actloc', $qb->getAllAliases(), true)) {
|
||||||
$qb->join('activity.location', 'actloc');
|
$qb->leftJoin('activity.location', 'actloc');
|
||||||
}
|
}
|
||||||
|
|
||||||
$qb->addSelect('IDENTITY(actloc.locationType) AS locationtype_aggregator');
|
$qb->addSelect('IDENTITY(actloc.locationType) AS locationtype_aggregator');
|
||||||
|
$qb->addGroupBy('locationtype_aggregator');
|
||||||
$groupBy = $qb->getDQLPart('groupBy');
|
|
||||||
|
|
||||||
if (!empty($groupBy)) {
|
|
||||||
$qb->addGroupBy('locationtype_aggregator');
|
|
||||||
} else {
|
|
||||||
$qb->groupBy('locationtype_aggregator');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function applyOn(): string
|
public function applyOn(): string
|
||||||
@ -72,6 +65,10 @@ class LocationTypeAggregator implements AggregatorInterface
|
|||||||
return 'Accepted locationtype';
|
return 'Accepted locationtype';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (null === $value) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
$lt = $this->locationTypeRepository->find($value);
|
$lt = $this->locationTypeRepository->find($value);
|
||||||
|
|
||||||
return $this->translatableStringHelper->localize(
|
return $this->translatableStringHelper->localize(
|
||||||
|
@ -41,18 +41,11 @@ class UserScopeAggregator implements AggregatorInterface
|
|||||||
public function alterQuery(QueryBuilder $qb, $data)
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
{
|
{
|
||||||
if (!in_array('actuser', $qb->getAllAliases(), true)) {
|
if (!in_array('actuser', $qb->getAllAliases(), true)) {
|
||||||
$qb->join('activity.user', 'actuser');
|
$qb->leftJoin('activity.user', 'actuser');
|
||||||
}
|
}
|
||||||
|
|
||||||
$qb->addSelect('IDENTITY(actuser.mainScope) AS userscope_aggregator');
|
$qb->addSelect('IDENTITY(actuser.mainScope) AS userscope_aggregator');
|
||||||
|
$qb->addGroupBy('userscope_aggregator');
|
||||||
$groupBy = $qb->getDQLPart('groupBy');
|
|
||||||
|
|
||||||
if (!empty($groupBy)) {
|
|
||||||
$qb->addGroupBy('userscope_aggregator');
|
|
||||||
} else {
|
|
||||||
$qb->groupBy('userscope_aggregator');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function applyOn(): string
|
public function applyOn(): string
|
||||||
@ -72,6 +65,10 @@ class UserScopeAggregator implements AggregatorInterface
|
|||||||
return 'Scope';
|
return 'Scope';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (null === $value) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
$s = $this->scopeRepository->find($value);
|
$s = $this->scopeRepository->find($value);
|
||||||
|
|
||||||
return $this->translatableStringHelper->localize(
|
return $this->translatableStringHelper->localize(
|
||||||
|
@ -12,7 +12,7 @@ declare(strict_types=1);
|
|||||||
namespace Chill\ActivityBundle\Export\Aggregator;
|
namespace Chill\ActivityBundle\Export\Aggregator;
|
||||||
|
|
||||||
use Chill\ActivityBundle\Export\Declarations;
|
use Chill\ActivityBundle\Export\Declarations;
|
||||||
use Chill\ActivityBundle\Repository\ActivityTypeRepository;
|
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
|
||||||
use Chill\MainBundle\Export\AggregatorInterface;
|
use Chill\MainBundle\Export\AggregatorInterface;
|
||||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||||
use Closure;
|
use Closure;
|
||||||
@ -25,12 +25,12 @@ class ActivityTypeAggregator implements AggregatorInterface
|
|||||||
{
|
{
|
||||||
public const KEY = 'activity_type_aggregator';
|
public const KEY = 'activity_type_aggregator';
|
||||||
|
|
||||||
protected ActivityTypeRepository $activityTypeRepository;
|
protected ActivityTypeRepositoryInterface $activityTypeRepository;
|
||||||
|
|
||||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
ActivityTypeRepository $activityTypeRepository,
|
ActivityTypeRepositoryInterface $activityTypeRepository,
|
||||||
TranslatableStringHelperInterface $translatableStringHelper
|
TranslatableStringHelperInterface $translatableStringHelper
|
||||||
) {
|
) {
|
||||||
$this->activityTypeRepository = $activityTypeRepository;
|
$this->activityTypeRepository = $activityTypeRepository;
|
||||||
@ -49,14 +49,7 @@ class ActivityTypeAggregator implements AggregatorInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
$qb->addSelect(sprintf('IDENTITY(activity.activityType) AS %s', self::KEY));
|
$qb->addSelect(sprintf('IDENTITY(activity.activityType) AS %s', self::KEY));
|
||||||
|
$qb->addGroupBy(self::KEY);
|
||||||
$groupby = $qb->getDQLPart('groupBy');
|
|
||||||
|
|
||||||
if (!empty($groupBy)) {
|
|
||||||
$qb->addGroupBy(self::KEY);
|
|
||||||
} else {
|
|
||||||
$qb->groupBy(self::KEY);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function applyOn(): string
|
public function applyOn(): string
|
||||||
@ -79,6 +72,10 @@ class ActivityTypeAggregator implements AggregatorInterface
|
|||||||
return 'Activity type';
|
return 'Activity type';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (null === $value) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
$t = $this->activityTypeRepository->find($value);
|
$t = $this->activityTypeRepository->find($value);
|
||||||
|
|
||||||
return $this->translatableStringHelper->localize($t->getName());
|
return $this->translatableStringHelper->localize($t->getName());
|
||||||
|
@ -61,14 +61,15 @@ class ActivityUserAggregator implements AggregatorInterface
|
|||||||
|
|
||||||
public function getLabels($key, $values, $data): Closure
|
public function getLabels($key, $values, $data): Closure
|
||||||
{
|
{
|
||||||
// preload users at once
|
return function ($value) {
|
||||||
$this->userRepository->findBy(['id' => $values]);
|
|
||||||
|
|
||||||
return function ($value) {
|
|
||||||
if ('_header' === $value) {
|
if ('_header' === $value) {
|
||||||
return 'Activity user';
|
return 'Activity user';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (null === $value) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
$u = $this->userRepository->find($value);
|
$u = $this->userRepository->find($value);
|
||||||
|
|
||||||
return $this->userRender->renderString($u, []);
|
return $this->userRender->renderString($u, []);
|
||||||
|
@ -55,10 +55,10 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
|
|||||||
{
|
{
|
||||||
// add select element
|
// add select element
|
||||||
if ('reasons' === $data['level']) {
|
if ('reasons' === $data['level']) {
|
||||||
$elem = 'reasons.id';
|
$elem = 'actreasons.id';
|
||||||
$alias = 'activity_reasons_id';
|
$alias = 'activity_reasons_id';
|
||||||
} elseif ('categories' === $data['level']) {
|
} elseif ('categories' === $data['level']) {
|
||||||
$elem = 'category.id';
|
$elem = 'actreasoncat.id';
|
||||||
$alias = 'activity_categories_id';
|
$alias = 'activity_categories_id';
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException('The data provided are not recognized.');
|
throw new RuntimeException('The data provided are not recognized.');
|
||||||
|
@ -17,6 +17,9 @@ use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
|||||||
use Chill\MainBundle\Export\ExportInterface;
|
use Chill\MainBundle\Export\ExportInterface;
|
||||||
use Chill\MainBundle\Export\FormatterInterface;
|
use Chill\MainBundle\Export\FormatterInterface;
|
||||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
|
||||||
|
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||||
|
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Doctrine\ORM\EntityRepository;
|
use Doctrine\ORM\EntityRepository;
|
||||||
use Doctrine\ORM\Query;
|
use Doctrine\ORM\Query;
|
||||||
@ -34,7 +37,6 @@ class AvgActivityDuration implements ExportInterface, GroupedExportInterface
|
|||||||
|
|
||||||
public function buildForm(FormBuilderInterface $builder)
|
public function buildForm(FormBuilderInterface $builder)
|
||||||
{
|
{
|
||||||
// TODO: Implement buildForm() method.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAllowedFormattersTypes(): array
|
public function getAllowedFormattersTypes(): array
|
||||||
@ -55,7 +57,7 @@ class AvgActivityDuration implements ExportInterface, GroupedExportInterface
|
|||||||
public function getLabels($key, array $values, $data)
|
public function getLabels($key, array $values, $data)
|
||||||
{
|
{
|
||||||
if ('export_avg_activity_duration' !== $key) {
|
if ('export_avg_activity_duration' !== $key) {
|
||||||
throw new LogicException("the key {$key} is not used by this export");
|
throw new \LogicException("the key {$key} is not used by this export");
|
||||||
}
|
}
|
||||||
|
|
||||||
return static fn ($value) => '_header' === $value ? 'Average activities linked to an accompanying period duration' : $value;
|
return static fn ($value) => '_header' === $value ? 'Average activities linked to an accompanying period duration' : $value;
|
||||||
@ -83,10 +85,28 @@ class AvgActivityDuration implements ExportInterface, GroupedExportInterface
|
|||||||
|
|
||||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
||||||
{
|
{
|
||||||
$qb = $this->repository->createQueryBuilder('activity')
|
$centers = array_map(static function ($el) {
|
||||||
->join('activity.accompanyingPeriod', 'actacp');
|
return $el['center'];
|
||||||
|
}, $acl);
|
||||||
|
|
||||||
$qb->select('AVG(activity.durationTime) as export_avg_activity_duration');
|
$qb = $this->repository->createQueryBuilder('activity');
|
||||||
|
|
||||||
|
$qb
|
||||||
|
->join('activity.accompanyingPeriod', 'acp')
|
||||||
|
->select('AVG(activity.durationTime) as export_avg_activity_duration')
|
||||||
|
->andWhere($qb->expr()->isNotNull('activity.durationTime'));
|
||||||
|
|
||||||
|
$qb
|
||||||
|
->andWhere(
|
||||||
|
$qb->expr()->exists(
|
||||||
|
'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part
|
||||||
|
JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||||
|
WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
|
||||||
|
'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
->setParameter('authorized_centers', $centers)
|
||||||
|
;
|
||||||
|
|
||||||
return $qb;
|
return $qb;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,9 @@ use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
|||||||
use Chill\MainBundle\Export\ExportInterface;
|
use Chill\MainBundle\Export\ExportInterface;
|
||||||
use Chill\MainBundle\Export\FormatterInterface;
|
use Chill\MainBundle\Export\FormatterInterface;
|
||||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
|
||||||
|
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||||
|
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Doctrine\ORM\EntityRepository;
|
use Doctrine\ORM\EntityRepository;
|
||||||
use Doctrine\ORM\Query;
|
use Doctrine\ORM\Query;
|
||||||
@ -55,7 +58,7 @@ class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterfac
|
|||||||
public function getLabels($key, array $values, $data)
|
public function getLabels($key, array $values, $data)
|
||||||
{
|
{
|
||||||
if ('export_avg_activity_visit_duration' !== $key) {
|
if ('export_avg_activity_visit_duration' !== $key) {
|
||||||
throw new LogicException("the key {$key} is not used by this export");
|
throw new \LogicException("the key {$key} is not used by this export");
|
||||||
}
|
}
|
||||||
|
|
||||||
return static fn ($value) => '_header' === $value ? 'Average activities linked to an accompanying period visit duration' : $value;
|
return static fn ($value) => '_header' === $value ? 'Average activities linked to an accompanying period visit duration' : $value;
|
||||||
@ -83,10 +86,29 @@ class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterfac
|
|||||||
|
|
||||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
||||||
{
|
{
|
||||||
$qb = $this->repository->createQueryBuilder('activity')
|
$centers = array_map(static function ($el) {
|
||||||
->join('activity.accompanyingPeriod', 'actacp');
|
return $el['center'];
|
||||||
|
}, $acl);
|
||||||
|
|
||||||
$qb->select('AVG(activity.travelTime) as export_avg_activity_visit_duration');
|
$qb = $this->repository->createQueryBuilder('activity');
|
||||||
|
|
||||||
|
$qb
|
||||||
|
->join('activity.accompanyingPeriod', 'acp')
|
||||||
|
->select('AVG(activity.travelTime) as export_avg_activity_visit_duration')
|
||||||
|
->andWhere($qb->expr()->isNotNull('activity.travelTime'))
|
||||||
|
;
|
||||||
|
|
||||||
|
$qb
|
||||||
|
->andWhere(
|
||||||
|
$qb->expr()->exists(
|
||||||
|
'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part
|
||||||
|
JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||||
|
WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
|
||||||
|
'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
->setParameter('authorized_centers', $centers)
|
||||||
|
;
|
||||||
|
|
||||||
return $qb;
|
return $qb;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@ use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
|||||||
use Chill\MainBundle\Export\ExportInterface;
|
use Chill\MainBundle\Export\ExportInterface;
|
||||||
use Chill\MainBundle\Export\FormatterInterface;
|
use Chill\MainBundle\Export\FormatterInterface;
|
||||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
|
||||||
|
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||||
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Doctrine\ORM\EntityRepository;
|
use Doctrine\ORM\EntityRepository;
|
||||||
@ -84,13 +86,27 @@ class CountActivity implements ExportInterface, GroupedExportInterface
|
|||||||
|
|
||||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
||||||
{
|
{
|
||||||
$qb = $this->repository->createQueryBuilder('activity');
|
$centers = array_map(static function ($el) {
|
||||||
|
return $el['center'];
|
||||||
|
}, $acl);
|
||||||
|
|
||||||
if (!in_array('actacp', $qb->getAllAliases(), true)) {
|
$qb = $this->repository
|
||||||
$qb->join('activity.accompanyingPeriod', 'actacp');
|
->createQueryBuilder('activity')
|
||||||
}
|
->join('activity.accompanyingPeriod', 'acp');
|
||||||
|
|
||||||
$qb->select('COUNT(activity.id) as export_count_activity');
|
$qb
|
||||||
|
->andWhere(
|
||||||
|
$qb->expr()->exists(
|
||||||
|
'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part
|
||||||
|
JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||||
|
WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
|
||||||
|
'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
->setParameter('authorized_centers', $centers)
|
||||||
|
;
|
||||||
|
|
||||||
|
$qb->select('COUNT(DISTINCT activity.id) as export_count_activity');
|
||||||
|
|
||||||
return $qb;
|
return $qb;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,9 @@ use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
|||||||
use Chill\MainBundle\Export\ExportInterface;
|
use Chill\MainBundle\Export\ExportInterface;
|
||||||
use Chill\MainBundle\Export\FormatterInterface;
|
use Chill\MainBundle\Export\FormatterInterface;
|
||||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
|
||||||
|
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||||
|
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Doctrine\ORM\EntityRepository;
|
use Doctrine\ORM\EntityRepository;
|
||||||
use Doctrine\ORM\Query;
|
use Doctrine\ORM\Query;
|
||||||
@ -55,7 +58,7 @@ class SumActivityDuration implements ExportInterface, GroupedExportInterface
|
|||||||
public function getLabels($key, array $values, $data)
|
public function getLabels($key, array $values, $data)
|
||||||
{
|
{
|
||||||
if ('export_sum_activity_duration' !== $key) {
|
if ('export_sum_activity_duration' !== $key) {
|
||||||
throw new LogicException("the key {$key} is not used by this export");
|
throw new \LogicException("the key {$key} is not used by this export");
|
||||||
}
|
}
|
||||||
|
|
||||||
return static fn ($value) => '_header' === $value ? 'Sum activities linked to an accompanying period duration' : $value;
|
return static fn ($value) => '_header' === $value ? 'Sum activities linked to an accompanying period duration' : $value;
|
||||||
@ -83,13 +86,28 @@ class SumActivityDuration implements ExportInterface, GroupedExportInterface
|
|||||||
|
|
||||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
||||||
{
|
{
|
||||||
$qb = $this->repository->createQueryBuilder('activity');
|
$centers = array_map(static function ($el) {
|
||||||
|
return $el['center'];
|
||||||
|
}, $acl);
|
||||||
|
|
||||||
if (!in_array('actacp', $qb->getAllAliases(), true)) {
|
$qb = $this->repository
|
||||||
$qb->join('activity.accompanyingPeriod', 'actacp');
|
->createQueryBuilder('activity')
|
||||||
}
|
->join('activity.accompanyingPeriod', 'acp');
|
||||||
|
|
||||||
$qb->select('SUM(activity.durationTime) as export_sum_activity_duration');
|
$qb->select('SUM(activity.durationTime) as export_sum_activity_duration')
|
||||||
|
->andWhere($qb->expr()->isNotNull('activity.durationTime'));
|
||||||
|
|
||||||
|
$qb
|
||||||
|
->andWhere(
|
||||||
|
$qb->expr()->exists(
|
||||||
|
'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part
|
||||||
|
JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||||
|
WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
|
||||||
|
'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
->setParameter('authorized_centers', $centers)
|
||||||
|
;
|
||||||
|
|
||||||
return $qb;
|
return $qb;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,9 @@ use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
|||||||
use Chill\MainBundle\Export\ExportInterface;
|
use Chill\MainBundle\Export\ExportInterface;
|
||||||
use Chill\MainBundle\Export\FormatterInterface;
|
use Chill\MainBundle\Export\FormatterInterface;
|
||||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
|
||||||
|
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||||
|
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Doctrine\ORM\EntityRepository;
|
use Doctrine\ORM\EntityRepository;
|
||||||
use Doctrine\ORM\Query;
|
use Doctrine\ORM\Query;
|
||||||
@ -55,7 +58,7 @@ class SumActivityVisitDuration implements ExportInterface, GroupedExportInterfac
|
|||||||
public function getLabels($key, array $values, $data)
|
public function getLabels($key, array $values, $data)
|
||||||
{
|
{
|
||||||
if ('export_sum_activity_visit_duration' !== $key) {
|
if ('export_sum_activity_visit_duration' !== $key) {
|
||||||
throw new LogicException("the key {$key} is not used by this export");
|
throw new \LogicException("the key {$key} is not used by this export");
|
||||||
}
|
}
|
||||||
|
|
||||||
return static fn ($value) => '_header' === $value ? 'Sum activities linked to an accompanying period visit duration' : $value;
|
return static fn ($value) => '_header' === $value ? 'Sum activities linked to an accompanying period visit duration' : $value;
|
||||||
@ -83,13 +86,28 @@ class SumActivityVisitDuration implements ExportInterface, GroupedExportInterfac
|
|||||||
|
|
||||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
||||||
{
|
{
|
||||||
$qb = $this->repository->createQueryBuilder('activity');
|
$centers = array_map(static function ($el) {
|
||||||
|
return $el['center'];
|
||||||
|
}, $acl);
|
||||||
|
|
||||||
if (!in_array('actacp', $qb->getAllAliases(), true)) {
|
$qb = $this->repository
|
||||||
$qb->join('activity.accompanyingPeriod', 'actacp');
|
->createQueryBuilder('activity')
|
||||||
}
|
->join('activity.accompanyingPeriod', 'acp');
|
||||||
|
|
||||||
$qb->select('SUM(activity.travelTime) as export_sum_activity_visit_duration');
|
$qb->select('SUM(activity.travelTime) as export_sum_activity_visit_duration')
|
||||||
|
->andWhere($qb->expr()->isNotNull('activity.travelTime'));
|
||||||
|
|
||||||
|
$qb
|
||||||
|
->andWhere(
|
||||||
|
$qb->expr()->exists(
|
||||||
|
'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part
|
||||||
|
JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||||
|
WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
|
||||||
|
'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
->setParameter('authorized_centers', $centers)
|
||||||
|
;
|
||||||
|
|
||||||
return $qb;
|
return $qb;
|
||||||
}
|
}
|
||||||
|
@ -84,16 +84,25 @@ class CountActivity implements ExportInterface, GroupedExportInterface
|
|||||||
{
|
{
|
||||||
$centers = array_map(static fn ($el) => $el['center'], $acl);
|
$centers = array_map(static fn ($el) => $el['center'], $acl);
|
||||||
|
|
||||||
$qb = $this->activityRepository->createQueryBuilder('activity');
|
$qb = $this->activityRepository
|
||||||
|
->createQueryBuilder('activity')
|
||||||
if (!in_array('actperson', $qb->getAllAliases(), true)) {
|
->join('activity.person', 'person')
|
||||||
$qb->join('activity.person', 'actperson');
|
->join('person.centerHistory', 'centerHistory')
|
||||||
}
|
;
|
||||||
|
|
||||||
$qb->select('COUNT(activity.id) as export_count_activity');
|
$qb->select('COUNT(activity.id) as export_count_activity');
|
||||||
|
|
||||||
$qb
|
$qb
|
||||||
->where($qb->expr()->in('person.center', ':centers'))
|
->where(
|
||||||
|
$qb->expr()->andX(
|
||||||
|
$qb->expr()->lte('centerHistory.startDate', 'activity.date'),
|
||||||
|
$qb->expr()->orX(
|
||||||
|
$qb->expr()->isNull('centerHistory.endDate'),
|
||||||
|
$qb->expr()->gt('centerHistory.endDate', 'activity.date')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
->andWhere($qb->expr()->in('centerHistory.center', ':centers'))
|
||||||
->setParameter('centers', $centers);
|
->setParameter('centers', $centers);
|
||||||
|
|
||||||
return $qb;
|
return $qb;
|
||||||
|
@ -210,7 +210,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
|||||||
|
|
||||||
$qb
|
$qb
|
||||||
->from('ChillActivityBundle:Activity', 'activity')
|
->from('ChillActivityBundle:Activity', 'activity')
|
||||||
->join('activity.person', 'actperson')
|
->join('activity.person', 'person')
|
||||||
->join('actperson.center', 'actcenter')
|
->join('actperson.center', 'actcenter')
|
||||||
->andWhere('actcenter IN (:authorized_centers)')
|
->andWhere('actcenter IN (:authorized_centers)')
|
||||||
->setParameter('authorized_centers', $centers);
|
->setParameter('authorized_centers', $centers);
|
||||||
|
@ -119,11 +119,24 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
|
|||||||
$select = 'SUM(activity.durationTime) AS export_stat_activity';
|
$select = 'SUM(activity.durationTime) AS export_stat_activity';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $qb->select($select)
|
$qb->select($select)
|
||||||
->join('activity.person', 'actperson')
|
->join('activity.person', 'person')
|
||||||
->join('actperson.center', 'actcenter')
|
->join('person.centerHistory', 'centerHistory');
|
||||||
->where($qb->expr()->in('actcenter', ':centers'))
|
|
||||||
->setParameter(':centers', $centers);
|
$qb
|
||||||
|
->where(
|
||||||
|
$qb->expr()->andX(
|
||||||
|
$qb->expr()->lte('centerHistory.startDate', 'activity.date'),
|
||||||
|
$qb->expr()->orX(
|
||||||
|
$qb->expr()->isNull('centerHistory.endDate'),
|
||||||
|
$qb->expr()->gt('centerHistory.endDate', 'activity.date')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
->andWhere($qb->expr()->in('centerHistory.center', ':centers'))
|
||||||
|
->setParameter('centers', $centers);
|
||||||
|
|
||||||
|
return $qb;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function requiredRole(): string
|
public function requiredRole(): string
|
||||||
|
@ -13,8 +13,9 @@ namespace Chill\ActivityBundle\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\Repository\ActivityTypeRepositoryInterface;
|
||||||
use Chill\MainBundle\Export\FilterInterface;
|
use Chill\MainBundle\Export\FilterInterface;
|
||||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||||
use Chill\PersonBundle\Export\Declarations;
|
use Chill\PersonBundle\Export\Declarations;
|
||||||
use Doctrine\ORM\Query\Expr;
|
use Doctrine\ORM\Query\Expr;
|
||||||
use Doctrine\ORM\Query\Expr\Andx;
|
use Doctrine\ORM\Query\Expr\Andx;
|
||||||
@ -22,15 +23,17 @@ use Doctrine\ORM\QueryBuilder;
|
|||||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO merge with ActivityTypeFilter in ChillActivity (!?).
|
|
||||||
*/
|
|
||||||
class ActivityTypeFilter implements FilterInterface
|
class ActivityTypeFilter implements FilterInterface
|
||||||
{
|
{
|
||||||
private TranslatableStringHelper $translatableStringHelper;
|
private ActivityTypeRepositoryInterface $activityTypeRepository;
|
||||||
|
|
||||||
public function __construct(TranslatableStringHelper $translatableStringHelper)
|
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||||
{
|
|
||||||
|
public function __construct(
|
||||||
|
ActivityTypeRepositoryInterface $activityTypeRepository,
|
||||||
|
TranslatableStringHelperInterface $translatableStringHelper
|
||||||
|
) {
|
||||||
|
$this->activityTypeRepository = $activityTypeRepository;
|
||||||
$this->translatableStringHelper = $translatableStringHelper;
|
$this->translatableStringHelper = $translatableStringHelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,21 +48,10 @@ class ActivityTypeFilter implements FilterInterface
|
|||||||
$qb->join(Activity::class, 'activity', Expr\Join::WITH, 'activity.accompanyingPeriod = acp');
|
$qb->join(Activity::class, 'activity', Expr\Join::WITH, 'activity.accompanyingPeriod = acp');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!in_array('acttype', $qb->getAllAliases(), true)) {
|
$clause = $qb->expr()->in('activity.activityType', ':selected_activity_types');
|
||||||
$qb->join('activity.activityType', 'acttype');
|
|
||||||
}
|
|
||||||
|
|
||||||
$where = $qb->getDQLPart('where');
|
$qb->andWhere($clause);
|
||||||
$clause = $qb->expr()->in('acttype.id', ':activitytypes');
|
$qb->setParameter('selected_activity_types', $data['types']);
|
||||||
|
|
||||||
if ($where instanceof Andx) {
|
|
||||||
$where->add($clause);
|
|
||||||
} else {
|
|
||||||
$where = $qb->expr()->andX($clause);
|
|
||||||
}
|
|
||||||
|
|
||||||
$qb->add('where', $where);
|
|
||||||
$qb->setParameter('activitytypes', $data['accepted_activitytypes']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function applyOn()
|
public function applyOn()
|
||||||
@ -71,8 +63,12 @@ class ActivityTypeFilter implements FilterInterface
|
|||||||
{
|
{
|
||||||
$builder->add('accepted_activitytypes', EntityType::class, [
|
$builder->add('accepted_activitytypes', EntityType::class, [
|
||||||
'class' => ActivityType::class,
|
'class' => ActivityType::class,
|
||||||
|
'choices' => $this->activityTypeRepository->findAllActive(),
|
||||||
'choice_label' => function (ActivityType $aty) {
|
'choice_label' => function (ActivityType $aty) {
|
||||||
return $this->translatableStringHelper->localize($aty->getName());
|
return
|
||||||
|
($aty->hasCategory() ? $this->translatableStringHelper->localize($aty->getCategory()->getName()) . ' > ' : '')
|
||||||
|
.
|
||||||
|
$this->translatableStringHelper->localize($aty->getName());
|
||||||
},
|
},
|
||||||
'multiple' => true,
|
'multiple' => true,
|
||||||
'expanded' => true,
|
'expanded' => true,
|
||||||
@ -88,7 +84,7 @@ class ActivityTypeFilter implements FilterInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ['Filtered by activity types: only %activitytypes%', [
|
return ['Filtered by activity types: only %activitytypes%', [
|
||||||
'%activitytypes%' => implode(', ou ', $types),
|
'%activitytypes%' => implode(', ', $types),
|
||||||
]];
|
]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ namespace Chill\ActivityBundle\Export\Filter;
|
|||||||
|
|
||||||
use Chill\ActivityBundle\Entity\ActivityType;
|
use Chill\ActivityBundle\Entity\ActivityType;
|
||||||
use Chill\ActivityBundle\Export\Declarations;
|
use Chill\ActivityBundle\Export\Declarations;
|
||||||
use Chill\ActivityBundle\Repository\ActivityTypeRepository;
|
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
|
||||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||||
use Chill\MainBundle\Export\FilterInterface;
|
use Chill\MainBundle\Export\FilterInterface;
|
||||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||||
@ -28,13 +28,13 @@ use function count;
|
|||||||
|
|
||||||
class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInterface
|
class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInterface
|
||||||
{
|
{
|
||||||
protected ActivityTypeRepository $activityTypeRepository;
|
protected ActivityTypeRepositoryInterface $activityTypeRepository;
|
||||||
|
|
||||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
TranslatableStringHelperInterface $translatableStringHelper,
|
TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
ActivityTypeRepository $activityTypeRepository
|
ActivityTypeRepositoryInterface $activityTypeRepository
|
||||||
) {
|
) {
|
||||||
$this->translatableStringHelper = $translatableStringHelper;
|
$this->translatableStringHelper = $translatableStringHelper;
|
||||||
$this->activityTypeRepository = $activityTypeRepository;
|
$this->activityTypeRepository = $activityTypeRepository;
|
||||||
@ -47,16 +47,9 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
|
|||||||
|
|
||||||
public function alterQuery(QueryBuilder $qb, $data)
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
{
|
{
|
||||||
$where = $qb->getDQLPart('where');
|
|
||||||
$clause = $qb->expr()->in('activity.activityType', ':selected_activity_types');
|
$clause = $qb->expr()->in('activity.activityType', ':selected_activity_types');
|
||||||
|
|
||||||
if ($where instanceof Expr\Andx) {
|
$qb->andWhere($clause);
|
||||||
$where->add($clause);
|
|
||||||
} else {
|
|
||||||
$where = $qb->expr()->andX($clause);
|
|
||||||
}
|
|
||||||
|
|
||||||
$qb->add('where', $where);
|
|
||||||
$qb->setParameter('selected_activity_types', $data['types']);
|
$qb->setParameter('selected_activity_types', $data['types']);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,11 +61,26 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
|
|||||||
public function buildForm(FormBuilderInterface $builder)
|
public function buildForm(FormBuilderInterface $builder)
|
||||||
{
|
{
|
||||||
$builder->add('types', EntityType::class, [
|
$builder->add('types', EntityType::class, [
|
||||||
|
'choices' => $this->activityTypeRepository->findAllActive(),
|
||||||
'class' => ActivityType::class,
|
'class' => ActivityType::class,
|
||||||
'choice_label' => fn (ActivityType $type) => $this->translatableStringHelper->localize($type->getName()),
|
'choice_label' => function (ActivityType $aty) {
|
||||||
'group_by' => fn (ActivityType $type) => $this->translatableStringHelper->localize($type->getCategory()->getName()),
|
return
|
||||||
|
($aty->hasCategory() ? $this->translatableStringHelper->localize($aty->getCategory()->getName()) . ' > ' : '')
|
||||||
|
.
|
||||||
|
$this->translatableStringHelper->localize($aty->getName());
|
||||||
|
},
|
||||||
|
'group_by' => function (ActivityType $type) {
|
||||||
|
if (!$type->hasCategory()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->translatableStringHelper->localize($type->getCategory()->getName());
|
||||||
|
},
|
||||||
'multiple' => true,
|
'multiple' => true,
|
||||||
'expanded' => false,
|
'expanded' => false,
|
||||||
|
'attr' => [
|
||||||
|
'class' => 'select2'
|
||||||
|
]
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\ActivityBundle\Export\Filter\PersonFilters;
|
namespace Chill\ActivityBundle\Export\Filter\PersonFilters;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
use Chill\ActivityBundle\Entity\ActivityReason;
|
use Chill\ActivityBundle\Entity\ActivityReason;
|
||||||
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
|
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
|
||||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||||
@ -59,10 +60,10 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt
|
|||||||
|
|
||||||
public function alterQuery(QueryBuilder $qb, $data)
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
{
|
{
|
||||||
// create a query for activity
|
// create a subquery for activity
|
||||||
$sqb = $qb->getEntityManager()->createQueryBuilder();
|
$sqb = $qb->getEntityManager()->createQueryBuilder();
|
||||||
$sqb->select('person_person_having_activity.id')
|
$sqb->select('person_person_having_activity.id')
|
||||||
->from('ChillActivityBundle:Activity', 'activity_person_having_activity')
|
->from(Activity::class, 'activity_person_having_activity')
|
||||||
->join('activity_person_having_activity.person', 'person_person_having_activity');
|
->join('activity_person_having_activity.person', 'person_person_having_activity');
|
||||||
|
|
||||||
// add clause between date
|
// add clause between date
|
||||||
|
@ -12,7 +12,7 @@ declare(strict_types=1);
|
|||||||
namespace Chill\ActivityBundle\Form\Type;
|
namespace Chill\ActivityBundle\Form\Type;
|
||||||
|
|
||||||
use Chill\ActivityBundle\Entity\ActivityType;
|
use Chill\ActivityBundle\Entity\ActivityType;
|
||||||
use Chill\ActivityBundle\Repository\ActivityTypeRepository;
|
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
|
||||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||||
use Doctrine\DBAL\Types\Types;
|
use Doctrine\DBAL\Types\Types;
|
||||||
use Doctrine\ORM\QueryBuilder;
|
use Doctrine\ORM\QueryBuilder;
|
||||||
@ -23,37 +23,25 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
|
|||||||
|
|
||||||
class TranslatableActivityType extends AbstractType
|
class TranslatableActivityType extends AbstractType
|
||||||
{
|
{
|
||||||
protected ActivityTypeRepository $activityTypeRepository;
|
protected ActivityTypeRepositoryInterface $activityTypeRepository;
|
||||||
|
|
||||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
TranslatableStringHelperInterface $helper,
|
TranslatableStringHelperInterface $helper,
|
||||||
ActivityTypeRepository $activityTypeRepository
|
ActivityTypeRepositoryInterface $activityTypeRepository
|
||||||
) {
|
) {
|
||||||
$this->translatableStringHelper = $helper;
|
$this->translatableStringHelper = $helper;
|
||||||
$this->activityTypeRepository = $activityTypeRepository;
|
$this->activityTypeRepository = $activityTypeRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
|
||||||
{
|
|
||||||
/** @var QueryBuilder $qb */
|
|
||||||
$qb = $options['query_builder'];
|
|
||||||
|
|
||||||
if (true === $options['active_only']) {
|
|
||||||
$qb->where($qb->expr()->eq('at.active', ':active'));
|
|
||||||
$qb->setParameter('active', true, Types::BOOLEAN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function configureOptions(OptionsResolver $resolver)
|
public function configureOptions(OptionsResolver $resolver)
|
||||||
{
|
{
|
||||||
$resolver->setDefaults(
|
$resolver->setDefaults(
|
||||||
[
|
[
|
||||||
'class' => ActivityType::class,
|
'class' => ActivityType::class,
|
||||||
'active_only' => true,
|
'active_only' => true,
|
||||||
'query_builder' => $this->activityTypeRepository
|
'choices' => $this->activityTypeRepository->findAllActive(),
|
||||||
->createQueryBuilder('at'),
|
|
||||||
'choice_label' => function (ActivityType $type) {
|
'choice_label' => function (ActivityType $type) {
|
||||||
return $this->translatableStringHelper->localize($type->getName());
|
return $this->translatableStringHelper->localize($type->getName());
|
||||||
},
|
},
|
||||||
|
@ -13,18 +13,58 @@ namespace Chill\ActivityBundle\Repository;
|
|||||||
|
|
||||||
use Chill\ActivityBundle\Entity\ActivityType;
|
use Chill\ActivityBundle\Entity\ActivityType;
|
||||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Doctrine\ORM\EntityRepository;
|
||||||
use Doctrine\Persistence\ManagerRegistry;
|
use Doctrine\Persistence\ManagerRegistry;
|
||||||
|
use UnexpectedValueException;
|
||||||
|
|
||||||
/**
|
final class ActivityTypeRepository implements ActivityTypeRepositoryInterface
|
||||||
* @method ActivityType|null find($id, $lockMode = null, $lockVersion = null)
|
|
||||||
* @method ActivityType|null findOneBy(array $criteria, array $orderBy = null)
|
|
||||||
* @method ActivityType[] findAll()
|
|
||||||
* @method ActivityType[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
|
||||||
*/
|
|
||||||
class ActivityTypeRepository extends ServiceEntityRepository
|
|
||||||
{
|
{
|
||||||
public function __construct(ManagerRegistry $registry)
|
private EntityRepository $repository;
|
||||||
|
|
||||||
|
public function __construct(EntityManagerInterface $em)
|
||||||
{
|
{
|
||||||
parent::__construct($registry, ActivityType::class);
|
$this->repository = $em->getRepository(ActivityType::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array|ActivityType[]
|
||||||
|
*/
|
||||||
|
public function findAllActive(): array
|
||||||
|
{
|
||||||
|
return $this->findBy(['active' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function find($id): ?ActivityType
|
||||||
|
{
|
||||||
|
return $this->repository->find($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array|ActivityType[]
|
||||||
|
*/
|
||||||
|
public function findAll(): array
|
||||||
|
{
|
||||||
|
return $this->repository->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array|ActivityType[]
|
||||||
|
*/
|
||||||
|
public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array
|
||||||
|
{
|
||||||
|
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findOneBy(array $criteria): ?ActivityType
|
||||||
|
{
|
||||||
|
return $this->repository->findOneBy($criteria);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getClassName(): string
|
||||||
|
{
|
||||||
|
return ActivityType::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Repository;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\ActivityType;
|
||||||
|
use Doctrine\Persistence\ObjectRepository;
|
||||||
|
|
||||||
|
interface ActivityTypeRepositoryInterface extends ObjectRepository
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array|ActivityType[]
|
||||||
|
*/
|
||||||
|
public function findAllActive(): array;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
|
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\BySocialActionAggregator;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
final class BySocialActionAggregatorTest extends AbstractAggregatorTest
|
||||||
|
{
|
||||||
|
private BySocialActionAggregator $aggregator;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
$this->aggregator = self::$container->get('chill.activity.export.bysocialaction_aggregator');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAggregator()
|
||||||
|
{
|
||||||
|
return $this->aggregator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
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.accompanyingPeriod', 'acp')
|
||||||
|
->join('activity.socialActions', 'actsocialaction')
|
||||||
|
,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
|
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\BySocialIssueAggregator;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
final class BySocialIssueAggregatorTest extends AbstractAggregatorTest
|
||||||
|
{
|
||||||
|
private BySocialIssueAggregator $aggregator;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
$this->aggregator = self::$container->get('chill.activity.export.bysocialissue_aggregator');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAggregator()
|
||||||
|
{
|
||||||
|
return $this->aggregator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
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.accompanyingPeriod', 'acp')
|
||||||
|
->join('activity.socialIssues', 'actsocialissue')
|
||||||
|
,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
|
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\ByThirdpartyAggregator;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
final class ByThirdpartyAggregatorTest extends AbstractAggregatorTest
|
||||||
|
{
|
||||||
|
private ByThirdpartyAggregator $aggregator;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
$this->aggregator = self::$container->get('chill.activity.export.bythirdparty_aggregator');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAggregator()
|
||||||
|
{
|
||||||
|
return $this->aggregator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
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.accompanyingPeriod', 'acp')
|
||||||
|
->join('activity.thirdParties', 'acttparty')
|
||||||
|
,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
|
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\ByUserAggregator;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
final class ByUserAggregatorTest extends AbstractAggregatorTest
|
||||||
|
{
|
||||||
|
private ByUserAggregator $aggregator;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
$this->aggregator = self::$container->get('chill.activity.export.byuser_aggregator');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAggregator()
|
||||||
|
{
|
||||||
|
return $this->aggregator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
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.accompanyingPeriod', 'acp')
|
||||||
|
->join('activity.users', 'actusers')
|
||||||
|
,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
|
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\DateAggregator;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
final class DateAggregatorTest extends AbstractAggregatorTest
|
||||||
|
{
|
||||||
|
private DateAggregator $aggregator;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
$this->aggregator = self::$container->get('chill.activity.export.date_aggregator');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAggregator()
|
||||||
|
{
|
||||||
|
return $this->aggregator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'frequency' => 'month',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'frequency' => 'week',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'frequency' => 'year',
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
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.accompanyingPeriod', 'acp')
|
||||||
|
,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
|
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\LocationTypeAggregator;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
final class LocationTypeAggregatorTest extends AbstractAggregatorTest
|
||||||
|
{
|
||||||
|
private LocationTypeAggregator $aggregator;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
$this->aggregator = self::$container->get('chill.activity.export.locationtype_aggregator');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAggregator()
|
||||||
|
{
|
||||||
|
return $this->aggregator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
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.accompanyingPeriod', 'acp')
|
||||||
|
->join('activity.location', 'actloc')
|
||||||
|
,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
|
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\UserScopeAggregator;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
final class UserScopeAggregatorTest extends AbstractAggregatorTest
|
||||||
|
{
|
||||||
|
private UserScopeAggregator $aggregator;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
$this->aggregator = self::$container->get('chill.activity.export.userscope_aggregator');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAggregator()
|
||||||
|
{
|
||||||
|
return $this->aggregator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
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.accompanyingPeriod', 'acp')
|
||||||
|
->join('activity.user', 'actuser')
|
||||||
|
,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\ActivityBundle\Tests\Export\Aggregator;
|
namespace Chill\ActivityBundle\Tests\Export\Aggregator;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Export\Aggregator\PersonAggregators\ActivityReasonAggregator;
|
||||||
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,10 +22,7 @@ use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
|||||||
*/
|
*/
|
||||||
final class ActivityReasonAggregatorTest extends AbstractAggregatorTest
|
final class ActivityReasonAggregatorTest extends AbstractAggregatorTest
|
||||||
{
|
{
|
||||||
/**
|
private ActivityReasonAggregator $aggregator;
|
||||||
* @var \Chill\ActivityBundle\Export\Aggregator\ActivityReasonAggregator
|
|
||||||
*/
|
|
||||||
private $aggregator;
|
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
|
@ -11,6 +11,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\ActivityBundle\Tests\Export\Aggregator;
|
namespace Chill\ActivityBundle\Tests\Export\Aggregator;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Export\Aggregator\PersonAggregators\ActivityTypeAggregator;
|
||||||
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,10 +22,7 @@ use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
|||||||
*/
|
*/
|
||||||
final class ActivityTypeAggregatorTest extends AbstractAggregatorTest
|
final class ActivityTypeAggregatorTest extends AbstractAggregatorTest
|
||||||
{
|
{
|
||||||
/**
|
private ActivityTypeAggregator $aggregator;
|
||||||
* @var \Chill\ActivityBundle\Export\Aggregator\ActivityReasonAggregator
|
|
||||||
*/
|
|
||||||
private $aggregator;
|
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
|
@ -11,6 +11,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\ActivityBundle\Tests\Export\Aggregator;
|
namespace Chill\ActivityBundle\Tests\Export\Aggregator;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Export\Aggregator\ActivityUserAggregator;
|
||||||
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,10 +22,7 @@ use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
|||||||
*/
|
*/
|
||||||
final class ActivityUserAggregatorTest extends AbstractAggregatorTest
|
final class ActivityUserAggregatorTest extends AbstractAggregatorTest
|
||||||
{
|
{
|
||||||
/**
|
private ActivityUserAggregator $aggregator;
|
||||||
* @var \Chill\ActivityBundle\Export\Aggregator\ActivityUserAggregator
|
|
||||||
*/
|
|
||||||
private $aggregator;
|
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Tests\Export\Aggregator\PersonAggregators;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
|
use Chill\ActivityBundle\Export\Aggregator\PersonAggregators\ActivityReasonAggregator;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
final class ActivityReasonAggregatorTest extends AbstractAggregatorTest
|
||||||
|
{
|
||||||
|
private ActivityReasonAggregator $aggregator;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
$this->aggregator = self::$container->get('chill.activity.export.reason_aggregator');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAggregator()
|
||||||
|
{
|
||||||
|
return $this->aggregator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'level' => 'reasons',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'level' => 'categories',
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
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.person', 'actperson')
|
||||||
|
->innerJoin('activity.reasons', 'actreasons')
|
||||||
|
->join('actreasons.category', 'actreasoncat')
|
||||||
|
,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Tests\Export\Filter\ACPFilters;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
|
use Chill\ActivityBundle\Entity\ActivityType;
|
||||||
|
use Chill\ActivityBundle\Export\Filter\ACPFilters\ActivityTypeFilter;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractFilterTest;
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Doctrine\ORM\Query\Expr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
final class ActivityTypeFilterTest extends AbstractFilterTest
|
||||||
|
{
|
||||||
|
private ActivityTypeFilter $filter;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
// add a fake request with a default locale (used in translatable string)
|
||||||
|
$request = $this->prophesize();
|
||||||
|
|
||||||
|
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
|
||||||
|
$request->getLocale()->willReturn('fr');
|
||||||
|
|
||||||
|
$this->filter = self::$container->get('chill.activity.export.filter_activitytype');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFilter()
|
||||||
|
{
|
||||||
|
return $this->filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData(): array
|
||||||
|
{
|
||||||
|
$em = self::$container->get(EntityManagerInterface::class);
|
||||||
|
|
||||||
|
$array = $em->createQueryBuilder()
|
||||||
|
->from(ActivityType::class, 'at')
|
||||||
|
->select('at')
|
||||||
|
->getQuery()
|
||||||
|
->getResult();
|
||||||
|
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
foreach ($array as $a) {
|
||||||
|
$data[] = [
|
||||||
|
'accepted_activitytypes' => $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(AccompanyingPeriod::class, 'acp')
|
||||||
|
->join(Activity::class, 'activity', Expr\Join::WITH, 'activity.accompanyingPeriod = acp')
|
||||||
|
->join('activity.activityType', 'acttype'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Tests\Export\Filter\ACPFilters;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
|
use Chill\ActivityBundle\Export\Filter\ACPFilters\BySocialActionFilter;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractFilterTest;
|
||||||
|
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
final class BySocialActionFilterTest extends AbstractFilterTest
|
||||||
|
{
|
||||||
|
private BySocialActionFilter $filter;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
// add a fake request with a default locale (used in translatable string)
|
||||||
|
$request = $this->prophesize();
|
||||||
|
|
||||||
|
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
|
||||||
|
$request->getLocale()->willReturn('fr');
|
||||||
|
|
||||||
|
$this->filter = self::$container->get('chill.activity.export.bysocialaction_filter');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFilter()
|
||||||
|
{
|
||||||
|
return $this->filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData(): array
|
||||||
|
{
|
||||||
|
$em = self::$container->get(EntityManagerInterface::class);
|
||||||
|
|
||||||
|
$array = $em->createQueryBuilder()
|
||||||
|
->from(SocialAction::class, 'sa')
|
||||||
|
->select('sa')
|
||||||
|
->getQuery()
|
||||||
|
->getResult();
|
||||||
|
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
foreach ($array as $a) {
|
||||||
|
$data[] = [
|
||||||
|
'accepted_socialactions' => $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.socialActions', 'actsocialaction'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Tests\Export\Filter\ACPFilters;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
|
use Chill\ActivityBundle\Export\Filter\ACPFilters\BySocialIssueFilter;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractFilterTest;
|
||||||
|
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
final class BySocialIssueFilterTest extends AbstractFilterTest
|
||||||
|
{
|
||||||
|
private BySocialIssueFilter $filter;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
// add a fake request with a default locale (used in translatable string)
|
||||||
|
$request = $this->prophesize();
|
||||||
|
|
||||||
|
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
|
||||||
|
$request->getLocale()->willReturn('fr');
|
||||||
|
|
||||||
|
$this->filter = self::$container->get('chill.activity.export.bysocialissue_filter');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFilter()
|
||||||
|
{
|
||||||
|
return $this->filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData(): array
|
||||||
|
{
|
||||||
|
$em = self::$container->get(EntityManagerInterface::class);
|
||||||
|
|
||||||
|
$array = $em->createQueryBuilder()
|
||||||
|
->from(SocialIssue::class, 'si')
|
||||||
|
->select('si')
|
||||||
|
->getQuery()
|
||||||
|
->getResult();
|
||||||
|
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
foreach ($array as $a) {
|
||||||
|
$data[] = [
|
||||||
|
'accepted_socialissues' => $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.socialIssues', 'actsocialissue')
|
||||||
|
,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Tests\Export\Filter\ACPFilters;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
|
use Chill\ActivityBundle\Export\Filter\ACPFilters\ByUserFilter;
|
||||||
|
use Chill\MainBundle\Entity\User;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractFilterTest;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
final class ByUserFilterTest extends AbstractFilterTest
|
||||||
|
{
|
||||||
|
private ByUserFilter $filter;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
// add a fake request with a default locale (used in translatable string)
|
||||||
|
$request = $this->prophesize();
|
||||||
|
|
||||||
|
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
|
||||||
|
$request->getLocale()->willReturn('fr');
|
||||||
|
|
||||||
|
$this->filter = self::$container->get('chill.activity.export.byuser_filter');
|
||||||
|
}
|
||||||
|
|
||||||
|
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'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Tests\Export\Filter\ACPFilters;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
|
use Chill\ActivityBundle\Export\Filter\ACPFilters\EmergencyFilter;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractFilterTest;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
final class EmergencyFilterTest extends AbstractFilterTest
|
||||||
|
{
|
||||||
|
private EmergencyFilter $filter;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
// add a fake request with a default locale (used in translatable string)
|
||||||
|
$request = $this->prophesize();
|
||||||
|
|
||||||
|
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
|
||||||
|
$request->getLocale()->willReturn('fr');
|
||||||
|
|
||||||
|
$this->filter = self::$container->get('chill.activity.export.emergency_filter');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFilter()
|
||||||
|
{
|
||||||
|
return $this->filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['accepted_emergency' => true ],
|
||||||
|
['accepted_emergency' => false ],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
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'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Tests\Export\Filter\ACPFilters;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
|
use Chill\ActivityBundle\Export\Filter\ACPFilters\LocationTypeFilter;
|
||||||
|
use Chill\MainBundle\Entity\LocationType;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractFilterTest;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
final class LocationTypeFilterTest extends AbstractFilterTest
|
||||||
|
{
|
||||||
|
private LocationTypeFilter $filter;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
// add a fake request with a default locale (used in translatable string)
|
||||||
|
$request = $this->prophesize();
|
||||||
|
|
||||||
|
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
|
||||||
|
$request->getLocale()->willReturn('fr');
|
||||||
|
|
||||||
|
$this->filter = self::$container->get('chill.activity.export.locationtype_filter');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFilter()
|
||||||
|
{
|
||||||
|
return $this->filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData(): array
|
||||||
|
{
|
||||||
|
$em = self::$container->get(EntityManagerInterface::class);
|
||||||
|
|
||||||
|
$array = $em->createQueryBuilder()
|
||||||
|
->from(LocationType::class, 'lt')
|
||||||
|
->select('lt')
|
||||||
|
->getQuery()
|
||||||
|
->getResult();
|
||||||
|
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
foreach ($array as $a) {
|
||||||
|
$data[] = [
|
||||||
|
'accepted_locationtype' => $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.location', 'actloc'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Tests\Export\Filter\ACPFilters;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
|
use Chill\ActivityBundle\Export\Filter\ACPFilters\SentReceivedFilter;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractFilterTest;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
final class SentReceivedFilterTest extends AbstractFilterTest
|
||||||
|
{
|
||||||
|
private SentReceivedFilter $filter;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
// add a fake request with a default locale (used in translatable string)
|
||||||
|
$request = $this->prophesize();
|
||||||
|
|
||||||
|
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
|
||||||
|
$request->getLocale()->willReturn('fr');
|
||||||
|
|
||||||
|
$this->filter = self::$container->get('chill.activity.export.sentreceived_filter');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFilter()
|
||||||
|
{
|
||||||
|
return $this->filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['accepted_sentreceived' => Activity::SENTRECEIVED_SENT ],
|
||||||
|
['accepted_sentreceived' => Activity::SENTRECEIVED_RECEIVED ]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
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'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Tests\Export\Filter\ACPFilters;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
|
use Chill\ActivityBundle\Export\Filter\ACPFilters\UserFilter;
|
||||||
|
use Chill\MainBundle\Entity\User;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractFilterTest;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
final class UserFilterTest extends AbstractFilterTest
|
||||||
|
{
|
||||||
|
private UserFilter $filter;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
// add a fake request with a default locale (used in translatable string)
|
||||||
|
$request = $this->prophesize();
|
||||||
|
|
||||||
|
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
|
||||||
|
$request->getLocale()->willReturn('fr');
|
||||||
|
|
||||||
|
$this->filter = self::$container->get('chill.activity.export.user_filter');
|
||||||
|
}
|
||||||
|
|
||||||
|
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'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Tests\Export\Filter\ACPFilters;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
|
use Chill\ActivityBundle\Export\Filter\ACPFilters\UserScopeFilter;
|
||||||
|
use Chill\MainBundle\Entity\Scope;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractFilterTest;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
final class UserScopeFilterTest extends AbstractFilterTest
|
||||||
|
{
|
||||||
|
private UserScopeFilter $filter;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
// add a fake request with a default locale (used in translatable string)
|
||||||
|
$request = $this->prophesize();
|
||||||
|
|
||||||
|
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
|
||||||
|
$request->getLocale()->willReturn('fr');
|
||||||
|
|
||||||
|
$this->filter = self::$container->get('chill.activity.export.userscope_filter');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFilter()
|
||||||
|
{
|
||||||
|
return $this->filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData(): array
|
||||||
|
{
|
||||||
|
$em = self::$container->get(EntityManagerInterface::class);
|
||||||
|
|
||||||
|
$array = $em->createQueryBuilder()
|
||||||
|
->from(Scope::class, 's')
|
||||||
|
->select('s')
|
||||||
|
->getQuery()
|
||||||
|
->getResult();
|
||||||
|
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
foreach ($array as $a) {
|
||||||
|
$data[] = [
|
||||||
|
'accepted_userscope' => $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.user', 'actuser'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Tests\Export\Filter;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
|
use Chill\ActivityBundle\Export\Filter\ActivityDateFilter;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractFilterTest;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
final class ActivityDateFilterTest extends AbstractFilterTest
|
||||||
|
{
|
||||||
|
private ActivityDateFilter $filter;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
// add a fake request with a default locale (used in translatable string)
|
||||||
|
$request = $this->prophesize();
|
||||||
|
|
||||||
|
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
|
||||||
|
$request->getLocale()->willReturn('fr');
|
||||||
|
|
||||||
|
$this->filter = self::$container->get('chill.activity.export.date_filter');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFilter()
|
||||||
|
{
|
||||||
|
return $this->filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'date_from' => \DateTime::createFromFormat('Y-m-d', '2020-01-01'),
|
||||||
|
'date_to' => \DateTime::createFromFormat('Y-m-d', '2021-01-01'),
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
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'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\ActivityBundle\Tests\Export\Filter;
|
namespace Chill\ActivityBundle\Tests\Export\Filter;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Export\Filter\PersonFilters\ActivityReasonFilter;
|
||||||
use Chill\MainBundle\Test\Export\AbstractFilterTest;
|
use Chill\MainBundle\Test\Export\AbstractFilterTest;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
|
||||||
@ -20,10 +21,7 @@ use Doctrine\Common\Collections\ArrayCollection;
|
|||||||
*/
|
*/
|
||||||
final class ActivityReasonFilterTest extends AbstractFilterTest
|
final class ActivityReasonFilterTest extends AbstractFilterTest
|
||||||
{
|
{
|
||||||
/**
|
private ActivityReasonFilter $filter;
|
||||||
* @var \Chill\PersonBundle\Export\Filter\GenderFilter
|
|
||||||
*/
|
|
||||||
private $filter;
|
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
|
@ -9,13 +9,13 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Chill\PersonBundle\Tests\Export\Filter\AccompanyingCourseFilters;
|
namespace Chill\ActivityBundle\Tests\Export\Filter;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
use Chill\ActivityBundle\Entity\ActivityType;
|
use Chill\ActivityBundle\Entity\ActivityType;
|
||||||
|
use Chill\ActivityBundle\Export\Filter\ActivityTypeFilter;
|
||||||
use Chill\MainBundle\Test\Export\AbstractFilterTest;
|
use Chill\MainBundle\Test\Export\AbstractFilterTest;
|
||||||
use Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters\ActivityTypeFilter;
|
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
@ -27,16 +27,15 @@ final class ActivityTypeFilterTest extends AbstractFilterTest
|
|||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
//parent::setUp();
|
|
||||||
self::bootKernel();
|
self::bootKernel();
|
||||||
|
|
||||||
// add a fake request with a default locale (used in translatable string)
|
// add a fake request with a default locale (used in translatable string)
|
||||||
$request = $this->prophesize();
|
$request = $this->prophesize();
|
||||||
|
|
||||||
$request->willExtend(Request::class);
|
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
|
||||||
$request->getLocale()->willReturn('fr');
|
$request->getLocale()->willReturn('fr');
|
||||||
|
|
||||||
$this->filter = self::$container->get('chill.person.export.filter_activitytype');
|
$this->filter = self::$container->get('chill.activity.export.type_filter');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFilter()
|
public function getFilter()
|
||||||
@ -56,8 +55,10 @@ final class ActivityTypeFilterTest extends AbstractFilterTest
|
|||||||
|
|
||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
foreach ($array as $t) {
|
foreach ($array as $a) {
|
||||||
$data[] = ['accepted_activitytypes' => $t];
|
$data[] = [
|
||||||
|
'types' => $a
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
@ -73,8 +74,8 @@ final class ActivityTypeFilterTest extends AbstractFilterTest
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
$em->createQueryBuilder()
|
$em->createQueryBuilder()
|
||||||
->from('ChillPersonBundle:AccompanyingPeriod', 'acp')
|
->select('count(activity.id)')
|
||||||
->select('acp.id'),
|
->from(Activity::class, 'activity'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Tests\Export\Filter\PersonFilters;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
|
use Chill\ActivityBundle\Entity\ActivityReason;
|
||||||
|
use Chill\ActivityBundle\Export\Filter\PersonFilters\ActivityReasonFilter;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractFilterTest;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
final class ActivityReasonFilterTest extends AbstractFilterTest
|
||||||
|
{
|
||||||
|
private ActivityReasonFilter $filter;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
// add a fake request with a default locale (used in translatable string)
|
||||||
|
$request = $this->prophesize();
|
||||||
|
|
||||||
|
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
|
||||||
|
$request->getLocale()->willReturn('fr');
|
||||||
|
|
||||||
|
$this->filter = self::$container->get('chill.activity.export.reason_filter');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFilter()
|
||||||
|
{
|
||||||
|
return $this->filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData(): array
|
||||||
|
{
|
||||||
|
$em = self::$container->get(EntityManagerInterface::class);
|
||||||
|
|
||||||
|
$array = $em->createQueryBuilder()
|
||||||
|
->from(ActivityReason::class, 'ar')
|
||||||
|
->select('ar')
|
||||||
|
->getQuery()
|
||||||
|
->getResult();
|
||||||
|
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
foreach ($array as $a) {
|
||||||
|
$data[] = [
|
||||||
|
'reasons' => $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.reasons', 'actreasons'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Tests\Export\Filter\PersonFilters;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Entity\Activity;
|
||||||
|
use Chill\ActivityBundle\Entity\ActivityReason;
|
||||||
|
use Chill\ActivityBundle\Export\Filter\PersonFilters\PersonHavingActivityBetweenDateFilter;
|
||||||
|
use Chill\MainBundle\Test\Export\AbstractFilterTest;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
final class PersonHavingActivityBetweenDateFilterTest extends AbstractFilterTest
|
||||||
|
{
|
||||||
|
private PersonHavingActivityBetweenDateFilter $filter;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
// add a fake request with a default locale (used in translatable string)
|
||||||
|
$request = $this->prophesize();
|
||||||
|
|
||||||
|
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
|
||||||
|
$request->getLocale()->willReturn('fr');
|
||||||
|
|
||||||
|
$this->filter = self::$container->get('chill.activity.export.person_having_an_activity_between_date_filter');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFilter()
|
||||||
|
{
|
||||||
|
return $this->filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormData(): array
|
||||||
|
{
|
||||||
|
$em = self::$container->get(EntityManagerInterface::class);
|
||||||
|
|
||||||
|
$array = $em->createQueryBuilder()
|
||||||
|
->from(ActivityReason::class, 'ar')
|
||||||
|
->select('ar')
|
||||||
|
->getQuery()
|
||||||
|
->getResult();
|
||||||
|
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
foreach ($array as $a) {
|
||||||
|
$data[] = [
|
||||||
|
'date_from' => \DateTime::createFromFormat('Y-m-d', '2021-07-01'),
|
||||||
|
'date_to' => \DateTime::createFromFormat('Y-m-d', '2022-07-01'),
|
||||||
|
'reasons' => $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'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\ActivityBundle\Tests\Export\Filter;
|
namespace Chill\ActivityBundle\Tests\Export\Filter;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Export\Filter\PersonFilters\PersonHavingActivityBetweenDateFilter;
|
||||||
use Chill\MainBundle\Test\Export\AbstractFilterTest;
|
use Chill\MainBundle\Test\Export\AbstractFilterTest;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use function array_slice;
|
use function array_slice;
|
||||||
@ -21,10 +22,7 @@ use function array_slice;
|
|||||||
*/
|
*/
|
||||||
final class PersonHavingActivityBetweenDateFilterTest extends AbstractFilterTest
|
final class PersonHavingActivityBetweenDateFilterTest extends AbstractFilterTest
|
||||||
{
|
{
|
||||||
/**
|
private PersonHavingActivityBetweenDateFilter $filter;
|
||||||
* @var \Chill\PersonBundle\Export\Filter\PersonHavingActivityBetweenDateFilter
|
|
||||||
*/
|
|
||||||
private $filter;
|
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
|
@ -67,10 +67,10 @@ 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.person.export.filter_activitytype:
|
chill.activity.export.filter_activitytype:
|
||||||
class: 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.locationtype_filter:
|
chill.activity.export.locationtype_filter:
|
||||||
class: Chill\ActivityBundle\Export\Filter\ACPFilters\LocationTypeFilter
|
class: Chill\ActivityBundle\Export\Filter\ACPFilters\LocationTypeFilter
|
||||||
|
@ -29,44 +29,58 @@ class ConfigRepository
|
|||||||
$this->charges = $charges;
|
$this->charges = $charges;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getChargesKeys(): array
|
public function getChargesKeys(bool $onlyActive = false): array
|
||||||
{
|
{
|
||||||
return array_map(static function ($element) { return $element['key']; }, $this->charges);
|
return array_map(static function ($element) { return $element['key']; }, $this->getCharges($onlyActive));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array where keys are the resource'key and label the ressource label
|
* @return array where keys are the resource'key and label the ressource label
|
||||||
*/
|
*/
|
||||||
public function getChargesLabels()
|
public function getChargesLabels(bool $onlyActive = false)
|
||||||
{
|
{
|
||||||
$charges = [];
|
$charges = [];
|
||||||
|
|
||||||
foreach ($this->charges as $definition) {
|
foreach ($this->getCharges($onlyActive) as $definition) {
|
||||||
$charges[$definition['key']] = $this->normalizeLabel($definition['labels']);
|
$charges[$definition['key']] = $this->normalizeLabel($definition['labels']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $charges;
|
return $charges;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getResourcesKeys(): array
|
public function getResourcesKeys(bool $onlyActive = false): array
|
||||||
{
|
{
|
||||||
return array_map(static function ($element) { return $element['key']; }, $this->resources);
|
return array_map(static function ($element) { return $element['key']; }, $this->getResources($onlyActive));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array where keys are the resource'key and label the ressource label
|
* @return array where keys are the resource'key and label the ressource label
|
||||||
*/
|
*/
|
||||||
public function getResourcesLabels()
|
public function getResourcesLabels(bool $onlyActive = false)
|
||||||
{
|
{
|
||||||
$resources = [];
|
$resources = [];
|
||||||
|
|
||||||
foreach ($this->resources as $definition) {
|
foreach ($this->getResources($onlyActive) as $definition) {
|
||||||
$resources[$definition['key']] = $this->normalizeLabel($definition['labels']);
|
$resources[$definition['key']] = $this->normalizeLabel($definition['labels']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $resources;
|
return $resources;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getCharges(bool $onlyActive = false): array
|
||||||
|
{
|
||||||
|
return $onlyActive ?
|
||||||
|
array_filter($this->charges, function ($el) { return $el['active']; })
|
||||||
|
: $this->charges;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getResources(bool $onlyActive = false): array
|
||||||
|
{
|
||||||
|
return $onlyActive ?
|
||||||
|
array_filter($this->resources, function ($el) { return $el['active']; })
|
||||||
|
: $this->resources;
|
||||||
|
}
|
||||||
|
|
||||||
private function normalizeLabel($labels)
|
private function normalizeLabel($labels)
|
||||||
{
|
{
|
||||||
$normalizedLabels = [];
|
$normalizedLabels = [];
|
||||||
|
@ -14,11 +14,6 @@ namespace Chill\BudgetBundle\DependencyInjection;
|
|||||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the class that validates and merges configuration from your app/config files.
|
|
||||||
*
|
|
||||||
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/configuration.html}
|
|
||||||
*/
|
|
||||||
class Configuration implements ConfigurationInterface
|
class Configuration implements ConfigurationInterface
|
||||||
{
|
{
|
||||||
public function getConfigTreeBuilder()
|
public function getConfigTreeBuilder()
|
||||||
@ -37,6 +32,7 @@ class Configuration implements ConfigurationInterface
|
|||||||
->info('the key stored in database')
|
->info('the key stored in database')
|
||||||
->example('salary')
|
->example('salary')
|
||||||
->end()
|
->end()
|
||||||
|
->booleanNode('active')->defaultTrue()->end()
|
||||||
->arrayNode('labels')->isRequired()->requiresAtLeastOneElement()
|
->arrayNode('labels')->isRequired()->requiresAtLeastOneElement()
|
||||||
->arrayPrototype()
|
->arrayPrototype()
|
||||||
->children()
|
->children()
|
||||||
@ -59,6 +55,7 @@ class Configuration implements ConfigurationInterface
|
|||||||
->info('the key stored in database')
|
->info('the key stored in database')
|
||||||
->example('salary')
|
->example('salary')
|
||||||
->end()
|
->end()
|
||||||
|
->booleanNode('active')->defaultTrue()->end()
|
||||||
->arrayNode('labels')->isRequired()->requiresAtLeastOneElement()
|
->arrayNode('labels')->isRequired()->requiresAtLeastOneElement()
|
||||||
->arrayPrototype()
|
->arrayPrototype()
|
||||||
->children()
|
->children()
|
||||||
|
@ -103,7 +103,7 @@ class ChargeType extends AbstractType
|
|||||||
private function getTypes()
|
private function getTypes()
|
||||||
{
|
{
|
||||||
$charges = $this->configRepository
|
$charges = $this->configRepository
|
||||||
->getChargesLabels();
|
->getChargesLabels(true);
|
||||||
|
|
||||||
// rewrite labels to filter in language
|
// rewrite labels to filter in language
|
||||||
foreach ($charges as $key => $labels) {
|
foreach ($charges as $key => $labels) {
|
||||||
|
@ -87,7 +87,7 @@ class ResourceType extends AbstractType
|
|||||||
private function getTypes()
|
private function getTypes()
|
||||||
{
|
{
|
||||||
$resources = $this->configRepository
|
$resources = $this->configRepository
|
||||||
->getResourcesLabels();
|
->getResourcesLabels(true);
|
||||||
|
|
||||||
// rewrite labels to filter in language
|
// rewrite labels to filter in language
|
||||||
foreach ($resources as $key => $labels) {
|
foreach ($resources as $key => $labels) {
|
||||||
|
@ -41,11 +41,13 @@ class PersonDocumentType extends AbstractType
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
TranslatableStringHelperInterface $translatableStringHelper,
|
TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
ScopeResolverDispatcher $scopeResolverDispatcher,
|
ScopeResolverDispatcher $scopeResolverDispatcher,
|
||||||
ParameterBagInterface $parameterBag
|
ParameterBagInterface $parameterBag,
|
||||||
|
CenterResolverDispatcher $centerResolverDispatcher
|
||||||
) {
|
) {
|
||||||
$this->translatableStringHelper = $translatableStringHelper;
|
$this->translatableStringHelper = $translatableStringHelper;
|
||||||
$this->scopeResolverDispatcher = $scopeResolverDispatcher;
|
$this->scopeResolverDispatcher = $scopeResolverDispatcher;
|
||||||
$this->parameterBag = $parameterBag;
|
$this->parameterBag = $parameterBag;
|
||||||
|
$this->centerResolverDispatcher = $centerResolverDispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
|
@ -126,7 +126,7 @@ class Version20160318111334 extends AbstractMigration
|
|||||||
$this->addSql('ALTER TABLE chill_event_participation '
|
$this->addSql('ALTER TABLE chill_event_participation '
|
||||||
. 'ADD CONSTRAINT FK_4E7768AC217BBB47 '
|
. 'ADD CONSTRAINT FK_4E7768AC217BBB47 '
|
||||||
. 'FOREIGN KEY (person_id) '
|
. 'FOREIGN KEY (person_id) '
|
||||||
. 'REFERENCES chill_person_person(id) '
|
. 'REFERENCES Person (id) '
|
||||||
. 'NOT DEFERRABLE INITIALLY IMMEDIATE');
|
. 'NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
$this->addSql('ALTER TABLE chill_event_participation '
|
$this->addSql('ALTER TABLE chill_event_participation '
|
||||||
. 'ADD CONSTRAINT FK_4E7768ACD60322AC '
|
. 'ADD CONSTRAINT FK_4E7768ACD60322AC '
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Command;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Service\Import\AddressReferenceBEFromBestAddress;
|
||||||
|
use Chill\MainBundle\Service\Import\PostalCodeBEFromBestAddress;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
|
class LoadAddressesBEFromBestAddressCommand extends Command
|
||||||
|
{
|
||||||
|
private AddressReferenceBEFromBestAddress $addressImporter;
|
||||||
|
|
||||||
|
private PostalCodeBEFromBestAddress $postalCodeBEFromBestAddressImporter;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
AddressReferenceBEFromBestAddress $addressImporter,
|
||||||
|
PostalCodeBEFromBestAddress $postalCodeBEFromBestAddressImporter
|
||||||
|
) {
|
||||||
|
parent::__construct();
|
||||||
|
$this->addressImporter = $addressImporter;
|
||||||
|
$this->postalCodeBEFromBestAddressImporter = $postalCodeBEFromBestAddressImporter;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this
|
||||||
|
->setName('chill:main:address-ref-from-best-addresses')
|
||||||
|
->addArgument('lang', InputArgument::REQUIRED)
|
||||||
|
->addArgument('list', InputArgument::IS_ARRAY, 'The list to add');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$this->postalCodeBEFromBestAddressImporter->import();
|
||||||
|
|
||||||
|
$this->addressImporter->import($input->getArgument('lang'), $input->getArgument('list'));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Command;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Service\Import\AddressReferenceFromBano;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
|
class LoadAddressesFRFromBANOCommand extends Command
|
||||||
|
{
|
||||||
|
private AddressReferenceFromBano $addressReferenceFromBano;
|
||||||
|
|
||||||
|
public function __construct(AddressReferenceFromBano $addressReferenceFromBano)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
$this->addressReferenceFromBano = $addressReferenceFromBano;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setName('chill:main:address-ref-from-bano')
|
||||||
|
->addArgument('departementNo', InputArgument::REQUIRED | InputArgument::IS_ARRAY, 'a list of departement numbers')
|
||||||
|
->setDescription('Import addresses from bano (see https://bano.openstreetmap.fr');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
foreach ($input->getArgument('departementNo') as $departementNo) {
|
||||||
|
$output->writeln('Import addresses for ' . $departementNo);
|
||||||
|
|
||||||
|
$this->addressReferenceFromBano->import($departementNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
42
src/Bundle/ChillMainBundle/Command/LoadPostalCodeFR.php
Normal file
42
src/Bundle/ChillMainBundle/Command/LoadPostalCodeFR.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Command;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Service\Import\PostalCodeFRFromOpenData;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
|
class LoadPostalCodeFR extends Command
|
||||||
|
{
|
||||||
|
private PostalCodeFRFromOpenData $loader;
|
||||||
|
|
||||||
|
public function __construct(PostalCodeFRFromOpenData $loader)
|
||||||
|
{
|
||||||
|
$this->loader = $loader;
|
||||||
|
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function configure(): void
|
||||||
|
{
|
||||||
|
$this->setName('chill:main:postal-code:load:FR')
|
||||||
|
->setDescription('Load France\'s postal code from online open data');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$this->loader->import();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
@ -442,6 +442,12 @@ class ExportController extends AbstractController
|
|||||||
}
|
}
|
||||||
|
|
||||||
$rawData = unserialize($serialized);
|
$rawData = unserialize($serialized);
|
||||||
|
|
||||||
|
$this->logger->notice('[export] choices for an export unserialized', [
|
||||||
|
'key' => $key,
|
||||||
|
'rawData' => json_encode($rawData)
|
||||||
|
]);
|
||||||
|
|
||||||
$alias = $rawData['alias'];
|
$alias = $rawData['alias'];
|
||||||
|
|
||||||
$formCenters = $this->createCreateFormExport($alias, 'generate_centers');
|
$formCenters = $this->createCreateFormExport($alias, 'generate_centers');
|
||||||
|
@ -318,19 +318,12 @@ class WorkflowController extends AbstractController
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO symfony 5: add those "future" on context ($workflow->apply($entityWorkflow, $transition, $context)
|
||||||
$entityWorkflow->futureDestUsers = $transitionForm['future_dest_users']->getData();
|
$entityWorkflow->futureDestUsers = $transitionForm['future_dest_users']->getData();
|
||||||
$entityWorkflow->futureDestEmails = $transitionForm['future_dest_emails']->getData();
|
$entityWorkflow->futureDestEmails = $transitionForm['future_dest_emails']->getData();
|
||||||
|
|
||||||
$workflow->apply($entityWorkflow, $transition);
|
$workflow->apply($entityWorkflow, $transition);
|
||||||
|
|
||||||
foreach ($transitionForm['future_dest_users']->getData() as $user) {
|
|
||||||
$entityWorkflow->getCurrentStep()->addDestUser($user);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($transitionForm['future_dest_emails']->getData() as $email) {
|
|
||||||
$entityWorkflow->getCurrentStep()->addDestEmail($email);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->entityManager->flush();
|
$this->entityManager->flush();
|
||||||
|
|
||||||
return $this->redirectToRoute('chill_main_workflow_show', ['id' => $entityWorkflow->getId()]);
|
return $this->redirectToRoute('chill_main_workflow_show', ['id' => $entityWorkflow->getId()]);
|
||||||
|
@ -20,6 +20,9 @@ use Symfony\Component\Serializer\Annotation\Groups;
|
|||||||
* @ORM\Entity
|
* @ORM\Entity
|
||||||
* @ORM\Table(name="chill_main_address_reference", indexes={
|
* @ORM\Table(name="chill_main_address_reference", indexes={
|
||||||
* @ORM\Index(name="address_refid", columns={"refId"})
|
* @ORM\Index(name="address_refid", columns={"refId"})
|
||||||
|
* },
|
||||||
|
* uniqueConstraints={
|
||||||
|
* @ORM\UniqueConstraint(name="chill_main_address_reference_unicity", columns={"refId", "source"})
|
||||||
* })
|
* })
|
||||||
* @ORM\HasLifecycleCallbacks
|
* @ORM\HasLifecycleCallbacks
|
||||||
*/
|
*/
|
||||||
|
@ -12,6 +12,11 @@ declare(strict_types=1);
|
|||||||
namespace Chill\MainBundle\Entity;
|
namespace Chill\MainBundle\Entity;
|
||||||
|
|
||||||
use Chill\MainBundle\Doctrine\Model\Point;
|
use Chill\MainBundle\Doctrine\Model\Point;
|
||||||
|
use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
|
||||||
|
use Chill\MainBundle\Doctrine\Model\TrackCreationTrait;
|
||||||
|
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
|
||||||
|
use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait;
|
||||||
|
use DateTimeImmutable;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
use Symfony\Component\Serializer\Annotation\Groups;
|
use Symfony\Component\Serializer\Annotation\Groups;
|
||||||
|
|
||||||
@ -21,6 +26,10 @@ use Symfony\Component\Serializer\Annotation\Groups;
|
|||||||
* @ORM\Entity
|
* @ORM\Entity
|
||||||
* @ORM\Table(
|
* @ORM\Table(
|
||||||
* name="chill_main_postal_code",
|
* name="chill_main_postal_code",
|
||||||
|
* uniqueConstraints={
|
||||||
|
* @ORM\UniqueConstraint(name="postal_code_import_unicity", columns={"code", "refpostalcodeid", "postalcodesource"},
|
||||||
|
* options={"where": "refpostalcodeid is not null"})
|
||||||
|
* },
|
||||||
* indexes={
|
* indexes={
|
||||||
* @ORM\Index(name="search_name_code", columns={"code", "label"}),
|
* @ORM\Index(name="search_name_code", columns={"code", "label"}),
|
||||||
* @ORM\Index(name="search_by_reference_code", columns={"code", "refpostalcodeid"})
|
* @ORM\Index(name="search_by_reference_code", columns={"code", "refpostalcodeid"})
|
||||||
@ -28,8 +37,12 @@ use Symfony\Component\Serializer\Annotation\Groups;
|
|||||||
*
|
*
|
||||||
* @ORM\HasLifecycleCallbacks
|
* @ORM\HasLifecycleCallbacks
|
||||||
*/
|
*/
|
||||||
class PostalCode
|
class PostalCode implements TrackUpdateInterface, TrackCreationInterface
|
||||||
{
|
{
|
||||||
|
use TrackCreationTrait;
|
||||||
|
|
||||||
|
use TrackUpdateTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is an internal column which is populated by database.
|
* This is an internal column which is populated by database.
|
||||||
*
|
*
|
||||||
@ -63,6 +76,11 @@ class PostalCode
|
|||||||
*/
|
*/
|
||||||
private $country;
|
private $country;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="datetime_immutable", nullable=true, options={"default": null})
|
||||||
|
*/
|
||||||
|
private ?DateTimeImmutable $deletedAt = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int
|
* @var int
|
||||||
*
|
*
|
||||||
|
@ -264,15 +264,17 @@ class ExportManager
|
|||||||
//handle aggregators
|
//handle aggregators
|
||||||
$this->handleAggregators($export, $query, $data[ExportType::AGGREGATOR_KEY], $centers);
|
$this->handleAggregators($export, $query, $data[ExportType::AGGREGATOR_KEY], $centers);
|
||||||
|
|
||||||
$this->logger->debug('current query is ' . $query->getDQL(), [
|
$this->logger->notice('[export] will execute this qb in export', [
|
||||||
'class' => self::class, 'function' => __FUNCTION__,
|
'dql' => $query->getDQL()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new UnexpectedValueException('The method `intiateQuery` should return '
|
throw new UnexpectedValueException('The method `intiateQuery` should return '
|
||||||
. 'a `\\Doctrine\\ORM\\NativeQuery` or a `Doctrine\\ORM\\QueryBuilder` '
|
. 'a `\\Doctrine\\ORM\\NativeQuery` or a `Doctrine\\ORM\\QueryBuilder` '
|
||||||
. 'object.');
|
. 'object.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$result = $export->getResult($query, $data[ExportType::EXPORT_KEY]);
|
$result = $export->getResult($query, $data[ExportType::EXPORT_KEY]);
|
||||||
|
|
||||||
if (!is_iterable($result)) {
|
if (!is_iterable($result)) {
|
||||||
@ -534,8 +536,8 @@ class ExportManager
|
|||||||
. 'an ExportInterface.');
|
. 'an ExportInterface.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null === $centers || [] === $centers) {
|
if (null === $centers || [] !== $centers) {
|
||||||
// we want to try if at least one center is reachable
|
// we want to try if at least one center is reachabler
|
||||||
return [] !== $this->authorizationHelper->getReachableCenters(
|
return [] !== $this->authorizationHelper->getReachableCenters(
|
||||||
$this->user,
|
$this->user,
|
||||||
$role
|
$role
|
||||||
|
@ -496,8 +496,13 @@ class SpreadSheetFormatter implements FormatterInterface
|
|||||||
// 3. iterate on `keysExportElementAssociation` to store the callable
|
// 3. iterate on `keysExportElementAssociation` to store the callable
|
||||||
// in cache
|
// in cache
|
||||||
foreach ($keysExportElementAssociation as $key => [$element, $data]) {
|
foreach ($keysExportElementAssociation as $key => [$element, $data]) {
|
||||||
$this->cacheDisplayableResult[$key] =
|
// handle the case when there is not results lines (query is empty)
|
||||||
$element->getLabels($key, array_unique($allValues[$key]), $data);
|
if ([] === $allValues) {
|
||||||
|
$this->cacheDisplayableResult[$key] = $element->getLabels($key, ['_header'], $data);
|
||||||
|
} else {
|
||||||
|
$this->cacheDisplayableResult[$key] =
|
||||||
|
$element->getLabels($key, array_unique($allValues[$key]), $data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the cache is initialized !
|
// the cache is initialized !
|
||||||
|
@ -0,0 +1,103 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Service\Import;
|
||||||
|
|
||||||
|
use League\Csv\Reader;
|
||||||
|
use League\Csv\Statement;
|
||||||
|
use RuntimeException;
|
||||||
|
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||||
|
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||||
|
|
||||||
|
class AddressReferenceBEFromBestAddress
|
||||||
|
{
|
||||||
|
private const RELEASE = 'https://gitea.champs-libres.be/api/v1/repos/Chill-project/belgian-bestaddresses-transform/releases/tags/v1.0.0';
|
||||||
|
|
||||||
|
private AddressReferenceBaseImporter $baseImporter;
|
||||||
|
|
||||||
|
private HttpClientInterface $client;
|
||||||
|
|
||||||
|
public function __construct(HttpClientInterface $client, AddressReferenceBaseImporter $baseImporter)
|
||||||
|
{
|
||||||
|
$this->client = $client;
|
||||||
|
$this->baseImporter = $baseImporter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function import(string $lang, array $lists): void
|
||||||
|
{
|
||||||
|
foreach ($lists as $list) {
|
||||||
|
$this->importList($lang, $list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getDownloadUrl(string $lang, string $list): string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$release = $this->client->request('GET', self::RELEASE)
|
||||||
|
->toArray();
|
||||||
|
} catch (TransportExceptionInterface $e) {
|
||||||
|
throw new RuntimeException('could not get the release definition', 0, $e);
|
||||||
|
}
|
||||||
|
|
||||||
|
$asset = array_filter($release['assets'], static function (array $item) use ($lang, $list) {
|
||||||
|
return 'addresses-' . $list . '.' . $lang . '.csv.gz' === $item['name'];
|
||||||
|
});
|
||||||
|
|
||||||
|
return array_values($asset)[0]['browser_download_url'];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function importList(string $lang, string $list): void
|
||||||
|
{
|
||||||
|
$downloadUrl = $this->getDownloadUrl($lang, $list);
|
||||||
|
|
||||||
|
$response = $this->client->request('GET', $downloadUrl);
|
||||||
|
|
||||||
|
if (200 !== $response->getStatusCode()) {
|
||||||
|
throw new Exception('Could not download CSV: ' . $response->getStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
$tmpname = tempnam(sys_get_temp_dir(), 'php-add-' . $list . $lang);
|
||||||
|
$file = fopen($tmpname, 'r+b');
|
||||||
|
|
||||||
|
foreach ($this->client->stream($response) as $chunk) {
|
||||||
|
fwrite($file, $chunk->getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($file);
|
||||||
|
|
||||||
|
$uncompressedStream = gzopen($tmpname, 'r');
|
||||||
|
|
||||||
|
$csv = Reader::createFromStream($uncompressedStream);
|
||||||
|
$csv->setDelimiter(',');
|
||||||
|
$csv->setHeaderOffset(0);
|
||||||
|
|
||||||
|
$stmt = Statement::create()
|
||||||
|
->process($csv);
|
||||||
|
|
||||||
|
foreach ($stmt as $record) {
|
||||||
|
$this->baseImporter->importAddress(
|
||||||
|
$record['best_id'],
|
||||||
|
$record['municipality_objectid'],
|
||||||
|
$record['postal_info_objectid'],
|
||||||
|
$record['streetname'],
|
||||||
|
$record['housenumber'] . $record['boxnumber'],
|
||||||
|
'bestaddress.' . $list,
|
||||||
|
(float) $record['X'],
|
||||||
|
(float) $record['Y'],
|
||||||
|
3812
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->baseImporter->finalize();
|
||||||
|
|
||||||
|
gzclose($uncompressedStream);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,220 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Service\Import;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Connection;
|
||||||
|
use Doctrine\DBAL\Statement;
|
||||||
|
use Exception;
|
||||||
|
use LogicException;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use function array_key_exists;
|
||||||
|
use function count;
|
||||||
|
|
||||||
|
final class AddressReferenceBaseImporter
|
||||||
|
{
|
||||||
|
private const INSERT = <<<'SQL'
|
||||||
|
INSERT INTO reference_address_temp
|
||||||
|
(postcode_id, refid, street, streetnumber, municipalitycode, source, point)
|
||||||
|
SELECT
|
||||||
|
cmpc.id, i.refid, i.street, i.streetnumber, i.refpostalcode, i.source,
|
||||||
|
CASE WHEN (i.lon::float != 0.0 AND i.lat::float != 0.0) THEN ST_Transform(ST_setSrid(ST_point(i.lon::float, i.lat::float), i.srid::int), 4326) ELSE NULL END
|
||||||
|
FROM
|
||||||
|
(VALUES
|
||||||
|
{{ values }}
|
||||||
|
) AS i (refid, refpostalcode, postalcode, street, streetnumber, source, lat, lon, srid)
|
||||||
|
JOIN chill_main_postal_code cmpc ON cmpc.refpostalcodeid = i.refpostalcode and cmpc.code = i.postalcode
|
||||||
|
SQL;
|
||||||
|
|
||||||
|
private const LOG_PREFIX = '[AddressReferenceImporter] ';
|
||||||
|
|
||||||
|
private const VALUE = '(?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<int, Statement>
|
||||||
|
*/
|
||||||
|
private array $cachingStatements = [];
|
||||||
|
|
||||||
|
private ?string $currentSource = null;
|
||||||
|
|
||||||
|
private Connection $defaultConnection;
|
||||||
|
|
||||||
|
private bool $isInitialized = false;
|
||||||
|
|
||||||
|
private LoggerInterface $logger;
|
||||||
|
|
||||||
|
private array $waitingForInsert = [];
|
||||||
|
|
||||||
|
public function __construct(Connection $defaultConnection, LoggerInterface $logger)
|
||||||
|
{
|
||||||
|
$this->defaultConnection = $defaultConnection;
|
||||||
|
$this->logger = $logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function finalize(): void
|
||||||
|
{
|
||||||
|
$this->doInsertPending();
|
||||||
|
|
||||||
|
$this->updateAddressReferenceTable();
|
||||||
|
|
||||||
|
$this->deleteTemporaryTable();
|
||||||
|
|
||||||
|
$this->currentSource = null;
|
||||||
|
$this->isInitialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function importAddress(
|
||||||
|
string $refAddress,
|
||||||
|
?string $refPostalCode,
|
||||||
|
string $postalCode,
|
||||||
|
string $street,
|
||||||
|
string $streetNumber,
|
||||||
|
string $source,
|
||||||
|
?float $lat = null,
|
||||||
|
?float $lon = null,
|
||||||
|
?int $srid = null
|
||||||
|
): void {
|
||||||
|
if (!$this->isInitialized) {
|
||||||
|
$this->initialize($source);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->currentSource !== $source) {
|
||||||
|
throw new LogicException('Cannot store addresses from different sources during same import. Execute finalize to commit inserts before changing the source');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->waitingForInsert[] = [
|
||||||
|
$refAddress,
|
||||||
|
$refPostalCode,
|
||||||
|
$postalCode,
|
||||||
|
$street,
|
||||||
|
$streetNumber,
|
||||||
|
$source,
|
||||||
|
$lat,
|
||||||
|
$lon,
|
||||||
|
$srid,
|
||||||
|
];
|
||||||
|
|
||||||
|
if (100 <= count($this->waitingForInsert)) {
|
||||||
|
$this->doInsertPending();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createTemporaryTable(): void
|
||||||
|
{
|
||||||
|
$this->defaultConnection->executeStatement('CREATE TEMPORARY TABLE reference_address_temp (
|
||||||
|
postcode_id INT,
|
||||||
|
refid VARCHAR(255),
|
||||||
|
street VARCHAR(255),
|
||||||
|
streetnumber VARCHAR(255),
|
||||||
|
municipalitycode VARCHAR(255),
|
||||||
|
source VARCHAR(255),
|
||||||
|
point GEOMETRY
|
||||||
|
);
|
||||||
|
');
|
||||||
|
$this->defaultConnection->executeStatement('SET work_mem TO \'50MB\'');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function deleteTemporaryTable(): void
|
||||||
|
{
|
||||||
|
$this->defaultConnection->executeStatement('DROP TABLE IF EXISTS reference_address_temp');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function doInsertPending(): void
|
||||||
|
{
|
||||||
|
if (!array_key_exists($forNumber = count($this->waitingForInsert), $this->cachingStatements)) {
|
||||||
|
$sql = strtr(self::INSERT, [
|
||||||
|
'{{ values }}' => implode(
|
||||||
|
', ',
|
||||||
|
array_fill(0, $forNumber, self::VALUE)
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->logger->debug(self::LOG_PREFIX . ' generated sql for insert', [
|
||||||
|
'sql' => $sql,
|
||||||
|
'forNumber' => $forNumber,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->cachingStatements[$forNumber] = $this->defaultConnection->prepare($sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 === $forNumber) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logger->debug(self::LOG_PREFIX . ' inserting pending addresses', [
|
||||||
|
'number' => $forNumber,
|
||||||
|
'first' => $this->waitingForInsert[0] ?? null,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$statement = $this->cachingStatements[$forNumber];
|
||||||
|
|
||||||
|
try {
|
||||||
|
$affected = $statement->executeStatement(array_merge(...$this->waitingForInsert));
|
||||||
|
|
||||||
|
if ($affected === 0) {
|
||||||
|
throw new \RuntimeException('no row affected');
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// in some case, we can add debug code here
|
||||||
|
//dump($this->waitingForInsert);
|
||||||
|
throw $e;
|
||||||
|
} finally {
|
||||||
|
$this->waitingForInsert = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function initialize(string $source): void
|
||||||
|
{
|
||||||
|
$this->currentSource = $source;
|
||||||
|
$this->deleteTemporaryTable();
|
||||||
|
$this->createTemporaryTable();
|
||||||
|
$this->isInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function updateAddressReferenceTable(): void
|
||||||
|
{
|
||||||
|
$this->defaultConnection->executeStatement(
|
||||||
|
'CREATE INDEX idx_ref_add_temp ON reference_address_temp (refid)'
|
||||||
|
);
|
||||||
|
|
||||||
|
//1) Add new addresses
|
||||||
|
$this->logger->info(self::LOG_PREFIX . 'upsert new addresses');
|
||||||
|
$affected = $this->defaultConnection->executeStatement("INSERT INTO chill_main_address_reference
|
||||||
|
(id, postcode_id, refid, street, streetnumber, municipalitycode, source, point, createdat, deletedat, updatedat)
|
||||||
|
SELECT
|
||||||
|
nextval('chill_main_address_reference_id_seq'),
|
||||||
|
postcode_id,
|
||||||
|
refid,
|
||||||
|
street,
|
||||||
|
streetnumber,
|
||||||
|
municipalitycode,
|
||||||
|
source,
|
||||||
|
point,
|
||||||
|
NOW(),
|
||||||
|
null,
|
||||||
|
NOW()
|
||||||
|
FROM reference_address_temp
|
||||||
|
ON CONFLICT (refid, source) DO UPDATE
|
||||||
|
SET postcode_id = excluded.postcode_id, refid = excluded.refid, street = excluded.street, streetnumber = excluded.streetnumber, municipalitycode = excluded.municipalitycode, source = excluded.source, point = excluded.point, updatedat = NOW(), deletedAt = NULL
|
||||||
|
");
|
||||||
|
$this->logger->info(self::LOG_PREFIX . 'addresses upserted', ['upserted' => $affected]);
|
||||||
|
|
||||||
|
//3) Delete addresses
|
||||||
|
$this->logger->info(self::LOG_PREFIX . 'soft delete adresses');
|
||||||
|
$affected = $this->defaultConnection->executeStatement('UPDATE chill_main_address_reference
|
||||||
|
SET deletedat = NOW()
|
||||||
|
WHERE
|
||||||
|
chill_main_address_reference.refid NOT IN (SELECT refid FROM reference_address_temp WHERE source LIKE ?)
|
||||||
|
AND chill_main_address_reference.source LIKE ?
|
||||||
|
', [$this->currentSource, $this->currentSource]);
|
||||||
|
$this->logger->info(self::LOG_PREFIX . 'addresses deleted', ['deleted' => $affected]);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Service\Import;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use League\Csv\Reader;
|
||||||
|
use League\Csv\Statement;
|
||||||
|
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||||
|
use UnexpectedValueException;
|
||||||
|
use function is_int;
|
||||||
|
|
||||||
|
class AddressReferenceFromBano
|
||||||
|
{
|
||||||
|
private AddressReferenceBaseImporter $baseImporter;
|
||||||
|
|
||||||
|
private HttpClientInterface $client;
|
||||||
|
|
||||||
|
public function __construct(HttpClientInterface $client, AddressReferenceBaseImporter $baseImporter)
|
||||||
|
{
|
||||||
|
$this->client = $client;
|
||||||
|
$this->baseImporter = $baseImporter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function import(string $departementNo): void
|
||||||
|
{
|
||||||
|
if (!is_numeric($departementNo) || !is_int((int) $departementNo)) {
|
||||||
|
throw new UnexpectedValueException('Could not parse this department number');
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = "https://bano.openstreetmap.fr/data/bano-{$departementNo}.csv";
|
||||||
|
|
||||||
|
$response = $this->client->request('GET', $url);
|
||||||
|
|
||||||
|
if (200 !== $response->getStatusCode()) {
|
||||||
|
throw new Exception('Could not download CSV: ' . $response->getStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = tmpfile();
|
||||||
|
|
||||||
|
foreach ($this->client->stream($response) as $chunk) {
|
||||||
|
fwrite($file, $chunk->getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek($file, 0);
|
||||||
|
|
||||||
|
$csv = Reader::createFromStream($file);
|
||||||
|
$csv->setDelimiter(',');
|
||||||
|
$stmt = Statement::create()
|
||||||
|
->process($csv, [
|
||||||
|
'refId',
|
||||||
|
'streetNumber',
|
||||||
|
'street',
|
||||||
|
'postcode',
|
||||||
|
'city',
|
||||||
|
'_o',
|
||||||
|
'lat',
|
||||||
|
'lon',
|
||||||
|
]);
|
||||||
|
|
||||||
|
foreach ($stmt as $record) {
|
||||||
|
$this->baseImporter->importAddress(
|
||||||
|
$record['refId'],
|
||||||
|
substr($record['refId'], 0, 5), // extract insee from reference
|
||||||
|
$record['postcode'],
|
||||||
|
$record['street'],
|
||||||
|
$record['streetNumber'],
|
||||||
|
'BANO.' . $departementNo,
|
||||||
|
(float) $record['lat'],
|
||||||
|
(float) $record['lon'],
|
||||||
|
4326
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->baseImporter->finalize();
|
||||||
|
|
||||||
|
fclose($file);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Service\Import;
|
||||||
|
|
||||||
|
use League\Csv\Reader;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use RuntimeException;
|
||||||
|
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||||
|
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||||
|
|
||||||
|
class PostalCodeBEFromBestAddress
|
||||||
|
{
|
||||||
|
private const RELEASE = 'https://gitea.champs-libres.be/api/v1/repos/Chill-project/belgian-bestaddresses-transform/releases/tags/v1.0.0';
|
||||||
|
|
||||||
|
private PostalCodeBaseImporter $baseImporter;
|
||||||
|
|
||||||
|
private HttpClientInterface $client;
|
||||||
|
|
||||||
|
private LoggerInterface $logger;
|
||||||
|
|
||||||
|
public function __construct(PostalCodeBaseImporter $baseImporter, HttpClientInterface $client, LoggerInterface $logger)
|
||||||
|
{
|
||||||
|
$this->baseImporter = $baseImporter;
|
||||||
|
$this->client = $client;
|
||||||
|
$this->logger = $logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function import(string $lang = 'fr'): void
|
||||||
|
{
|
||||||
|
$fileDownloadUrl = $this->getFileDownloadUrl($lang);
|
||||||
|
|
||||||
|
$response = $this->client->request('GET', $fileDownloadUrl);
|
||||||
|
|
||||||
|
$tmpname = tempnam(sys_get_temp_dir(), 'postalcodes');
|
||||||
|
$tmpfile = fopen($tmpname, 'r+b');
|
||||||
|
|
||||||
|
if (false === $tmpfile) {
|
||||||
|
throw new RuntimeException('could not create temporary file');
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->client->stream($response) as $chunk) {
|
||||||
|
fwrite($tmpfile, $chunk->getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($tmpfile);
|
||||||
|
|
||||||
|
$uncompressedStream = gzopen($tmpname, 'r');
|
||||||
|
|
||||||
|
$csv = Reader::createFromStream($uncompressedStream);
|
||||||
|
$csv->setDelimiter(',');
|
||||||
|
$csv->setHeaderOffset(0);
|
||||||
|
|
||||||
|
foreach ($csv as $offset => $record) {
|
||||||
|
$this->handleRecord($record);
|
||||||
|
}
|
||||||
|
|
||||||
|
gzclose($uncompressedStream);
|
||||||
|
unlink($tmpname);
|
||||||
|
|
||||||
|
$this->logger->info(__CLASS__ . ' list of postal code downloaded');
|
||||||
|
|
||||||
|
$this->baseImporter->finalize();
|
||||||
|
|
||||||
|
$this->logger->info(__CLASS__ . ' postal code fetched', ['offset' => $offset ?? 0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getFileDownloadUrl(string $lang): string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$release = $this->client->request('GET', self::RELEASE)
|
||||||
|
->toArray();
|
||||||
|
} catch (TransportExceptionInterface $e) {
|
||||||
|
throw new RuntimeException('could not get the release definition', 0, $e);
|
||||||
|
}
|
||||||
|
|
||||||
|
$postals = array_filter($release['assets'], static function (array $item) use ($lang) {
|
||||||
|
return 'postals.' . $lang . '.csv.gz' === $item['name'];
|
||||||
|
});
|
||||||
|
|
||||||
|
return array_values($postals)[0]['browser_download_url'];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleRecord(array $record): void
|
||||||
|
{
|
||||||
|
$this->baseImporter->importCode(
|
||||||
|
'BE',
|
||||||
|
trim($record['municipality_name']),
|
||||||
|
trim($record['postal_info_objectid']),
|
||||||
|
$record['municipality_objectid'],
|
||||||
|
'bestaddress',
|
||||||
|
$record['Y'],
|
||||||
|
$record['X'],
|
||||||
|
3812
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,124 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Service\Import;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Connection;
|
||||||
|
use Doctrine\DBAL\Statement;
|
||||||
|
use Exception;
|
||||||
|
use function array_key_exists;
|
||||||
|
use function count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optimized way to load postal code into database.
|
||||||
|
*/
|
||||||
|
class PostalCodeBaseImporter
|
||||||
|
{
|
||||||
|
private const QUERY = <<<'SQL'
|
||||||
|
WITH g AS (
|
||||||
|
SELECT DISTINCT
|
||||||
|
country.id AS country_id,
|
||||||
|
g.*
|
||||||
|
FROM (VALUES
|
||||||
|
{{ values }}
|
||||||
|
) AS g (countrycode, label, code, refpostalcodeid, postalcodeSource, lon, lat, srid)
|
||||||
|
JOIN country ON country.countrycode = g.countrycode
|
||||||
|
)
|
||||||
|
INSERT INTO chill_main_postal_code (id, country_id, label, code, origin, refpostalcodeid, postalcodeSource, center, createdAt, updatedAt)
|
||||||
|
SELECT
|
||||||
|
nextval('chill_main_postal_code_id_seq'),
|
||||||
|
g.country_id,
|
||||||
|
g.label AS glabel,
|
||||||
|
g.code,
|
||||||
|
0,
|
||||||
|
g.refpostalcodeid,
|
||||||
|
g.postalcodeSource,
|
||||||
|
CASE WHEN (g.lon::float != 0.0 AND g.lat::float != 0.0) THEN ST_Transform(ST_setSrid(ST_point(g.lon::float, g.lat::float), g.srid::int), 4326) ELSE NULL END,
|
||||||
|
NOW(),
|
||||||
|
NOW()
|
||||||
|
FROM g
|
||||||
|
ON CONFLICT (code, refpostalcodeid, postalcodeSource) WHERE refpostalcodeid IS NOT NULL DO UPDATE SET label = excluded.label, center = excluded.center, updatedAt = NOW()
|
||||||
|
SQL;
|
||||||
|
|
||||||
|
private const VALUE = '(?, ?, ?, ?, ?, ?, ?, ?)';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<int, Statement>
|
||||||
|
*/
|
||||||
|
private array $cachingStatements = [];
|
||||||
|
|
||||||
|
private Connection $defaultConnection;
|
||||||
|
|
||||||
|
private array $waitingForInsert = [];
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
Connection $defaultConnection
|
||||||
|
) {
|
||||||
|
$this->defaultConnection = $defaultConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function finalize(): void
|
||||||
|
{
|
||||||
|
$this->doInsertPending();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function importCode(
|
||||||
|
string $countryCode,
|
||||||
|
string $label,
|
||||||
|
string $code,
|
||||||
|
string $refPostalCodeId,
|
||||||
|
string $refPostalCodeSource,
|
||||||
|
float $centerLat,
|
||||||
|
float $centerLon,
|
||||||
|
int $centerSRID
|
||||||
|
): void {
|
||||||
|
$this->waitingForInsert[] = [
|
||||||
|
$countryCode,
|
||||||
|
$label,
|
||||||
|
$code,
|
||||||
|
$refPostalCodeId,
|
||||||
|
$refPostalCodeSource,
|
||||||
|
$centerLon,
|
||||||
|
$centerLat,
|
||||||
|
$centerSRID,
|
||||||
|
];
|
||||||
|
|
||||||
|
if (100 <= count($this->waitingForInsert)) {
|
||||||
|
$this->doInsertPending();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function doInsertPending(): void
|
||||||
|
{
|
||||||
|
if (!array_key_exists($forNumber = count($this->waitingForInsert), $this->cachingStatements)) {
|
||||||
|
$sql = strtr(self::QUERY, [
|
||||||
|
'{{ values }}' => implode(
|
||||||
|
', ',
|
||||||
|
array_fill(0, $forNumber, self::VALUE)
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->cachingStatements[$forNumber] = $this->defaultConnection->prepare($sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
$statement = $this->cachingStatements[$forNumber];
|
||||||
|
|
||||||
|
try {
|
||||||
|
$statement->executeStatement(array_merge(...$this->waitingForInsert));
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// in some case, we can add debug code here
|
||||||
|
//dump($this->waitingForInsert);
|
||||||
|
throw $e;
|
||||||
|
} finally {
|
||||||
|
$this->waitingForInsert = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Service\Import;
|
||||||
|
|
||||||
|
use League\Csv\Reader;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use RuntimeException;
|
||||||
|
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load French's postal codes from opendata.
|
||||||
|
*
|
||||||
|
* Currently, the source is datanova / la poste:
|
||||||
|
* https://datanova.legroupe.laposte.fr/explore/dataset/laposte_hexasmal/information/
|
||||||
|
*/
|
||||||
|
class PostalCodeFRFromOpenData
|
||||||
|
{
|
||||||
|
private const CSV = 'https://datanova.legroupe.laposte.fr/explore/dataset/laposte_hexasmal/download/?format=csv&timezone=Europe/Berlin&lang=fr&use_labels_for_header=true&csv_separator=%3B';
|
||||||
|
|
||||||
|
private PostalCodeBaseImporter $baseImporter;
|
||||||
|
|
||||||
|
private HttpClientInterface $client;
|
||||||
|
|
||||||
|
private LoggerInterface $logger;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
PostalCodeBaseImporter $baseImporter,
|
||||||
|
HttpClientInterface $client,
|
||||||
|
LoggerInterface $logger
|
||||||
|
) {
|
||||||
|
$this->baseImporter = $baseImporter;
|
||||||
|
$this->client = $client;
|
||||||
|
$this->logger = $logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function import(): void
|
||||||
|
{
|
||||||
|
$response = $this->client->request('GET', self::CSV);
|
||||||
|
|
||||||
|
if (200 !== $response->getStatusCode()) {
|
||||||
|
throw new RuntimeException('could not download CSV');
|
||||||
|
}
|
||||||
|
|
||||||
|
$tmpfile = tmpfile();
|
||||||
|
|
||||||
|
if (false === $tmpfile) {
|
||||||
|
throw new RuntimeException('could not create temporary file');
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->client->stream($response) as $chunk) {
|
||||||
|
fwrite($tmpfile, $chunk->getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek($tmpfile, 0);
|
||||||
|
|
||||||
|
$csv = Reader::createFromStream($tmpfile);
|
||||||
|
$csv->setDelimiter(';');
|
||||||
|
$csv->setHeaderOffset(0);
|
||||||
|
|
||||||
|
foreach ($csv as $offset => $record) {
|
||||||
|
$this->handleRecord($record);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->baseImporter->finalize();
|
||||||
|
fclose($tmpfile);
|
||||||
|
|
||||||
|
$this->logger->info(__CLASS__ . ' postal code fetched', ['offset' => $offset ?? 0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleRecord(array $record): void
|
||||||
|
{
|
||||||
|
if ('' !== trim($record['coordonnees_gps'])) {
|
||||||
|
[$lat, $lon] = array_map(static fn ($el) => (float) trim($el), explode(',', $record['coordonnees_gps']));
|
||||||
|
} else {
|
||||||
|
$lat = $lon = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ref = trim($record['Code_commune_INSEE']);
|
||||||
|
|
||||||
|
if ('987' === substr($ref, 0, 3)) {
|
||||||
|
// some differences in French Polynesia
|
||||||
|
$ref .= '.' . trim($record['Libellé_d_acheminement']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->baseImporter->importCode(
|
||||||
|
'FR',
|
||||||
|
trim($record['Libellé_d_acheminement']),
|
||||||
|
trim($record['Code_postal']),
|
||||||
|
$ref,
|
||||||
|
'INSEE',
|
||||||
|
$lat,
|
||||||
|
$lon,
|
||||||
|
4326
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -25,7 +25,6 @@ use function is_string;
|
|||||||
/**
|
/**
|
||||||
* Helper which creates a set of test for aggregators.
|
* Helper which creates a set of test for aggregators.
|
||||||
*
|
*
|
||||||
* @internal
|
|
||||||
*/
|
*/
|
||||||
abstract class AbstractAggregatorTest extends KernelTestCase
|
abstract class AbstractAggregatorTest extends KernelTestCase
|
||||||
{
|
{
|
||||||
|
@ -24,7 +24,6 @@ use function is_string;
|
|||||||
/**
|
/**
|
||||||
* Helper to test filters.
|
* Helper to test filters.
|
||||||
*
|
*
|
||||||
* @internal
|
|
||||||
*/
|
*/
|
||||||
abstract class AbstractFilterTest extends KernelTestCase
|
abstract class AbstractFilterTest extends KernelTestCase
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Services\Import;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\PostalCode;
|
||||||
|
use Chill\MainBundle\Repository\AddressReferenceRepository;
|
||||||
|
use Chill\MainBundle\Repository\PostalCodeRepository;
|
||||||
|
use Chill\MainBundle\Service\Import\AddressReferenceBaseImporter;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||||
|
|
||||||
|
class AddressReferenceBaseImporterTest extends KernelTestCase
|
||||||
|
{
|
||||||
|
private AddressReferenceBaseImporter $importer;
|
||||||
|
private AddressReferenceRepository $addressReferenceRepository;
|
||||||
|
private EntityManagerInterface $entityManager;
|
||||||
|
private PostalCodeRepository $postalCodeRepository;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
$this->importer = self::$container->get(AddressReferenceBaseImporter::class);
|
||||||
|
$this->addressReferenceRepository = self::$container->get(AddressReferenceRepository::class);
|
||||||
|
$this->entityManager = self::$container->get(EntityManagerInterface::class);
|
||||||
|
$this->postalCodeRepository = self::$container->get(PostalCodeRepository::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testImportAddress(): void
|
||||||
|
{
|
||||||
|
$postalCode = (new PostalCode())
|
||||||
|
->setRefPostalCodeId($postalCodeId = '1234'.uniqid())
|
||||||
|
->setPostalCodeSource('testing')
|
||||||
|
->setCode('TEST456')
|
||||||
|
->setName('testing');
|
||||||
|
|
||||||
|
$this->entityManager->persist($postalCode);
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
$this->importer->importAddress(
|
||||||
|
'0000',
|
||||||
|
$postalCodeId,
|
||||||
|
'TEST456',
|
||||||
|
'Rue test abccc-guessed',
|
||||||
|
'-1',
|
||||||
|
'unit-test',
|
||||||
|
50.0,
|
||||||
|
5.0,
|
||||||
|
4326
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->importer->finalize();
|
||||||
|
|
||||||
|
$addresses = $this->addressReferenceRepository->findByPostalCodePattern(
|
||||||
|
$postalCode,
|
||||||
|
'Rue test abcc guessed');
|
||||||
|
|
||||||
|
$this->assertCount(1, $addresses);
|
||||||
|
$this->assertEquals('Rue test abccc-guessed', $addresses[0]->getStreet());
|
||||||
|
|
||||||
|
$previousAddressId = $addresses[0]->getId();
|
||||||
|
|
||||||
|
$this->entityManager->clear();
|
||||||
|
|
||||||
|
$this->importer->importAddress(
|
||||||
|
'0000',
|
||||||
|
$postalCodeId,
|
||||||
|
'TEST456',
|
||||||
|
'Rue test abccc guessed fixed',
|
||||||
|
'-1',
|
||||||
|
'unit-test',
|
||||||
|
50.0,
|
||||||
|
5.0,
|
||||||
|
4326
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->importer->finalize();
|
||||||
|
|
||||||
|
$addresses = $this->addressReferenceRepository->findByPostalCodePattern(
|
||||||
|
$postalCode,
|
||||||
|
'abcc guessed fixed');
|
||||||
|
|
||||||
|
$this->assertCount('1', $addresses);
|
||||||
|
$this->assertEquals( 'Rue test abccc guessed fixed', $addresses[0]->getStreet());
|
||||||
|
$this->assertEquals($previousAddressId, $addresses[0]->getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Services\Import;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Repository\CountryRepository;
|
||||||
|
use Chill\MainBundle\Repository\PostalCodeRepository;
|
||||||
|
use Chill\MainBundle\Service\Import\PostalCodeBaseImporter;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||||
|
|
||||||
|
class PostalCodeBaseImporterTest extends KernelTestCase
|
||||||
|
{
|
||||||
|
private EntityManagerInterface $entityManager;
|
||||||
|
|
||||||
|
private PostalCodeBaseImporter $importer;
|
||||||
|
|
||||||
|
private PostalCodeRepository $postalCodeRepository;
|
||||||
|
|
||||||
|
private CountryRepository $countryRepository;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
$this->entityManager = self::$container->get(EntityManagerInterface::class);
|
||||||
|
$this->importer = self::$container->get(PostalCodeBaseImporter::class);
|
||||||
|
$this->postalCodeRepository = self::$container->get(PostalCodeRepository::class);
|
||||||
|
$this->countryRepository = self::$container->get(CountryRepository::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testImportPostalCode(): void
|
||||||
|
{
|
||||||
|
$this->importer->importCode(
|
||||||
|
'BE',
|
||||||
|
'tested with pattern '. ($uniqid = uniqid()),
|
||||||
|
'12345',
|
||||||
|
$refPostalCodeId = 'test'.uniqid(),
|
||||||
|
'test',
|
||||||
|
50.0,
|
||||||
|
5.0,
|
||||||
|
4326
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->importer->finalize();
|
||||||
|
|
||||||
|
$postalCodes = $this->postalCodeRepository->findByPattern(
|
||||||
|
'with pattern '.$uniqid,
|
||||||
|
$this->countryRepository->findOneBy(['countryCode' => 'BE'])
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertCount(1, $postalCodes);
|
||||||
|
$this->assertStringStartsWith('tested with pattern', $postalCodes[0]->getName());
|
||||||
|
|
||||||
|
$previousId = $postalCodes[0]->getId();
|
||||||
|
|
||||||
|
$this->entityManager->clear();
|
||||||
|
|
||||||
|
$this->importer->importCode(
|
||||||
|
'BE',
|
||||||
|
'tested with adapted pattern '. ($uniqid = uniqid()),
|
||||||
|
'12345',
|
||||||
|
$refPostalCodeId,
|
||||||
|
'test',
|
||||||
|
50.0,
|
||||||
|
5.0,
|
||||||
|
4326
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->importer->finalize();
|
||||||
|
|
||||||
|
$postalCodes = $this->postalCodeRepository->findByPattern(
|
||||||
|
'with pattern '.$uniqid,
|
||||||
|
$this->countryRepository->findOneBy(['countryCode' => 'BE'])
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertCount(1, $postalCodes);
|
||||||
|
$this->assertStringStartsWith('tested with adapted pattern', $postalCodes[0]->getName());
|
||||||
|
$this->assertEquals($previousId, $postalCodes[0]->getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,102 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Tests\Workflow\EventSubscriber;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Notification;
|
||||||
|
use Chill\MainBundle\Entity\User;
|
||||||
|
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
|
||||||
|
use Chill\MainBundle\Entity\Workflow\EntityWorkflowStep;
|
||||||
|
use Chill\MainBundle\Workflow\EventSubscriber\NotificationOnTransition;
|
||||||
|
use Chill\MainBundle\Workflow\Helper\MetadataExtractor;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Prophecy\Argument;
|
||||||
|
use Prophecy\Call\Call;
|
||||||
|
use Prophecy\Exception\Prediction\FailedPredictionException;
|
||||||
|
use Prophecy\PhpUnit\ProphecyTrait;
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
use Symfony\Component\Templating\EngineInterface;
|
||||||
|
use Symfony\Component\Workflow\Event\Event;
|
||||||
|
use Symfony\Component\Workflow\Marking;
|
||||||
|
use Symfony\Component\Workflow\Registry;
|
||||||
|
use Symfony\Component\Workflow\Transition;
|
||||||
|
use Symfony\Component\Workflow\Workflow;
|
||||||
|
use Symfony\Component\Workflow\WorkflowInterface;
|
||||||
|
|
||||||
|
class NotificationOnTransitionTest extends TestCase
|
||||||
|
{
|
||||||
|
use ProphecyTrait;
|
||||||
|
|
||||||
|
public function testOnCompleteSendNotification(): void
|
||||||
|
{
|
||||||
|
$dest = new User();
|
||||||
|
$currentUser = new User();
|
||||||
|
$workflowProphecy = $this->prophesize(WorkflowInterface::class);
|
||||||
|
$workflow = $workflowProphecy->reveal();
|
||||||
|
$entityWorkflow = new EntityWorkflow();
|
||||||
|
$entityWorkflow
|
||||||
|
->setWorkflowName('workflow_name')
|
||||||
|
->setRelatedEntityClass(\stdClass::class)
|
||||||
|
->setRelatedEntityId(1)
|
||||||
|
;
|
||||||
|
// force an id to entityWorkflow:
|
||||||
|
$reflection = new \ReflectionClass($entityWorkflow);
|
||||||
|
$id = $reflection->getProperty('id');
|
||||||
|
$id->setAccessible(true);
|
||||||
|
$id->setValue($entityWorkflow, 1);
|
||||||
|
|
||||||
|
$step = new EntityWorkflowStep();
|
||||||
|
$entityWorkflow->addStep($step);
|
||||||
|
$step->addDestUser($dest)
|
||||||
|
->setCurrentStep('to_state')
|
||||||
|
;
|
||||||
|
|
||||||
|
$em = $this->prophesize(EntityManagerInterface::class);
|
||||||
|
$em->persist(Argument::type(Notification::class))->should(
|
||||||
|
function($args) use ($dest) {
|
||||||
|
/** @var Call[] $args */
|
||||||
|
if (1 !== count($args)) {
|
||||||
|
throw new FailedPredictionException('no notification sent');
|
||||||
|
}
|
||||||
|
|
||||||
|
$notification = $args[0]->getArguments()[0];
|
||||||
|
|
||||||
|
if (!$notification instanceof Notification) {
|
||||||
|
throw new FailedPredictionException('persist is not a notification');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$notification->getAddressees()->contains($dest)) {
|
||||||
|
throw new FailedPredictionException('the dest is not notified');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$engine = $this->prophesize(EngineInterface::class);
|
||||||
|
$engine->render(Argument::type('string'), Argument::type('array'))
|
||||||
|
->willReturn('dummy text');
|
||||||
|
|
||||||
|
$extractor = $this->prophesize(MetadataExtractor::class);
|
||||||
|
$extractor->buildArrayPresentationForPlace(Argument::type(EntityWorkflow::class), Argument::any())
|
||||||
|
->willReturn([]);
|
||||||
|
$extractor->buildArrayPresentationForWorkflow(Argument::any())
|
||||||
|
->willReturn([]);
|
||||||
|
|
||||||
|
$registry = $this->prophesize(Registry::class);
|
||||||
|
$registry->get(Argument::type(EntityWorkflow::class), Argument::type('string'))
|
||||||
|
->willReturn($workflow);
|
||||||
|
|
||||||
|
$security = $this->prophesize(Security::class);
|
||||||
|
$security->getUser()->willReturn($currentUser);
|
||||||
|
|
||||||
|
$notificationOnTransition = new NotificationOnTransition(
|
||||||
|
$em->reveal(),
|
||||||
|
$engine->reveal(),
|
||||||
|
$extractor->reveal(),
|
||||||
|
$security->reveal(),
|
||||||
|
$registry->reveal()
|
||||||
|
);
|
||||||
|
|
||||||
|
$event = new Event($entityWorkflow, new Marking(), new Transition('dummy_transition', ['from_state'], ['to_state']), $workflow);
|
||||||
|
|
||||||
|
$notificationOnTransition->onCompletedSendNotification($event);
|
||||||
|
}
|
||||||
|
}
|
@ -45,13 +45,33 @@ class EntityWorkflowTransitionEventSubscriber implements EventSubscriberInterfac
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'workflow.transition' => 'onTransition',
|
'workflow.transition' => 'onTransition',
|
||||||
'workflow.completed' => 'onCompleted',
|
'workflow.completed' => [
|
||||||
|
['markAsFinal', 2048],
|
||||||
|
['addDests', 2048],
|
||||||
|
],
|
||||||
'workflow.guard' => [
|
'workflow.guard' => [
|
||||||
['guardEntityWorkflow', 0],
|
['guardEntityWorkflow', 0],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function addDests(Event $event): void
|
||||||
|
{
|
||||||
|
if (!$event->getSubject() instanceof EntityWorkflow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var EntityWorkflow $entityWorkflow */
|
||||||
|
$entityWorkflow = $event->getSubject();
|
||||||
|
foreach ($entityWorkflow->futureDestUsers as $user) {
|
||||||
|
$entityWorkflow->getCurrentStep()->addDestUser($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($entityWorkflow->futureDestEmails as $email) {
|
||||||
|
$entityWorkflow->getCurrentStep()->addDestEmail($email);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function guardEntityWorkflow(GuardEvent $event)
|
public function guardEntityWorkflow(GuardEvent $event)
|
||||||
{
|
{
|
||||||
if (!$event->getSubject() instanceof EntityWorkflow) {
|
if (!$event->getSubject() instanceof EntityWorkflow) {
|
||||||
@ -90,7 +110,7 @@ class EntityWorkflowTransitionEventSubscriber implements EventSubscriberInterfac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onCompleted(Event $event): void
|
public function markAsFinal(Event $event): void
|
||||||
{
|
{
|
||||||
if (!$event->getSubject() instanceof EntityWorkflow) {
|
if (!$event->getSubject() instanceof EntityWorkflow) {
|
||||||
return;
|
return;
|
||||||
|
@ -52,10 +52,20 @@ class NotificationOnTransition implements EventSubscriberInterface
|
|||||||
public static function getSubscribedEvents(): array
|
public static function getSubscribedEvents(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'workflow.completed' => 'onCompletedSendNotification',
|
'workflow.completed' => ['onCompletedSendNotification', 2048],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a notification to:
|
||||||
|
*
|
||||||
|
* * the dests of the new step;
|
||||||
|
* * the users which subscribed to workflow, on each step, or on final
|
||||||
|
*
|
||||||
|
* **Warning** take care that this method must be executed **after** the dest users are added to
|
||||||
|
* the step (@link{EntityWorkflowStep::addDestUser}). Currently, this is done during
|
||||||
|
* @link{EntityWorkflowTransitionEventSubscriber::addDests}.
|
||||||
|
*/
|
||||||
public function onCompletedSendNotification(Event $event): void
|
public function onCompletedSendNotification(Event $event): void
|
||||||
{
|
{
|
||||||
if (!$event->getSubject() instanceof EntityWorkflow) {
|
if (!$event->getSubject() instanceof EntityWorkflow) {
|
||||||
@ -65,23 +75,27 @@ class NotificationOnTransition implements EventSubscriberInterface
|
|||||||
/** @var EntityWorkflow $entityWorkflow */
|
/** @var EntityWorkflow $entityWorkflow */
|
||||||
$entityWorkflow = $event->getSubject();
|
$entityWorkflow = $event->getSubject();
|
||||||
|
|
||||||
$dests = array_merge(
|
/** @var array<string, User> $dests array of unique values, where keys is the object's hash */
|
||||||
|
$dests = [];
|
||||||
|
foreach (array_merge(
|
||||||
|
// the subscriber to each step
|
||||||
$entityWorkflow->getSubscriberToStep()->toArray(),
|
$entityWorkflow->getSubscriberToStep()->toArray(),
|
||||||
|
// the subscriber to final, only if final
|
||||||
$entityWorkflow->isFinal() ? $entityWorkflow->getSubscriberToFinal()->toArray() : [],
|
$entityWorkflow->isFinal() ? $entityWorkflow->getSubscriberToFinal()->toArray() : [],
|
||||||
$entityWorkflow->getCurrentStepChained()->getPrevious()->getDestUser()->toArray()
|
// the dests for the current step
|
||||||
);
|
$entityWorkflow->getCurrentStep()->getDestUser()->toArray()
|
||||||
|
) as $dest) {
|
||||||
|
$dests[spl_object_hash($dest)] = $dest;
|
||||||
|
}
|
||||||
|
|
||||||
$place = $this->metadataExtractor->buildArrayPresentationForPlace($entityWorkflow);
|
$place = $this->metadataExtractor->buildArrayPresentationForPlace($entityWorkflow);
|
||||||
$workflow = $this->metadataExtractor->buildArrayPresentationForWorkflow(
|
$workflow = $this->metadataExtractor->buildArrayPresentationForWorkflow(
|
||||||
$this->registry->get($entityWorkflow, $entityWorkflow->getWorkflowName())
|
$this->registry->get($entityWorkflow, $entityWorkflow->getWorkflowName())
|
||||||
);
|
);
|
||||||
|
|
||||||
$visited = [];
|
|
||||||
|
|
||||||
foreach ($dests as $subscriber) {
|
foreach ($dests as $subscriber) {
|
||||||
if (
|
if (
|
||||||
$this->security->getUser() === $subscriber
|
$this->security->getUser() === $subscriber
|
||||||
|| in_array($subscriber->getId(), $visited, true)
|
|
||||||
) {
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -102,8 +116,6 @@ class NotificationOnTransition implements EventSubscriberInterface
|
|||||||
->setMessage($this->engine->render('@ChillMain/Workflow/workflow_notification_on_transition_completed_content.fr.txt.twig', $context))
|
->setMessage($this->engine->render('@ChillMain/Workflow/workflow_notification_on_transition_completed_content.fr.txt.twig', $context))
|
||||||
->addAddressee($subscriber);
|
->addAddressee($subscriber);
|
||||||
$this->entityManager->persist($notification);
|
$this->entityManager->persist($notification);
|
||||||
|
|
||||||
$visited[] = $subscriber->getId();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,3 +93,7 @@ services:
|
|||||||
|
|
||||||
Chill\MainBundle\Security\Resolver\CenterResolverDispatcherInterface: '@Chill\MainBundle\Security\Resolver\CenterResolverDispatcher'
|
Chill\MainBundle\Security\Resolver\CenterResolverDispatcherInterface: '@Chill\MainBundle\Security\Resolver\CenterResolverDispatcher'
|
||||||
|
|
||||||
|
Chill\MainBundle\Service\Import\:
|
||||||
|
resource: '../Service/Import/'
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
|
@ -43,3 +43,21 @@ services:
|
|||||||
$entityManager: '@doctrine.orm.entity_manager'
|
$entityManager: '@doctrine.orm.entity_manager'
|
||||||
tags:
|
tags:
|
||||||
- { name: console.command }
|
- { name: console.command }
|
||||||
|
|
||||||
|
Chill\MainBundle\Command\LoadAddressesFRFromBANOCommand:
|
||||||
|
autoconfigure: true
|
||||||
|
autowire: true
|
||||||
|
tags:
|
||||||
|
- { name: console.command }
|
||||||
|
|
||||||
|
Chill\MainBundle\Command\LoadAddressesBEFromBestAddressCommand:
|
||||||
|
autoconfigure: true
|
||||||
|
autowire: true
|
||||||
|
tags:
|
||||||
|
- { name: console.command }
|
||||||
|
|
||||||
|
Chill\MainBundle\Command\LoadPostalCodeFR:
|
||||||
|
autoconfigure: true
|
||||||
|
autowire: true
|
||||||
|
tags:
|
||||||
|
- { name: console.command }
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\Migrations\Main;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
final class Version20220729205416 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('DROP INDEX postal_code_import_unicity');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_postal_code DROP deletedAt');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_postal_code DROP updatedAt');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_postal_code DROP createdAt');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_postal_code DROP updatedBy_id');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_postal_code DROP createdBy_id');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_postal_code DROP CONSTRAINT chill_internal_postal_code_import_unicity');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'postal code: add columns to track creation, update and deletion';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('ALTER TABLE chill_main_postal_code ADD deletedAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_postal_code ADD updatedAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_postal_code ADD createdAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_postal_code ADD updatedBy_id INT DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_postal_code ADD createdBy_id INT DEFAULT NULL');
|
||||||
|
$this->addSql('COMMENT ON COLUMN chill_main_postal_code.deletedAt IS \'(DC2Type:datetime_immutable)\'');
|
||||||
|
$this->addSql('COMMENT ON COLUMN chill_main_postal_code.updatedAt IS \'(DC2Type:datetime_immutable)\'');
|
||||||
|
$this->addSql('COMMENT ON COLUMN chill_main_postal_code.createdAt IS \'(DC2Type:datetime_immutable)\'');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_postal_code ADD CONSTRAINT FK_6CA145FA65FF1AEC FOREIGN KEY (updatedBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_postal_code ADD CONSTRAINT FK_6CA145FA3174800F FOREIGN KEY (createdBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('CREATE INDEX IDX_6CA145FA65FF1AEC ON chill_main_postal_code (updatedBy_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_6CA145FA3174800F ON chill_main_postal_code (createdBy_id)');
|
||||||
|
$this->addSql('CREATE UNIQUE INDEX postal_code_import_unicity ON chill_main_postal_code (code, refpostalcodeid, postalcodesource) WHERE refpostalcodeid is not null');
|
||||||
|
//$this->addSql('ALTER TABLE chill_main_postal_code ADD CONSTRAINT chill_internal_postal_code_import_unicity '.
|
||||||
|
// 'EXCLUDE (code WITH =, refpostalcodeid WITH =, postalcodesource WITH =) WHERE (refpostalcodeid IS NOT NULL)');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\Migrations\Main;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
final class Version20220730204216 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'Add an unique constraint on addresses references';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('CREATE UNIQUE INDEX chill_main_address_reference_unicity ON chill_main_address_reference (refId, source)');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('DROP INDEX chill_main_address_reference_unicity');
|
||||||
|
}
|
||||||
|
}
|
@ -27,6 +27,8 @@ use Chill\MainBundle\Validation\Constraint\PhonenumberConstraint;
|
|||||||
use Chill\PersonBundle\Entity\Household\Household;
|
use Chill\PersonBundle\Entity\Household\Household;
|
||||||
use Chill\PersonBundle\Entity\Household\HouseholdMember;
|
use Chill\PersonBundle\Entity\Household\HouseholdMember;
|
||||||
use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress;
|
use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress;
|
||||||
|
use Chill\PersonBundle\Entity\Person\PersonCenterCurrent;
|
||||||
|
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||||
use Chill\PersonBundle\Entity\Person\PersonCurrentAddress;
|
use Chill\PersonBundle\Entity\Person\PersonCurrentAddress;
|
||||||
use Chill\PersonBundle\Entity\Person\PersonResource;
|
use Chill\PersonBundle\Entity\Person\PersonResource;
|
||||||
use Chill\PersonBundle\Validator\Constraints\Household\HouseholdMembershipSequential;
|
use Chill\PersonBundle\Validator\Constraints\Household\HouseholdMembershipSequential;
|
||||||
@ -180,9 +182,21 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
|||||||
* The person's center.
|
* The person's center.
|
||||||
*
|
*
|
||||||
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Center")
|
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Center")
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
private ?Center $center = null;
|
private ?Center $center = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\OneToMany(targetEntity=PersonCenterHistory::class, mappedBy="person", cascade={"persist"})
|
||||||
|
* @var Collection|PersonCenterHistory[]
|
||||||
|
*/
|
||||||
|
private Collection $centerHistory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\OneToOne(targetEntity=PersonCenterCurrent::class, mappedBy="person")
|
||||||
|
*/
|
||||||
|
private ?PersonCenterCurrent $centerCurrent = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array where customfield's data are stored.
|
* Array where customfield's data are stored.
|
||||||
*
|
*
|
||||||
@ -523,6 +537,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
|||||||
$this->budgetResources = new ArrayCollection();
|
$this->budgetResources = new ArrayCollection();
|
||||||
$this->budgetCharges = new ArrayCollection();
|
$this->budgetCharges = new ArrayCollection();
|
||||||
$this->resources = new ArrayCollection();
|
$this->resources = new ArrayCollection();
|
||||||
|
$this->centerHistory = new ArrayCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -895,9 +910,43 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
|||||||
return $this->budgetResources;
|
return $this->budgetResources;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getCurrentCenterHistory(): ?PersonCenterHistory
|
||||||
|
{
|
||||||
|
if (0 === $this->centerHistory->count()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$criteria = Criteria::create();
|
||||||
|
$now = new DateTimeImmutable('now');
|
||||||
|
$criteria->where(Criteria::expr()->lte('startDate', $now))
|
||||||
|
->andWhere(Criteria::expr()->orX(
|
||||||
|
Criteria::expr()->isNull('endDate'),
|
||||||
|
Criteria::expr()->gt('endDate', $now)
|
||||||
|
));
|
||||||
|
|
||||||
|
$histories = $this->centerHistory->matching($criteria);
|
||||||
|
|
||||||
|
switch ($histories->count()) {
|
||||||
|
case 0:
|
||||||
|
return null;
|
||||||
|
case 1:
|
||||||
|
return $histories->first();
|
||||||
|
default:
|
||||||
|
throw new \UnexpectedValueException('It should not contains more than one center at a time');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function getCenter(): ?Center
|
public function getCenter(): ?Center
|
||||||
{
|
{
|
||||||
return $this->center;
|
if (null !== $this->centerCurrent) {
|
||||||
|
return $this->centerCurrent->getCenter();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $currentCenterHistory = $this->getCurrentCenterHistory()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $currentCenterHistory->getCenter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCFData(): ?array
|
public function getCFData(): ?array
|
||||||
@ -1510,17 +1559,67 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associate the center with the person. The association start on 'now'.
|
||||||
|
*
|
||||||
|
* @param Center $center
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
public function setCenter(Center $center): self
|
public function setCenter(Center $center): self
|
||||||
{
|
{
|
||||||
$this->center = $center;
|
$this->center = $center;
|
||||||
|
|
||||||
|
$modification = new DateTimeImmutable('now');
|
||||||
|
|
||||||
|
foreach ($this->centerHistory as $centerHistory) {
|
||||||
|
if (null === $centerHistory->getEndDate()) {
|
||||||
|
$centerHistory->setEndDate($modification);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->centerHistory[] = $new = new PersonCenterHistory($this, $center, $modification);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Report
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function setCFData(?array $cFData)
|
public function getCenterHistory(): Collection
|
||||||
|
{
|
||||||
|
return $this->centerHistory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $centerHistory
|
||||||
|
* @return Person
|
||||||
|
*/
|
||||||
|
public function setCenterHistory(Collection $centerHistory): Person
|
||||||
|
{
|
||||||
|
$this->centerHistory = $centerHistory;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return PersonCenterCurrent|null
|
||||||
|
*/
|
||||||
|
public function getCenterCurrent(): ?PersonCenterCurrent
|
||||||
|
{
|
||||||
|
if (null !== $this->centerCurrent) {
|
||||||
|
return $this->centerCurrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $currentCenterHistory = $this->getCurrentCenterHistory()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PersonCenterCurrent($currentCenterHistory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Person
|
||||||
|
*/
|
||||||
|
public function setCFData(?array $cFData): self
|
||||||
{
|
{
|
||||||
$this->cFData = $cFData;
|
$this->cFData = $cFData;
|
||||||
|
|
||||||
|
@ -0,0 +1,112 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Entity\Person;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
|
||||||
|
use Chill\MainBundle\Doctrine\Model\TrackCreationTrait;
|
||||||
|
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
|
||||||
|
use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait;
|
||||||
|
use Chill\MainBundle\Entity\Center;
|
||||||
|
use Chill\MainBundle\Entity\User;
|
||||||
|
use Chill\PersonBundle\Entity\Person;
|
||||||
|
use DateTimeInterface;
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associate a Person with the current center.
|
||||||
|
*
|
||||||
|
* The process of selecting the current center is done on database side,
|
||||||
|
* using a SQL view.
|
||||||
|
*
|
||||||
|
* @ORM\Entity(readOnly=true)
|
||||||
|
* @ORM\Table(name="view_chill_person_person_center_history_current")
|
||||||
|
* @psalm-internal Chill\PersonBundle\Entity
|
||||||
|
*/
|
||||||
|
class PersonCenterCurrent
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @ORM\Id
|
||||||
|
* @ORM\Column(type="integer")
|
||||||
|
*/
|
||||||
|
private ?int $id = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\ManyToOne(targetEntity=Person::class, inversedBy="centerCurrent")
|
||||||
|
*/
|
||||||
|
private Person $person;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\ManyToOne(targetEntity=Center::class)
|
||||||
|
*/
|
||||||
|
private Center $center;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="date_immutable", nullable=false)
|
||||||
|
*/
|
||||||
|
private \DateTimeImmutable $startDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="date_immutable", nullable=true, options={"default": null})
|
||||||
|
*/
|
||||||
|
private ?\DateTimeImmutable $endDate = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate the properties person, center, start and end date from history.
|
||||||
|
*
|
||||||
|
* The creator and updatedby are not filled.
|
||||||
|
*
|
||||||
|
* @internal Should not be instantied, unless inside Person entity
|
||||||
|
* @param PersonCenterHistory $history
|
||||||
|
*/
|
||||||
|
public function __construct(PersonCenterHistory $history)
|
||||||
|
{
|
||||||
|
$this->person = $history->getPerson();
|
||||||
|
$this->center = $history->getCenter();
|
||||||
|
$this->startDate = $history->getStartDate();
|
||||||
|
$this->endDate = $history->getEndDate();
|
||||||
|
$this->id = $history->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The id will be the same as the current @link{PersonCenterHistory::class}
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getId(): int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Person
|
||||||
|
*/
|
||||||
|
public function getPerson(): Person
|
||||||
|
{
|
||||||
|
return $this->person;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Center
|
||||||
|
*/
|
||||||
|
public function getCenter(): Center
|
||||||
|
{
|
||||||
|
return $this->center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \DateTimeImmutable
|
||||||
|
*/
|
||||||
|
public function getStartDate(): \DateTimeImmutable
|
||||||
|
{
|
||||||
|
return $this->startDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \DateTimeImmutable|null
|
||||||
|
*/
|
||||||
|
public function getEndDate(): ?\DateTimeImmutable
|
||||||
|
{
|
||||||
|
return $this->endDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,142 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Entity\Person;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
|
||||||
|
use Chill\MainBundle\Doctrine\Model\TrackCreationTrait;
|
||||||
|
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
|
||||||
|
use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait;
|
||||||
|
use Chill\MainBundle\Entity\Center;
|
||||||
|
use Chill\PersonBundle\Entity\Person;
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associate a Person with a Center. The association may change on date intervals
|
||||||
|
*
|
||||||
|
* @ORM\Entity
|
||||||
|
* @ORM\Table(name="chill_person_person_center_history")
|
||||||
|
*/
|
||||||
|
class PersonCenterHistory implements TrackCreationInterface, TrackUpdateInterface
|
||||||
|
{
|
||||||
|
use TrackCreationTrait;
|
||||||
|
use TrackUpdateTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Id
|
||||||
|
* @ORM\GeneratedValue
|
||||||
|
* @ORM\Column(type="integer")
|
||||||
|
*/
|
||||||
|
private ?int $id = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\ManyToOne(targetEntity=Person::class, inversedBy="centerHistory")
|
||||||
|
*/
|
||||||
|
private ?Person $person = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\ManyToOne(targetEntity=Center::class)
|
||||||
|
*/
|
||||||
|
private ?Center $center = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="date_immutable", nullable=false)
|
||||||
|
*/
|
||||||
|
private ?\DateTimeImmutable $startDate = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="date_immutable", nullable=true, options={"default": null})
|
||||||
|
*/
|
||||||
|
private ?\DateTimeImmutable $endDate = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Person|null $person
|
||||||
|
* @param Center|null $center
|
||||||
|
* @param \DateTimeImmutable|null $startDate
|
||||||
|
*/
|
||||||
|
public function __construct(?Person $person = null, ?Center $center = null, ?\DateTimeImmutable $startDate = null)
|
||||||
|
{
|
||||||
|
$this->person = $person;
|
||||||
|
$this->center = $center;
|
||||||
|
$this->startDate = $startDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int|null
|
||||||
|
*/
|
||||||
|
public function getId(): ?int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Person|null
|
||||||
|
*/
|
||||||
|
public function getPerson(): ?Person
|
||||||
|
{
|
||||||
|
return $this->person;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Person|null $person
|
||||||
|
*/
|
||||||
|
public function setPerson(?Person $person): self
|
||||||
|
{
|
||||||
|
$this->person = $person;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Center|null
|
||||||
|
*/
|
||||||
|
public function getCenter(): ?Center
|
||||||
|
{
|
||||||
|
return $this->center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Center|null $center
|
||||||
|
*/
|
||||||
|
public function setCenter(?Center $center): self
|
||||||
|
{
|
||||||
|
$this->center = $center;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \DateTimeImmutable|null
|
||||||
|
*/
|
||||||
|
public function getStartDate(): ?\DateTimeImmutable
|
||||||
|
{
|
||||||
|
return $this->startDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \DateTimeImmutable|null $startDate
|
||||||
|
*/
|
||||||
|
public function setStartDate(?\DateTimeImmutable $startDate): self
|
||||||
|
{
|
||||||
|
$this->startDate = $startDate;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \DateTimeImmutable|null
|
||||||
|
*/
|
||||||
|
public function getEndDate(): ?\DateTimeImmutable
|
||||||
|
{
|
||||||
|
return $this->endDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \DateTimeImmutable|null $endDate
|
||||||
|
*/
|
||||||
|
public function setEndDate(?\DateTimeImmutable $endDate): self
|
||||||
|
{
|
||||||
|
$this->endDate = $endDate;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
@ -49,9 +49,8 @@ class Evaluation
|
|||||||
/**
|
/**
|
||||||
* @ORM\ManyToMany(
|
* @ORM\ManyToMany(
|
||||||
* targetEntity=SocialAction::class,
|
* targetEntity=SocialAction::class,
|
||||||
* inversedBy="evaluations"
|
* mappedBy="evaluations"
|
||||||
* )
|
* )
|
||||||
* @ORM\JoinTable(name="chill_person_social_work_evaluation_action")
|
|
||||||
*/
|
*/
|
||||||
private Collection $socialActions;
|
private Collection $socialActions;
|
||||||
|
|
||||||
|
@ -25,23 +25,17 @@ class AbstractAccompanyingPeriodExportElement
|
|||||||
*/
|
*/
|
||||||
protected function addJoinAccompanyingPeriod(QueryBuilder $query): void
|
protected function addJoinAccompanyingPeriod(QueryBuilder $query): void
|
||||||
{
|
{
|
||||||
if (false === $this->havingAccompanyingPeriodInJoin($query)) {
|
if (false === in_array('person', $query->getAllAliases(), true)) {
|
||||||
if (false === in_array('person', $query->getAllAliases(), true)) {
|
throw new LogicException("the alias 'person' does not exists in "
|
||||||
throw new LogicException("the alias 'person' does not exists in "
|
. 'query builder');
|
||||||
. 'query builder');
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$query->join('person.accompanyingPeriods', 'accompanying_period');
|
if (!in_array('acppart', $query->getAllAliases(), true)) {
|
||||||
|
$query->join('person.accompanyingPeriodParticipations', 'acppart');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in_array('acp', $query->getAllAliases(), true)) {
|
||||||
|
$query->join('acppart.accompanyingPeriod', 'acp');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if "accompanying_period" alias is present in the query alises.
|
|
||||||
*/
|
|
||||||
protected function havingAccompanyingPeriodInJoin(QueryBuilder $query): bool
|
|
||||||
{
|
|
||||||
$joins = $query->getDQLPart('join') ?? [];
|
|
||||||
|
|
||||||
return in_array('accompanying_period', $query->getAllAliases(), true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -40,18 +40,11 @@ class AdministrativeLocationAggregator implements AggregatorInterface
|
|||||||
public function alterQuery(QueryBuilder $qb, $data)
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
{
|
{
|
||||||
if (!in_array('acploc', $qb->getAllAliases(), true)) {
|
if (!in_array('acploc', $qb->getAllAliases(), true)) {
|
||||||
$qb->join('acp.administrativeLocation', 'acploc');
|
$qb->leftJoin('acp.administrativeLocation', 'acploc');
|
||||||
}
|
}
|
||||||
|
|
||||||
$qb->addSelect('IDENTITY(acp.administrativeLocation) AS location_aggregator');
|
$qb->addSelect('IDENTITY(acp.administrativeLocation) AS location_aggregator');
|
||||||
|
$qb->addGroupBy('location_aggregator');
|
||||||
$groupBy = $qb->getDQLPart('groupBy');
|
|
||||||
|
|
||||||
if (!empty($groupBy)) {
|
|
||||||
$qb->addGroupBy('location_aggregator');
|
|
||||||
} else {
|
|
||||||
$qb->groupBy('location_aggregator');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function applyOn(): string
|
public function applyOn(): string
|
||||||
@ -71,6 +64,10 @@ class AdministrativeLocationAggregator implements AggregatorInterface
|
|||||||
return 'Administrative location';
|
return 'Administrative location';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (null === $value) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
$l = $this->locationRepository->find($value);
|
$l = $this->locationRepository->find($value);
|
||||||
|
|
||||||
return $l->getName() . ' (' . $this->translatableStringHelper->localize($l->getLocationType()->getTitle()) . ')';
|
return $l->getName() . ' (' . $this->translatableStringHelper->localize($l->getLocationType()->getTitle()) . ')';
|
||||||
|
@ -15,21 +15,23 @@ use Chill\MainBundle\Export\AggregatorInterface;
|
|||||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive;
|
use Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive;
|
||||||
use Chill\PersonBundle\Export\Declarations;
|
use Chill\PersonBundle\Export\Declarations;
|
||||||
|
use Chill\PersonBundle\Repository\AccompanyingPeriod\ClosingMotiveRepository;
|
||||||
|
use Chill\PersonBundle\Repository\AccompanyingPeriod\ClosingMotiveRepositoryInterface;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Doctrine\ORM\QueryBuilder;
|
use Doctrine\ORM\QueryBuilder;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
|
||||||
class ClosingMotiveAggregator implements AggregatorInterface
|
class ClosingMotiveAggregator implements AggregatorInterface
|
||||||
{
|
{
|
||||||
private EntityManagerInterface $em;
|
private ClosingMotiveRepositoryInterface $motiveRepository;
|
||||||
|
|
||||||
private TranslatableStringHelper $translatableStringHelper;
|
private TranslatableStringHelper $translatableStringHelper;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
EntityManagerInterface $em,
|
ClosingMotiveRepositoryInterface $motiveRepository,
|
||||||
TranslatableStringHelper $translatableStringHelper
|
TranslatableStringHelper $translatableStringHelper
|
||||||
) {
|
) {
|
||||||
$this->motiveRepository = $em->getRepository(ClosingMotive::class);
|
$this->motiveRepository = $motiveRepository;
|
||||||
$this->translatableStringHelper = $translatableStringHelper;
|
$this->translatableStringHelper = $translatableStringHelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,19 +42,8 @@ class ClosingMotiveAggregator implements AggregatorInterface
|
|||||||
|
|
||||||
public function alterQuery(QueryBuilder $qb, $data)
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
{
|
{
|
||||||
if (!in_array('acpmotive', $qb->getAllAliases(), true)) {
|
|
||||||
$qb->join('acp.closingMotive', 'acpmotive');
|
|
||||||
}
|
|
||||||
|
|
||||||
$qb->addSelect('IDENTITY(acp.closingMotive) AS closingmotive_aggregator');
|
$qb->addSelect('IDENTITY(acp.closingMotive) AS closingmotive_aggregator');
|
||||||
|
$qb->addGroupBy('closingmotive_aggregator');
|
||||||
$groupBy = $qb->getDQLPart('groupBy');
|
|
||||||
|
|
||||||
if (!empty($groupBy)) {
|
|
||||||
$qb->addGroupBy('closingmotive_aggregator');
|
|
||||||
} else {
|
|
||||||
$qb->groupBy('closingmotive_aggregator');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function applyOn(): string
|
public function applyOn(): string
|
||||||
@ -72,6 +63,10 @@ class ClosingMotiveAggregator implements AggregatorInterface
|
|||||||
return 'Closing motive';
|
return 'Closing motive';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (NULL === $value) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
$cm = $this->motiveRepository->find($value);
|
$cm = $this->motiveRepository->find($value);
|
||||||
|
|
||||||
return $this->translatableStringHelper->localize(
|
return $this->translatableStringHelper->localize(
|
||||||
|
@ -35,14 +35,7 @@ class ConfidentialAggregator implements AggregatorInterface
|
|||||||
public function alterQuery(QueryBuilder $qb, $data)
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
{
|
{
|
||||||
$qb->addSelect('acp.confidential AS confidential_aggregator');
|
$qb->addSelect('acp.confidential AS confidential_aggregator');
|
||||||
|
$qb->addGroupBy('confidential_aggregator');
|
||||||
$groupBy = $qb->getDQLPart('groupBy');
|
|
||||||
|
|
||||||
if (!empty($groupBy)) {
|
|
||||||
$qb->addGroupBy('confidential_aggregator');
|
|
||||||
} else {
|
|
||||||
$qb->groupBy('confidential_aggregator');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function applyOn(): string
|
public function applyOn(): string
|
||||||
|
@ -44,15 +44,8 @@ final class DurationAggregator implements AggregatorInterface
|
|||||||
// et ajouter une fonction custom qui calcule plus précisément les intervals, comme doctrineum/date-interval
|
// et ajouter une fonction custom qui calcule plus précisément les intervals, comme doctrineum/date-interval
|
||||||
// https://packagist.org/packages/doctrineum/date-interval#3.1.0 (mais composer fait un conflit de dépendance)
|
// https://packagist.org/packages/doctrineum/date-interval#3.1.0 (mais composer fait un conflit de dépendance)
|
||||||
|
|
||||||
$groupBy = $qb->getDQLPart('groupBy');
|
$qb->addGroupBy('duration_aggregator');
|
||||||
|
$qb->addOrderBy('duration_aggregator');
|
||||||
if (!empty($groupBy)) {
|
|
||||||
$qb->addGroupBy('duration_aggregator');
|
|
||||||
} else {
|
|
||||||
$qb->groupBy('duration_aggregator');
|
|
||||||
}
|
|
||||||
|
|
||||||
$qb->orderBy('duration_aggregator');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function applyOn(): string
|
public function applyOn(): string
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user