diff --git a/.changes/unreleased/Feature-20231011-155115.yaml b/.changes/unreleased/Feature-20231011-155115.yaml
new file mode 100644
index 000000000..77aac142b
--- /dev/null
+++ b/.changes/unreleased/Feature-20231011-155115.yaml
@@ -0,0 +1,5 @@
+kind: Feature
+body: '[export] add an aggregator for activities: group by job scope aggregator'
+time: 2023-10-11T15:51:15.022779832+02:00
+custom:
+ Issue: ""
diff --git a/exports_alias_conventions.csv b/exports_alias_conventions.csv
deleted file mode 100644
index ab32cda8e..000000000
--- a/exports_alias_conventions.csv
+++ /dev/null
@@ -1,63 +0,0 @@
-Entity,Join,Attribute,Alias
-AccompanyingPeriod::class,,,acp
-,AccompanyingPeriodWork::class,acp.works,acpw
-,AccompanyingPeriodParticipation::class,acp.participations,acppart
-,Location::class,acp.administrativeLocation,acploc
-,ClosingMotive::class,acp.closingMotive,acpmotive
-,UserJob::class,acp.job,acpjob
-,Origin::class,acp.origin,acporigin
-,Scope::class,acp.scopes,acpscope
-,SocialIssue::class,acp.socialIssues,acpsocialissue
-,User::class,acp.user,acpuser
-AccompanyingPeriodWork::class,,,acpw
-,AccompanyingPeriodWorkEvaluation::class,acpw.accompanyingPeriodWorkEvaluations,workeval
-,User::class,acpw.referrers,acpwuser
-,SocialAction::class,acpw.socialAction,acpwsocialaction
-,Goal::class,acpw.goals,goal
-,Result::class,acpw.results,result
-AccompanyingPeriodParticipation::class,,,acppart
-,Person::class,acppart.person,partperson
-AccompanyingPeriodWorkEvaluation::class,,,workeval
-,Evaluation::class,workeval.evaluation,eval
-Goal::class,,,goal
-,Result::class,goal.results,goalresult
-Person::class,,,person
-,Center::class,person.center,center
-,HouseholdMember::class,partperson.householdParticipations,householdmember
-,MaritalStatus::class,person.maritalStatus,personmarital
-,VendeePerson::class,,vp
-,VendeePersonMineur::class,,vpm
-ResidentialAddress::class,,,resaddr
-,ThirdParty::class,resaddr.hostThirdParty,tparty
-ThirdParty::class,,,tparty
-,ThirdPartyCategory::class,tparty.categories,tpartycat
-HouseholdMember::class,,,householdmember
-,Household::class,householdmember.household,household
-,Person::class,householdmember.person,memberperson
-,,memberperson.center,membercenter
-Household::class,,,household
-,HouseholdComposition::class,household.compositions,composition
-Activity::class,,,activity
-,Person::class,activity.person,actperson
-,AccompanyingPeriod::class,activity.accompanyingPeriod,acp
-,Person::class,activity_person_having_activity.person,person_person_having_activity
-,ActivityReason::class,activity_person_having_activity.reasons,reasons_person_having_activity
-,ActivityType::class,activity.activityType,acttype
-,Location::class,activity.location,actloc
-,SocialAction::class,activity.socialActions,actsocialaction
-,SocialIssue::class,activity.socialIssues,actsocialssue
-,ThirdParty::class,activity.thirdParties,acttparty
-,User::class,activity.user,actuser
-,User::class,activity.users,actusers
-,ActivityReason::class,activity.reasons,actreasons
-,Center::class,actperson.center,actcenter
-ActivityReason::class,,,actreasons
-,ActivityReasonCategory::class,actreason.category,actreasoncat
-Calendar::class,,,cal
-,CancelReason::class,cal.cancelReason,calcancel
-,Location::class,cal.location,calloc
-,User::class,cal.user,caluser
-VendeePerson::class,,,vp
-,SituationProfessionelle::class,vp.situationProfessionelle,vpprof
-,StatutLogement::class,vp.statutLogement,vplog
-,TempsDeTravail::class,vp.tempsDeTravail,vptt
diff --git a/exports_alias_conventions.md b/exports_alias_conventions.md
index 64df91030..eb0545702 100644
--- a/exports_alias_conventions.md
+++ b/exports_alias_conventions.md
@@ -21,7 +21,6 @@ These are alias conventions :
| | AccompanyingPeriodInfo::class | not existing (using custom WITH clause) | acpinfo |
| AccompanyingPeriodWork::class | | | acpw |
| | AccompanyingPeriodWorkEvaluation::class | acpw.accompanyingPeriodWorkEvaluations | workeval |
-| | User::class | acpw.referrers | acpwuser |
| | SocialAction::class | acpw.socialAction | acpwsocialaction |
| | Goal::class | acpw.goals | goal |
| | Result::class | acpw.results | result |
diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php
index 2c053b035..e2357bd7d 100644
--- a/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php
+++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php
@@ -93,7 +93,7 @@ class CreatorScopeAggregator implements AggregatorInterface
public function getQueryKeys($data): array
{
- return ['_select'];
+ return [self::PREFIX . '_select'];
}
public function getTitle(): string
diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/JobScopeAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/JobScopeAggregator.php
new file mode 100644
index 000000000..251f67b36
--- /dev/null
+++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/JobScopeAggregator.php
@@ -0,0 +1,104 @@
+leftJoin("activity.createdBy", "{$p}_user")
+ ->leftJoin(
+ UserJobHistory::class,
+ "{$p}_history",
+ Join::WITH,
+ $qb->expr()->eq("{$p}_history.user", "{$p}_user")
+ )
+ // job_at based on activity.date
+ ->andWhere(
+ $qb->expr()->andX(
+ $qb->expr()->lte("{$p}_history.startDate", "activity.date"),
+ $qb->expr()->orX(
+ $qb->expr()->isNull("{$p}_history.endDate"),
+ $qb->expr()->gt("{$p}_history.endDate", "activity.date")
+ )
+ )
+ )
+ ->addSelect("IDENTITY({$p}_history.job) AS {$p}_select")
+ ->addGroupBy("{$p}_select");
+ }
+
+ public function applyOn(): string
+ {
+ return Declarations::ACTIVITY;
+ }
+
+ public function buildForm(FormBuilderInterface $builder) {}
+
+ public function getFormDefaultData(): array
+ {
+ return [];
+ }
+
+ public function getLabels($key, array $values, $data)
+ {
+ return function ($value): string {
+ if ('_header' === $value) {
+ return 'Scope';
+ }
+
+ if (null === $value || '' === $value) {
+ return '';
+ }
+
+ $s = $this->scopeRepository->find($value);
+
+ return $this->translatableStringHelper->localize(
+ $s->getName()
+ );
+ };
+ }
+
+ public function getQueryKeys($data): array
+ {
+ return [self::PREFIX . '_select'];
+ }
+
+ public function getTitle(): string
+ {
+ return 'export.aggregator.activity.by_creator_job.Group activity by creator job';
+ }
+}
diff --git a/src/Bundle/ChillActivityBundle/Export/Export/ListActivityHelper.php b/src/Bundle/ChillActivityBundle/Export/Export/ListActivityHelper.php
index 84d94c000..ea43d387d 100644
--- a/src/Bundle/ChillActivityBundle/Export/Export/ListActivityHelper.php
+++ b/src/Bundle/ChillActivityBundle/Export/Export/ListActivityHelper.php
@@ -57,7 +57,7 @@ class ListActivityHelper
->addSelect('AGGREGATE(actPerson.id) AS personsNames')
->leftJoin('activity.users', 'users_u')
->addSelect('AGGREGATE(users_u.id) AS usersIds')
- ->addSelect('AGGREGATE(users_u.id) AS usersNames')
+ ->addSelect('AGGREGATE(JSON_BUILD_OBJECT(\'uid\', users_u.id, \'d\', activity.date)) AS usersNames')
->leftJoin('activity.thirdParties', 'thirdparty')
->addSelect('AGGREGATE(thirdparty.id) AS thirdPartiesIds')
->addSelect('AGGREGATE(thirdparty.id) AS thirdPartiesNames')
@@ -68,9 +68,9 @@ class ListActivityHelper
->leftJoin('activity.location', 'location')
->addSelect('location.name AS locationName')
->addSelect('activity.sentReceived')
- ->addSelect('IDENTITY(activity.createdBy) AS createdBy')
+ ->addSelect('JSON_BUILD_OBJECT(\'uid\', IDENTITY(activity.createdBy), \'d\', activity.createdAt) AS createdBy')
->addSelect('activity.createdAt')
- ->addSelect('IDENTITY(activity.updatedBy) AS updatedBy')
+ ->addSelect('JSON_BUILD_OBJECT(\'uid\', IDENTITY(activity.updatedBy), \'d\', activity.updatedAt) AS updatedBy')
->addSelect('activity.updatedAt')
->addGroupBy('activity.id')
->addGroupBy('location.id');
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/UserScopeFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/UserScopeFilter.php
index ec87ce954..d33ae1a10 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/UserScopeFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/UserScopeFilter.php
@@ -59,9 +59,10 @@ class UserScopeFilter implements FilterInterface
->andWhere(
$qb->expr()->in("{$p}_history.scope", ":{$p}_scopes")
)
- ->setParameters([
- "{$p}_scopes" => $data["scopes"],
- ]);
+ ->setParameter(
+ "{$p}_scopes",
+ $data["scopes"],
+ );
}
public function applyOn(): string
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/UsersJobFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/UsersJobFilter.php
index b49397521..d787f30ea 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/UsersJobFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/UsersJobFilter.php
@@ -51,9 +51,10 @@ class UsersJobFilter implements FilterInterface
. "AND {$p}_history.job IN ( :{$p}_jobs )"
)
)
- ->setParameters([
- "{$p}_jobs" => $data["jobs"],
- ]);
+ ->setParameter(
+ "{$p}_jobs",
+ $data["jobs"]
+ );
}
public function applyOn()
diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/UsersScopeFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/UsersScopeFilter.php
index 3391f92cf..a1bcb958b 100644
--- a/src/Bundle/ChillActivityBundle/Export/Filter/UsersScopeFilter.php
+++ b/src/Bundle/ChillActivityBundle/Export/Filter/UsersScopeFilter.php
@@ -53,9 +53,10 @@ class UsersScopeFilter implements FilterInterface
. "AND {$p}_history.scope IN ( :{$p}_scopes )"
)
)
- ->setParameters([
- "{$p}_scopes" => $data["scopes"],
- ]);
+ ->setParameter(
+ "{$p}_scopes",
+ $data["scopes"]
+ );
}
public function applyOn(): string
diff --git a/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php b/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php
index f9db5c158..d61e0999e 100644
--- a/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php
+++ b/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php
@@ -122,9 +122,30 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
->leftJoin('a.user', 'activity_u')
->andWhere(
$qb->expr()->orX(
- 'creator.userJob IN (:jobs)',
- 'activity_u.userJob IN (:jobs)',
- 'EXISTS (SELECT 1 FROM ' . User::class . ' activity_user WHERE activity_user MEMBER OF a.users AND activity_user.userJob IN (:jobs))'
+ $qb->expr()->exists(
+ sprintf(
+ "SELECT 1 FROM %s ujh_creator WHERE ujh_creator.user = a.createdBy "
+ . "AND ujh_creator.job IN (:jobs) AND a.createdAt > ujh_creator.startDate "
+ . "AND (ujh_creator.endDate IS NULL or ujh_creator.endDate > a.date)",
+ User\UserJobHistory::class
+ )
+ ),
+ $qb->expr()->exists(
+ sprintf(
+ "SELECT 1 FROM %s ujh_u WHERE ujh_u.user = a.user "
+ . "AND ujh_u.job IN (:jobs) AND a.createdAt > ujh_u.startDate "
+ . "AND (ujh_u.endDate IS NULL or ujh_u.endDate > a.date)",
+ User\UserJobHistory::class
+ )
+ ),
+ $qb->expr()->exists(
+ sprintf(
+ "SELECT 1 FROM %s ujh_users WHERE ujh_users.user MEMBER OF a.users "
+ . "AND ujh_users.job IN (:jobs) AND a.createdAt > ujh_users.startDate "
+ . "AND (ujh_users.endDate IS NULL or ujh_users.endDate > a.date)",
+ User\UserJobHistory::class
+ )
+ ),
)
)
->setParameter('jobs', $jobs);
@@ -172,16 +193,17 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos
return $qb->getQuery()->getResult();
}
- public function findUserJobByAssociated(Person|AccompanyingPeriod $associated): array
+ public function findUserJobByAssociated(AccompanyingPeriod|Person $associated): array
{
$in = $this->em->createQueryBuilder();
- $in->select('IDENTITY(u.userJob)')
- ->from(User::class, 'u')
+ $in->select('IDENTITY(u.job)')
+ ->distinct()
+ ->from(User\UserJobHistory::class, 'u')
->join(
Activity::class,
'a',
Join::WITH,
- 'a.createdBy = u OR a.user = u OR u MEMBER OF a.users'
+ 'a.createdBy = u.user OR a.user = u.user OR u.user MEMBER OF a.users AND a.date >= u.startDate ANd (u.endDate IS NULL or u.endDate > a.date)'
);
if ($associated instanceof Person) {
diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/JobScopeAggregatorTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/JobScopeAggregatorTest.php
new file mode 100644
index 000000000..3771e6e32
--- /dev/null
+++ b/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/JobScopeAggregatorTest.php
@@ -0,0 +1,60 @@
+aggregator = self::$container->get(JobScopeAggregator::class);
+ }
+
+ public function getAggregator()
+ {
+ return $this->aggregator;
+ }
+
+ public function getFormData(): array
+ {
+ return [
+ [],
+ ];
+ }
+
+ public function getQueryBuilders(): array
+ {
+ self::bootKernel();
+
+ $em = self::$container->get(EntityManagerInterface::class);
+
+ return [
+ $em->createQueryBuilder()
+ ->select('count(activity.id)')
+ ->from(Activity::class, 'activity')
+ ->leftJoin('activity.accompanyingPeriod', 'acp')
+ ->leftJoin('activity.user', 'actuser'),
+ ];
+ }
+}
diff --git a/src/Bundle/ChillActivityBundle/config/services/export.yaml b/src/Bundle/ChillActivityBundle/config/services/export.yaml
index 563ea7bf5..09a5227eb 100644
--- a/src/Bundle/ChillActivityBundle/config/services/export.yaml
+++ b/src/Bundle/ChillActivityBundle/config/services/export.yaml
@@ -177,6 +177,10 @@ services:
tags:
- { name: chill.export_aggregator, alias: activity_creator_scope_aggregator }
+ Chill\ActivityBundle\Export\Aggregator\JobScopeAggregator:
+ tags:
+ - { name: chill.export_aggregator, alias: activity_creator_job_aggregator }
+
Chill\ActivityBundle\Export\Aggregator\ActivityUsersAggregator:
tags:
- { name: chill.export_aggregator, alias: activity_users_aggregator }
diff --git a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml
index 3496f7a52..8deebbb8c 100644
--- a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml
+++ b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml
@@ -395,6 +395,9 @@ export:
by_creator_scope:
Group activity by creator scope: Grouper les échanges par service du créateur de l'échange
Calc date: Date de calcul du service du créateur de l'échange
+ by_creator_job:
+ Group activity by creator job: Grouper les échanges par service du créateur de l'échange
+ Calc date: Date de calcul du service du créateur de l'échange
generic_doc:
filter:
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php
index f01c3efc2..0981c6bf8 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php
+++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php
@@ -182,7 +182,10 @@ final readonly class ListAsideActivity implements ListInterface, GroupedExportIn
{
$qb = $this->em->createQueryBuilder()
->from(AsideActivity::class, 'aside')
- ->leftJoin('aside.agent', 'agent');
+ ->leftJoin('aside.agent', 'agent')
+ ->leftJoin('agent.scopeHistories', 'scopeHistories')
+ ->andWhere('scopeHistories.startDate <= aside.date AND (scopeHistories.endDate IS NULL or scopeHistories.endDate > aside.date)')
+ ;
$qb
->addSelect('aside.id AS id')
@@ -190,7 +193,7 @@ final readonly class ListAsideActivity implements ListInterface, GroupedExportIn
->addSelect('aside.updatedAt AS updatedAt')
->addSelect('IDENTITY(aside.agent) AS agent_id')
->addSelect('IDENTITY(aside.createdBy) AS creator_id')
- ->addSelect('IDENTITY(agent.mainScope) AS main_scope') ///
+ ->addSelect('IDENTITY(scopeHistories.scope) AS main_scope')
->addSelect('IDENTITY(agent.mainCenter) AS main_center')
->addSelect('IDENTITY(aside.type) AS aside_activity_type')
->addSelect('aside.date')
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php
index d76d6d126..69aaa376f 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php
+++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php
@@ -51,9 +51,10 @@ class ByUserJobFilter implements FilterInterface
. "AND {$p}_history.job IN ( :{$p}_jobs )"
)
)
- ->setParameters([
- "{$p}_jobs" => $data["jobs"],
- ]);
+ ->setParameter(
+ "{$p}_jobs",
+ $data["jobs"],
+ );
}
public function applyOn(): string
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php
index 7df450bde..bcaabdcea 100644
--- a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php
+++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php
@@ -53,9 +53,10 @@ class ByUserScopeFilter implements FilterInterface
. "AND {$p}_history.scope IN ( :{$p}_scopes )"
)
)
- ->setParameters([
- "{$p}_scopes" => $data["scopes"],
- ]);
+ ->setParameter(
+ "{$p}_scopes",
+ $data["scopes"],
+ );
}
public function applyOn(): string
diff --git a/src/Bundle/ChillAsideActivityBundle/src/Tests/Export/Export/ListAsideActivityTest.php b/src/Bundle/ChillAsideActivityBundle/src/Tests/Export/Export/ListAsideActivityTest.php
new file mode 100644
index 000000000..6bd29ef1d
--- /dev/null
+++ b/src/Bundle/ChillAsideActivityBundle/src/Tests/Export/Export/ListAsideActivityTest.php
@@ -0,0 +1,43 @@
+listAsideActivity = self::$container->get(ListAsideActivity::class);
+ }
+
+ public function testExecuteQuery(): void
+ {
+ $qb = $this->listAsideActivity->initiateQuery([], [], [])
+ ->setMaxResults(1);
+
+ $results = $qb->getQuery()->getResult(AbstractQuery::HYDRATE_ARRAY);
+
+ self::assertIsArray($results, "smoke test: test that the result is an array");
+ }
+}
diff --git a/src/Bundle/ChillBudgetBundle/Repository/ChargeRepository.php b/src/Bundle/ChillBudgetBundle/Repository/ChargeRepository.php
index 9b89010dc..475657f68 100644
--- a/src/Bundle/ChillBudgetBundle/Repository/ChargeRepository.php
+++ b/src/Bundle/ChillBudgetBundle/Repository/ChargeRepository.php
@@ -34,7 +34,7 @@ class ChargeRepository extends ServiceEntityRepository
/**
* @return Charge[]
*/
- public function findAllByEntity(Person|Household $entity): array
+ public function findAllByEntity(Household|Person $entity): array
{
$qb = $this->createQueryBuilder('c');
diff --git a/src/Bundle/ChillBudgetBundle/Repository/ResourceRepository.php b/src/Bundle/ChillBudgetBundle/Repository/ResourceRepository.php
index 836f13e4b..6ecf13d28 100644
--- a/src/Bundle/ChillBudgetBundle/Repository/ResourceRepository.php
+++ b/src/Bundle/ChillBudgetBundle/Repository/ResourceRepository.php
@@ -35,7 +35,7 @@ class ResourceRepository extends ServiceEntityRepository
/**
* @return Resource[]
*/
- public function findAllByEntity(Person|Household $entity): array
+ public function findAllByEntity(Household|Person $entity): array
{
$qb = $this->createQueryBuilder('r');
@@ -47,7 +47,7 @@ class ResourceRepository extends ServiceEntityRepository
return $qb->getQuery()->getResult();
}
- public function findByEntityAndDate(Person|Household $entity, DateTime $date, $sort = null)
+ public function findByEntityAndDate(Household|Person $entity, DateTime $date, $sort = null)
{
$qb = $this->createQueryBuilder('c');
diff --git a/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php b/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php
index 1b666019b..93def5631 100644
--- a/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php
+++ b/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php
@@ -22,13 +22,12 @@ use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
-class JobFilter implements FilterInterface
+final readonly class JobFilter implements FilterInterface
{
private const PREFIX = 'cal_filter_job';
public function __construct(
- protected TranslatorInterface $translator,
- private readonly TranslatableStringHelper $translatableStringHelper
+ private TranslatableStringHelper $translatableStringHelper
) {}
public function addRole(): ?string
@@ -59,9 +58,10 @@ class JobFilter implements FilterInterface
)
)
->andWhere($qb->expr()->in("{$p}_history.job", ":{$p}_job"))
- ->setParameters([
- "{$p}_job" => $data["job"],
- ]);
+ ->setParameter(
+ "{$p}_job",
+ $data["job"]
+ );
}
diff --git a/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php b/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php
index 61ec8d50d..e04bd922b 100644
--- a/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php
+++ b/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php
@@ -59,9 +59,10 @@ class ScopeFilter implements FilterInterface
)
)
->andWhere($qb->expr()->in("{$p}_history.scope", ":{$p}_scope"))
- ->setParameters([
- "{$p}_scope" => $data["scope"],
- ]);
+ ->setParameter(
+ "{$p}_scope",
+ $data["scope"]
+ );
}
public function applyOn(): string
diff --git a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/MSUserAbsenceReader.php b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/MSUserAbsenceReader.php
index a81ef34c3..740666cd6 100644
--- a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/MSUserAbsenceReader.php
+++ b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/MSUserAbsenceReader.php
@@ -33,7 +33,7 @@ final readonly class MSUserAbsenceReader implements MSUserAbsenceReaderInterface
/**
* @throw UserAbsenceSyncException when the data cannot be reached or is not valid from microsoft
*/
- public function isUserAbsent(User $user): bool|null
+ public function isUserAbsent(User $user): null|bool
{
$id = $this->mapCalendarToUser->getUserId($user);
diff --git a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/MSUserAbsenceReaderInterface.php b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/MSUserAbsenceReaderInterface.php
index a918bb7ea..f67562e27 100644
--- a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/MSUserAbsenceReaderInterface.php
+++ b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/MSUserAbsenceReaderInterface.php
@@ -18,5 +18,5 @@ interface MSUserAbsenceReaderInterface
/**
* @throw UserAbsenceSyncException when the data cannot be reached or is not valid from microsoft
*/
- public function isUserAbsent(User $user): bool|null;
+ public function isUserAbsent(User $user): null|bool;
}
diff --git a/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/JobFilterTest.php b/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/JobFilterTest.php
index a395062db..d571508c8 100644
--- a/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/JobFilterTest.php
+++ b/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/JobFilterTest.php
@@ -22,6 +22,7 @@ use Chill\CalendarBundle\Entity\Calendar;
use Chill\CalendarBundle\Export\Filter\JobFilter;
use Chill\MainBundle\Entity\UserJob;
use Chill\MainBundle\Test\Export\AbstractFilterTest;
+use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\EntityManagerInterface;
/**
@@ -62,15 +63,11 @@ final class JobFilterTest extends AbstractFilterTest
->setMaxResults(1)
->getResult();
- $data = [];
-
- foreach ($array as $a) {
- $data[] = [
- 'job' => $a,
- ];
- }
-
- return $data;
+ return [
+ [
+ 'job' => new ArrayCollection($array)
+ ]
+ ];
}
public function getQueryBuilders(): array
diff --git a/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/ScopeFilterTest.php b/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/ScopeFilterTest.php
index eef7d1362..06d36846b 100644
--- a/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/ScopeFilterTest.php
+++ b/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/ScopeFilterTest.php
@@ -22,6 +22,7 @@ use Chill\CalendarBundle\Entity\Calendar;
use Chill\CalendarBundle\Export\Filter\ScopeFilter;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Test\Export\AbstractFilterTest;
+use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\EntityManagerInterface;
/**
@@ -62,15 +63,11 @@ final class ScopeFilterTest extends AbstractFilterTest
->setMaxResults(1)
->getResult();
- $data = [];
-
- foreach ($array as $a) {
- $data[] = [
- 'scope' => $a,
- ];
- }
-
- return $data;
+ return [
+ [
+ 'scope' => new ArrayCollection($array)
+ ]
+ ];
}
public function getQueryBuilders(): array
diff --git a/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldChoice.php b/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldChoice.php
index 27a4f930f..2ee0a9c48 100644
--- a/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldChoice.php
+++ b/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldChoice.php
@@ -366,7 +366,7 @@ class CustomFieldChoice extends AbstractCustomField
* If the value had an 'allow_other' = true option, the returned value
* **is not** the content of the _other field, but the `_other` string.
*/
- private function guessValue(array|string|null $value)
+ private function guessValue(null|array|string $value)
{
if (null === $value) {
return null;
diff --git a/src/Bundle/ChillCustomFieldsBundle/Entity/CustomFieldsGroup.php b/src/Bundle/ChillCustomFieldsBundle/Entity/CustomFieldsGroup.php
index 7ede1a08a..41fc535fe 100644
--- a/src/Bundle/ChillCustomFieldsBundle/Entity/CustomFieldsGroup.php
+++ b/src/Bundle/ChillCustomFieldsBundle/Entity/CustomFieldsGroup.php
@@ -138,7 +138,7 @@ class CustomFieldsGroup
/**
* Get name.
*/
- public function getName(?string $language = null): string|array
+ public function getName(?string $language = null): array|string
{
//TODO set this in a service, PLUS twig function
if (null !== $language) {
diff --git a/src/Bundle/ChillEventBundle/Controller/ParticipationController.php b/src/Bundle/ChillEventBundle/Controller/ParticipationController.php
index 126178a9e..54dc763ef 100644
--- a/src/Bundle/ChillEventBundle/Controller/ParticipationController.php
+++ b/src/Bundle/ChillEventBundle/Controller/ParticipationController.php
@@ -44,7 +44,7 @@ class ParticipationController extends AbstractController
* @return Response|\Symfony\Component\HttpFoundation\RedirectResponse
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/event/participation/create", name="chill_event_participation_create")
*/
- public function createAction(Request $request): \Symfony\Component\HttpFoundation\Response|\Symfony\Component\HttpFoundation\RedirectResponse
+ public function createAction(Request $request): \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
{
// test the request is correct
try {
@@ -162,7 +162,7 @@ class ParticipationController extends AbstractController
/**
* @return Response|\Symfony\Component\HttpFoundation\RedirectResponse
*/
- public function createMultiple(Request $request): \Symfony\Component\HttpFoundation\Response|\Symfony\Component\HttpFoundation\RedirectResponse
+ public function createMultiple(Request $request): \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
{
$participations = $this->handleRequest($request, new Participation(), true);
@@ -205,7 +205,7 @@ class ParticipationController extends AbstractController
/**
* @return Response|\Symfony\Component\HttpFoundation\RedirectResponse
*/
- public function createSingle(Request $request): \Symfony\Component\HttpFoundation\Response|\Symfony\Component\HttpFoundation\RedirectResponse
+ public function createSingle(Request $request): \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
{
$participation = $this->handleRequest($request, new Participation(), false);
@@ -249,7 +249,7 @@ class ParticipationController extends AbstractController
* @return Response|\Symfony\Component\HttpFoundation\RedirectResponse
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/event/participation/{participation_id}/delete", name="chill_event_participation_delete", requirements={"participation_id"="\d+"}, methods={"GET", "DELETE"})
*/
- public function deleteAction($participation_id, Request $request): \Symfony\Component\HttpFoundation\Response|\Symfony\Component\HttpFoundation\RedirectResponse
+ public function deleteAction($participation_id, Request $request): \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
{
$em = $this->getDoctrine()->getManager();
$participation = $em->getRepository(\Chill\EventBundle\Entity\Participation::class)->findOneBy([
@@ -330,7 +330,7 @@ class ParticipationController extends AbstractController
* @return Response|\Symfony\Component\HttpFoundation\RedirectResponse
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/event/participation/{event_id}/edit_multiple", name="chill_event_participation_edit_multiple")
*/
- public function editMultipleAction($event_id): \Symfony\Component\HttpFoundation\Response|\Symfony\Component\HttpFoundation\RedirectResponse
+ public function editMultipleAction($event_id): \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
{
$event = $this->getDoctrine()->getRepository(\Chill\EventBundle\Entity\Event::class)
->find($event_id);
@@ -388,7 +388,7 @@ class ParticipationController extends AbstractController
* @return Response|\Symfony\Component\HttpFoundation\RedirectResponse
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/event/participation/new", name="chill_event_participation_new")
*/
- public function newAction(Request $request): \Symfony\Component\HttpFoundation\Response|\Symfony\Component\HttpFoundation\RedirectResponse
+ public function newAction(Request $request): \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
{
// test the request is correct
try {
@@ -560,7 +560,7 @@ class ParticipationController extends AbstractController
Request $request,
Participation $participation,
bool $multiple = false
- ): \Chill\EventBundle\Entity\Participation|array {
+ ): array|\Chill\EventBundle\Entity\Participation {
$em = $this->getDoctrine()->getManager();
if ($em->contains($participation)) {
@@ -637,7 +637,7 @@ class ParticipationController extends AbstractController
*
* @return Response|\Symfony\Component\HttpFoundation\RedirectResponse
*/
- protected function newMultiple(Request $request): \Symfony\Component\HttpFoundation\Response|\Symfony\Component\HttpFoundation\RedirectResponse
+ protected function newMultiple(Request $request): \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
{
$participations = $this->handleRequest($request, new Participation(), true);
$ignoredParticipations = $newParticipations = [];
diff --git a/src/Bundle/ChillEventBundle/Entity/Event.php b/src/Bundle/ChillEventBundle/Entity/Event.php
index 17f7899fc..b2e00c24e 100644
--- a/src/Bundle/ChillEventBundle/Entity/Event.php
+++ b/src/Bundle/ChillEventBundle/Entity/Event.php
@@ -135,7 +135,7 @@ class Event implements HasCenterInterface, HasScopeInterface
return $this->id;
}
- public function getModerator(): User|null
+ public function getModerator(): null|User
{
return $this->moderator;
}
diff --git a/src/Bundle/ChillMainBundle/Command/LoadPostalCodesCommand.php b/src/Bundle/ChillMainBundle/Command/LoadPostalCodesCommand.php
index 6b6bfa8e0..c68cf6762 100644
--- a/src/Bundle/ChillMainBundle/Command/LoadPostalCodesCommand.php
+++ b/src/Bundle/ChillMainBundle/Command/LoadPostalCodesCommand.php
@@ -96,7 +96,7 @@ class LoadPostalCodesCommand extends Command
try {
$this->addPostalCode($row, $output);
++$num;
- } catch (ExistingPostalCodeException|CountryCodeNotFoundException|PostalCodeNotValidException $ex) {
+ } catch (CountryCodeNotFoundException|ExistingPostalCodeException|PostalCodeNotValidException $ex) {
$output->writeln(' on line ' . $line . ' : ' . $ex->getMessage() . '');
}
++$line;
diff --git a/src/Bundle/ChillMainBundle/Controller/PasswordController.php b/src/Bundle/ChillMainBundle/Controller/PasswordController.php
index 1c1d11f84..dc0856cc0 100644
--- a/src/Bundle/ChillMainBundle/Controller/PasswordController.php
+++ b/src/Bundle/ChillMainBundle/Controller/PasswordController.php
@@ -99,7 +99,7 @@ class PasswordController extends AbstractController
* @return Response|\Symfony\Component\HttpFoundation\RedirectResponse
* @\Symfony\Component\Routing\Annotation\Route(path="/public/{_locale}/password/recover", name="password_recover")
*/
- public function recoverAction(Request $request): \Symfony\Component\HttpFoundation\Response|\Symfony\Component\HttpFoundation\RedirectResponse
+ public function recoverAction(Request $request): \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
{
if (false === $this->isGranted(PasswordRecoverVoter::ASK_TOKEN)) {
return new Response($this->translator->trans('You are not allowed '
@@ -168,7 +168,7 @@ class PasswordController extends AbstractController
* @return Response|\Symfony\Component\HttpFoundation\RedirectResponse
* @\Symfony\Component\Routing\Annotation\Route(path="/public/{_locale}/password/request-recover", name="password_request_recover")
*/
- public function requestRecoverAction(Request $request): \Symfony\Component\HttpFoundation\Response|\Symfony\Component\HttpFoundation\RedirectResponse
+ public function requestRecoverAction(Request $request): \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
{
if (false === $this->isGranted(PasswordRecoverVoter::ASK_TOKEN)) {
return new Response($this->translator->trans('You are not allowed '
diff --git a/src/Bundle/ChillMainBundle/Controller/UserExportController.php b/src/Bundle/ChillMainBundle/Controller/UserExportController.php
index 04778dfae..fe318c4ae 100644
--- a/src/Bundle/ChillMainBundle/Controller/UserExportController.php
+++ b/src/Bundle/ChillMainBundle/Controller/UserExportController.php
@@ -50,7 +50,7 @@ final readonly class UserExportController
fn (string $e) => $this->translator->trans('admin.users.export.' . $e),
[
'id',
- 'username',
+ // 'username',
'email',
'enabled',
'civility_id',
@@ -59,10 +59,10 @@ final readonly class UserExportController
'label',
'mainCenter_id' ,
'mainCenter_name',
- 'mainScope_id', ///
- 'mainScope_name', ///
- 'userJob_id', ///
- 'userJob_name', ///
+ 'mainScope_id',
+ 'mainScope_name',
+ 'userJob_id',
+ 'userJob_name',
'currentLocation_id',
'currentLocation_name',
'mainLocation_id',
diff --git a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php
index 4d81c3980..72848303f 100644
--- a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php
+++ b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php
@@ -33,6 +33,7 @@ use Chill\MainBundle\Doctrine\DQL\Greatest;
use Chill\MainBundle\Doctrine\DQL\JsonAggregate;
use Chill\MainBundle\Doctrine\DQL\JsonbArrayLength;
use Chill\MainBundle\Doctrine\DQL\JsonbExistsInArray;
+use Chill\MainBundle\Doctrine\DQL\JsonBuildObject;
use Chill\MainBundle\Doctrine\DQL\JsonExtract;
use Chill\MainBundle\Doctrine\DQL\Least;
use Chill\MainBundle\Doctrine\DQL\OverlapsI;
@@ -255,6 +256,7 @@ class ChillMainExtension extends Extension implements
'AGGREGATE' => JsonAggregate::class,
'REPLACE' => Replace::class,
'JSON_EXTRACT' => JsonExtract::class,
+ 'JSON_BUILD_OBJECT' => JsonBuildObject::class,
],
'numeric_functions' => [
'JSONB_EXISTS_IN_ARRAY' => JsonbExistsInArray::class,
diff --git a/src/Bundle/ChillMainBundle/Doctrine/DQL/Extract.php b/src/Bundle/ChillMainBundle/Doctrine/DQL/Extract.php
index a63f04164..6fc763c6d 100644
--- a/src/Bundle/ChillMainBundle/Doctrine/DQL/Extract.php
+++ b/src/Bundle/ChillMainBundle/Doctrine/DQL/Extract.php
@@ -29,7 +29,7 @@ class Extract extends FunctionNode
{
private string $field;
- private \Doctrine\ORM\Query\AST\Node|string|null $value = null;
+ private null|\Doctrine\ORM\Query\AST\Node|string $value = null;
//private PathExpression $value;
//private FunctionNode $value;
//private DateDiffFunction $value;
diff --git a/src/Bundle/ChillMainBundle/Doctrine/DQL/JsonBuildObject.php b/src/Bundle/ChillMainBundle/Doctrine/DQL/JsonBuildObject.php
new file mode 100644
index 000000000..4a8c3485a
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Doctrine/DQL/JsonBuildObject.php
@@ -0,0 +1,53 @@
+ $expr->dispatch($sqlWalker), $this->exprs)) . ')';
+ }
+
+ public function parse(Parser $parser)
+ {
+ $lexer = $parser->getLexer();
+ $parser->match(Lexer::T_IDENTIFIER);
+ $parser->match(Lexer::T_OPEN_PARENTHESIS);
+
+ $this->exprs[] = $parser->ArithmeticPrimary();
+
+ while (Lexer::T_COMMA === $lexer->lookahead['type']) {
+ $parser->match(Lexer::T_COMMA);
+ $this->exprs[] = $parser->ArithmeticPrimary();
+ }
+
+ $parser->match(Lexer::T_CLOSE_PARENTHESIS);
+ }
+}
diff --git a/src/Bundle/ChillMainBundle/Doctrine/DQL/JsonExtract.php b/src/Bundle/ChillMainBundle/Doctrine/DQL/JsonExtract.php
index 95d851790..7d93071b7 100644
--- a/src/Bundle/ChillMainBundle/Doctrine/DQL/JsonExtract.php
+++ b/src/Bundle/ChillMainBundle/Doctrine/DQL/JsonExtract.php
@@ -18,7 +18,7 @@ use Doctrine\ORM\Query\SqlWalker;
class JsonExtract extends FunctionNode
{
- private \Doctrine\ORM\Query\AST\Node|string|null $element = null;
+ private null|\Doctrine\ORM\Query\AST\Node|string $element = null;
private ?\Doctrine\ORM\Query\AST\ArithmeticExpression $keyToExtract = null;
diff --git a/src/Bundle/ChillMainBundle/Doctrine/DQL/ToChar.php b/src/Bundle/ChillMainBundle/Doctrine/DQL/ToChar.php
index ef150867e..a5e73209d 100644
--- a/src/Bundle/ChillMainBundle/Doctrine/DQL/ToChar.php
+++ b/src/Bundle/ChillMainBundle/Doctrine/DQL/ToChar.php
@@ -23,7 +23,7 @@ class ToChar extends FunctionNode
{
private ?\Doctrine\ORM\Query\AST\ArithmeticExpression $datetime = null;
- private \Doctrine\ORM\Query\AST\Node|string|null $fmt = null;
+ private null|\Doctrine\ORM\Query\AST\Node|string $fmt = null;
public function getSql(SqlWalker $sqlWalker)
{
diff --git a/src/Bundle/ChillMainBundle/Entity/User.php b/src/Bundle/ChillMainBundle/Entity/User.php
index 33c8be166..5df70134b 100644
--- a/src/Bundle/ChillMainBundle/Entity/User.php
+++ b/src/Bundle/ChillMainBundle/Entity/User.php
@@ -292,9 +292,7 @@ class User implements UserInterface, \Stringable
$sortedScopeHistories = $scopeHistories->toArray();
- usort($sortedScopeHistories, function ($a, $b) {
- return $a->getStartDate() < $b->getStartDate() ? 1 : -1;
- });
+ usort($sortedScopeHistories, fn ($a, $b) => $a->getStartDate() < $b->getStartDate() ? 1 : -1);
return new ArrayCollection($sortedScopeHistories);
}
@@ -346,9 +344,7 @@ class User implements UserInterface, \Stringable
$sortedJobHistories = $jobHistories->toArray();
- usort($sortedJobHistories, function ($a, $b) {
- return $a->getStartDate() < $b->getStartDate() ? 1 : -1;
- });
+ usort($sortedJobHistories, fn ($a, $b) => $a->getStartDate() < $b->getStartDate() ? 1 : -1);
return new ArrayCollection($sortedJobHistories);
}
diff --git a/src/Bundle/ChillMainBundle/Export/ExportFormHelper.php b/src/Bundle/ChillMainBundle/Export/ExportFormHelper.php
index e21ea7f4d..8d9320424 100644
--- a/src/Bundle/ChillMainBundle/Export/ExportFormHelper.php
+++ b/src/Bundle/ChillMainBundle/Export/ExportFormHelper.php
@@ -28,7 +28,7 @@ final readonly class ExportFormHelper
private FormFactoryInterface $formFactory,
) {}
- public function getDefaultData(string $step, ExportInterface|DirectExportInterface $export, array $options = []): array
+ public function getDefaultData(string $step, DirectExportInterface|ExportInterface $export, array $options = []): array
{
return match ($step) {
'centers', 'generate_centers' => ['centers' => $this->authorizationHelper->getReachableCenters($export->requiredRole())],
@@ -45,7 +45,7 @@ final readonly class ExportFormHelper
return $formatter->getFormDefaultData($options['aggregator_aliases']);
}
- private function getDefaultDataStepExport(ExportInterface|DirectExportInterface $export, array $options): array
+ private function getDefaultDataStepExport(DirectExportInterface|ExportInterface $export, array $options): array
{
$data = [
ExportType::EXPORT_KEY => $export->getFormDefaultData(),
diff --git a/src/Bundle/ChillMainBundle/Export/ExportManager.php b/src/Bundle/ChillMainBundle/Export/ExportManager.php
index 612ff4140..dae3f7de3 100644
--- a/src/Bundle/ChillMainBundle/Export/ExportManager.php
+++ b/src/Bundle/ChillMainBundle/Export/ExportManager.php
@@ -101,7 +101,7 @@ class ExportManager
*
* @return FilterInterface[] a \Generator that contains filters. The key is the filter's alias
*/
- public function &getFiltersApplyingOn(ExportInterface|DirectExportInterface $export, ?array $centers = null): iterable
+ public function &getFiltersApplyingOn(DirectExportInterface|ExportInterface $export, ?array $centers = null): iterable
{
if ($export instanceof DirectExportInterface) {
return;
@@ -124,7 +124,7 @@ class ExportManager
*
* @return null|iterable a \Generator that contains aggretagors. The key is the filter's alias
*/
- public function &getAggregatorsApplyingOn(ExportInterface|DirectExportInterface $export, ?array $centers = null): ?iterable
+ public function &getAggregatorsApplyingOn(DirectExportInterface|ExportInterface $export, ?array $centers = null): ?iterable
{
if ($export instanceof ListInterface || $export instanceof DirectExportInterface) {
return;
@@ -307,7 +307,7 @@ class ExportManager
*
* @throws RuntimeException
*/
- public function getExport($alias): ExportInterface|DirectExportInterface
+ public function getExport($alias): DirectExportInterface|ExportInterface
{
if (!array_key_exists($alias, $this->exports)) {
throw new RuntimeException("The export with alias {$alias} is not known.");
@@ -453,7 +453,7 @@ class ExportManager
*
*/
public function isGrantedForElement(
- ExportInterface|DirectExportInterface|ModifierInterface $element,
+ DirectExportInterface|ExportInterface|ModifierInterface $element,
\Chill\MainBundle\Export\DirectExportInterface|\Chill\MainBundle\Export\ExportInterface $export = null,
?array $centers = null
): bool {
diff --git a/src/Bundle/ChillMainBundle/Export/Helper/ExportAddressHelper.php b/src/Bundle/ChillMainBundle/Export/Helper/ExportAddressHelper.php
index 01bd7f2fc..a3e4bae86 100644
--- a/src/Bundle/ChillMainBundle/Export/Helper/ExportAddressHelper.php
+++ b/src/Bundle/ChillMainBundle/Export/Helper/ExportAddressHelper.php
@@ -281,9 +281,9 @@ class ExportAddressHelper
};
case 'country':
- return function ($value) use ($key) {
+ return function ($value) use ($sanitizedKey, $translationPrefix) {
if ('_header' === $value) {
- return 'export.list.acp' . $key;
+ return $translationPrefix . $sanitizedKey;
}
if (null === $value) {
diff --git a/src/Bundle/ChillMainBundle/Export/Helper/UserHelper.php b/src/Bundle/ChillMainBundle/Export/Helper/UserHelper.php
index 996f8d925..44c2f260f 100644
--- a/src/Bundle/ChillMainBundle/Export/Helper/UserHelper.php
+++ b/src/Bundle/ChillMainBundle/Export/Helper/UserHelper.php
@@ -20,21 +20,64 @@ class UserHelper
{
public function __construct(private readonly UserRender $userRender, private readonly UserRepositoryInterface $userRepository) {}
+ /**
+ * Return a callable that will transform a value into a string representing a user
+ *
+ * The callable may receive as argument:
+ *
+ * - an int or a string, the id of the user;
+ * - a string containing a json which will be decoded, and will have this structure: array{uid: int, d: string}. The job and scopes will be shown at this date
+ *
+ * @param string $key the key of the content
+ * @param array $values the list of values
+ * @param string $header the header's content
+ */
public function getLabel($key, array $values, string $header): callable
{
- return function ($value) use ($header) {
+ return function (null|int|string $value) use ($header) {
if ('_header' === $value) {
return $header;
}
- if (null === $value || null === $user = $this->userRepository->find($value)) {
+ if (null === $value) {
return '';
}
- return $this->userRender->renderString($user, []);
+ if (is_numeric($value)) {
+ $uid = $value;
+ $date = null;
+ } else {
+ $decode = json_decode($value, true, 512, JSON_THROW_ON_ERROR);
+ $uid = $decode['uid'];
+
+ if (null === $uid) {
+ return '';
+ }
+
+ $date = new \DateTimeImmutable($decode['d']);
+ }
+
+ if (null === $user = $this->userRepository->find($uid)) {
+ return '';
+ }
+
+ return $this->userRender->renderString($user, ['at' => $date]);
};
}
+ /**
+ * Return a callable that will transform a value into a string representing a user
+ *
+ * The callable may receive as argument:
+ *
+ * - an int or a string, the id of the user;
+ * - a string containing a json which will be decoded, and will have this structure: array{uid: int, d: string}. The job and scopes will be shown at this date * @param $key
+ *
+ * @param string $key the key of the element
+ * @param array $values a list of values
+ * @param string $header the header's content
+ * @return callable
+ */
public function getLabelMulti($key, array $values, string $header): callable
{
return function ($value) use ($header) {
@@ -46,31 +89,36 @@ class UserHelper
return '';
}
- $decoded = json_decode((string) $value, null, 512, JSON_THROW_ON_ERROR);
+ $decoded = json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR);
if (0 === count($decoded)) {
return '';
}
+ $asStrings = [];
- return
- implode(
- '|',
- array_map(
- function (int $userId) {
- $user = $this->userRepository->find($userId);
+ foreach ($decoded as $userId) {
+ if (is_array($userId)) {
+ $uid = $userId['uid'];
+ $date = new \DateTimeImmutable($userId['d']);
+ } else {
+ $uid = $userId;
+ $date = null;
+ }
- if (null === $user) {
- return '';
- }
+ if (null === $uid) {
+ continue;
+ }
- return $this->userRender->renderString($user, []);
- },
- array_unique(
- array_filter($decoded, static fn (?int $userId) => null !== $userId),
- SORT_NUMERIC
- )
- )
- );
+ $user = $this->userRepository->find($uid);
+
+ if (null === $user) {
+ continue;
+ }
+
+ $asStrings[$uid] = $this->userRender->renderString($user, ['absence' => false, 'at' => $date]);
+ }
+
+ return implode('|', $asStrings);
};
}
}
diff --git a/src/Bundle/ChillMainBundle/Repository/UserRepository.php b/src/Bundle/ChillMainBundle/Repository/UserRepository.php
index a59ddc399..17775f475 100644
--- a/src/Bundle/ChillMainBundle/Repository/UserRepository.php
+++ b/src/Bundle/ChillMainBundle/Repository/UserRepository.php
@@ -13,7 +13,8 @@ namespace Chill\MainBundle\Repository;
use Chill\MainBundle\Entity\GroupCenter;
use Chill\MainBundle\Entity\User;
-use Doctrine\ORM\AbstractQuery;
+use Doctrine\DBAL\Connection;
+use Doctrine\DBAL\Exception;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\NoResultException;
@@ -27,7 +28,11 @@ final readonly class UserRepository implements UserRepositoryInterface
{
private EntityRepository $repository;
- public function __construct(private EntityManagerInterface $entityManager)
+ private const FIELDS = ['id', 'email', 'enabled', 'civility_id', 'civility_abbreviation', 'civility_name', 'label', 'mainCenter_id',
+ 'mainCenter_name', 'mainScope_id', 'mainScope_name', 'userJob_id', 'userJob_name', 'currentLocation_id', 'currentLocation_name',
+ 'mainLocation_id', 'mainLocation_name'];
+
+ public function __construct(private EntityManagerInterface $entityManager, private Connection $connection)
{
$this->repository = $entityManager->getRepository(User::class);
}
@@ -75,48 +80,55 @@ final readonly class UserRepository implements UserRepositoryInterface
}
/**
- * @param string $lang
+ * @throws Exception
*/
public function findAllAsArray(string $lang): iterable
{
- $dql = sprintf(<<<'DQL'
+ $sql = sprintf(<<<'SQL'
SELECT
- u.id AS id,
+ u.id,
u.username AS username,
- u.email,
+ u.email AS email,
u.enabled,
- IDENTITY(u.civility) AS civility_id,
- JSON_EXTRACT(civility.abbreviation, :lang) AS civility_abbreviation,
- JSON_EXTRACT(civility.name, :lang) AS civility_name,
+ u.civility_id,
+ civility.abbreviation->>:lang AS civility_abbreviation,
+ civility.name->>:lang AS civility_name,
u.label,
mainCenter.id AS mainCenter_id,
mainCenter.name AS mainCenter_name,
- IDENTITY(u.mainScope) AS mainScope_id,
- JSON_EXTRACT(mainScope.name, :lang) AS mainScope_name,
- IDENTITY(u.userJob) AS userJob_id,
- JSON_EXTRACT(userJob.label, :lang) AS userJob_name,
+ mainScope.id AS mainScope_id,
+ mainScope.name->>:lang AS mainScope_name,
+ userJob.id AS userJob_id,
+ userJob.label->>:lang AS userJob_name,
currentLocation.id AS currentLocation_id,
currentLocation.name AS currentLocation_name,
mainLocation.id AS mainLocation_id,
mainLocation.name AS mainLocation_name,
u.absenceStart
- FROM Chill\MainBundle\Entity\User u
- LEFT JOIN u.civility civility
- LEFT JOIN u.currentLocation currentLocation
- LEFT JOIN u.mainLocation mainLocation
- LEFT JOIN u.mainCenter mainCenter
- LEFT JOIN u.mainScope mainScope
- LEFT JOIN u.userJob userJob
- ORDER BY u.label
- DQL); /// mainScope userJob
+ FROM users u
+ LEFT JOIN chill_main_civility civility ON u.civility_id = civility.id
+ LEFT JOIN centers mainCenter ON u.maincenter_id = mainCenter.id
+ LEFT JOIN chill_main_user_job_history userJobHistory ON u.id = userJobHistory.user_id
+ LEFT JOIN chill_main_user_job userJob ON userJobHistory.job_id = userJob.id AND tstzrange(userJobHistory.startdate, userJobHistory.enddate) @> NOW()
+ LEFT JOIN chill_main_user_scope_history userScopeHistory ON u.id = userScopeHistory.user_id AND tstzrange(userScopeHistory.startdate, userScopeHistory.enddate) @> NOW()
+ LEFT JOIN scopes mainScope ON userScopeHistory.scope_id = mainScope.id
+ LEFT JOIN chill_main_location currentLocation ON u.currentlocation_id = currentLocation.id
+ LEFT JOIN chill_main_location mainLocation ON u.mainlocation_id = mainLocation.id
+ ORDER BY u.label, u.id
+ SQL);
- $query = $this->entityManager->createQuery($dql)
- ->setHydrationMode(AbstractQuery::HYDRATE_ARRAY)
- ->setParameter('lang', $lang)
- ;
+ $query = $this->connection->prepare($sql);
- foreach ($query->toIterable() as $u) {
- yield $u;
+ foreach ($query->executeQuery(['lang' => $lang])->iterateAssociative() as $u) {
+ $converted = [];
+ foreach (self::FIELDS as $f) {
+ $converted[$f] = $u[strtolower($f)];
+ }
+
+ $converted['absenceStart'] = null !== $u['absencestart'] ? new \DateTimeImmutable($u['absencestart']) : null;
+
+ /** @phpstan-ignore-next-line phpstan does not take into account that all required keys will be present */
+ yield $converted;
}
}
diff --git a/src/Bundle/ChillMainBundle/Resources/views/Entity/user.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Entity/user.html.twig
index ad05a5a2c..c95308610 100644
--- a/src/Bundle/ChillMainBundle/Resources/views/Entity/user.html.twig
+++ b/src/Bundle/ChillMainBundle/Resources/views/Entity/user.html.twig
@@ -1,10 +1,10 @@
{{- user.label }}
- {%- if opts['user_job'] and user.userJob is not null %}
- ({{ user.userJob.label|localize_translatable_string }})
+ {%- if opts['user_job'] and user.userJob(opts['at']) is not null %}
+ ({{ user.userJob(opts['at']).label|localize_translatable_string }})
{%- endif -%}
- {%- if opts['main_scope'] and user.mainScope is not null %}
- ({{ user.mainScope.name|localize_translatable_string }})
+ {%- if opts['main_scope'] and user.mainScope(opts['at']) is not null %}
+ ({{ user.mainScope(opts['at']).name|localize_translatable_string }})
{%- endif -%}
{%- if opts['absence'] and user.isAbsent %}
{{ 'absence.A'|trans }}
diff --git a/src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php b/src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php
index 574d98b90..413492915 100644
--- a/src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php
+++ b/src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php
@@ -66,7 +66,7 @@ class AuthorizationHelper implements AuthorizationHelperInterface
*
* @return User[]
*/
- public function findUsersReaching(string $role, array|\Chill\MainBundle\Entity\Center $center, array|\Chill\MainBundle\Entity\Scope|null $scope = null, bool $onlyEnabled = true): array
+ public function findUsersReaching(string $role, array|\Chill\MainBundle\Entity\Center $center, null|array|\Chill\MainBundle\Entity\Scope $scope = null, bool $onlyEnabled = true): array
{
return $this->userACLAwareRepository
->findUsersByReachedACL($role, $center, $scope, $onlyEnabled);
@@ -130,7 +130,7 @@ class AuthorizationHelper implements AuthorizationHelperInterface
* @param Center|Center[] $center
* @return Scope[]
*/
- public function getReachableCircles(UserInterface $user, string $role, \Chill\MainBundle\Entity\Center|array $center)
+ public function getReachableCircles(UserInterface $user, string $role, array|\Chill\MainBundle\Entity\Center $center)
{
$scopes = [];
@@ -162,7 +162,7 @@ class AuthorizationHelper implements AuthorizationHelperInterface
/**
* Return all reachable scope for a given user, center and role.
*/
- public function getReachableScopes(UserInterface $user, string $role, Center|array $center): array
+ public function getReachableScopes(UserInterface $user, string $role, array|Center $center): array
{
return $this->getReachableCircles($user, $role, $center);
}
@@ -172,7 +172,7 @@ class AuthorizationHelper implements AuthorizationHelperInterface
*
* @param Center|Center[] $center May be an array of center
*/
- public function userCanReachCenter(User $user, \Chill\MainBundle\Entity\Center|array $center): bool
+ public function userCanReachCenter(User $user, array|\Chill\MainBundle\Entity\Center $center): bool
{
if ($center instanceof Traversable) {
foreach ($center as $c) {
diff --git a/src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelperInterface.php b/src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelperInterface.php
index 1dc9668ec..2a8c6587c 100644
--- a/src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelperInterface.php
+++ b/src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelperInterface.php
@@ -29,5 +29,5 @@ interface AuthorizationHelperInterface
* @param Center|array $center
* @return list
*/
- public function getReachableScopes(UserInterface $user, string $role, Center|array $center): array;
+ public function getReachableScopes(UserInterface $user, string $role, array|Center $center): array;
}
diff --git a/src/Bundle/ChillMainBundle/Security/Resolver/ScopeResolverDispatcher.php b/src/Bundle/ChillMainBundle/Security/Resolver/ScopeResolverDispatcher.php
index afec7c6ad..a4a464e45 100644
--- a/src/Bundle/ChillMainBundle/Security/Resolver/ScopeResolverDispatcher.php
+++ b/src/Bundle/ChillMainBundle/Security/Resolver/ScopeResolverDispatcher.php
@@ -32,7 +32,7 @@ final readonly class ScopeResolverDispatcher
return false;
}
- public function resolveScope(mixed $entity, ?array $options = []): iterable|\Chill\MainBundle\Entity\Scope|null
+ public function resolveScope(mixed $entity, ?array $options = []): null|\Chill\MainBundle\Entity\Scope|iterable
{
foreach ($this->resolvers as $resolver) {
if ($resolver->supports($entity, $options)) {
diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/DiscriminatedObjectDenormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/DiscriminatedObjectDenormalizer.php
index 58dc7e839..4149e387b 100644
--- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/DiscriminatedObjectDenormalizer.php
+++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/DiscriminatedObjectDenormalizer.php
@@ -45,7 +45,7 @@ class DiscriminatedObjectDenormalizer implements ContextAwareDenormalizerInterfa
if ($this->denormalizer->supportsDenormalization($data, $localType, $format)) {
try {
return $this->denormalizer->denormalize($data, $localType, $format, $context);
- } catch (RuntimeException|NotNormalizableValueException $e) {
+ } catch (NotNormalizableValueException|RuntimeException $e) {
$lastException = $e;
}
}
diff --git a/src/Bundle/ChillMainBundle/Service/EntityInfo/ViewEntityInfoManager.php b/src/Bundle/ChillMainBundle/Service/EntityInfo/ViewEntityInfoManager.php
index 5057d76e5..c5ef96d0b 100644
--- a/src/Bundle/ChillMainBundle/Service/EntityInfo/ViewEntityInfoManager.php
+++ b/src/Bundle/ChillMainBundle/Service/EntityInfo/ViewEntityInfoManager.php
@@ -12,6 +12,7 @@ declare(strict_types=1);
namespace Chill\MainBundle\Service\EntityInfo;
use Doctrine\DBAL\Connection;
+use Psr\Log\LoggerInterface;
class ViewEntityInfoManager
{
@@ -21,6 +22,7 @@ class ViewEntityInfoManager
*/
private readonly iterable $vienEntityInfoProviders,
private readonly Connection $connection,
+ private readonly LoggerInterface $logger,
) {}
public function synchronizeOnDB(): void
@@ -28,6 +30,8 @@ class ViewEntityInfoManager
$this->connection->transactional(function (Connection $conn): void {
foreach ($this->vienEntityInfoProviders as $viewProvider) {
foreach ($this->createOrReplaceViewSQL($viewProvider, $viewProvider->getViewName()) as $sql) {
+ $this->logger->debug("Will execute create view sql", ['sql' => $sql]);
+ $this->logger->debug($sql);
$conn->executeQuery($sql);
}
}
@@ -41,7 +45,7 @@ class ViewEntityInfoManager
{
return [
"DROP VIEW IF EXISTS {$viewName}",
- sprintf("CREATE VIEW {$viewName} AS %s", $viewProvider->getViewQuery())
+ sprintf("CREATE OR REPLACE VIEW {$viewName} AS %s", $viewProvider->getViewQuery())
];
}
}
diff --git a/src/Bundle/ChillMainBundle/Templating/Entity/UserRender.php b/src/Bundle/ChillMainBundle/Templating/Entity/UserRender.php
index 0878453b2..c26664bf1 100644
--- a/src/Bundle/ChillMainBundle/Templating/Entity/UserRender.php
+++ b/src/Bundle/ChillMainBundle/Templating/Entity/UserRender.php
@@ -28,10 +28,14 @@ class UserRender implements ChillEntityRenderInterface
'main_scope' => true,
'user_job' => true,
'absence' => true,
+ 'at' => null,
];
public function __construct(private readonly TranslatableStringHelper $translatableStringHelper, private readonly \Twig\Environment $engine, private readonly TranslatorInterface $translator) {}
+ /**
+ * @param mixed $entity
+ */
public function renderBox($entity, array $options): string
{
$opts = array_merge(self::DEFAULT_OPTIONS, $options);
@@ -42,20 +46,23 @@ class UserRender implements ChillEntityRenderInterface
]);
}
+ /**
+ * @param mixed $entity
+ */
public function renderString($entity, array $options): string
{
$opts = array_merge(self::DEFAULT_OPTIONS, $options);
$str = $entity->getLabel();
- if (null !== $entity->getUserJob() && $opts['user_job']) {
+ if (null !== $entity->getUserJob($opts['at']) && $opts['user_job']) {
$str .= ' (' . $this->translatableStringHelper
- ->localize($entity->getUserJob()->getLabel()) . ')';
+ ->localize($entity->getUserJob($opts['at'])->getLabel()) . ')';
}
- if (null !== $entity->getMainScope() && $opts['main_scope']) {
+ if (null !== $entity->getMainScope($opts['at']) && $opts['main_scope']) {
$str .= ' (' . $this->translatableStringHelper
- ->localize($entity->getMainScope()->getName()) . ')';
+ ->localize($entity->getMainScope($opts['at'])->getName()) . ')';
}
if ($entity->isAbsent() && $opts['absence']) {
diff --git a/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/JsonBuildObjectTest.php b/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/JsonBuildObjectTest.php
new file mode 100644
index 000000000..d2897546c
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/JsonBuildObjectTest.php
@@ -0,0 +1,61 @@
+entityManager = self::$container->get(EntityManagerInterface::class);
+ }
+
+ /**
+ * @dataProvider provideQueries
+ */
+ public function testQuery(string $sql, array $params, array $paramType): void
+ {
+ $query = $this->entityManager->createQuery($sql);
+
+ foreach ($params as $k => $v) {
+ $query->setParameter($k, $v, $paramType[$k]);
+ }
+ $query->setMaxResults(1);
+
+ $result = $query->getResult(AbstractQuery::HYDRATE_ARRAY);
+
+ self::assertIsArray($result);
+ }
+
+ public function provideQueries(): iterable
+ {
+ yield ["SELECT JSON_BUILD_OBJECT(1, 2, 3, 4) FROM " . Address::class . " a", [], []];
+ yield ["SELECT JSON_BUILD_OBJECT('st', a.street, 'sn', a.streetNumber) FROM " . Address::class . ' a', [], []];
+ // next query make the test fails. But we do not need it for now.
+ //yield ["SELECT JSON_BUILD_OBJECT(a.street, :param), LOWER(:param) FROM " . Address::class . " a", ['param' => 1], ['param' => Types::INTEGER]];
+ }
+
+}
diff --git a/src/Bundle/ChillPersonBundle/Doctrine/DQL/AddressPart.php b/src/Bundle/ChillPersonBundle/Doctrine/DQL/AddressPart.php
index 229a69f2c..38d13ea43 100644
--- a/src/Bundle/ChillPersonBundle/Doctrine/DQL/AddressPart.php
+++ b/src/Bundle/ChillPersonBundle/Doctrine/DQL/AddressPart.php
@@ -40,7 +40,7 @@ abstract class AddressPart extends FunctionNode
'country_id',
];
- private \Doctrine\ORM\Query\AST\Node|string|null $date = null;
+ private null|\Doctrine\ORM\Query\AST\Node|string $date = null;
/**
* @var \Doctrine\ORM\Query\AST\Node
diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php
index 2224f307b..e074f53ef 100644
--- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php
+++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php
@@ -977,7 +977,7 @@ class AccompanyingPeriod implements
/**
* @Groups({"read"})
*/
- public function getRequestor(): Person|ThirdParty|null
+ public function getRequestor(): null|Person|ThirdParty
{
return $this->requestorPerson ?? $this->requestorThirdParty;
}
diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php
index 611f1763e..0c17276ae 100644
--- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php
+++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php
@@ -156,8 +156,7 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues
/**
* @var Collection
- * @ORM\OneToMany(targetEntity=AccompanyingPeriodWorkReferrerHistory::class, cascade={"persist", "remove"}, mappedBy="accompanyingPeriodWork")
- * @ORM\JoinTable(name="chill_person_accompanying_period_work_referrer")
+ * @ORM\OneToMany(targetEntity=AccompanyingPeriodWorkReferrerHistory::class, cascade={"persist", "remove"}, mappedBy="accompanyingPeriodWork", orphanRemoval=true)
*/
private Collection $referrersHistory;
@@ -357,9 +356,17 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues
*/
public function getReferrers(): ReadableCollection
{
- return $this->referrersHistory->map(fn (AccompanyingPeriodWorkReferrerHistory $h) => $h->getUser());
+ return $this->referrersHistory
+ ->filter(fn (AccompanyingPeriodWorkReferrerHistory $h) => null === $h->getEndDate())
+ ->map(fn (AccompanyingPeriodWorkReferrerHistory $h) => $h->getUser());
}
+ public function getReferrersHistory(): Collection
+ {
+ return $this->referrersHistory;
+ }
+
+
/**
* @return Collection
*/
@@ -442,6 +449,7 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues
if ($history->isDateRangeEmpty()) {
$history->removeAccompanyingPeriodWork();
+ $this->referrersHistory->removeElement($history);
}
}
}
diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkReferrerHistory.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkReferrerHistory.php
index 48b75d3e4..057b5a409 100644
--- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkReferrerHistory.php
+++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkReferrerHistory.php
@@ -38,29 +38,24 @@ class AccompanyingPeriodWorkReferrerHistory implements TrackCreationInterface, T
* @var \DateTimeImmutable|null
* @ORM\Column(type="date_immutable", nullable=true, options={"default": null})
*/
- private ?\DateTimeImmutable $endDate;
-
- /**
- * @var AccompanyingPeriodWork|null
- * @ORM\ManyToOne(targetEntity=AccompanyingPeriodWork::class, inversedBy="referrersHistory")
- */
- private ?AccompanyingPeriodWork $accompanyingPeriodWork;
+ private ?\DateTimeImmutable $endDate = null;
public function __construct(
- AccompanyingPeriodWork $accompanyingPeriodWork,
+ /**
+ * @ORM\ManyToOne(targetEntity=AccompanyingPeriodWork::class, inversedBy="referrersHistory")
+ */
+ private ?AccompanyingPeriodWork $accompanyingPeriodWork,
/**
* @var User
* @ORM\ManyToOne(targetEntity=User::class)
*/
- private readonly User $user,
+ private User $user,
/**
* @var \DateTimeImmutable
* @ORM\Column(type="date_immutable", nullable=false)
*/
- private readonly \DateTimeImmutable $startDate,
- ) {
- $this->accompanyingPeriodWork = $accompanyingPeriodWork;
- }
+ private \DateTimeImmutable $startDate
+ ) {}
public function getId(): ?int
{
diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php
index c9f1e9279..abe171df1 100644
--- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php
+++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Resource.php
@@ -96,7 +96,7 @@ class Resource
/**
* @Groups({"read"})
*/
- public function getResource(): \Chill\PersonBundle\Entity\Person|\Chill\ThirdPartyBundle\Entity\ThirdParty|null
+ public function getResource(): null|\Chill\PersonBundle\Entity\Person|\Chill\ThirdPartyBundle\Entity\ThirdParty
{
return $this->person ?? $this->thirdParty;
}
diff --git a/src/Bundle/ChillPersonBundle/Entity/Person.php b/src/Bundle/ChillPersonBundle/Entity/Person.php
index 832afb987..3265f09e1 100644
--- a/src/Bundle/ChillPersonBundle/Entity/Person.php
+++ b/src/Bundle/ChillPersonBundle/Entity/Person.php
@@ -619,7 +619,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
* @return true | array True if the accompanying periods are not collapsing,
* an array with data for displaying the error
*/
- public function checkAccompanyingPeriodsAreNotCollapsing(): bool|array
+ public function checkAccompanyingPeriodsAreNotCollapsing(): array|bool
{
$periods = $this->getAccompanyingPeriodsOrdered();
$periodsNbr = count($periods);
diff --git a/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialAction.php b/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialAction.php
index a5475263e..f98964fcb 100644
--- a/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialAction.php
+++ b/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialAction.php
@@ -156,7 +156,7 @@ class SocialAction
*
* @return Collection|SocialAction[] a list with the elements of the given list which are parent of other elements in the given list
*/
- public static function findAncestorSocialActions(\Doctrine\Common\Collections\Collection|array $socialActions): Collection
+ public static function findAncestorSocialActions(array|\Doctrine\Common\Collections\Collection $socialActions): Collection
{
$ancestors = new ArrayCollection();
@@ -236,7 +236,7 @@ class SocialAction
/**
* @param Collection|SocialAction[] $socialActions
*/
- public static function getDescendantsWithThisForActions(\Doctrine\Common\Collections\Collection|array $socialActions): Collection
+ public static function getDescendantsWithThisForActions(array|\Doctrine\Common\Collections\Collection $socialActions): Collection
{
$unique = [];
@@ -420,7 +420,7 @@ class SocialAction
return $this;
}
- public static function filterRemoveDeactivatedActions(ReadableCollection|array $actions, \DateTime $comparisonDate): ReadableCollection|array
+ public static function filterRemoveDeactivatedActions(array|ReadableCollection $actions, \DateTime $comparisonDate): array|ReadableCollection
{
$filterFn = fn (SocialAction $socialAction) => !$socialAction->isDesactivated($comparisonDate);
diff --git a/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialIssue.php b/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialIssue.php
index 5c9f1a9c4..000d83397 100644
--- a/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialIssue.php
+++ b/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialIssue.php
@@ -110,7 +110,7 @@ class SocialIssue
*
* @return Collection|SocialIssue[]
*/
- public static function findAncestorSocialIssues(\Doctrine\Common\Collections\Collection|array $socialIssues): Collection
+ public static function findAncestorSocialIssues(array|\Doctrine\Common\Collections\Collection $socialIssues): Collection
{
$ancestors = new ArrayCollection();
diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php
index ad38b4a6b..b42bb0cd5 100644
--- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php
+++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php
@@ -81,7 +81,7 @@ final readonly class JobWorkingOnCourseAggregator implements AggregatorInterface
public function getLabels($key, array $values, $data): \Closure
{
- return function (int|string|null $jobId) {
+ return function (null|int|string $jobId) {
if (null === $jobId || '' === $jobId) {
return '';
}
diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php
index fbc4947bf..f0dcff515 100644
--- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php
+++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php
@@ -81,7 +81,7 @@ final readonly class ScopeWorkingOnCourseAggregator implements AggregatorInterfa
public function getLabels($key, array $values, $data): \Closure
{
- return function (int|string|null $scopeId) {
+ return function (null|int|string $scopeId) {
if (null === $scopeId || '' === $scopeId) {
return '';
}
diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserWorkingOnCourseAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserWorkingOnCourseAggregator.php
index 862a2de79..b36795cdd 100644
--- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserWorkingOnCourseAggregator.php
+++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserWorkingOnCourseAggregator.php
@@ -41,7 +41,7 @@ final readonly class UserWorkingOnCourseAggregator implements AggregatorInterfac
public function getLabels($key, array $values, $data): \Closure
{
- return function (int|string|null $userId) {
+ return function (null|int|string $userId) {
if (null === $userId || '' === $userId) {
return '';
}
diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/CenterAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/CenterAggregator.php
index 99187264a..c6d8cfae0 100644
--- a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/CenterAggregator.php
+++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/CenterAggregator.php
@@ -46,7 +46,7 @@ final readonly class CenterAggregator implements AggregatorInterface
public function getLabels($key, array $values, $data): Closure
{
- return function (int|string|null $value) {
+ return function (null|int|string $value) {
if (null === $value || '' === $value) {
return '';
}
diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php
index 6012bbcab..c95d4ef37 100644
--- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php
+++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php
@@ -11,13 +11,16 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Export\Aggregator\SocialWorkAggregators;
+use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\User\UserJobHistory;
+use Chill\MainBundle\Entity\UserJob;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Repository\UserJobRepository;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverter;
use Chill\MainBundle\Templating\TranslatableStringHelper;
+use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkReferrerHistory;
use Chill\PersonBundle\Export\Declarations;
use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\QueryBuilder;
@@ -29,7 +32,6 @@ final readonly class JobAggregator implements AggregatorInterface
private const PREFIX = 'acp_work_action_agg_user_job';
public function __construct(
- private RollingDateConverter $rollingDateConverter,
private UserJobRepository $jobRepository,
private TranslatableStringHelper $translatableStringHelper
) {}
@@ -44,27 +46,16 @@ final readonly class JobAggregator implements AggregatorInterface
$p = self::PREFIX;
$qb
- ->leftJoin("acpw.referrers", "{$p}_user")
->leftJoin(
- UserJobHistory::class,
- "{$p}_history",
+ UserJob::class,
+ "{$p}_job",
Expr\Join::WITH,
- $qb->expr()->eq("{$p}_history.user", "{$p}_user")
- )
- ->andWhere(
- $qb->expr()->andX(
- $qb->expr()->lte("{$p}_history.startDate", ":{$p}_at"),
- $qb->expr()->orX(
- $qb->expr()->isNull("{$p}_history.endDate"),
- $qb->expr()->gt("{$p}_history.endDate", ":{$p}_at")
- )
- )
- )
- ->addSelect("IDENTITY({$p}_history.job) as {$p}_select")
- ->setParameter(
- "{$p}_at",
- $this->rollingDateConverter->convert($data['job_at'])
+ 'EXISTS (SELECT 1 FROM ' . AccompanyingPeriodWorkReferrerHistory::class . " {$p}_ref_history
+ JOIN {$p}_ref_history.user {$p}_ref_history_user JOIN {$p}_ref_history_user.jobHistories {$p}_job_history
+ WHERE {$p}_ref_history.accompanyingPeriodWork = acpw AND IDENTITY({$p}_job_history.job) = {$p}_job.id AND {$p}_job_history.startDate <= {$p}_ref_history.startDate
+ AND ({$p}_job_history.endDate IS NULL or {$p}_job_history.endDate >= {$p}_ref_history.startDate))"
)
+ ->addSelect("{$p}_job.id as {$p}_select")
->addGroupBy("{$p}_select");
}
@@ -73,17 +64,11 @@ final readonly class JobAggregator implements AggregatorInterface
return Declarations::SOCIAL_WORK_ACTION_TYPE;
}
- public function buildForm(FormBuilderInterface $builder)
- {
- $builder->add('job_at', PickRollingDateType::class, [
- 'label' => 'export.aggregator.course_work.by_agent_job.Calc date',
- 'required' => true
- ]);
- }
+ public function buildForm(FormBuilderInterface $builder) {}
public function getFormDefaultData(): array
{
- return ['job_at' => new RollingDate(RollingDate::T_TODAY)];
+ return [];
}
public function getLabels($key, array $values, $data)
diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ReferrerAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ReferrerAggregator.php
index 6af106715..99f766ebc 100644
--- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ReferrerAggregator.php
+++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ReferrerAggregator.php
@@ -12,7 +12,10 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Export\Aggregator\SocialWorkAggregators;
use Chill\MainBundle\Export\AggregatorInterface;
+use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Repository\UserRepository;
+use Chill\MainBundle\Service\RollingDate\RollingDate;
+use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\MainBundle\Templating\Entity\UserRender;
use Chill\PersonBundle\Export\Declarations;
use Doctrine\ORM\QueryBuilder;
@@ -21,7 +24,13 @@ use function in_array;
final readonly class ReferrerAggregator implements AggregatorInterface
{
- public function __construct(private UserRepository $userRepository, private UserRender $userRender) {}
+ private const PREFIX = 'acpw_referrer_aggregator';
+
+ public function __construct(
+ private UserRepository $userRepository,
+ private UserRender $userRender,
+ private RollingDateConverterInterface $rollingDateConverter
+ ) {}
public function addRole(): ?string
{
@@ -30,11 +39,16 @@ final readonly class ReferrerAggregator implements AggregatorInterface
public function alterQuery(QueryBuilder $qb, $data)
{
- if (!in_array('acpwuser', $qb->getAllAliases(), true)) {
- $qb->leftJoin('acpw.referrers', 'acpwuser');
- }
+ $p = self::PREFIX;
- $qb->addSelect('acpwuser.id AS referrer_aggregator');
+ $qb
+ ->leftJoin('acpw.referrersHistory', $p . "_acpwusers_history")
+ ->andWhere("{$p}_acpwusers_history.startDate <= :{$p}_calc_date AND ({$p}_acpwusers_history.endDate IS NULL or {$p}_acpwusers_history.endDate > :{$p}_calc_date)");
+
+ $qb->setParameter("{$p}_calc_date", $this->rollingDateConverter->convert(
+ $data['referrer_at'] ?? new RollingDate(RollingDate::T_TODAY)
+ ));
+ $qb->addSelect("IDENTITY({$p}_acpwusers_history.user) AS referrer_aggregator");
$qb->addGroupBy('referrer_aggregator');
}
@@ -45,11 +59,16 @@ final readonly class ReferrerAggregator implements AggregatorInterface
public function buildForm(FormBuilderInterface $builder)
{
- // no form
+ $builder->add('referrer_at', PickRollingDateType::class, [
+ 'label' => 'export.aggregator.course_work.by_treating_agent.Calc date'
+ ]);
}
+
public function getFormDefaultData(): array
{
- return [];
+ return [
+ 'referrer_at' => new RollingDate(RollingDate::T_TODAY),
+ ];
}
public function getLabels($key, array $values, $data)
@@ -65,7 +84,7 @@ final readonly class ReferrerAggregator implements AggregatorInterface
$r = $this->userRepository->find($value);
- return $this->userRender->renderString($r, []);
+ return $this->userRender->renderString($r, ['absence' => false, 'user_job' => false, 'main_scope' => false]);
};
}
@@ -76,6 +95,6 @@ final readonly class ReferrerAggregator implements AggregatorInterface
public function getTitle(): string
{
- return 'Group by treating agent';
+ return 'export.aggregator.course_work.by_treating_agent.Group by treating agent';
}
}
diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php
index b6c799079..6fc158dad 100644
--- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php
+++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php
@@ -11,13 +11,16 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Export\Aggregator\SocialWorkAggregators;
+use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\User\UserScopeHistory;
+use Chill\MainBundle\Entity\UserJob;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Repository\ScopeRepository;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverter;
use Chill\MainBundle\Templating\TranslatableStringHelper;
+use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkReferrerHistory;
use Chill\PersonBundle\Export\Declarations;
use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\QueryBuilder;
@@ -29,7 +32,6 @@ final readonly class ScopeAggregator implements AggregatorInterface
private const PREFIX = 'acp_work_action_agg_user_scope';
public function __construct(
- private RollingDateConverter $rollingDateConverter,
private ScopeRepository $scopeRepository,
private TranslatableStringHelper $translatableStringHelper
) {}
@@ -44,27 +46,16 @@ final readonly class ScopeAggregator implements AggregatorInterface
$p = self::PREFIX;
$qb
- ->leftJoin("acpw.referrers", "{$p}_user")
->leftJoin(
- UserScopeHistory::class,
- "{$p}_history",
+ Scope::class,
+ "{$p}_scope",
Expr\Join::WITH,
- $qb->expr()->eq("{$p}_history.user", "{$p}_user")
- )
- ->andWhere(
- $qb->expr()->andX(
- $qb->expr()->lte("{$p}_history.startDate", ":{$p}_at"),
- $qb->expr()->orX(
- $qb->expr()->isNull("{$p}_history.endDate"),
- $qb->expr()->gt("{$p}_history.endDate", ":{$p}_at")
- )
- )
- )
- ->addSelect("IDENTITY({$p}_history.scope) as {$p}_select")
- ->setParameter(
- "{$p}_at",
- $this->rollingDateConverter->convert($data['scope_at'])
+ 'EXISTS (SELECT 1 FROM ' . AccompanyingPeriodWorkReferrerHistory::class . " {$p}_ref_history
+ JOIN {$p}_ref_history.user {$p}_ref_history_user JOIN {$p}_ref_history_user.scopeHistories {$p}_scope_history
+ WHERE {$p}_ref_history.accompanyingPeriodWork = acpw AND IDENTITY({$p}_scope_history.scope) = {$p}_scope.id AND {$p}_scope_history.startDate <= {$p}_ref_history.startDate
+ AND ({$p}_scope_history.endDate IS NULL or {$p}_scope_history.endDate >= {$p}_ref_history.startDate))"
)
+ ->addSelect("{$p}_scope.id as {$p}_select")
->addGroupBy("{$p}_select");
}
@@ -73,17 +64,11 @@ final readonly class ScopeAggregator implements AggregatorInterface
return Declarations::SOCIAL_WORK_ACTION_TYPE;
}
- public function buildForm(FormBuilderInterface $builder)
- {
- $builder->add('scope_at', PickRollingDateType::class, [
- 'label' => 'export.aggregator.course_work.by_agent_scope.Calc date',
- 'required' => true,
- ]);
- }
+ public function buildForm(FormBuilderInterface $builder) {}
public function getFormDefaultData(): array
{
- return ['scope_at' => new RollingDate(RollingDate::T_TODAY)];
+ return [];
}
public function getLabels($key, array $values, $data)
diff --git a/src/Bundle/ChillPersonBundle/Export/Export/ListAccompanyingPeriodWork.php b/src/Bundle/ChillPersonBundle/Export/Export/ListAccompanyingPeriodWork.php
index 0b34899b9..3923936b8 100644
--- a/src/Bundle/ChillPersonBundle/Export/Export/ListAccompanyingPeriodWork.php
+++ b/src/Bundle/ChillPersonBundle/Export/Export/ListAccompanyingPeriodWork.php
@@ -24,6 +24,7 @@ use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkGoal;
+use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkReferrerHistory;
use Chill\PersonBundle\Entity\AccompanyingPeriod\UserHistory;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
@@ -69,6 +70,7 @@ class ListAccompanyingPeriodWork implements ListInterface, GroupedExportInterfac
'personsName',
'thirdParties',
'handlingThierParty',
+ //'acpwReferrers',
'referrers',
'createdAt',
'createdBy',
@@ -76,7 +78,20 @@ class ListAccompanyingPeriodWork implements ListInterface, GroupedExportInterfac
'updatedBy',
];
- public function __construct(private readonly EntityManagerInterface $entityManager, private readonly DateTimeHelper $dateTimeHelper, private readonly UserHelper $userHelper, private readonly LabelPersonHelper $personHelper, private readonly LabelThirdPartyHelper $thirdPartyHelper, private readonly TranslatableStringExportLabelHelper $translatableStringExportLabelHelper, private readonly SocialIssueRender $socialIssueRender, private readonly SocialIssueRepository $socialIssueRepository, private readonly SocialActionRender $socialActionRender, private readonly RollingDateConverterInterface $rollingDateConverter, private readonly AggregateStringHelper $aggregateStringHelper, private readonly SocialActionRepository $socialActionRepository) {}
+ public function __construct(
+ private readonly EntityManagerInterface $entityManager,
+ private readonly DateTimeHelper $dateTimeHelper,
+ private readonly UserHelper $userHelper,
+ private readonly LabelPersonHelper $personHelper,
+ private readonly LabelThirdPartyHelper $thirdPartyHelper,
+ private readonly TranslatableStringExportLabelHelper $translatableStringExportLabelHelper,
+ private readonly SocialIssueRender $socialIssueRender,
+ private readonly SocialIssueRepository $socialIssueRepository,
+ private readonly SocialActionRender $socialActionRender,
+ private readonly RollingDateConverterInterface $rollingDateConverter,
+ private readonly AggregateStringHelper $aggregateStringHelper,
+ private readonly SocialActionRepository $socialActionRepository
+ ) {}
public function buildForm(FormBuilderInterface $builder)
{
@@ -141,6 +156,7 @@ class ListAccompanyingPeriodWork implements ListInterface, GroupedExportInterfac
},
'createdBy', 'updatedBy', 'acp_user' => $this->userHelper->getLabel($key, $values, 'export.list.acpw.' . $key),
'referrers' => $this->userHelper->getLabel($key, $values, 'export.list.acpw.' . $key),
+ //'acpwReferrers' => $this->userHelper->getLabelMulti($key, $values, 'export.list.acpw.' . $key),
'personsName' => $this->personHelper->getLabelMulti($key, $values, 'export.list.acpw.' . $key),
'handlingThierParty' => $this->thirdPartyHelper->getLabel($key, $values, 'export.list.acpw.' . $key),
'thirdParties' => $this->thirdPartyHelper->getLabelMulti($key, $values, 'export.list.acpw.' . $key),
@@ -167,7 +183,7 @@ class ListAccompanyingPeriodWork implements ListInterface, GroupedExportInterfac
public function getResult($query, $data)
{
- return $query->getQuery()->getResult(AbstractQuery::HYDRATE_SCALAR);
+ return dump($query->getQuery()->getResult(AbstractQuery::HYDRATE_SCALAR));
}
public function getTitle(): string
@@ -269,9 +285,20 @@ class ListAccompanyingPeriodWork implements ListInterface, GroupedExportInterfac
// referrers => at date XXXX
$qb
- ->addSelect('(SELECT IDENTITY(history.user) FROM ' . UserHistory::class . ' history ' .
+ ->addSelect('(SELECT JSON_BUILD_OBJECT(\'uid\', IDENTITY(history.user), \'d\', history.startDate) FROM ' . UserHistory::class . ' history ' .
'WHERE history.accompanyingPeriod = acp AND history.startDate <= :calcDate AND (history.endDate IS NULL OR history.endDate > :calcDate)) AS referrers');
+ /*
+ // acpwReferrers at date XXX
+ $qb
+ ->addSelect('(
+ SELECT IDENTITY(acpw_ref_history.accompanyingPeriodWork) AS acpw_ref_history_id,
+ JSON_BUILD_OBJECT(\'uid\', IDENTITY(acpw_ref_history.user), \'d\', acpw_ref_history.startDate)
+ FROM ' . AccompanyingPeriodWorkReferrerHistory::class . ' acpw_ref_history ' .
+ 'WHERE acpw_ref_history.accompanyingPeriodWork = acpw AND acpw_ref_history.startDate <= :calcDate AND (acpw_ref_history.endDate IS NULL or acpw_ref_history.endDate > :calcDate) GROUP BY acpw_ref_history_id) AS acpwReferrers'
+ );
+ */
+
// thirdparties
$qb
->addSelect('(SELECT AGGREGATE(tp.id) FROM ' . ThirdParty::class . ' tp '
diff --git a/src/Bundle/ChillPersonBundle/Export/Export/ListEvaluation.php b/src/Bundle/ChillPersonBundle/Export/Export/ListEvaluation.php
index 34646dbd0..253b4f34c 100644
--- a/src/Bundle/ChillPersonBundle/Export/Export/ListEvaluation.php
+++ b/src/Bundle/ChillPersonBundle/Export/Export/ListEvaluation.php
@@ -132,7 +132,7 @@ class ListEvaluation implements ListInterface, GroupedExportInterface
);
},
'createdBy', 'updatedBy', 'acpw_acp_user' => $this->userHelper->getLabel($key, $values, 'export.list.eval.' . $key),
- 'acpw_referrers' => $this->userHelper->getLabel($key, $values, 'export.list.eval.' . $key),
+ 'acpw_referrers' => $this->userHelper->getLabelMulti($key, $values, 'export.list.eval.' . $key),
'acpw_persons_id' => $this->aggregateStringHelper->getLabelMulti($key, $values, 'export.list.eval.' . $key),
'acpw_persons' => $this->personHelper->getLabelMulti($key, $values, 'export.list.eval.' . $key),
'eval_title' => $this->translatableStringExportLabelHelper
@@ -252,8 +252,8 @@ class ListEvaluation implements ListInterface, GroupedExportInterface
// referrers => at date XXXX
$qb
- ->addSelect('(SELECT IDENTITY(history.user) FROM ' . UserHistory::class . ' history ' .
- 'WHERE history.accompanyingPeriod = acp AND history.startDate <= :calc_date AND (history.endDate IS NULL OR history.endDate > :calc_date)) AS acpw_referrers');
+ ->addSelect('(SELECT JSON_BUILD_OBJECT(\'uid\', IDENTITY(history.user), \'d\', history.startDate) FROM ' . UserHistory::class . ' history ' .
+ 'WHERE history.accompanyingPeriod = acp AND history.startDate <= :calc_date AND (history.endDate IS NULL OR history.endDate > :calc_date)) AS referrers');
// persons
$qb
diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php
index 7053654df..10467f911 100644
--- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php
+++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php
@@ -72,9 +72,10 @@ class CreatorJobFilter implements FilterInterface
)
)
->andWhere($qb->expr()->in("{$p}_history.job", ":{$p}_jobs"))
- ->setParameters([
- "{$p}_jobs" => $data["creator_job"],
- ]);
+ ->setParameter(
+ "{$p}_jobs",
+ $data["creator_job"],
+ );
}
public function applyOn(): string
diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/JobWorkingOnCourseFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/JobWorkingOnCourseFilter.php
index 393a726fc..7024d837d 100644
--- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/JobWorkingOnCourseFilter.php
+++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/JobWorkingOnCourseFilter.php
@@ -63,11 +63,15 @@ readonly class JobWorkingOnCourseFilter implements FilterInterface
. "AND {$p}_info.infoDate >= :{$p}_start and {$p}_info.infoDate < :{$p}_end"
)
)
- ->setParameters([
- "{$p}_jobs" => $data['jobs'],
- "{$p}_start" => $this->rollingDateConverter->convert($data['start_date']),
- "{$p}_end" => $this->rollingDateConverter->convert($data['end_date'])
- ])
+ ->setParameter("{$p}_jobs", $data['jobs'])
+ ->setParameter(
+ "{$p}_start",
+ $this->rollingDateConverter->convert($data['start_date']),
+ )
+ ->setParameter(
+ "{$p}_end",
+ $this->rollingDateConverter->convert($data['end_date'])
+ )
;
}
diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ScopeWorkingOnCourseFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ScopeWorkingOnCourseFilter.php
index 97f592c3d..491122968 100644
--- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ScopeWorkingOnCourseFilter.php
+++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ScopeWorkingOnCourseFilter.php
@@ -63,11 +63,15 @@ readonly class ScopeWorkingOnCourseFilter implements FilterInterface
. "AND {$p}_info.infoDate >= :{$p}_start AND {$p}_info.infoDate < :{$p}_end"
)
)
- ->setParameters([
- "{$p}_scopes" => $data["scopes"],
- "{$p}_start" => $this->rollingDateConverter->convert($data["start_date"]),
- "{$p}_end" => $this->rollingDateConverter->convert($data["end_date"])
- ])
+ ->setParameter("{$p}_scopes", $data["scopes"])
+ ->setParameter(
+ "{$p}_start",
+ $this->rollingDateConverter->convert($data["start_date"]),
+ )
+ ->setParameter(
+ "{$p}_end",
+ $this->rollingDateConverter->convert($data["end_date"])
+ )
;
}
diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php
index 04d1b2cb8..dc55fd454 100644
--- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php
+++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php
@@ -72,9 +72,10 @@ class UserJobFilter implements FilterInterface
)
)
->andWhere($qb->expr()->in("{$p}_jobHistory.job", ":{$p}_job"))
- ->setParameters([
- "{$p}_job" => $data["jobs"],
- ])
+ ->setParameter(
+ "{$p}_job",
+ $data["jobs"],
+ )
;
}
diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php
index 2abad7823..3e53f49f1 100644
--- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php
+++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php
@@ -72,9 +72,10 @@ class UserScopeFilter implements FilterInterface
)
)
->andWhere($qb->expr()->in("{$p}_scopeHistory.scope", ":{$p}_scopes"))
- ->setParameters([
- "{$p}_scopes" => $data["scopes"],
- ])
+ ->setParameter(
+ "{$p}_scopes",
+ $data["scopes"],
+ )
;
}
diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php
index 2ad01c3ff..c0de87d65 100644
--- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php
+++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php
@@ -18,6 +18,7 @@ use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverter;
use Chill\MainBundle\Templating\TranslatableStringHelper;
+use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkReferrerHistory;
use Chill\PersonBundle\Export\Declarations;
use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\Query\Expr\Andx;
@@ -32,7 +33,6 @@ class JobFilter implements FilterInterface
private const PREFIX = 'acp_work_action_filter_user_job';
public function __construct(
- private readonly RollingDateConverter $rollingDateConverter,
protected TranslatorInterface $translator,
private readonly TranslatableStringHelper $translatableStringHelper
) {}
@@ -46,30 +46,14 @@ class JobFilter implements FilterInterface
{
$p = self::PREFIX;
- $qb
- ->leftJoin("acpw.referrers", "{$p}_user")
- ->leftJoin(
- UserJobHistory::class,
- "{$p}_history",
- Expr\Join::WITH,
- $qb->expr()->eq("{$p}_history.user", "{$p}_user")
- )
- ->andWhere(
- $qb->expr()->andX(
- $qb->expr()->lte("{$p}_history.startDate", ":{$p}_at"),
- $qb->expr()->orX(
- $qb->expr()->isNull("{$p}_history.endDate"),
- $qb->expr()->gt("{$p}_history.endDate", ":{$p}_at")
- )
- )
- )
- ->andWhere(
- $qb->expr()->in("{$p}_history.job", ":{$p}_job")
- )
- ->setParameters([
- "{$p}_job" => $data["job"],
- "{$p}_at" => $this->rollingDateConverter->convert($data['job_at'])
- ]);
+ $qb->andWhere(
+ 'EXISTS (SELECT 1 FROM ' . AccompanyingPeriodWorkReferrerHistory::class . " {$p}_ref_history
+ JOIN {$p}_ref_history.user {$p}_ref_history_user JOIN {$p}_ref_history_user.jobHistories {$p}_job_history
+ WHERE {$p}_ref_history.accompanyingPeriodWork = acpw AND {$p}_job_history.job IN (:{$p}_job) AND {$p}_job_history.startDate <= {$p}_ref_history.startDate
+ AND ({$p}_job_history.endDate IS NULL or {$p}_job_history.endDate >= {$p}_ref_history.startDate))"
+ );
+
+ $qb->setParameter("{$p}_job", $data["job"]);
}
public function applyOn(): string
@@ -88,10 +72,6 @@ class JobFilter implements FilterInterface
'multiple' => true,
'expanded' => true,
])
- ->add('job_at', PickRollingDateType::class, [
- 'label' => 'export.filter.work.by_user_job.Calc date',
- 'required' => true,
- ])
;
}
diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ReferrerFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ReferrerFilter.php
index bddcfbf9b..2410a5d08 100644
--- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ReferrerFilter.php
+++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ReferrerFilter.php
@@ -12,7 +12,10 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Export\Filter\SocialWorkFilters;
use Chill\MainBundle\Export\FilterInterface;
+use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Form\Type\PickUserDynamicType;
+use Chill\MainBundle\Service\RollingDate\RollingDate;
+use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\MainBundle\Templating\Entity\UserRender;
use Chill\PersonBundle\Export\Declarations;
use Doctrine\ORM\Query\Expr\Andx;
@@ -20,8 +23,12 @@ use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use function in_array;
-class ReferrerFilter implements FilterInterface
+final readonly class ReferrerFilter implements FilterInterface
{
+ private const PREFIX = 'acpw_referrer_filter';
+
+ public function __construct(private RollingDateConverterInterface $rollingDateConverter) {}
+
public function addRole(): ?string
{
return null;
@@ -29,21 +36,19 @@ class ReferrerFilter implements FilterInterface
public function alterQuery(QueryBuilder $qb, $data)
{
- if (!in_array('acpwuser', $qb->getAllAliases(), true)) {
- $qb->join('acpw.referrers', 'acpwuser');
- }
+ $p = self::PREFIX;
- $where = $qb->getDQLPart('where');
- $clause = $qb->expr()->in('acpwuser', ':agents');
+ $qb
+ ->leftJoin('acpw.referrersHistory', $p . "_acpwusers_history")
+ ->andWhere("{$p}_acpwusers_history.startDate <= :{$p}_calc_date AND ({$p}_acpwusers_history.endDate IS NULL or {$p}_acpwusers_history.endDate > :{$p}_calc_date)")
+ ->andWhere("{$p}_acpwusers_history.user IN (:{$p}_agents)");
- if ($where instanceof Andx) {
- $where->add($clause);
- } else {
- $where = $qb->expr()->andX($clause);
- }
-
- $qb->add('where', $where);
- $qb->setParameter('agents', $data['accepted_agents']);
+ $qb
+ ->setParameter("{$p}_agents", $data['accepted_agents'])
+ ->setParameter("{$p}_calc_date", $this->rollingDateConverter->convert(
+ $data['agent_at'] ?? new RollingDate(RollingDate::T_TODAY)
+ ))
+ ;
}
public function applyOn(): string
@@ -53,13 +58,23 @@ class ReferrerFilter implements FilterInterface
public function buildForm(FormBuilderInterface $builder)
{
- $builder->add('accepted_agents', PickUserDynamicType::class, [
- 'multiple' => true,
- ]);
+ $builder
+ ->add('accepted_agents', PickUserDynamicType::class, [
+ 'multiple' => true,
+ 'label' => 'export.filter.work.by_treating_agent.Accepted agents'
+ ])
+ ->add('agent_at', PickRollingDateType::class, [
+ 'label' => 'export.filter.work.by_treating_agent.Calc date',
+ 'help' => 'export.filter.work.by_treating_agent.calc_date_help',
+ ])
+ ;
}
public function getFormDefaultData(): array
{
- return [];
+ return [
+ 'accepted_agents' => [],
+ 'agent_at' => new RollingDate(RollingDate::T_TODAY),
+ ];
}
public function describeAction($data, $format = 'string'): array
@@ -71,13 +86,14 @@ class ReferrerFilter implements FilterInterface
}
return [
- 'Filtered by treating agent: only %agents%', [
- '%agents' => implode(', ', $users),
+ 'exports.filter.work.by_treating_agent.Filtered by treating agent at date', [
+ 'agents' => implode(', ', $users),
+ 'agent_at' => $this->rollingDateConverter->convert($data['agent_at'] ?? new RollingDate(RollingDate::T_TODAY)),
], ];
}
public function getTitle(): string
{
- return 'Filter by treating agent';
+ return 'export.filter.work.by_treating_agent.Filter by treating agent';
}
}
diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php
index c5041aa6c..ce9b4e585 100644
--- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php
+++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php
@@ -18,6 +18,7 @@ use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverter;
use Chill\MainBundle\Templating\TranslatableStringHelper;
+use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkReferrerHistory;
use Chill\PersonBundle\Export\Declarations;
use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\QueryBuilder;
@@ -30,7 +31,6 @@ class ScopeFilter implements FilterInterface
private const PREFIX = 'acp_work_action_filter_user_scope';
public function __construct(
- private readonly RollingDateConverter $rollingDateConverter,
protected TranslatorInterface $translator,
private readonly TranslatableStringHelper $translatableStringHelper
) {}
@@ -44,30 +44,13 @@ class ScopeFilter implements FilterInterface
{
$p = self::PREFIX;
- $qb
- ->leftJoin("acpw.referrers", "{$p}_user")
- ->leftJoin(
- UserScopeHistory::class,
- "{$p}_history",
- Expr\Join::WITH,
- $qb->expr()->eq("{$p}_history.user", "{$p}_user")
- )
- ->andWhere(
- $qb->expr()->andX(
- $qb->expr()->lte("{$p}_history.startDate", ":{$p}_at"),
- $qb->expr()->orX(
- $qb->expr()->isNull("{$p}_history.endDate"),
- $qb->expr()->gt("{$p}_history.endDate", ":{$p}_at")
- )
- )
- )
- ->andWhere(
- $qb->expr()->in("{$p}_history.scope", ":{$p}_scope")
- )
- ->setParameters([
- "{$p}_scope" => $data["scope"],
- "{$p}_at" => $this->rollingDateConverter->convert($data['scope_at'])
- ]);
+ $qb->andWhere(
+ 'EXISTS (SELECT 1 FROM ' . AccompanyingPeriodWorkReferrerHistory::class . " {$p}_ref_history
+ JOIN {$p}_ref_history.user {$p}_ref_history_user JOIN {$p}_ref_history_user.scopeHistories {$p}_scope_history
+ WHERE {$p}_ref_history.accompanyingPeriodWork = acpw AND {$p}_scope_history.scope IN (:{$p}_scope) AND {$p}_scope_history.startDate <= {$p}_ref_history.startDate
+ AND ({$p}_scope_history.endDate IS NULL or {$p}_scope_history.endDate >= {$p}_ref_history.startDate))"
+ )
+ ->setParameter("{$p}_scope", $data["scope"]);
}
public function applyOn()
@@ -86,10 +69,6 @@ class ScopeFilter implements FilterInterface
'multiple' => true,
'expanded' => true,
])
- ->add('scope_at', PickRollingDateType::class, [
- 'label' => 'export.filter.work.by_user_scope.Calc date',
- 'required' => true,
- ])
;
}
diff --git a/src/Bundle/ChillPersonBundle/Export/Helper/ListAccompanyingPeriodHelper.php b/src/Bundle/ChillPersonBundle/Export/Helper/ListAccompanyingPeriodHelper.php
index 7349c5457..1531b0489 100644
--- a/src/Bundle/ChillPersonBundle/Export/Helper/ListAccompanyingPeriodHelper.php
+++ b/src/Bundle/ChillPersonBundle/Export/Helper/ListAccompanyingPeriodHelper.php
@@ -15,6 +15,7 @@ use Chill\MainBundle\Entity\Address;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Export\Helper\DateTimeHelper;
use Chill\MainBundle\Export\Helper\ExportAddressHelper;
+use Chill\MainBundle\Export\Helper\UserHelper;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress;
@@ -59,8 +60,10 @@ final readonly class ListAccompanyingPeriodHelper
'scopes',
'socialIssues',
'acpCreatedAt',
+ 'acpCreatedBy_id',
'acpCreatedBy',
'acpUpdatedAt',
+ 'acpUpdatedBy_id',
'acpUpdatedBy',
];
@@ -75,6 +78,7 @@ final readonly class ListAccompanyingPeriodHelper
private SocialIssueRender $socialIssueRender,
private TranslatableStringHelperInterface $translatableStringHelper,
private TranslatorInterface $translator,
+ private UserHelper $userHelper,
) {}
public function getQueryKeys($data)
@@ -104,6 +108,7 @@ final readonly class ListAccompanyingPeriodHelper
return $this->translatableStringHelper->localize(json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR));
},
+ 'acpCreatedBy', 'acpUpdatedBy', 'referrer' => $this->userHelper->getLabel($key, $values, 'export.list.acp.' . $key),
'locationPersonName', 'requestorPerson' => function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.acp.' . $key;
@@ -204,11 +209,11 @@ final readonly class ListAccompanyingPeriodHelper
// add the field which are simple association
$qb
- ->leftJoin('acp.createdBy', "acp_created_by_t")
- ->addSelect('acp_created_by_t.label AS acpCreatedBy');
+ ->addSelect('IDENTITY(acp.createdBy) AS acpCreatedBy_id')
+ ->addSelect('JSON_BUILD_OBJECT(\'uid\', IDENTITY(acp.createdBy), \'d\', acp.createdAt) AS acpCreatedBy');
$qb
- ->leftJoin('acp.updatedBy', "acp_updated_by_t")
- ->addSelect('acp_updated_by_t.label AS acpUpdatedBy');
+ ->addSelect('IDENTITY(acp.updatedBy) AS acpUpdatedBy_id')
+ ->addSelect('JSON_BUILD_OBJECT(\'uid\', IDENTITY(acp.updatedBy), \'d\', acp.updatedAt) AS acpUpdatedBy');
foreach (['origin' => 'label', 'closingMotive' => 'name', 'job' => 'label', 'administrativeLocation' => 'name'] as $entity => $field) {
$qb
@@ -230,7 +235,7 @@ final readonly class ListAccompanyingPeriodHelper
// referree at date
$qb
- ->addSelect('referrer_t.label AS referrer')
+ ->addSelect('JSON_BUILD_OBJECT(\'uid\', IDENTITY(userHistory.user), \'d\', userHistory.startDate) AS referrer')
->addSelect('userHistory.startDate AS referrerSince')
->leftJoin('acp.userHistories', 'userHistory')
->leftJoin('userHistory.user', 'referrer_t')
diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationRepository.php
index 28cbca270..fb1bb4ffa 100644
--- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationRepository.php
+++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationRepository.php
@@ -12,6 +12,7 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Repository\AccompanyingPeriod;
use Chill\MainBundle\Entity\User;
+use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
@@ -91,7 +92,9 @@ class AccompanyingPeriodWorkEvaluationRepository implements ObjectRepository
$qb->expr()->gte(':now', $qb->expr()->diff('e.maxDate', 'e.warningInterval')),
$qb->expr()->orX(
$qb->expr()->eq('period.user', ':user'),
- $qb->expr()->isMemberOf(':user', 'work.referrers')
+ $qb->expr()->exists(
+ 'SELECT 1 FROM ' . AccompanyingPeriodWork::class . ' subw JOIN subw.referrersHistory subw_ref_history WHERE subw.id = work.id AND subw_ref_history.user = :user'
+ )
)
)
)
diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
index 04ce8928e..4cbbab9fc 100644
--- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
+++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php
@@ -132,10 +132,10 @@ final readonly class AccompanyingPeriodWorkRepository implements ObjectRepositor
// set limit and offset
$sql .= " ORDER BY
- CASE WHEN enddate IS NULL THEN '-infinity'::timestamp ELSE 'infinity'::timestamp END ASC,
- startdate DESC,
- enddate DESC,
- id DESC";
+ CASE WHEN w.enddate IS NULL THEN '-infinity'::timestamp ELSE 'infinity'::timestamp END ASC,
+ w.startdate DESC,
+ w.enddate DESC,
+ w.id DESC";
$sql .= " LIMIT :limit OFFSET :offset";
@@ -239,7 +239,9 @@ final readonly class AccompanyingPeriodWorkRepository implements ObjectRepositor
$qb->expr()->lte('w.startDate', ':until'),
$qb->expr()->orX(
$qb->expr()->eq('period.user', ':user'),
- $qb->expr()->isMemberOf(':user', 'w.referrers')
+ $qb->expr()->exists(
+ 'SELECT 1 FROM ' . AccompanyingPeriodWork::class . ' subw JOIN subw.referrersHistory subw_ref_history WHERE subw.id = w.id AND subw_ref_history.user = :user and subw.ref_history.endDate IS NULL'
+ )
)
)
)
diff --git a/src/Bundle/ChillPersonBundle/Serializer/Normalizer/AccompanyingPeriodWorkNormalizer.php b/src/Bundle/ChillPersonBundle/Serializer/Normalizer/AccompanyingPeriodWorkNormalizer.php
index f6faeed12..86e94f52e 100644
--- a/src/Bundle/ChillPersonBundle/Serializer/Normalizer/AccompanyingPeriodWorkNormalizer.php
+++ b/src/Bundle/ChillPersonBundle/Serializer/Normalizer/AccompanyingPeriodWorkNormalizer.php
@@ -37,7 +37,7 @@ class AccompanyingPeriodWorkNormalizer implements ContextAwareNormalizerInterfac
*
* @throws ExceptionInterface
*/
- public function normalize($object, ?string $format = null, array $context = []): array|\ArrayObject|bool|float|int|string|null
+ public function normalize($object, ?string $format = null, array $context = []): null|array|\ArrayObject|bool|float|int|string
{
$initial = $this->normalizer->normalize($object, $format, array_merge(
$context,
diff --git a/src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkEndQueryPartForAccompanyingPeriodInfo.php b/src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkEndQueryPartForAccompanyingPeriodInfo.php
index 8ba9b9640..f0b38b635 100644
--- a/src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkEndQueryPartForAccompanyingPeriodInfo.php
+++ b/src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkEndQueryPartForAccompanyingPeriodInfo.php
@@ -54,7 +54,7 @@ class AccompanyingPeriodWorkEndQueryPartForAccompanyingPeriodInfo implements Acc
public function getFromStatement(): string
{
return 'chill_person_accompanying_period_work w
- LEFT JOIN chill_person_accompanying_period_work_referrer cpapwr on w.id = cpapwr.accompanyingperiodwork_id';
+ LEFT JOIN chill_person_accompanying_period_work_referrer cpapwr ON w.id = cpapwr.accompanyingperiodwork_id AND daterange(cpapwr.startDate, cpapwr.endDate) @> w.endDate';
}
public function getWhereClause(): string
diff --git a/src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkEvaluationWarningDateQueryPartForAccompanyingPeriodInfo.php b/src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkEvaluationCreationQueryPartForAccompanyingPeriodInfo.php
similarity index 73%
rename from src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkEvaluationWarningDateQueryPartForAccompanyingPeriodInfo.php
rename to src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkEvaluationCreationQueryPartForAccompanyingPeriodInfo.php
index a71fe4d29..53b5e31ad 100644
--- a/src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkEvaluationWarningDateQueryPartForAccompanyingPeriodInfo.php
+++ b/src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkEvaluationCreationQueryPartForAccompanyingPeriodInfo.php
@@ -11,10 +11,11 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Service\EntityInfo\AccompanyingPeriodInfoQueryPart;
+use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
use Chill\PersonBundle\Service\EntityInfo\AccompanyingPeriodInfoUnionQueryPartInterface;
-class AccompanyingPeriodWorkEvaluationWarningDateQueryPartForAccompanyingPeriodInfo implements AccompanyingPeriodInfoUnionQueryPartInterface
+class AccompanyingPeriodWorkEvaluationCreationQueryPartForAccompanyingPeriodInfo implements AccompanyingPeriodInfoUnionQueryPartInterface
{
public function getAccompanyingPeriodIdColumn(): string
{
@@ -33,12 +34,12 @@ class AccompanyingPeriodWorkEvaluationWarningDateQueryPartForAccompanyingPeriodI
public function getUserIdColumn(): string
{
- return 'cpapwr.user_id';
+ return 'e.createdBy_id';
}
public function getDateTimeColumn(): string
{
- return 'e.maxDate';
+ return 'e.createdAt';
}
public function getMetadataColumn(): string
@@ -48,18 +49,18 @@ class AccompanyingPeriodWorkEvaluationWarningDateQueryPartForAccompanyingPeriodI
public function getDiscriminator(): string
{
- return 'accompanying_period_work_evaluation_max';
+ return 'accompanying_period_work_evaluation_creation';
}
public function getFromStatement(): string
{
return 'chill_person_accompanying_period_work_evaluation e
JOIN chill_person_accompanying_period_work cpapw ON cpapw.id = e.accompanyingperiodwork_id
- LEFT JOIN chill_person_accompanying_period_work_referrer cpapwr ON cpapw.id = cpapwr.accompanyingperiodwork_id';
+ LEFT JOIN chill_person_accompanying_period_work_referrer cpapwr ON cpapw.id = cpapwr.accompanyingperiodwork_id AND daterange(cpapwr.startDate, cpapwr.endDate) @> e.startDate';
}
public function getWhereClause(): string
{
- return 'e.maxDate IS NOT NULL';
+ return 'e.createdAt IS NOT NULL';
}
}
diff --git a/src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkEvaluationMaxQueryPartForAccompanyingPeriodInfo.php b/src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkEvaluationMaxQueryPartForAccompanyingPeriodInfo.php
index b89f77460..843602249 100644
--- a/src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkEvaluationMaxQueryPartForAccompanyingPeriodInfo.php
+++ b/src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkEvaluationMaxQueryPartForAccompanyingPeriodInfo.php
@@ -56,7 +56,7 @@ class AccompanyingPeriodWorkEvaluationMaxQueryPartForAccompanyingPeriodInfo impl
{
return 'chill_person_accompanying_period_work_evaluation e
JOIN chill_person_accompanying_period_work cpapw ON cpapw.id = e.accompanyingperiodwork_id
- LEFT JOIN chill_person_accompanying_period_work_referrer cpapwr ON cpapw.id = cpapwr.accompanyingperiodwork_id';
+ LEFT JOIN chill_person_accompanying_period_work_referrer cpapwr ON cpapw.id = cpapwr.accompanyingperiodwork_id AND daterange(cpapwr.startDate, cpapwr.endDate) @> e.maxDate';
}
public function getWhereClause(): string
diff --git a/src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkEvaluationStartQueryPartForAccompanyingPeriodInfo.php b/src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkEvaluationStartQueryPartForAccompanyingPeriodInfo.php
index 8ea3e579c..cc82fc9ab 100644
--- a/src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkEvaluationStartQueryPartForAccompanyingPeriodInfo.php
+++ b/src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkEvaluationStartQueryPartForAccompanyingPeriodInfo.php
@@ -56,11 +56,11 @@ class AccompanyingPeriodWorkEvaluationStartQueryPartForAccompanyingPeriodInfo im
{
return 'chill_person_accompanying_period_work_evaluation e
JOIN chill_person_accompanying_period_work cpapw ON cpapw.id = e.accompanyingperiodwork_id
- LEFT JOIN chill_person_accompanying_period_work_referrer cpapwr ON cpapw.id = cpapwr.accompanyingperiodwork_id';
+ LEFT JOIN chill_person_accompanying_period_work_referrer cpapwr ON cpapw.id = cpapwr.accompanyingperiodwork_id AND daterange(cpapwr.startDate, cpapwr.endDate) @> e.startDate';
}
public function getWhereClause(): string
{
- return '';
+ return 'e.startDate IS NOT NULL';
}
}
diff --git a/src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkNewReferrerQueryPartForAccompanyingPeriodInfo.php b/src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkNewReferrerQueryPartForAccompanyingPeriodInfo.php
new file mode 100644
index 000000000..2208c2975
--- /dev/null
+++ b/src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkNewReferrerQueryPartForAccompanyingPeriodInfo.php
@@ -0,0 +1,64 @@
+ w.startDate';
}
public function getWhereClause(): string
diff --git a/src/Bundle/ChillPersonBundle/Tests/Action/Remove/PersonMoveTest.php b/src/Bundle/ChillPersonBundle/Tests/Action/Remove/PersonMoveTest.php
index ce3d8a3d1..64826930f 100644
--- a/src/Bundle/ChillPersonBundle/Tests/Action/Remove/PersonMoveTest.php
+++ b/src/Bundle/ChillPersonBundle/Tests/Action/Remove/PersonMoveTest.php
@@ -24,6 +24,7 @@ use Chill\PersonBundle\Entity\Household\HouseholdMember;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\Relationships\Relation;
use Chill\PersonBundle\Entity\Relationships\Relationship;
+use Chill\PersonBundle\Repository\Person\PersonCenterHistoryInterface;
use Chill\PersonBundle\Repository\PersonRepository;
use Doctrine\DBAL\Connection;
use Doctrine\ORM\EntityManagerInterface;
@@ -44,6 +45,8 @@ class PersonMoveTest extends KernelTestCase
private CenterRepositoryInterface $centerRepository;
+ private PersonCenterHistoryInterface $personCenterHistory;
+
/**
* @var list
*/
@@ -56,6 +59,7 @@ class PersonMoveTest extends KernelTestCase
$this->personMoveManager = self::$container->get(PersonMoveManager::class);
$this->eventDispatcher = self::$container->get(EventDispatcherInterface::class);
$this->centerRepository = self::$container->get(CenterRepositoryInterface::class);
+ $this->personCenterHistory = self::$container->get(PersonCenterHistoryInterface::class);
}
public static function tearDownAfterClass(): void
@@ -146,18 +150,22 @@ class PersonMoveTest extends KernelTestCase
$personB = $this->em->find(Person::class, $personB->getId());
$message = 'Move persons with overlapping center histories';
- $this->em->refresh($personB);
-
self::assertCount(0, $personsByIdOfA);
self::assertNotNull($personB?->getId(), $message);
- $centerHistoriesB = $personB->getCenterHistory();
- $oldestDate = new \DateTimeImmutable('2023-01-01');
+ $centersHistories = $this->personCenterHistory->findBy(['person' => $personB]);
- $this->em->refresh($centerHistoriesB->first());
+ // compute the oldest center history
+ $oldestCenterHistory = null;
+ foreach ($centersHistories as $centerHistory) {
+ $this->em->refresh($centerHistory);
+ if (null === $oldestCenterHistory || ($oldestCenterHistory instanceof Person\PersonCenterHistory && $oldestCenterHistory->getStartDate() >= $centerHistory->getStartDate())) {
+ $oldestCenterHistory = $centerHistory;
+ }
+ }
- self::assertCount(2, $centerHistoriesB);
- self::assertEquals($oldestDate, $centerHistoriesB->first()->getStartDate());
+ self::assertCount(2, $centersHistories);
+ self::assertEquals('2023-01-01', $oldestCenterHistory?->getStartDate()->format('Y-m-d'));
self::$entitiesToDelete[] = [Person::class, $personA];
self::$entitiesToDelete[] = [Person::class, $personB];
@@ -218,11 +226,11 @@ class PersonMoveTest extends KernelTestCase
$this->em->persist($memberA);
$this->em->persist($memberB);
- self::$entitiesToDelete[] = [Person::class, $personA];
- self::$entitiesToDelete[] = [Person::class, $personB];
self::$entitiesToDelete[] = [HouseholdMember::class, $memberA];
self::$entitiesToDelete[] = [HouseholdMember::class, $memberB];
self::$entitiesToDelete[] = [Household::class, $household];
+ self::$entitiesToDelete[] = [Person::class, $personA];
+ self::$entitiesToDelete[] = [Person::class, $personB];
yield [$personA, $personB, "move 2 people having the same household at the same time"];
diff --git a/src/Bundle/ChillPersonBundle/Tests/Controller/AccompanyingCourseApiControllerTest.php b/src/Bundle/ChillPersonBundle/Tests/Controller/AccompanyingCourseApiControllerTest.php
index 64b78f49e..4f2d19f54 100644
--- a/src/Bundle/ChillPersonBundle/Tests/Controller/AccompanyingCourseApiControllerTest.php
+++ b/src/Bundle/ChillPersonBundle/Tests/Controller/AccompanyingCourseApiControllerTest.php
@@ -52,16 +52,6 @@ final class AccompanyingCourseApiControllerTest extends WebTestCase
private ?int $personId = null;
- private KernelBrowser $client;
-
- /**
- * Setup before each test method (see phpunit doc).
- */
- protected function setUp(): void
- {
- $this->client = $this->getClientAuthenticated();
- }
-
protected function tearDown(): void
{
self::ensureKernelShutdown();
@@ -427,8 +417,9 @@ final class AccompanyingCourseApiControllerTest extends WebTestCase
*/
public function testAccompanyingCourseShow(int $personId, int $periodId)
{
- $c = $this->client->request(Request::METHOD_GET, sprintf('/api/1.0/person/accompanying-course/%d.json', $periodId));
- $response = $this->client->getResponse();
+ $client = $this->getClientAuthenticated();
+ $client->request(Request::METHOD_GET, sprintf('/api/1.0/person/accompanying-course/%d.json', $periodId));
+ $response = $client->getResponse();
$this->assertTrue(in_array($response->getStatusCode(), [200, 422], true));
@@ -548,12 +539,13 @@ final class AccompanyingCourseApiControllerTest extends WebTestCase
*/
public function testReferralAvailable(int $personId, int $periodId)
{
- $this->client->request(
+ $client = $this->getClientAuthenticated();
+ $client->request(
Request::METHOD_POST,
sprintf('/api/1.0/person/accompanying-course/%d/referrers-suggested.json', $periodId)
);
- $this->assertTrue(in_array($this->client->getResponse()->getStatusCode(), [200, 422], true));
+ $this->assertTrue(in_array($client->getResponse()->getStatusCode(), [200, 422], true));
}
/**
@@ -732,8 +724,9 @@ final class AccompanyingCourseApiControllerTest extends WebTestCase
public function testShow404()
{
- $this->client->request(Request::METHOD_GET, sprintf('/api/1.0/person/accompanying-course/%d.json', 99999));
- $response = $this->client->getResponse();
+ $client = $this->getClientAuthenticated();
+ $client->request(Request::METHOD_GET, sprintf('/api/1.0/person/accompanying-course/%d.json', 99999));
+ $response = $client->getResponse();
$this->assertEquals(404, $response->getStatusCode(), "Test that the response of rest api has a status code 'not found' (404)");
}
diff --git a/src/Bundle/ChillPersonBundle/Tests/Controller/HouseholdApiControllerTest.php b/src/Bundle/ChillPersonBundle/Tests/Controller/HouseholdApiControllerTest.php
index 2e1c58c64..e98539de5 100644
--- a/src/Bundle/ChillPersonBundle/Tests/Controller/HouseholdApiControllerTest.php
+++ b/src/Bundle/ChillPersonBundle/Tests/Controller/HouseholdApiControllerTest.php
@@ -137,20 +137,17 @@ final class HouseholdApiControllerTest extends WebTestCase
$qb = self::$container->get(EntityManagerInterface::class)
->createQueryBuilder();
- $period = $qb
- ->select('ap')
- ->from(AccompanyingPeriod::class, 'ap')
+ $personIds = $qb
+ ->select("p.id AS pid")
+ ->from(Person::class, 'p')
->where(
- $qb->expr()->gte('SIZE(ap.participations)', 2)
+ $qb->expr()->gte('SIZE(p.accompanyingPeriodParticipations)', 2)
)
->getQuery()
->setMaxResults(1)
->getSingleResult();
- $person = $period->getParticipations()
- ->first()->getPerson();
-
- yield [$person->getId()];
+ yield [$personIds['pid']];
self::ensureKernelShutdown();
}
diff --git a/src/Bundle/ChillPersonBundle/Tests/Entity/AccompanyingPeriod/AccompanyingPeriodWorkTest.php b/src/Bundle/ChillPersonBundle/Tests/Entity/AccompanyingPeriod/AccompanyingPeriodWorkTest.php
new file mode 100644
index 000000000..6771b0305
--- /dev/null
+++ b/src/Bundle/ChillPersonBundle/Tests/Entity/AccompanyingPeriod/AccompanyingPeriodWorkTest.php
@@ -0,0 +1,96 @@
+getReferrers());
+
+ $work->addReferrer($userA);
+
+ self::assertCount(1, $work->getReferrers());
+ self::assertContains($userA, $work->getReferrers());
+
+ $work->addReferrer($userB);
+
+ self::assertCount(2, $work->getReferrers());
+ self::assertContains($userA, $work->getReferrers());
+ self::assertContains($userB, $work->getReferrers());
+
+ $work->addReferrer($userC);
+ $work->removeReferrer($userB);
+
+ self::assertCount(2, $work->getReferrers());
+ self::assertContains($userA, $work->getReferrers());
+ self::assertNotContains($userB, $work->getReferrers());
+ self::assertContains($userC, $work->getReferrers());
+
+ $work->removeReferrer($userA);
+ self::assertNotContains($userA, $work->getReferrers());
+ self::assertNotContains($userB, $work->getReferrers());
+ self::assertContains($userC, $work->getReferrers());
+ }
+
+ public function testReferrerHistoryOnDifferentDays(): void
+ {
+
+ $work = new AccompanyingPeriodWork();
+ $userA = new User();
+ $userB = new User();
+ $userC = new User();
+
+ $work->addReferrer($userA);
+
+ $historyA = $work->getReferrersHistory()->first();
+ $reflection = new \ReflectionClass($historyA);
+ $startDateReflection = $reflection->getProperty('startDate');
+ $startDateReflection->setAccessible(true);
+ $startDateReflection->setValue($historyA, new \DateTimeImmutable('1 year ago'));
+
+ $work->addReferrer($userB);
+ $work->addReferrer($userC);
+
+ $work->removeReferrer($userB);
+ $work->removeReferrer($userA);
+
+ self::assertCount(1, $work->getReferrers());
+ self::assertNotContains($userA, $work->getReferrers());
+ self::assertNotContains($userB, $work->getReferrers());
+ self::assertContains($userC, $work->getReferrers());
+
+ self::assertCount(2, $work->getReferrersHistory());
+
+ $historyA = $work->getReferrersHistory()
+ ->filter(fn (AccompanyingPeriodWorkReferrerHistory $h) => $userA === $h->getUser())
+ ->first();
+
+ self::assertNotFalse($historyA);
+ self::assertSame($userA, $historyA->getUser());
+ self::assertEquals((new \DateTimeImmutable())->format('Y-m-d'), $historyA->getEndDate()->format('Y-m-d'));
+ }
+}
diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/JobAggregatorTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/JobAggregatorTest.php
index 5a20fc3b1..dfd6db053 100644
--- a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/JobAggregatorTest.php
+++ b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/JobAggregatorTest.php
@@ -40,9 +40,7 @@ final class JobAggregatorTest extends AbstractAggregatorTest
public function getFormData(): array
{
return [
- [
- 'job_at' => new RollingDate(RollingDate::T_FIXED_DATE, \DateTimeImmutable::createFromFormat('Y-m-d', '2020-01-01')),
- ],
+ [],
];
}
@@ -57,7 +55,6 @@ final class JobAggregatorTest extends AbstractAggregatorTest
->select('count(acp.id)')
->from(AccompanyingPeriod::class, 'acp')
->join('acp.works', 'acpw')
- ->join('acpw.referrers', 'acpwuser'),
];
}
}
diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/ReferrerAggregatorTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/ReferrerAggregatorTest.php
index 21f185469..19ca8b615 100644
--- a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/ReferrerAggregatorTest.php
+++ b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/ReferrerAggregatorTest.php
@@ -11,6 +11,7 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Tests\Export\Aggregator\SocialWorkAggregators;
+use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
use Chill\PersonBundle\Export\Aggregator\SocialWorkAggregators\ReferrerAggregator;
@@ -39,7 +40,10 @@ final class ReferrerAggregatorTest extends AbstractAggregatorTest
public function getFormData(): array
{
return [
- [],
+ [], // there are previous saved export which does not contains any data
+ [
+ 'referrer_at' => new RollingDate(RollingDate::T_TODAY)
+ ]
];
}
diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/ScopeAggregatorTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/ScopeAggregatorTest.php
index 0bb9fba13..3cd8c93fe 100644
--- a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/ScopeAggregatorTest.php
+++ b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/ScopeAggregatorTest.php
@@ -40,9 +40,7 @@ final class ScopeAggregatorTest extends AbstractAggregatorTest
public function getFormData(): array
{
return [
- [
- 'scope_at' => new RollingDate(RollingDate::T_FIXED_DATE, \DateTimeImmutable::createFromFormat('Y-m-d', '2020-01-01')),
- ],
+ [],
];
}
@@ -57,7 +55,6 @@ final class ScopeAggregatorTest extends AbstractAggregatorTest
->select('count(acp.id)')
->from(AccompanyingPeriod::class, 'acp')
->join('acp.works', 'acpw')
- ->join('acpw.referrers', 'acpwuser'),
];
}
}
diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListAccompanyingPeriodTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListAccompanyingPeriodTest.php
new file mode 100644
index 000000000..24a49bab3
--- /dev/null
+++ b/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListAccompanyingPeriodTest.php
@@ -0,0 +1,53 @@
+listAccompanyingPeriod = self::$container->get(ListAccompanyingPeriod::class);
+ $this->centerRepository = self::$container->get(CenterRepositoryInterface::class);
+ }
+
+ public function testQuery(): void
+ {
+ $centers = $this->centerRepository->findAll();
+
+ $query = $this->listAccompanyingPeriod->initiateQuery([], array_map(fn (Center $c) => ['center' => $c ], $centers), $exportOpts = ['calc_date' => new RollingDate(RollingDate::T_TODAY)]);
+
+ $query->setMaxResults(1);
+
+ $actual = $query->getQuery()->getResult(AbstractQuery::HYDRATE_ARRAY);
+
+ self::assertIsArray($actual);
+ }
+}
diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListAccompanyingPeriodWorkTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListAccompanyingPeriodWorkTest.php
new file mode 100644
index 000000000..3467f15a7
--- /dev/null
+++ b/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListAccompanyingPeriodWorkTest.php
@@ -0,0 +1,49 @@
+listAccompanyingPeriodWork = self::$container->get(ListAccompanyingPeriodWork::class);
+ $this->centerRepository = self::$container->get(CenterRepositoryInterface::class);
+ }
+
+ public function testQuery(): void
+ {
+ $centers = $this->centerRepository->findAll();
+
+ $query = $this->listAccompanyingPeriodWork->initiateQuery([], array_map(fn (Center $c) => ['center' => $c], $centers), ['calc_date' => new RollingDate(RollingDate::T_TODAY)]);
+ $query->setMaxResults(1);
+
+ self::assertIsArray($query->getQuery()->getResult(AbstractQuery::HYDRATE_ARRAY));
+ }
+}
diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListEvaluationTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListEvaluationTest.php
new file mode 100644
index 000000000..d7db24a82
--- /dev/null
+++ b/src/Bundle/ChillPersonBundle/Tests/Export/Export/ListEvaluationTest.php
@@ -0,0 +1,49 @@
+listEvaluation = self::$container->get(ListEvaluation::class);
+ $this->centerRepository = self::$container->get(CenterRepositoryInterface::class);
+ }
+
+ public function testQuery(): void
+ {
+ $centers = $this->centerRepository->findAll();
+
+ $query = $this->listEvaluation->initiateQuery([], array_map(fn (Center $c) => ['center' => $c], $centers), ['calc_date' => new RollingDate(RollingDate::T_TODAY)]);
+ $query->setMaxResults(1);
+
+ self::assertIsArray($query->getQuery()->getResult(AbstractQuery::HYDRATE_ARRAY));
+ }
+}
diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/JobFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/JobFilterTest.php
index f5836c18c..e8ed85ad4 100644
--- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/JobFilterTest.php
+++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/JobFilterTest.php
@@ -51,7 +51,6 @@ final class JobFilterTest extends AbstractFilterTest
return [
[
'job' => new ArrayCollection($jobs),
- 'job_at' => new RollingDate(RollingDate::T_FIXED_DATE, \DateTimeImmutable::createFromFormat('Y-m-d', '2020-01-01'))
]
];
}
diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ReferrerFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ReferrerFilterTest.php
index 68fab1250..a77c6d9c9 100644
--- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ReferrerFilterTest.php
+++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ReferrerFilterTest.php
@@ -12,6 +12,7 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Tests\Export\Filter\SocialWorkFilters;
use Chill\MainBundle\Entity\User;
+use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Test\Export\AbstractFilterTest;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Export\Filter\SocialWorkFilters\ReferrerFilter;
@@ -47,8 +48,13 @@ final class ReferrerFilterTest extends AbstractFilterTest
$data = [];
foreach ($users as $u) {
+ $data[] = [
+ 'accepted_agents' => $u, // some saved export does not have the parameter "agent_at"
+ ];
+
$data[] = [
'accepted_agents' => $u,
+ 'agent_at' => new RollingDate(RollingDate::T_TODAY)
];
}
diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ScopeFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ScopeFilterTest.php
index f2ffce2e4..c3e29f71e 100644
--- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ScopeFilterTest.php
+++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ScopeFilterTest.php
@@ -50,7 +50,6 @@ final class ScopeFilterTest extends AbstractFilterTest
return [
[
'scope' => $scopes,
- 'scope_at' => new RollingDate(RollingDate::T_FIXED_DATE, \DateTimeImmutable::createFromFormat('Y-m-d', '2020-01-01'))
]
];
}
diff --git a/src/Bundle/ChillPersonBundle/Tests/Repository/AccompanyingPeriodACLAwareRepositoryTest.php b/src/Bundle/ChillPersonBundle/Tests/Repository/AccompanyingPeriodACLAwareRepositoryTest.php
index 050a839e6..83335c02a 100644
--- a/src/Bundle/ChillPersonBundle/Tests/Repository/AccompanyingPeriodACLAwareRepositoryTest.php
+++ b/src/Bundle/ChillPersonBundle/Tests/Repository/AccompanyingPeriodACLAwareRepositoryTest.php
@@ -518,7 +518,7 @@ class AccompanyingPeriodACLAwareRepositoryTest extends KernelTestCase
/**
* @param array $scopes
*/
- private function buildPeriod(Person $person, array $scopes, User|null $creator, bool $confirm): AccompanyingPeriod
+ private function buildPeriod(Person $person, array $scopes, null|User $creator, bool $confirm): AccompanyingPeriod
{
$period = new AccompanyingPeriod();
$period->addPerson($person);
diff --git a/src/Bundle/ChillPersonBundle/Tests/Repository/UserRepositoryTest.php b/src/Bundle/ChillPersonBundle/Tests/Repository/UserRepositoryTest.php
new file mode 100644
index 000000000..5a99b8e4c
--- /dev/null
+++ b/src/Bundle/ChillPersonBundle/Tests/Repository/UserRepositoryTest.php
@@ -0,0 +1,44 @@
+userRepository = self::$container->get(UserRepository::class);
+ }
+
+ public function testFindAllAsArray(): void
+ {
+ $userIterator = $this->userRepository->findAllAsArray('fr');
+
+ self::assertIsIterable($userIterator);
+ $i = 0;
+ foreach ($userIterator as $u) {
+ self::assertIsArray($u);
+ $i++;
+ }
+ self::assertGreaterThan(0, $i);
+ }
+}
diff --git a/src/Bundle/ChillPersonBundle/translations/messages+intl-icu.fr.yaml b/src/Bundle/ChillPersonBundle/translations/messages+intl-icu.fr.yaml
index 250bca9c7..a8d2080fb 100644
--- a/src/Bundle/ChillPersonBundle/translations/messages+intl-icu.fr.yaml
+++ b/src/Bundle/ChillPersonBundle/translations/messages+intl-icu.fr.yaml
@@ -135,7 +135,11 @@ exports:
by_person:
Filtered by person\'s geographical unit (based on address) computed at date, only units:
"Filtré par zone géographique sur base de l'adresse, calculé à {datecalc, date, short}, seulement les zones suivantes: {units}"
-
+ filter:
+ work:
+ by_treating_agent:
+ Filtered by treating agent at date: >-
+ Les agents traitant au { agent_at, date, medium }, seulement {agents}
'total persons matching the search pattern': >-
{ total, plural,
=0 {Aucun usager ne correspond aux termes de recherche}
diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml
index 639de0443..e142e0f8e 100644
--- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml
+++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml
@@ -588,10 +588,6 @@ Filter by current evaluations: Filtrer les évaluations en cours
## social actions filters/aggr
Filter by scope: Filtrer par service
-Filter by treating agent: Filtrer les actions par agent traitant
-Accepted agents: Agent traitant
-"Filtered by treating agent: only %agents%": "Filtré par agent traitant: uniquement %agents%"
-Group by treating agent: Grouper les actions par agent traitant
Group social work actions by action type: Grouper les actions par type
Group social work actions by goal: Grouper les actions par objectif
@@ -1040,6 +1036,9 @@ export:
Group course by scope: Grouper les parcours par service
course_work:
+ by_treating_agent:
+ Calc date: Référent à la date
+ Group by treating agent: Grouper les actions par agent traitant
by_current_action:
Current action ?: Action en cours ?
Group by current actions: Grouper les actions en cours
@@ -1160,6 +1159,12 @@ export:
Filter by treating agent scope: Filtrer les actions par service de l'agent traitant
"Filtered by treating agent scope: only %scopes%": "Filtré par service de l'agent traitant: uniquement %scopes%"
Calc date: Date de calcul du service de l'agent traitant
+ by_treating_agent:
+ Filter by treating agent: Filtrer les actions par agent traitant
+ Accepted agents: Agent traitant
+ Calc date: Date à laquelle l'agent est en situation de désignation sur l'action
+ calc_date_help: Il s'agit de la date à laquelle l'agent est actif comme agent traitant de l'action, et non la date à la quelle l'agent est désigné comme agent traitant.
+ "Filtered by treating agent: only %agents%": "Filtré par agent traitant: uniquement %agents%"
list:
person_with_acp:
@@ -1187,7 +1192,9 @@ export:
origin: Origine du parcours
acpClosingMotive: Motif de fermeture
acpJob: Métier du parcours
+ acpCreatedBy_id: Créé par (identifiant)
acpCreatedBy: Créé par
+ acpUpdatedBy_id: Dernière modificaton par (identifiant)
acpUpdatedBy: Dernière modification par
administrativeLocation: Location administrative
step: Etape
diff --git a/src/Bundle/ChillReportBundle/DataFixtures/ORM/LoadReports.php b/src/Bundle/ChillReportBundle/DataFixtures/ORM/LoadReports.php
index 80c1edd87..3593b612c 100644
--- a/src/Bundle/ChillReportBundle/DataFixtures/ORM/LoadReports.php
+++ b/src/Bundle/ChillReportBundle/DataFixtures/ORM/LoadReports.php
@@ -165,7 +165,7 @@ final class LoadReports extends AbstractFixture implements OrderedFixtureInterfa
*
* @return string|string[]
*/
- private function getRandomChoice(CustomField $field): string|array
+ private function getRandomChoice(CustomField $field): array|string
{
$choices = $field->getOptions()['choices'];
$multiple = $field->getOptions()['multiple'];
diff --git a/src/Bundle/ChillTaskBundle/Security/Authorization/AuthorizationEvent.php b/src/Bundle/ChillTaskBundle/Security/Authorization/AuthorizationEvent.php
index 203963d80..de8b52c4c 100644
--- a/src/Bundle/ChillTaskBundle/Security/Authorization/AuthorizationEvent.php
+++ b/src/Bundle/ChillTaskBundle/Security/Authorization/AuthorizationEvent.php
@@ -27,7 +27,7 @@ class AuthorizationEvent extends \Symfony\Contracts\EventDispatcher\Event
protected $vote;
public function __construct(
- private readonly Person|AbstractTask|AccompanyingPeriod|null $subject,
+ private readonly null|AbstractTask|AccompanyingPeriod|Person $subject,
private readonly string $attribute,
private readonly TokenInterface $token
) {}
diff --git a/src/Bundle/ChillWopiBundle/src/Controller/Convert.php b/src/Bundle/ChillWopiBundle/src/Controller/Convert.php
index 665386ffe..c4702c2b2 100644
--- a/src/Bundle/ChillWopiBundle/src/Controller/Convert.php
+++ b/src/Bundle/ChillWopiBundle/src/Controller/Convert.php
@@ -78,7 +78,7 @@ class Convert
return new Response($response->getContent(), Response::HTTP_OK, [
'Content-Type' => 'application/pdf',
]);
- } catch (ClientExceptionInterface|TransportExceptionInterface|RedirectionExceptionInterface|ServerExceptionInterface $exception) {
+ } catch (ClientExceptionInterface|RedirectionExceptionInterface|ServerExceptionInterface|TransportExceptionInterface $exception) {
return $this->onConversionFailed($url, $exception->getResponse());
}
}