From d47e6c5ba133a1b60caffea7a2718bbeb4ac361d Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 12 Sep 2023 15:55:08 +0200 Subject: [PATCH 01/62] add new entities UserScopeHistory and UserJobHistory --- .../Entity/User/UserJobHistory.php | 107 ++++++++++++++++++ .../Entity/User/UserScopeHistory.php | 107 ++++++++++++++++++ .../User/UserJobHistoryRepository.php | 51 +++++++++ .../User/UserScopeHistoryRepository.php | 51 +++++++++ 4 files changed, 316 insertions(+) create mode 100644 src/Bundle/ChillMainBundle/Entity/User/UserJobHistory.php create mode 100644 src/Bundle/ChillMainBundle/Entity/User/UserScopeHistory.php create mode 100644 src/Bundle/ChillMainBundle/Repository/User/UserJobHistoryRepository.php create mode 100644 src/Bundle/ChillMainBundle/Repository/User/UserScopeHistoryRepository.php diff --git a/src/Bundle/ChillMainBundle/Entity/User/UserJobHistory.php b/src/Bundle/ChillMainBundle/Entity/User/UserJobHistory.php new file mode 100644 index 000000000..233a48e2a --- /dev/null +++ b/src/Bundle/ChillMainBundle/Entity/User/UserJobHistory.php @@ -0,0 +1,107 @@ +endDate; + } + + public function getId(): ?int + { + return $this->id; + } + + public function getJob(): ?UserJob + { + return $this->job; + } + + public function getStartDate(): ?DateTimeImmutable + { + return $this->startDate; + } + + public function getUser(): User + { + return $this->user; + } + + public function setEndDate(?DateTimeImmutable $endDate): self + { + $this->endDate = $endDate; + + return $this; + } + + public function setJob(?UserJob $job): UserJobHistory + { + $this->job = $job; + + return $this; + } + + public function setStartDate(DateTimeImmutable $startDate): self + { + $this->startDate = $startDate; + + return $this; + } + + public function setUser(User $user): UserJobHistory + { + $this->user = $user; + + return $this; + } + +} diff --git a/src/Bundle/ChillMainBundle/Entity/User/UserScopeHistory.php b/src/Bundle/ChillMainBundle/Entity/User/UserScopeHistory.php new file mode 100644 index 000000000..3c4d28d4f --- /dev/null +++ b/src/Bundle/ChillMainBundle/Entity/User/UserScopeHistory.php @@ -0,0 +1,107 @@ +endDate; + } + + public function getId(): ?int + { + return $this->id; + } + + public function getScope(): ?Scope + { + return $this->scope; + } + + public function getStartDate(): ?DateTimeImmutable + { + return $this->startDate; + } + + public function getUser(): User + { + return $this->user; + } + + public function setEndDate(?DateTimeImmutable $endDate): self + { + $this->endDate = $endDate; + + return $this; + } + + public function setScope(?Scope $scope): UserScopeHistory + { + $this->scope = $scope; + + return $this; + } + + public function setStartDate(DateTimeImmutable $startDate): self + { + $this->startDate = $startDate; + + return $this; + } + + public function setUser(User $user): UserScopeHistory + { + $this->user = $user; + + return $this; + } + +} diff --git a/src/Bundle/ChillMainBundle/Repository/User/UserJobHistoryRepository.php b/src/Bundle/ChillMainBundle/Repository/User/UserJobHistoryRepository.php new file mode 100644 index 000000000..a66575e3b --- /dev/null +++ b/src/Bundle/ChillMainBundle/Repository/User/UserJobHistoryRepository.php @@ -0,0 +1,51 @@ +_em->persist($entity); + if ($flush) { + $this->_em->flush(); + } + } + + /** + * @throws ORMException + * @throws OptimisticLockException + */ + public function remove(UserJobHistory $entity, bool $flush = true): void + { + $this->_em->remove($entity); + if ($flush) { + $this->_em->flush(); + } + } + +} diff --git a/src/Bundle/ChillMainBundle/Repository/User/UserScopeHistoryRepository.php b/src/Bundle/ChillMainBundle/Repository/User/UserScopeHistoryRepository.php new file mode 100644 index 000000000..aa6738870 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Repository/User/UserScopeHistoryRepository.php @@ -0,0 +1,51 @@ +_em->persist($entity); + if ($flush) { + $this->_em->flush(); + } + } + + /** + * @throws ORMException + * @throws OptimisticLockException + */ + public function remove(UserScopeHistory $entity, bool $flush = true): void + { + $this->_em->remove($entity); + if ($flush) { + $this->_em->flush(); + } + } + +} From bebc746d570dc19bf20e4728aa293c2e632e1f42 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 13 Sep 2023 13:52:42 +0200 Subject: [PATCH 02/62] migration for UserScopeHistory and UserJobHistory --- .../migrations/Version20230711152947.php | 2 +- .../migrations/Version20230913114115.php | 105 ++++++++++++++++++ 2 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 src/Bundle/ChillMainBundle/migrations/Version20230913114115.php diff --git a/src/Bundle/ChillMainBundle/migrations/Version20230711152947.php b/src/Bundle/ChillMainBundle/migrations/Version20230711152947.php index ed804473e..d11a9f78a 100644 --- a/src/Bundle/ChillMainBundle/migrations/Version20230711152947.php +++ b/src/Bundle/ChillMainBundle/migrations/Version20230711152947.php @@ -18,7 +18,7 @@ final class Version20230711152947 extends AbstractMigration { public function getDescription(): string { - return 'Add data to '; + return 'Add last execution data to cronjon execution table'; } public function up(Schema $schema): void diff --git a/src/Bundle/ChillMainBundle/migrations/Version20230913114115.php b/src/Bundle/ChillMainBundle/migrations/Version20230913114115.php new file mode 100644 index 000000000..2ef12dd7d --- /dev/null +++ b/src/Bundle/ChillMainBundle/migrations/Version20230913114115.php @@ -0,0 +1,105 @@ +addSql('ALTER TABLE chill_main_user_job_history DROP CONSTRAINT user_job_history_endate_null_or_after_startdate'); + $this->addSql('ALTER TABLE chill_main_user_job_history DROP CONSTRAINT user_job_history_not_overlaps'); + $this->addSql('DROP SEQUENCE chill_main_user_job_history_id_seq CASCADE'); + $this->addSql('ALTER TABLE chill_main_user_job_history DROP CONSTRAINT FK_4E3BF4DDBE04EA9'); + $this->addSql('ALTER TABLE chill_main_user_job_history DROP CONSTRAINT FK_4E3BF4DDA76ED395'); + $this->addSql('DROP TABLE chill_main_user_job_history'); + + // drop scope_history + $this->addSql('ALTER TABLE chill_main_user_scope_history DROP CONSTRAINT user_scope_history_endate_null_or_after_startdate'); + $this->addSql('ALTER TABLE chill_main_user_scope_history DROP CONSTRAINT user_scope_history_not_overlaps'); + $this->addSql('DROP SEQUENCE chill_main_user_scope_history_id_seq CASCADE'); + $this->addSql('ALTER TABLE chill_main_user_scope_history DROP CONSTRAINT FK_48B969D7682B5931'); + $this->addSql('ALTER TABLE chill_main_user_scope_history DROP CONSTRAINT FK_48B969D7A76ED395'); + $this->addSql('DROP TABLE chill_main_user_scope_history'); + } + + public function getDescription(): string + { + return 'Add new entities UserScopeHistory and UserJobHistory'; + } + + public function up(Schema $schema): void + { + // create scope_history + $this->addSql('CREATE SEQUENCE chill_main_user_scope_history_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE TABLE chill_main_user_scope_history (' + . 'id INT NOT NULL,' + . 'scope_id INT DEFAULT NULL,' + . 'user_id INT DEFAULT NULL,' + . 'endDate TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL,' + . 'startDate TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,' + . 'PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_48B969D7682B5931 ON chill_main_user_scope_history (scope_id)'); + $this->addSql('CREATE INDEX IDX_48B969D7A76ED395 ON chill_main_user_scope_history (user_id)'); + $this->addSql('COMMENT ON COLUMN chill_main_user_scope_history.endDate IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_main_user_scope_history.startDate IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE chill_main_user_scope_history ADD CONSTRAINT FK_48B969D7682B5931 ' + . 'FOREIGN KEY (scope_id) REFERENCES scopes (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_main_user_scope_history ADD CONSTRAINT FK_48B969D7A76ED395 ' + . 'FOREIGN KEY (user_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_main_user_scope_history ' + . 'ADD CONSTRAINT user_scope_history_not_overlaps ' + . 'EXCLUDE USING GIST (user_id with =, tsrange(startDate, endDate) with &&) ' + . 'DEFERRABLE INITIALLY DEFERRED'); + $this->addSql('ALTER TABLE chill_main_user_scope_history ' + . 'ADD CONSTRAINT user_scope_history_endate_null_or_after_startdate ' + . 'CHECK (startDate <= endDate OR endDate IS NULL)'); + + // insert user scope_history datas + $this->addSql('INSERT INTO chill_main_user_scope_history (id, startDate, endDate, user_id, scope_id) ' + . 'SELECT nextval(\'chill_main_user_scope_history_id_seq\'), \'1970-01-01\'::date, NULL, users.id, mainscope_id ' + . 'FROM users'); + + // create job_history + $this->addSql('CREATE SEQUENCE chill_main_user_job_history_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE TABLE chill_main_user_job_history (' + . 'id INT NOT NULL,' + . 'job_id INT DEFAULT NULL,' + . 'user_id INT DEFAULT NULL,' + . 'endDate TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL,' + . 'startDate TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,' + . 'PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_4E3BF4DDBE04EA9 ON chill_main_user_job_history (job_id)'); + $this->addSql('CREATE INDEX IDX_4E3BF4DDA76ED395 ON chill_main_user_job_history (user_id)'); + $this->addSql('COMMENT ON COLUMN chill_main_user_job_history.endDate IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_main_user_job_history.startDate IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE chill_main_user_job_history ADD CONSTRAINT FK_4E3BF4DDBE04EA9 ' + . 'FOREIGN KEY (job_id) REFERENCES chill_main_user_job (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_main_user_job_history ADD CONSTRAINT FK_4E3BF4DDA76ED395 ' + . 'FOREIGN KEY (user_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_main_user_job_history ' + . 'ADD CONSTRAINT user_job_history_not_overlaps ' + . 'EXCLUDE USING GIST (user_id with =, tsrange(startDate, endDate) with &&) ' + . 'DEFERRABLE INITIALLY DEFERRED'); + $this->addSql('ALTER TABLE chill_main_user_job_history ' + . 'ADD CONSTRAINT user_job_history_endate_null_or_after_startdate ' + . 'CHECK (startDate <= endDate OR endDate IS NULL)'); + + // insert user job_history datas + $this->addSql('INSERT INTO chill_main_user_job_history (id, startDate, endDate, user_id, job_id) ' + . 'SELECT nextval(\'chill_main_user_job_history_id_seq\'), \'1970-01-01\'::date, NULL, users.id, userjob_id ' + . 'FROM users'); + } +} From 096fb6219fba6309fd67ddeab646be45b08e53d7 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Thu, 14 Sep 2023 15:52:20 +0200 Subject: [PATCH 03/62] adapt User Entity to get/set MainScope and UserJob with Histories Collection --- src/Bundle/ChillMainBundle/Entity/User.php | 116 ++++++++++++++++++--- 1 file changed, 104 insertions(+), 12 deletions(-) diff --git a/src/Bundle/ChillMainBundle/Entity/User.php b/src/Bundle/ChillMainBundle/Entity/User.php index 8cb45cd57..9656cb3e6 100644 --- a/src/Bundle/ChillMainBundle/Entity/User.php +++ b/src/Bundle/ChillMainBundle/Entity/User.php @@ -11,10 +11,14 @@ declare(strict_types=1); namespace Chill\MainBundle\Entity; +use Chill\MainBundle\Entity\User\UserJobHistory; +use Chill\MainBundle\Entity\User\UserScopeHistory; use DateTimeImmutable; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; +use Doctrine\Common\Collections\Criteria; use Doctrine\ORM\Mapping as ORM; +use Iterator; use RuntimeException; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Serializer\Annotation as Serializer; @@ -113,9 +117,11 @@ class User implements UserInterface, \Stringable private ?Location $mainLocation = null; /** - * @ORM\ManyToOne(targetEntity=Scope::class) + * @var Collection + * @ORM\OneToMany(targetEntity=UserScopeHistory::class, + * mappedBy="user", cascade={"persist", "remove"}, orphanRemoval=true) */ - private ?Scope $mainScope = null; + private Collection $scopeHistories; /** * @ORM\Column(type="string", length=255) @@ -130,9 +136,11 @@ class User implements UserInterface, \Stringable private ?string $salt = null; /** - * @ORM\ManyToOne(targetEntity=UserJob::class) + * @var Collection + * @ORM\OneToMany(targetEntity=UserJobHistory::class, + * mappedBy="user", cascade={"persist", "remove"}, orphanRemoval=true) */ - private ?UserJob $userJob = null; + private Collection $jobHistories; /** * @ORM\Column(type="string", length=80) @@ -154,6 +162,8 @@ class User implements UserInterface, \Stringable public function __construct() { $this->groupCenters = new ArrayCollection(); + $this->scopeHistories = new ArrayCollection(); + $this->jobHistories = new ArrayCollection(); } /** @@ -252,9 +262,29 @@ class User implements UserInterface, \Stringable return $this->mainLocation; } - public function getMainScope(): ?Scope + public function getMainScope(?DateTimeImmutable $at = null): ?UserScopeHistory { - return $this->mainScope; + $at ??= new DateTimeImmutable('today'); + $criteria = new Criteria(); + $expr = Criteria::expr(); + + $criteria->where( + $expr->andX( + $expr->orX( + $expr->isNull('endDate'), + $expr->gt('endDate', $at) + ), + $expr->lte('startDate', $at) + ) + ); + + $scopes = $this->scopeHistories->matching($criteria); + + if ($scopes->count() > 0) { + return $scopes->first(); + } + + return null; } /** @@ -275,9 +305,28 @@ class User implements UserInterface, \Stringable return $this->salt; } - public function getUserJob(): ?UserJob + public function getUserJob(?DateTimeImmutable $at = null): ?UserJobHistory { - return $this->userJob; + $at ??= new DateTimeImmutable('today'); + $criteria = new Criteria(); + $expr = Criteria::expr(); + + $criteria->where( + $expr->andX( + $expr->orX( + $expr->isNull('endDate'), + $expr->gt('endDate', $at) + ), + $expr->lte('startDate') + ) + ); + + $jobs = $this->jobHistories->matching($criteria); + if ($jobs->count() > 0) { + return $jobs->first(); + } + + return null; } /** @@ -453,9 +502,31 @@ class User implements UserInterface, \Stringable return $this; } - public function setMainScope(?Scope $mainScope): User + public function setMainScope(UserScopeHistory $mainScope): User { - $this->mainScope = $mainScope; + if (!$this->scopeHistories->contains($mainScope)) { + $this->scopeHistories[] = $mainScope; + $mainScope->setUser($this); + } + + // ensure continuity of histories + $criteria = new Criteria(); + $criteria->orderBy(['startDate' => Criteria::ASC, 'id' => Criteria::ASC]); + + /** @var Iterator $scopes */ + $scopes = $this->getMainScope()->matching($criteria)->getIterator(); + $scopes->rewind(); + + do { + /** @var UserScopeHistory $current */ + $current = $scopes->current(); + $scopes->next(); + + if ($scopes->valid()) { + $next = $scopes->current(); + $current->setEndDate($next->getStartDate()); + } + } while ($scopes->valid()); return $this; } @@ -484,9 +555,30 @@ class User implements UserInterface, \Stringable return $this; } - public function setUserJob(?UserJob $userJob): User + public function setUserJob(UserJobHistory $userJob): User { - $this->userJob = $userJob; + if (!$this->jobHistories->contains($userJob)) { + $this->jobHistories[] = $userJob; + $userJob->setUser($this); + } + + $criteria = new Criteria(); + $criteria->orderBy(['startDate' => Criteria::ASC, 'id' => Criteria::ASC]); + + /** @var Iterator $jobs */ + $jobs = $this->getUserJob()->matching($criteria)->getIterator(); + $jobs->rewind(); + + do { + /** @var UserJobHistory $current */ + $current = $jobs->current(); + $jobs->next(); + + if ($jobs->valid()) { + $next = $jobs->current(); + $current->setEndDate($next->getStartDate()); + } + } while ($jobs->valid()); return $this; } From 124abf563eb62895bd125e018ea418d5624d0b5c Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 20 Sep 2023 12:24:27 +0200 Subject: [PATCH 04/62] Create twig templates for admin jobs/scopes histories --- .../ChillMainExtension.php | 28 +++++++++ .../Resources/views/Scope/history.html.twig | 59 +++++++++++++++++++ .../Resources/views/Scope/index.html.twig | 15 +++-- .../Resources/views/UserJob/history.html.twig | 59 +++++++++++++++++++ .../Resources/views/UserJob/index.html.twig | 5 +- .../translations/messages.fr.yml | 18 ++++++ 6 files changed, 177 insertions(+), 7 deletions(-) create mode 100644 src/Bundle/ChillMainBundle/Resources/views/Scope/history.html.twig create mode 100644 src/Bundle/ChillMainBundle/Resources/views/UserJob/history.html.twig diff --git a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php index 6760a798f..236848435 100644 --- a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php +++ b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php @@ -56,6 +56,8 @@ use Chill\MainBundle\Entity\Regroupment; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Form\CenterType; +use Chill\MainBundle\Entity\User\UserJobHistory; +use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Form\CivilityType; use Chill\MainBundle\Form\CountryType; use Chill\MainBundle\Form\LanguageType; @@ -371,6 +373,32 @@ class ChillMainExtension extends Extension implements ], ], ], + [ + 'class' => UserJobHistory::class, + //'controller' => UserJobHistoryController::class, + 'name' => 'admin_user_job_history', + 'base_path' => '/admin/main/user-job-history', + 'base_role' => 'ROLE_ADMIN', + 'actions' => [ + 'index' => [ + 'role' => 'ROLE_ADMIN', + 'template' => '@ChillMain/UserJob/history.html.twig', + ], + ], + ], + [ + 'class' => UserScopeHistory::class, + //'controller' => UserScopeHistoryController::class, + 'name' => 'admin_user_scope_history', + 'base_path' => '/admin/main/user-scope-history', + 'base_role' => 'ROLE_ADMIN', + 'actions' => [ + 'index' => [ + 'role' => 'ROLE_ADMIN', + 'template' => '@ChillMain/Scope/history.html.twig', + ], + ], + ], [ 'class' => User::class, 'controller' => UserController::class, diff --git a/src/Bundle/ChillMainBundle/Resources/views/Scope/history.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Scope/history.html.twig new file mode 100644 index 000000000..3c08620c7 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/Scope/history.html.twig @@ -0,0 +1,59 @@ +{% extends '@ChillMain/CRUD/Admin/index.html.twig' %} + +{% block admin_content %} + {% embed '@ChillMain/CRUD/_index.html.twig' %} + + {% block table_entities_thead_tr %} + {{ 'crud.admin_user_scope_history.index.start'|trans }} + {{ 'crud.admin_user_scope_history.index.end'|trans }} + {{ 'crud.admin_user_scope_history.index.user'|trans }} + {{ 'crud.admin_user_scope_history.index.scope'|trans }} + {% endblock %} + + {% block table_entities_tbody %} + {{ dump(entities) }} + {# + #} + {% for entity in entities %} + + + {# {{ dump(entity.id) }} #} + {{ entity.startDate|format_datetime('medium') }} + + {{ entity.endDate|format_datetime('medium') }} + + {% for scope in entity.scope %} + {# + #} + {{ dump(scope) }} + {{ scope.label|localize_translatable_string }} + {% endfor %} + + + {% for user in entity.user %} + {# + #} + {{ dump(user.id) }} + {{ user.usernameCanonical }} + {% endfor %} + + + {% endfor %} + {% endblock %} + + {% block actions_before %} +
  • + {{'Back to the admin'|trans }} +
  • + {% endblock %} + + {% block list_actions %} + + {% endblock %} + {% endembed %} +{% endblock %} + diff --git a/src/Bundle/ChillMainBundle/Resources/views/Scope/index.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Scope/index.html.twig index 60beb7ed7..ac52afa30 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Scope/index.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Scope/index.html.twig @@ -4,20 +4,20 @@ {% block admin_content -%} {% embed '@ChillMain/CRUD/_index.html.twig' %} - + {% block index_header %}

    {{ 'List circles'|trans }}

    {% endblock %} - + {% block filter_order %}{% endblock %} - + {% block table_entities_thead_tr %} id {{ 'Name'|trans }} {{ 'Active'|trans }} {{ 'Actions'|trans }} {% endblock %} - + {% block table_entities_tbody %} {% for entity in entities %} @@ -40,14 +40,17 @@ {% endfor %} {% endblock %} - + {% block pagination %}{% endblock %} - + {% block list_actions %}
    • {{'Back to the admin'|trans}}
    • +
    • + {{ 'crud.admin_user_scope_history.Show scope history'|trans }} +
    • {{ 'Create a new circle'|trans }}
    • diff --git a/src/Bundle/ChillMainBundle/Resources/views/UserJob/history.html.twig b/src/Bundle/ChillMainBundle/Resources/views/UserJob/history.html.twig new file mode 100644 index 000000000..c7f3867c9 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/UserJob/history.html.twig @@ -0,0 +1,59 @@ +{% extends '@ChillMain/CRUD/Admin/index.html.twig' %} + +{% block admin_content %} + {% embed '@ChillMain/CRUD/_index.html.twig' %} + + {% block table_entities_thead_tr %} + {{ 'crud.admin_user_job_history.index.start'|trans }} + {{ 'crud.admin_user_job_history.index.end'|trans }} + {{ 'crud.admin_user_job_history.index.user'|trans }} + {{ 'crud.admin_user_job_history.index.job'|trans }} + {% endblock %} + + {% block table_entities_tbody %} + {{ dump(entities) }} + {# + #} + {% for entity in entities %} + + + {# {{ dump(entity.id) }} #} + {{ entity.startDate|format_datetime('medium') }} + + {{ entity.endDate|format_datetime('medium') }} + + {% for job in entity.job %} + {# + #} + {{ dump(job) }} + {{ job.label|localize_translatable_string }} + {% endfor %} + + + {% for user in entity.user %} + {# + #} + {{ dump(user.id) }} + {{ user.usernameCanonical }} + {% endfor %} + + + {% endfor %} + {% endblock %} + + {% block actions_before %} +
    • + {{'Back to the admin'|trans }} +
    • + {% endblock %} + + {% block list_actions %} + + {% endblock %} + {% endembed %} +{% endblock %} + diff --git a/src/Bundle/ChillMainBundle/Resources/views/UserJob/index.html.twig b/src/Bundle/ChillMainBundle/Resources/views/UserJob/index.html.twig index 3902b33cf..7ec15f14d 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/UserJob/index.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/UserJob/index.html.twig @@ -35,7 +35,10 @@ {% block actions_before %}
    • - {{'Back to the admin'|trans}} + {{'Back to the admin'|trans }} +
    • +
    • + {{ 'crud.admin_user_job_history.Show job history'|trans }}
    • {% endblock %} diff --git a/src/Bundle/ChillMainBundle/translations/messages.fr.yml b/src/Bundle/ChillMainBundle/translations/messages.fr.yml index 6cbb1fef4..aa61c3dbf 100644 --- a/src/Bundle/ChillMainBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillMainBundle/translations/messages.fr.yml @@ -389,6 +389,24 @@ crud: add_new: Créer title_new: Nouveau métier title_edit: Modifier un métier + admin_user_job_history: + index: + title: Historique des métiers + start: Du + end: Au + user: Utilisateur + job: Métier + Show job history: Voir l'historique + Back to user job: Revenir aux métiers + admin_user_scope_history: + index: + title: Historique des cercles + start: Du + end: Au + user: Utilisateur + scope: Cercle + Show scope history: Voir l'historique + Back to user scope: Revenir aux cercles main_location_type: index: title: Liste des types de localisations From 8a6f29ef79a411cfdedddc744e0f5065d3db5e23 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 20 Sep 2023 14:32:32 +0200 Subject: [PATCH 05/62] add crud controller to user job/scope history --- .../Controller/UserJobHistoryController.php | 29 +++++++++++++++++++ .../Controller/UserScopeHistoryController.php | 29 +++++++++++++++++++ .../ChillMainExtension.php | 6 ++-- 3 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 src/Bundle/ChillMainBundle/Controller/UserJobHistoryController.php create mode 100644 src/Bundle/ChillMainBundle/Controller/UserScopeHistoryController.php diff --git a/src/Bundle/ChillMainBundle/Controller/UserJobHistoryController.php b/src/Bundle/ChillMainBundle/Controller/UserJobHistoryController.php new file mode 100644 index 000000000..069ef5385 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Controller/UserJobHistoryController.php @@ -0,0 +1,29 @@ +addOrderBy('e.startDate', 'ASC') + ->addOrderBy('e.id', 'ASC') + ; + + return parent::orderQuery($action, $query, $request, $paginator); + } +} diff --git a/src/Bundle/ChillMainBundle/Controller/UserScopeHistoryController.php b/src/Bundle/ChillMainBundle/Controller/UserScopeHistoryController.php new file mode 100644 index 000000000..5b4e4cb96 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Controller/UserScopeHistoryController.php @@ -0,0 +1,29 @@ +addOrderBy('e.startDate', 'ASC') + ->addOrderBy('e.id', 'ASC') + ; + + return parent::orderQuery($action, $query, $request, $paginator); + } +} diff --git a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php index 236848435..80febcae9 100644 --- a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php +++ b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php @@ -23,6 +23,8 @@ use Chill\MainBundle\Controller\RegroupmentController; use Chill\MainBundle\Controller\UserController; use Chill\MainBundle\Controller\UserJobApiController; use Chill\MainBundle\Controller\UserJobController; +use Chill\MainBundle\Controller\UserJobHistoryController; +use Chill\MainBundle\Controller\UserScopeHistoryController; use Chill\MainBundle\DependencyInjection\Widget\Factory\WidgetFactoryInterface; use Chill\MainBundle\Doctrine\DQL\Age; use Chill\MainBundle\Doctrine\DQL\Extract; @@ -375,7 +377,7 @@ class ChillMainExtension extends Extension implements ], [ 'class' => UserJobHistory::class, - //'controller' => UserJobHistoryController::class, + 'controller' => UserJobHistoryController::class, 'name' => 'admin_user_job_history', 'base_path' => '/admin/main/user-job-history', 'base_role' => 'ROLE_ADMIN', @@ -388,7 +390,7 @@ class ChillMainExtension extends Extension implements ], [ 'class' => UserScopeHistory::class, - //'controller' => UserScopeHistoryController::class, + 'controller' => UserScopeHistoryController::class, 'name' => 'admin_user_scope_history', 'base_path' => '/admin/main/user-scope-history', 'base_role' => 'ROLE_ADMIN', From d2feb0f0b4489d6dca5b2b5c46e6cefb7086e74b Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 20 Sep 2023 14:34:42 +0200 Subject: [PATCH 06/62] Fix return type in user getters for mainScope and userJob --- src/Bundle/ChillMainBundle/Entity/User.php | 10 +++---- .../Resources/views/Scope/history.html.twig | 28 ++++--------------- .../Resources/views/User/index.html.twig | 4 ++- .../Resources/views/UserJob/history.html.twig | 28 ++++--------------- .../translations/messages.fr.yml | 6 ++-- 5 files changed, 24 insertions(+), 52 deletions(-) diff --git a/src/Bundle/ChillMainBundle/Entity/User.php b/src/Bundle/ChillMainBundle/Entity/User.php index 9656cb3e6..8eab3bb11 100644 --- a/src/Bundle/ChillMainBundle/Entity/User.php +++ b/src/Bundle/ChillMainBundle/Entity/User.php @@ -262,7 +262,7 @@ class User implements UserInterface, \Stringable return $this->mainLocation; } - public function getMainScope(?DateTimeImmutable $at = null): ?UserScopeHistory + public function getMainScope(?DateTimeImmutable $at = null): ?Scope { $at ??= new DateTimeImmutable('today'); $criteria = new Criteria(); @@ -281,7 +281,7 @@ class User implements UserInterface, \Stringable $scopes = $this->scopeHistories->matching($criteria); if ($scopes->count() > 0) { - return $scopes->first(); + return $scopes->first()->getScope(); } return null; @@ -305,7 +305,7 @@ class User implements UserInterface, \Stringable return $this->salt; } - public function getUserJob(?DateTimeImmutable $at = null): ?UserJobHistory + public function getUserJob(?DateTimeImmutable $at = null): ?UserJob { $at ??= new DateTimeImmutable('today'); $criteria = new Criteria(); @@ -317,13 +317,13 @@ class User implements UserInterface, \Stringable $expr->isNull('endDate'), $expr->gt('endDate', $at) ), - $expr->lte('startDate') + $expr->lte('startDate', $at) ) ); $jobs = $this->jobHistories->matching($criteria); if ($jobs->count() > 0) { - return $jobs->first(); + return $jobs->first()->getJob(); } return null; diff --git a/src/Bundle/ChillMainBundle/Resources/views/Scope/history.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Scope/history.html.twig index 3c08620c7..952aa3a5b 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Scope/history.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Scope/history.html.twig @@ -11,32 +11,16 @@ {% endblock %} {% block table_entities_tbody %} - {{ dump(entities) }} - {# - #} {% for entity in entities %} + {{ entity.startDate|format_datetime('medium') }} - {# {{ dump(entity.id) }} #} - {{ entity.startDate|format_datetime('medium') }} - - {{ entity.endDate|format_datetime('medium') }} - - {% for scope in entity.scope %} - {# - #} - {{ dump(scope) }} - {{ scope.label|localize_translatable_string }} - {% endfor %} - - - {% for user in entity.user %} - {# - #} - {{ dump(user.id) }} - {{ user.usernameCanonical }} - {% endfor %} + {{ (entity.endDate is null) + ? "crud.admin_user_scope_history.index.today"|trans + : entity.endDate|format_datetime('medium') }} + {{ entity.user.usernameCanonical }} + {{ entity.scope.name|localize_translatable_string }} {% endfor %} {% endblock %} diff --git a/src/Bundle/ChillMainBundle/Resources/views/User/index.html.twig b/src/Bundle/ChillMainBundle/Resources/views/User/index.html.twig index c5cd73d18..5393f09c8 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/User/index.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/User/index.html.twig @@ -56,7 +56,9 @@
    • métier: - {% if entity.userJob %}{{ entity.userJob.label|localize_translatable_string }}{% endif %} + {% if entity.userJob %} + {{ entity.userJob.label|localize_translatable_string }} + {% endif %}
    • cercle/centre: diff --git a/src/Bundle/ChillMainBundle/Resources/views/UserJob/history.html.twig b/src/Bundle/ChillMainBundle/Resources/views/UserJob/history.html.twig index c7f3867c9..75ad32058 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/UserJob/history.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/UserJob/history.html.twig @@ -11,32 +11,16 @@ {% endblock %} {% block table_entities_tbody %} - {{ dump(entities) }} - {# - #} {% for entity in entities %} + {{ entity.startDate|format_datetime('medium') }} - {# {{ dump(entity.id) }} #} - {{ entity.startDate|format_datetime('medium') }} - - {{ entity.endDate|format_datetime('medium') }} - - {% for job in entity.job %} - {# - #} - {{ dump(job) }} - {{ job.label|localize_translatable_string }} - {% endfor %} - - - {% for user in entity.user %} - {# - #} - {{ dump(user.id) }} - {{ user.usernameCanonical }} - {% endfor %} + {{ (entity.endDate is null) + ? "crud.admin_user_job_history.index.today"|trans + : entity.endDate|format_datetime('medium') }} + {{ entity.user.usernameCanonical }} + {{ entity.job.label|localize_translatable_string }} {% endfor %} {% endblock %} diff --git a/src/Bundle/ChillMainBundle/translations/messages.fr.yml b/src/Bundle/ChillMainBundle/translations/messages.fr.yml index aa61c3dbf..e4977eb60 100644 --- a/src/Bundle/ChillMainBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillMainBundle/translations/messages.fr.yml @@ -393,7 +393,8 @@ crud: index: title: Historique des métiers start: Du - end: Au + end: Jusque + today: aujourd'hui user: Utilisateur job: Métier Show job history: Voir l'historique @@ -402,7 +403,8 @@ crud: index: title: Historique des cercles start: Du - end: Au + end: Jusque + today: aujourd'hui user: Utilisateur scope: Cercle Show scope history: Voir l'historique From 024790128a656e1ffd09ea7f3ffb888f1c19adcd Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 20 Sep 2023 16:11:50 +0200 Subject: [PATCH 07/62] adjust history order --- .../ChillMainBundle/Controller/UserJobHistoryController.php | 4 ++-- .../ChillMainBundle/Controller/UserScopeHistoryController.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Bundle/ChillMainBundle/Controller/UserJobHistoryController.php b/src/Bundle/ChillMainBundle/Controller/UserJobHistoryController.php index 069ef5385..eb181f252 100644 --- a/src/Bundle/ChillMainBundle/Controller/UserJobHistoryController.php +++ b/src/Bundle/ChillMainBundle/Controller/UserJobHistoryController.php @@ -20,8 +20,8 @@ class UserJobHistoryController extends CRUDController protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator) { $query - ->addOrderBy('e.startDate', 'ASC') - ->addOrderBy('e.id', 'ASC') + ->addOrderBy('e.startDate', 'DESC') + ->addOrderBy('e.user', 'ASC') ; return parent::orderQuery($action, $query, $request, $paginator); diff --git a/src/Bundle/ChillMainBundle/Controller/UserScopeHistoryController.php b/src/Bundle/ChillMainBundle/Controller/UserScopeHistoryController.php index 5b4e4cb96..2d425456f 100644 --- a/src/Bundle/ChillMainBundle/Controller/UserScopeHistoryController.php +++ b/src/Bundle/ChillMainBundle/Controller/UserScopeHistoryController.php @@ -20,8 +20,8 @@ class UserScopeHistoryController extends CRUDController protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator) { $query - ->addOrderBy('e.startDate', 'ASC') - ->addOrderBy('e.id', 'ASC') + ->addOrderBy('e.startDate', 'DESC') + ->addOrderBy('e.user', 'ASC') ; return parent::orderQuery($action, $query, $request, $paginator); From 6228cc5eded3d3b77c35ec3a32cd2ffcbe5cbd00 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 20 Sep 2023 17:24:18 +0200 Subject: [PATCH 08/62] fix errors in user getter/setters for mainScope and userJob --- src/Bundle/ChillMainBundle/Entity/User.php | 54 ++++++++++++++++------ 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/src/Bundle/ChillMainBundle/Entity/User.php b/src/Bundle/ChillMainBundle/Entity/User.php index 8eab3bb11..414ae47aa 100644 --- a/src/Bundle/ChillMainBundle/Entity/User.php +++ b/src/Bundle/ChillMainBundle/Entity/User.php @@ -264,7 +264,8 @@ class User implements UserInterface, \Stringable public function getMainScope(?DateTimeImmutable $at = null): ?Scope { - $at ??= new DateTimeImmutable('today'); + $at ??= new DateTimeImmutable('now'); + $criteria = new Criteria(); $expr = Criteria::expr(); @@ -307,7 +308,8 @@ class User implements UserInterface, \Stringable public function getUserJob(?DateTimeImmutable $at = null): ?UserJob { - $at ??= new DateTimeImmutable('today'); + $at ??= new DateTimeImmutable('now'); + $criteria = new Criteria(); $expr = Criteria::expr(); @@ -322,6 +324,7 @@ class User implements UserInterface, \Stringable ); $jobs = $this->jobHistories->matching($criteria); + if ($jobs->count() > 0) { return $jobs->first()->getJob(); } @@ -502,19 +505,31 @@ class User implements UserInterface, \Stringable return $this; } - public function setMainScope(UserScopeHistory $mainScope): User + public function setMainScope(?Scope $mainScope): User { - if (!$this->scopeHistories->contains($mainScope)) { - $this->scopeHistories[] = $mainScope; - $mainScope->setUser($this); + $currentScopeUnchanged = array_filter( + $this->scopeHistories->toArray(), + fn($row) => $row->getEndDate() === null && $row->getScope() === $mainScope + ); + + if (count($currentScopeUnchanged) > 0) { + return $this; } - // ensure continuity of histories + $newScope = new UserScopeHistory(); + + $newScope + ->setStartDate(new DateTimeImmutable('now')) + ->setScope($mainScope) + ->setUser($this); + + $this->scopeHistories[] = $newScope; + $criteria = new Criteria(); $criteria->orderBy(['startDate' => Criteria::ASC, 'id' => Criteria::ASC]); /** @var Iterator $scopes */ - $scopes = $this->getMainScope()->matching($criteria)->getIterator(); + $scopes = $this->scopeHistories->matching($criteria)->getIterator(); $scopes->rewind(); do { @@ -555,18 +570,31 @@ class User implements UserInterface, \Stringable return $this; } - public function setUserJob(UserJobHistory $userJob): User + public function setUserJob(?UserJob $userJob): User { - if (!$this->jobHistories->contains($userJob)) { - $this->jobHistories[] = $userJob; - $userJob->setUser($this); + $currentJobUnchanged = array_filter( + $this->jobHistories->toArray(), + fn($row) => $row->getEndDate() === null && $row->getJob() === $userJob + ); + + if (count($currentJobUnchanged) > 0) { + return $this; } + $newJob = new UserJobHistory(); + + $newJob + ->setStartDate(new DateTimeImmutable('now')) + ->setJob($userJob) + ->setUser($this); + + $this->jobHistories[] = $newJob; + $criteria = new Criteria(); $criteria->orderBy(['startDate' => Criteria::ASC, 'id' => Criteria::ASC]); /** @var Iterator $jobs */ - $jobs = $this->getUserJob()->matching($criteria)->getIterator(); + $jobs = $this->jobHistories->matching($criteria)->getIterator(); $jobs->rewind(); do { From c590d60a7f1346a2bb661720dd31c3dcc0abfe83 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 20 Sep 2023 17:45:58 +0200 Subject: [PATCH 09/62] make tables more readable in templates --- .../Resources/views/Scope/history.html.twig | 16 ++++++++++++---- .../Resources/views/UserJob/history.html.twig | 16 ++++++++++++---- .../ChillMainBundle/translations/messages.fr.yml | 6 ++++-- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/Bundle/ChillMainBundle/Resources/views/Scope/history.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Scope/history.html.twig index 952aa3a5b..b7d4d6d18 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Scope/history.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Scope/history.html.twig @@ -15,12 +15,20 @@ {{ entity.startDate|format_datetime('medium') }} - {{ (entity.endDate is null) - ? "crud.admin_user_scope_history.index.today"|trans - : entity.endDate|format_datetime('medium') }} + {% if entity.endDate is not null %} + {{ entity.endDate|format_datetime('medium') }} + {% else %} + {{ "crud.admin_user_scope_history.index.today"|trans }} + {% endif %} {{ entity.user.usernameCanonical }} - {{ entity.scope.name|localize_translatable_string }} + + {% if entity.scope %} + {{ entity.scope.name|localize_translatable_string }} + {% else %} + {{ 'crud.admin_user_scope_history.index.undefined'|trans }} + {% endif %} + {% endfor %} {% endblock %} diff --git a/src/Bundle/ChillMainBundle/Resources/views/UserJob/history.html.twig b/src/Bundle/ChillMainBundle/Resources/views/UserJob/history.html.twig index 75ad32058..a0adf3e30 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/UserJob/history.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/UserJob/history.html.twig @@ -15,12 +15,20 @@ {{ entity.startDate|format_datetime('medium') }} - {{ (entity.endDate is null) - ? "crud.admin_user_job_history.index.today"|trans - : entity.endDate|format_datetime('medium') }} + {% if entity.endDate is not null %} + {{ entity.endDate|format_datetime('medium') }} + {% else %} + {{ "crud.admin_user_job_history.index.today"|trans }} + {% endif %} {{ entity.user.usernameCanonical }} - {{ entity.job.label|localize_translatable_string }} + + {% if entity.job %} + {{ entity.job.label|localize_translatable_string }} + {% else %} + {{ 'crud.admin_user_job_history.index.undefined'|trans }} + {% endif %} + {% endfor %} {% endblock %} diff --git a/src/Bundle/ChillMainBundle/translations/messages.fr.yml b/src/Bundle/ChillMainBundle/translations/messages.fr.yml index e4977eb60..05a02bde1 100644 --- a/src/Bundle/ChillMainBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillMainBundle/translations/messages.fr.yml @@ -394,7 +394,8 @@ crud: title: Historique des métiers start: Du end: Jusque - today: aujourd'hui + today: en cours + undefined: non défini user: Utilisateur job: Métier Show job history: Voir l'historique @@ -404,7 +405,8 @@ crud: title: Historique des cercles start: Du end: Jusque - today: aujourd'hui + today: en cours + undefined: non défini user: Utilisateur scope: Cercle Show scope history: Voir l'historique From e6e42777d734710027496ee66c63749fd20fc25f Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 20 Sep 2023 17:52:44 +0200 Subject: [PATCH 10/62] add new changie --- .changes/unreleased/Feature-20230920-175207.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changes/unreleased/Feature-20230920-175207.yaml diff --git a/.changes/unreleased/Feature-20230920-175207.yaml b/.changes/unreleased/Feature-20230920-175207.yaml new file mode 100644 index 000000000..ec8b51f77 --- /dev/null +++ b/.changes/unreleased/Feature-20230920-175207.yaml @@ -0,0 +1,6 @@ +kind: Feature +body: | + Add history to scopes and to jobs in administrator section. When user job or main scope of user is changed, automaticaly add a new row in history. +time: 2023-09-20T17:52:07.160601133+02:00 +custom: + Issue: "147" From 949c5424f021fe9e4744a294bb121c1b863bca1c Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Fri, 22 Sep 2023 13:48:37 +0200 Subject: [PATCH 11/62] improve check in setters and add types in repositories --- src/Bundle/ChillMainBundle/Entity/User.php | 14 ++-------- .../User/UserJobHistoryRepository.php | 28 ++----------------- .../User/UserScopeHistoryRepository.php | 28 ++----------------- 3 files changed, 8 insertions(+), 62 deletions(-) diff --git a/src/Bundle/ChillMainBundle/Entity/User.php b/src/Bundle/ChillMainBundle/Entity/User.php index 414ae47aa..f6f9d55f6 100644 --- a/src/Bundle/ChillMainBundle/Entity/User.php +++ b/src/Bundle/ChillMainBundle/Entity/User.php @@ -507,12 +507,7 @@ class User implements UserInterface, \Stringable public function setMainScope(?Scope $mainScope): User { - $currentScopeUnchanged = array_filter( - $this->scopeHistories->toArray(), - fn($row) => $row->getEndDate() === null && $row->getScope() === $mainScope - ); - - if (count($currentScopeUnchanged) > 0) { + if ($mainScope === $this->getMainScope()) { return $this; } @@ -572,12 +567,7 @@ class User implements UserInterface, \Stringable public function setUserJob(?UserJob $userJob): User { - $currentJobUnchanged = array_filter( - $this->jobHistories->toArray(), - fn($row) => $row->getEndDate() === null && $row->getJob() === $userJob - ); - - if (count($currentJobUnchanged) > 0) { + if ($userJob === $this->getUserJob()) { return $this; } diff --git a/src/Bundle/ChillMainBundle/Repository/User/UserJobHistoryRepository.php b/src/Bundle/ChillMainBundle/Repository/User/UserJobHistoryRepository.php index a66575e3b..39186241f 100644 --- a/src/Bundle/ChillMainBundle/Repository/User/UserJobHistoryRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/User/UserJobHistoryRepository.php @@ -17,35 +17,13 @@ use Doctrine\ORM\OptimisticLockException; use Doctrine\ORM\ORMException; use Doctrine\Persistence\ManagerRegistry; +/** + * @extends ServiceEntityRepository + */ class UserJobHistoryRepository extends ServiceEntityRepository { public function __construct(ManagerRegistry $registry) { parent::__construct($registry, UserJobHistory::class); } - - /** - * @throws ORMException - * @throws OptimisticLockException - */ - public function add(UserJobHistory $entity, bool $flush = true): void - { - $this->_em->persist($entity); - if ($flush) { - $this->_em->flush(); - } - } - - /** - * @throws ORMException - * @throws OptimisticLockException - */ - public function remove(UserJobHistory $entity, bool $flush = true): void - { - $this->_em->remove($entity); - if ($flush) { - $this->_em->flush(); - } - } - } diff --git a/src/Bundle/ChillMainBundle/Repository/User/UserScopeHistoryRepository.php b/src/Bundle/ChillMainBundle/Repository/User/UserScopeHistoryRepository.php index aa6738870..739e653c3 100644 --- a/src/Bundle/ChillMainBundle/Repository/User/UserScopeHistoryRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/User/UserScopeHistoryRepository.php @@ -17,35 +17,13 @@ use Doctrine\ORM\OptimisticLockException; use Doctrine\ORM\ORMException; use Doctrine\Persistence\ManagerRegistry; +/** + * @extends ServiceEntityRepository + */ final class UserScopeHistoryRepository extends ServiceEntityRepository { public function __construct(ManagerRegistry $registry) { parent::__construct($registry, UserScopeHistory::class); } - - /** - * @throws ORMException - * @throws OptimisticLockException - */ - public function add(UserScopeHistory $entity, bool $flush = true): void - { - $this->_em->persist($entity); - if ($flush) { - $this->_em->flush(); - } - } - - /** - * @throws ORMException - * @throws OptimisticLockException - */ - public function remove(UserScopeHistory $entity, bool $flush = true): void - { - $this->_em->remove($entity); - if ($flush) { - $this->_em->flush(); - } - } - } From fc919e9547bee546dbaae7d8335c739a1553e00f Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 19 Sep 2023 10:19:51 +0200 Subject: [PATCH 12/62] add tests for MainScope and UserJob getters/setters --- src/Bundle/ChillMainBundle/Entity/User.php | 10 +++ .../ChillMainBundle/Tests/Entity/UserTest.php | 72 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 src/Bundle/ChillMainBundle/Tests/Entity/UserTest.php diff --git a/src/Bundle/ChillMainBundle/Entity/User.php b/src/Bundle/ChillMainBundle/Entity/User.php index f6f9d55f6..e0aa43d9a 100644 --- a/src/Bundle/ChillMainBundle/Entity/User.php +++ b/src/Bundle/ChillMainBundle/Entity/User.php @@ -288,6 +288,11 @@ class User implements UserInterface, \Stringable return null; } + public function getMainScopeHistories(): Collection + { + return $this->scopeHistories; + } + /** * @return string */ @@ -332,6 +337,11 @@ class User implements UserInterface, \Stringable return null; } + public function getUserJobHistories(): Collection + { + return $this->jobHistories; + } + /** * @return string */ diff --git a/src/Bundle/ChillMainBundle/Tests/Entity/UserTest.php b/src/Bundle/ChillMainBundle/Tests/Entity/UserTest.php new file mode 100644 index 000000000..17bb38d11 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Entity/UserTest.php @@ -0,0 +1,72 @@ +setMainScope($scopeA); + $user->setMainScope($scopeB); + + // 1. check getMainScope get now scopeB, not scopeA + self::assertSame($scopeB, $user->getMainScope()); + + // 2. get scopeA history, check endDate is not null + $histories = $user->getMainScopeHistories(); + $scopeHistoryA = null; + foreach ($histories as $row) { + /** @var User\UserScopeHistory $row */ + if ($scopeA === $row->getScope()) { + $scopeHistoryA = $row; + } + } + self::assertNotNull($scopeHistoryA->getEndDate()); + } + + public function testUserJobHistory() + { + $user = new User(); + $jobA = new UserJob(); + $jobB = new UserJob(); + + $user->setUserJob($jobA); + $user->setUserJob($jobB); + + // 1. check getUserJob get now jobB, not jobA + self::assertSame($jobB, $user->getUserJob()); + + // 2. get jobA history, check endDate is not null + $histories = $user->getUserJobHistories(); + $jobHistoryA = null; + foreach ($histories as $row) { + /** @var User\UserJobHistory $row */ + if ($jobA === $row->getJob()) { + $jobHistoryA = $row; + } + } + self::assertNotNull($jobHistoryA->getEndDate()); + } + +} From 6665a443b95fc5cd6c1cafb08fe240f89830a2ad Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Mon, 25 Sep 2023 11:50:54 +0200 Subject: [PATCH 13/62] phpstan, rector, cs-fixer --- src/Bundle/ChillMainBundle/Entity/User.php | 4 ++-- .../Repository/User/UserJobHistoryRepository.php | 2 +- .../Repository/User/UserScopeHistoryRepository.php | 2 +- src/Bundle/ChillMainBundle/Tests/Entity/UserTest.php | 4 ++++ tests/Kernel.php | 9 +++++++++ tests/app/config/bootstrap.php | 9 +++++++++ tests/app/config/bundles.php | 9 +++++++++ tests/app/config/preload.php | 9 +++++++++ tests/bootstrap.php | 9 +++++++++ tests/symfony-container.php | 9 +++++++++ 10 files changed, 62 insertions(+), 4 deletions(-) diff --git a/src/Bundle/ChillMainBundle/Entity/User.php b/src/Bundle/ChillMainBundle/Entity/User.php index e0aa43d9a..db9f8ade6 100644 --- a/src/Bundle/ChillMainBundle/Entity/User.php +++ b/src/Bundle/ChillMainBundle/Entity/User.php @@ -279,7 +279,7 @@ class User implements UserInterface, \Stringable ) ); - $scopes = $this->scopeHistories->matching($criteria); + $scopes = $this->scopeHistories->matching($criteria)->getIterator(); if ($scopes->count() > 0) { return $scopes->first()->getScope(); @@ -328,7 +328,7 @@ class User implements UserInterface, \Stringable ) ); - $jobs = $this->jobHistories->matching($criteria); + $jobs = $this->jobHistories->matching($criteria)->getIterator(); if ($jobs->count() > 0) { return $jobs->first()->getJob(); diff --git a/src/Bundle/ChillMainBundle/Repository/User/UserJobHistoryRepository.php b/src/Bundle/ChillMainBundle/Repository/User/UserJobHistoryRepository.php index 39186241f..443e01213 100644 --- a/src/Bundle/ChillMainBundle/Repository/User/UserJobHistoryRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/User/UserJobHistoryRepository.php @@ -11,7 +11,7 @@ declare(strict_types=1); namespace Chill\MainBundle\Repository\User; -use App\Entity\UserJobHistory; +use Chill\MainBundle\Entity\User\UserJobHistory; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\ORM\OptimisticLockException; use Doctrine\ORM\ORMException; diff --git a/src/Bundle/ChillMainBundle/Repository/User/UserScopeHistoryRepository.php b/src/Bundle/ChillMainBundle/Repository/User/UserScopeHistoryRepository.php index 739e653c3..040155457 100644 --- a/src/Bundle/ChillMainBundle/Repository/User/UserScopeHistoryRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/User/UserScopeHistoryRepository.php @@ -11,7 +11,7 @@ declare(strict_types=1); namespace Chill\MainBundle\Repository\User; -use App\Entity\UserScopeHistory; +use Chill\MainBundle\Entity\User\UserScopeHistory; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\ORM\OptimisticLockException; use Doctrine\ORM\ORMException; diff --git a/src/Bundle/ChillMainBundle/Tests/Entity/UserTest.php b/src/Bundle/ChillMainBundle/Tests/Entity/UserTest.php index 17bb38d11..a303354ed 100644 --- a/src/Bundle/ChillMainBundle/Tests/Entity/UserTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Entity/UserTest.php @@ -17,6 +17,10 @@ use Chill\MainBundle\Entity\UserJob; use PHPUnit\Framework\TestCase; use Prophecy\PhpUnit\ProphecyTrait; +/** + * @internal + * @coversNothing + */ class UserTest extends TestCase { use ProphecyTrait; diff --git a/tests/Kernel.php b/tests/Kernel.php index 5047bfa32..a0ede51ac 100644 --- a/tests/Kernel.php +++ b/tests/Kernel.php @@ -1,5 +1,14 @@ ['all' => true], Chill\ActivityBundle\ChillActivityBundle::class => ['all' => true], diff --git a/tests/app/config/preload.php b/tests/app/config/preload.php index 064bdcd6a..d98989af6 100644 --- a/tests/app/config/preload.php +++ b/tests/app/config/preload.php @@ -1,5 +1,14 @@ Date: Tue, 26 Sep 2023 11:27:36 +0200 Subject: [PATCH 14/62] fix Entity/UserTest and phpstan error --- src/Bundle/ChillMainBundle/Entity/User.php | 55 ++++++------------- .../ChillMainBundle/Tests/Entity/UserTest.php | 31 +++++------ 2 files changed, 30 insertions(+), 56 deletions(-) diff --git a/src/Bundle/ChillMainBundle/Entity/User.php b/src/Bundle/ChillMainBundle/Entity/User.php index db9f8ade6..18d208c99 100644 --- a/src/Bundle/ChillMainBundle/Entity/User.php +++ b/src/Bundle/ChillMainBundle/Entity/User.php @@ -17,6 +17,7 @@ use DateTimeImmutable; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Criteria; +use Doctrine\Common\Collections\Selectable; use Doctrine\ORM\Mapping as ORM; use Iterator; use RuntimeException; @@ -117,11 +118,11 @@ class User implements UserInterface, \Stringable private ?Location $mainLocation = null; /** - * @var Collection + * @var Collection&Selectable * @ORM\OneToMany(targetEntity=UserScopeHistory::class, * mappedBy="user", cascade={"persist", "remove"}, orphanRemoval=true) */ - private Collection $scopeHistories; + private Collection&Selectable $scopeHistories; /** * @ORM\Column(type="string", length=255) @@ -136,11 +137,11 @@ class User implements UserInterface, \Stringable private ?string $salt = null; /** - * @var Collection + * @var Collection&Selectable * @ORM\OneToMany(targetEntity=UserJobHistory::class, * mappedBy="user", cascade={"persist", "remove"}, orphanRemoval=true) */ - private Collection $jobHistories; + private Collection&Selectable $jobHistories; /** * @ORM\Column(type="string", length=80) @@ -266,23 +267,12 @@ class User implements UserInterface, \Stringable { $at ??= new DateTimeImmutable('now'); - $criteria = new Criteria(); - $expr = Criteria::expr(); - - $criteria->where( - $expr->andX( - $expr->orX( - $expr->isNull('endDate'), - $expr->gt('endDate', $at) - ), - $expr->lte('startDate', $at) - ) - ); - - $scopes = $this->scopeHistories->matching($criteria)->getIterator(); - - if ($scopes->count() > 0) { - return $scopes->first()->getScope(); + foreach ($this->scopeHistories as $scopeHistory) { + if ($at >= $scopeHistory->getStartDate() && ( + null === $scopeHistory->getEndDate() || $at < $scopeHistory->getEndDate() + )) { + return $scopeHistory->getScope(); + } } return null; @@ -315,23 +305,12 @@ class User implements UserInterface, \Stringable { $at ??= new DateTimeImmutable('now'); - $criteria = new Criteria(); - $expr = Criteria::expr(); - - $criteria->where( - $expr->andX( - $expr->orX( - $expr->isNull('endDate'), - $expr->gt('endDate', $at) - ), - $expr->lte('startDate', $at) - ) - ); - - $jobs = $this->jobHistories->matching($criteria)->getIterator(); - - if ($jobs->count() > 0) { - return $jobs->first()->getJob(); + foreach ($this->jobHistories as $jobHistory) { + if ($at >= $jobHistory->getStartDate() && ( + null === $jobHistory->getEndDate() || $at < $jobHistory->getEndDate() + )) { + return $jobHistory->getJob(); + } } return null; diff --git a/src/Bundle/ChillMainBundle/Tests/Entity/UserTest.php b/src/Bundle/ChillMainBundle/Tests/Entity/UserTest.php index a303354ed..a0502593e 100644 --- a/src/Bundle/ChillMainBundle/Tests/Entity/UserTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Entity/UserTest.php @@ -38,15 +38,13 @@ class UserTest extends TestCase self::assertSame($scopeB, $user->getMainScope()); // 2. get scopeA history, check endDate is not null - $histories = $user->getMainScopeHistories(); - $scopeHistoryA = null; - foreach ($histories as $row) { - /** @var User\UserScopeHistory $row */ - if ($scopeA === $row->getScope()) { - $scopeHistoryA = $row; - } - } - self::assertNotNull($scopeHistoryA->getEndDate()); + self::assertNotNull( + $user + ->getMainScopeHistories() + ->filter(fn (User\UserScopeHistory $userScopeHistory) => $userScopeHistory->getScope() === $scopeA ) + ->first()->getEndDate() + ); + } public function testUserJobHistory() @@ -62,15 +60,12 @@ class UserTest extends TestCase self::assertSame($jobB, $user->getUserJob()); // 2. get jobA history, check endDate is not null - $histories = $user->getUserJobHistories(); - $jobHistoryA = null; - foreach ($histories as $row) { - /** @var User\UserJobHistory $row */ - if ($jobA === $row->getJob()) { - $jobHistoryA = $row; - } - } - self::assertNotNull($jobHistoryA->getEndDate()); + self::assertNotNull( + $user + ->getUserJobHistories() + ->filter(fn(User\UserJobHistory $userJobHistory) => $userJobHistory->getJob() === $jobA ) + ->first()->getEndDate() + ); } } From 2d4d1eda50fba3b9ed2ab639795d89bf0dfec6bb Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 26 Sep 2023 12:04:59 +0200 Subject: [PATCH 15/62] cs-fixer --- src/Bundle/ChillMainBundle/Entity/User.php | 2 +- src/Bundle/ChillMainBundle/Tests/Entity/UserTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Bundle/ChillMainBundle/Entity/User.php b/src/Bundle/ChillMainBundle/Entity/User.php index 18d208c99..64f0e18f6 100644 --- a/src/Bundle/ChillMainBundle/Entity/User.php +++ b/src/Bundle/ChillMainBundle/Entity/User.php @@ -270,7 +270,7 @@ class User implements UserInterface, \Stringable foreach ($this->scopeHistories as $scopeHistory) { if ($at >= $scopeHistory->getStartDate() && ( null === $scopeHistory->getEndDate() || $at < $scopeHistory->getEndDate() - )) { + )) { return $scopeHistory->getScope(); } } diff --git a/src/Bundle/ChillMainBundle/Tests/Entity/UserTest.php b/src/Bundle/ChillMainBundle/Tests/Entity/UserTest.php index a0502593e..2aeadc574 100644 --- a/src/Bundle/ChillMainBundle/Tests/Entity/UserTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Entity/UserTest.php @@ -41,7 +41,7 @@ class UserTest extends TestCase self::assertNotNull( $user ->getMainScopeHistories() - ->filter(fn (User\UserScopeHistory $userScopeHistory) => $userScopeHistory->getScope() === $scopeA ) + ->filter(fn (User\UserScopeHistory $userScopeHistory) => $userScopeHistory->getScope() === $scopeA) ->first()->getEndDate() ); @@ -63,7 +63,7 @@ class UserTest extends TestCase self::assertNotNull( $user ->getUserJobHistories() - ->filter(fn(User\UserJobHistory $userJobHistory) => $userJobHistory->getJob() === $jobA ) + ->filter(fn (User\UserJobHistory $userJobHistory) => $userJobHistory->getJob() === $jobA) ->first()->getEndDate() ); } From c5b153e6ed38fdc517e5d595d676fd273d9ca3b8 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 26 Sep 2023 13:04:18 +0200 Subject: [PATCH 16/62] fix missing queries in job/scope history migration: remove mainscope_id and userjob_id from user table --- .../migrations/Version20230913114115.php | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/Bundle/ChillMainBundle/migrations/Version20230913114115.php b/src/Bundle/ChillMainBundle/migrations/Version20230913114115.php index 2ef12dd7d..3e79412bb 100644 --- a/src/Bundle/ChillMainBundle/migrations/Version20230913114115.php +++ b/src/Bundle/ChillMainBundle/migrations/Version20230913114115.php @@ -26,6 +26,10 @@ final class Version20230913114115 extends AbstractMigration $this->addSql('ALTER TABLE chill_main_user_job_history DROP CONSTRAINT FK_4E3BF4DDA76ED395'); $this->addSql('DROP TABLE chill_main_user_job_history'); + $this->addSql('ALTER TABLE users ADD userjob_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE users ADD CONSTRAINT fk_1483a5e964b65c5b FOREIGN KEY (userjob_id) REFERENCES chill_main_user_job (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('CREATE INDEX idx_1483a5e964b65c5b ON users (userjob_id)'); + // drop scope_history $this->addSql('ALTER TABLE chill_main_user_scope_history DROP CONSTRAINT user_scope_history_endate_null_or_after_startdate'); $this->addSql('ALTER TABLE chill_main_user_scope_history DROP CONSTRAINT user_scope_history_not_overlaps'); @@ -33,6 +37,11 @@ final class Version20230913114115 extends AbstractMigration $this->addSql('ALTER TABLE chill_main_user_scope_history DROP CONSTRAINT FK_48B969D7682B5931'); $this->addSql('ALTER TABLE chill_main_user_scope_history DROP CONSTRAINT FK_48B969D7A76ED395'); $this->addSql('DROP TABLE chill_main_user_scope_history'); + + $this->addSql('ALTER TABLE users ADD mainscope_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE users ADD CONSTRAINT fk_1483a5e9115e73f3 FOREIGN KEY (mainscope_id) REFERENCES scopes (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('CREATE INDEX idx_1483a5e9115e73f3 ON users (mainscope_id)'); + } public function getDescription(): string @@ -51,18 +60,24 @@ final class Version20230913114115 extends AbstractMigration . 'endDate TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL,' . 'startDate TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,' . 'PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_48B969D7682B5931 ON chill_main_user_scope_history (scope_id)'); $this->addSql('CREATE INDEX IDX_48B969D7A76ED395 ON chill_main_user_scope_history (user_id)'); + $this->addSql('COMMENT ON COLUMN chill_main_user_scope_history.endDate IS \'(DC2Type:datetime_immutable)\''); $this->addSql('COMMENT ON COLUMN chill_main_user_scope_history.startDate IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE chill_main_user_scope_history ADD CONSTRAINT FK_48B969D7682B5931 ' . 'FOREIGN KEY (scope_id) REFERENCES scopes (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_main_user_scope_history ADD CONSTRAINT FK_48B969D7A76ED395 ' . 'FOREIGN KEY (user_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_main_user_scope_history ' . 'ADD CONSTRAINT user_scope_history_not_overlaps ' . 'EXCLUDE USING GIST (user_id with =, tsrange(startDate, endDate) with &&) ' . 'DEFERRABLE INITIALLY DEFERRED'); + $this->addSql('ALTER TABLE chill_main_user_scope_history ' . 'ADD CONSTRAINT user_scope_history_endate_null_or_after_startdate ' . 'CHECK (startDate <= endDate OR endDate IS NULL)'); @@ -72,6 +87,11 @@ final class Version20230913114115 extends AbstractMigration . 'SELECT nextval(\'chill_main_user_scope_history_id_seq\'), \'1970-01-01\'::date, NULL, users.id, mainscope_id ' . 'FROM users'); + // remove mainscope + $this->addSql('ALTER TABLE users DROP CONSTRAINT fk_1483a5e9115e73f3'); + $this->addSql('ALTER TABLE users DROP mainscope_id'); + + // create job_history $this->addSql('CREATE SEQUENCE chill_main_user_job_history_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); $this->addSql('CREATE TABLE chill_main_user_job_history (' @@ -81,18 +101,24 @@ final class Version20230913114115 extends AbstractMigration . 'endDate TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL,' . 'startDate TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,' . 'PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_4E3BF4DDBE04EA9 ON chill_main_user_job_history (job_id)'); $this->addSql('CREATE INDEX IDX_4E3BF4DDA76ED395 ON chill_main_user_job_history (user_id)'); + $this->addSql('COMMENT ON COLUMN chill_main_user_job_history.endDate IS \'(DC2Type:datetime_immutable)\''); $this->addSql('COMMENT ON COLUMN chill_main_user_job_history.startDate IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE chill_main_user_job_history ADD CONSTRAINT FK_4E3BF4DDBE04EA9 ' . 'FOREIGN KEY (job_id) REFERENCES chill_main_user_job (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_main_user_job_history ADD CONSTRAINT FK_4E3BF4DDA76ED395 ' . 'FOREIGN KEY (user_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_main_user_job_history ' . 'ADD CONSTRAINT user_job_history_not_overlaps ' . 'EXCLUDE USING GIST (user_id with =, tsrange(startDate, endDate) with &&) ' . 'DEFERRABLE INITIALLY DEFERRED'); + $this->addSql('ALTER TABLE chill_main_user_job_history ' . 'ADD CONSTRAINT user_job_history_endate_null_or_after_startdate ' . 'CHECK (startDate <= endDate OR endDate IS NULL)'); @@ -101,5 +127,10 @@ final class Version20230913114115 extends AbstractMigration $this->addSql('INSERT INTO chill_main_user_job_history (id, startDate, endDate, user_id, job_id) ' . 'SELECT nextval(\'chill_main_user_job_history_id_seq\'), \'1970-01-01\'::date, NULL, users.id, userjob_id ' . 'FROM users'); + + // remove userjob + $this->addSql('ALTER TABLE users DROP CONSTRAINT fk_1483a5e964b65c5b'); + $this->addSql('ALTER TABLE users DROP userjob_id'); + } } From 28583f4193e1cd1658e3ec408716dd58d18c6c0a Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 26 Sep 2023 15:33:18 +0200 Subject: [PATCH 17/62] [export] fix calendar jobAggregator query + unit test --- .../Export/Aggregator/JobAggregator.php | 51 +++++++++++++++---- .../Export/Aggregator/JobAggregatorTest.php | 5 +- .../translations/messages.fr.yml | 2 + 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php index 139de7b17..fa6be1169 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php +++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php @@ -12,17 +12,27 @@ declare(strict_types=1); namespace Chill\CalendarBundle\Export\Aggregator; use Chill\CalendarBundle\Export\Declarations; +use Chill\MainBundle\Entity\User\UserJobHistory; 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\RollingDateConverterInterface; use Chill\MainBundle\Templating\TranslatableStringHelper; use Closure; +use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; -use function in_array; final readonly class JobAggregator implements AggregatorInterface { - public function __construct(private UserJobRepository $jobRepository, private TranslatableStringHelper $translatableStringHelper) {} + private const PREFIX = 'cal_agg'; + + public function __construct( + private RollingDateConverterInterface $rollingDateConverter, + private UserJobRepository $jobRepository, + private TranslatableStringHelper $translatableStringHelper + ) {} public function addRole(): ?string { @@ -31,12 +41,26 @@ final readonly class JobAggregator implements AggregatorInterface public function alterQuery(QueryBuilder $qb, $data) { - if (!in_array('caluser', $qb->getAllAliases(), true)) { - $qb->join('cal.mainUser', 'caluser'); - } + $p = self::PREFIX; - $qb->addSelect('IDENTITY(caluser.userJob) as job_aggregator'); - $qb->addGroupBy('job_aggregator'); + $qb + ->leftJoin( + 'cal.mainUser', + "{$p}_user" + ) + ->leftJoin( + UserJobHistory::class, + "{$p}_ujh", + Expr\Join::WITH, + $qb->expr()->eq("{$p}_ujh.user", "{$p}_user") + ) + ->andWhere("{$p}_ujh.startDate <= :{$p}_at AND ({$p}_ujh.endDate IS NULL OR {$p}_ujh.endDate > :{$p}_at)") + ->addSelect("IDENTITY({$p}_ujh.job) AS {$p}_select") + ->setParameter( + "{$p}_at", + $this->rollingDateConverter->convert($data['job_at']) + ) + ->addGroupBy("{$p}_select"); } public function applyOn(): string @@ -46,11 +70,14 @@ final readonly class JobAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - // no form + $builder->add('job_at', PickRollingDateType::class, [ + 'label' => 'export.aggregator.calendar.Calc date', + ]); } + public function getFormDefaultData(): array { - return []; + return ['job_at' => new RollingDate(RollingDate::T_TODAY)]; } public function getLabels($key, array $values, $data): Closure @@ -64,7 +91,9 @@ final readonly class JobAggregator implements AggregatorInterface return ''; } - $j = $this->jobRepository->find($value); + if (null === $j = $this->jobRepository->find($value)) { + return ''; + } return $this->translatableStringHelper->localize( $j->getLabel() @@ -74,7 +103,7 @@ final readonly class JobAggregator implements AggregatorInterface public function getQueryKeys($data): array { - return ['job_aggregator']; + return [self::PREFIX . '_select']; } public function getTitle(): string diff --git a/src/Bundle/ChillCalendarBundle/Tests/Export/Aggregator/JobAggregatorTest.php b/src/Bundle/ChillCalendarBundle/Tests/Export/Aggregator/JobAggregatorTest.php index 8dda425f7..838f8b988 100644 --- a/src/Bundle/ChillCalendarBundle/Tests/Export/Aggregator/JobAggregatorTest.php +++ b/src/Bundle/ChillCalendarBundle/Tests/Export/Aggregator/JobAggregatorTest.php @@ -20,6 +20,7 @@ namespace Chill\CalendarBundle\Tests\Export\Aggregator; use Chill\CalendarBundle\Entity\Calendar; use Chill\CalendarBundle\Export\Aggregator\JobAggregator; +use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Test\Export\AbstractAggregatorTest; use Doctrine\ORM\EntityManagerInterface; @@ -46,7 +47,9 @@ 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')), + ] ]; } diff --git a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml index c56d7835f..f608bfc12 100644 --- a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml @@ -117,6 +117,8 @@ Group calendars by cancel reason: Grouper les rendez-vous par motif d'annulation Group calendars by month and year: Grouper les rendez-vous par mois et année Group calendars by urgency: Grouper les rendez-vous par urgent ou non +export.aggregator.calendar.Calc date: Date de calcul du métier de l'agent + Scope: Service Job: Métier Location type: Type de localisation From f18ee2383c200a09eca6e3627d39f8b3d057ba3f Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 26 Sep 2023 16:00:42 +0200 Subject: [PATCH 18/62] [export] fix calendar scopeAggregator query + unit test --- .../Export/Aggregator/JobAggregator.php | 12 ++--- .../Export/Aggregator/ScopeAggregator.php | 44 +++++++++++++++---- .../Export/Aggregator/ScopeAggregatorTest.php | 5 ++- .../translations/messages.fr.yml | 6 ++- 4 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php index fa6be1169..94807d709 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php +++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php @@ -26,7 +26,7 @@ use Symfony\Component\Form\FormBuilderInterface; final readonly class JobAggregator implements AggregatorInterface { - private const PREFIX = 'cal_agg'; + private const PREFIX = 'cal_agg_job'; public function __construct( private RollingDateConverterInterface $rollingDateConverter, @@ -50,12 +50,12 @@ final readonly class JobAggregator implements AggregatorInterface ) ->leftJoin( UserJobHistory::class, - "{$p}_ujh", + "{$p}_history", Expr\Join::WITH, - $qb->expr()->eq("{$p}_ujh.user", "{$p}_user") + $qb->expr()->eq("{$p}_history.user", "{$p}_user") ) - ->andWhere("{$p}_ujh.startDate <= :{$p}_at AND ({$p}_ujh.endDate IS NULL OR {$p}_ujh.endDate > :{$p}_at)") - ->addSelect("IDENTITY({$p}_ujh.job) AS {$p}_select") + ->andWhere("{$p}_history.startDate <= :{$p}_at AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > :{$p}_at)") + ->addSelect("IDENTITY({$p}_history.job) AS {$p}_select") ->setParameter( "{$p}_at", $this->rollingDateConverter->convert($data['job_at']) @@ -71,7 +71,7 @@ final readonly class JobAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { $builder->add('job_at', PickRollingDateType::class, [ - 'label' => 'export.aggregator.calendar.Calc date', + 'label' => 'export.aggregator.calendar.agent_job.Calc date', ]); } diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php index f1daa643c..df68b7c42 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php +++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php @@ -12,17 +12,26 @@ declare(strict_types=1); namespace Chill\CalendarBundle\Export\Aggregator; use Chill\CalendarBundle\Export\Declarations; +use Chill\MainBundle\Entity\User\UserScopeHistory; 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\RollingDateConverterInterface; use Chill\MainBundle\Templating\TranslatableStringHelper; use Closure; +use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; +use PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Exp; use Symfony\Component\Form\FormBuilderInterface; use function in_array; final readonly class ScopeAggregator implements AggregatorInterface { + private const PREFIX = "cal_agg_scope"; + public function __construct( + private RollingDateConverterInterface $rollingDateConverter, private ScopeRepository $scopeRepository, private TranslatableStringHelper $translatableStringHelper ) {} @@ -34,12 +43,25 @@ final readonly class ScopeAggregator implements AggregatorInterface public function alterQuery(QueryBuilder $qb, $data) { - if (!in_array('caluser', $qb->getAllAliases(), true)) { - $qb->join('cal.mainUser', 'caluser'); - } + $p = self::PREFIX; - $qb->addSelect('IDENTITY(caluser.mainScope) as scope_aggregator'); - $qb->addGroupBy('scope_aggregator'); + $qb + ->leftJoin( + "cal.mainUser", + "{$p}_user" + ) + ->leftJoin( + UserScopeHistory::class, + "{$p}_history", + Expr\Join::WITH, + $qb->expr()->eq("{$p}_history.user", "{$p}_user") + ) + ->andWhere("{$p}_history.startDate <= :{$p}_at AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > :{$p}_at)") + ->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select") + ->setParameter( + "{$p}_at", + $this->rollingDateConverter->convert($data['scope_at'])) + ->addGroupBy("{$p}_select"); } public function applyOn(): string @@ -49,11 +71,13 @@ final readonly class ScopeAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - // no form + $builder->add('scope_at', PickRollingDateType::class, [ + 'label' => 'export.aggregator.calendar.agent_scope.Calc date', + ]); } public function getFormDefaultData(): array { - return []; + return ['scope_at' => new RollingDate(RollingDate::T_TODAY)]; } public function getLabels($key, array $values, $data): Closure @@ -67,7 +91,9 @@ final readonly class ScopeAggregator implements AggregatorInterface return ''; } - $s = $this->scopeRepository->find($value); + if (null === $s = $this->scopeRepository->find($value)) { + return ''; + } return $this->translatableStringHelper->localize( $s->getName() @@ -77,7 +103,7 @@ final readonly class ScopeAggregator implements AggregatorInterface public function getQueryKeys($data): array { - return ['scope_aggregator']; + return [self::PREFIX . '_select']; } public function getTitle(): string diff --git a/src/Bundle/ChillCalendarBundle/Tests/Export/Aggregator/ScopeAggregatorTest.php b/src/Bundle/ChillCalendarBundle/Tests/Export/Aggregator/ScopeAggregatorTest.php index c9a2b9e5c..43900d53a 100644 --- a/src/Bundle/ChillCalendarBundle/Tests/Export/Aggregator/ScopeAggregatorTest.php +++ b/src/Bundle/ChillCalendarBundle/Tests/Export/Aggregator/ScopeAggregatorTest.php @@ -20,6 +20,7 @@ namespace Chill\CalendarBundle\Tests\Export\Aggregator; use Chill\CalendarBundle\Entity\Calendar; use Chill\CalendarBundle\Export\Aggregator\ScopeAggregator; +use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Test\Export\AbstractAggregatorTest; use Doctrine\ORM\EntityManagerInterface; @@ -46,7 +47,9 @@ 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')), + ], ]; } diff --git a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml index f608bfc12..20e9604db 100644 --- a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml @@ -117,7 +117,11 @@ Group calendars by cancel reason: Grouper les rendez-vous par motif d'annulation Group calendars by month and year: Grouper les rendez-vous par mois et année Group calendars by urgency: Grouper les rendez-vous par urgent ou non -export.aggregator.calendar.Calc date: Date de calcul du métier de l'agent +export.aggregator.calendar: + agent_job: + Calc date: Date de calcul du métier de l'agent + agent_scope: + Calc date: Date de calcul du service de l'agent Scope: Service Job: Métier From 3f4a42adb2d98d459803e1339b7a23efdb537dd0 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 27 Sep 2023 10:05:25 +0200 Subject: [PATCH 19/62] [export] fix calendar scope/job Filters query + unit test (partial) --- .../Export/Aggregator/JobAggregator.php | 2 +- .../Export/Aggregator/ScopeAggregator.php | 5 +- .../Export/Filter/JobFilter.php | 73 +++++++++++------- .../Export/Filter/ScopeFilter.php | 74 +++++++++++-------- .../Tests/Export/Filter/JobFilterTest.php | 12 ++- .../Tests/Export/Filter/ScopeFilterTest.php | 2 + .../translations/messages.fr.yml | 2 +- 7 files changed, 111 insertions(+), 59 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php index 94807d709..4de1f863b 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php +++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php @@ -71,7 +71,7 @@ final readonly class JobAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { $builder->add('job_at', PickRollingDateType::class, [ - 'label' => 'export.aggregator.calendar.agent_job.Calc date', + 'label' => 'export.calendar.agent_job.Calc date', ]); } diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php index df68b7c42..9e395de80 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php +++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php @@ -60,7 +60,8 @@ final readonly class ScopeAggregator implements AggregatorInterface ->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select") ->setParameter( "{$p}_at", - $this->rollingDateConverter->convert($data['scope_at'])) + $this->rollingDateConverter->convert($data['scope_at']) + ) ->addGroupBy("{$p}_select"); } @@ -72,7 +73,7 @@ final readonly class ScopeAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { $builder->add('scope_at', PickRollingDateType::class, [ - 'label' => 'export.aggregator.calendar.agent_scope.Calc date', + 'label' => 'export.calendar.agent_scope.Calc date', ]); } public function getFormDefaultData(): array diff --git a/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php b/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php index 1391c4968..ae36fe2f0 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php +++ b/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php @@ -12,19 +12,28 @@ declare(strict_types=1); namespace Chill\CalendarBundle\Export\Filter; use Chill\CalendarBundle\Export\Declarations; +use Chill\MainBundle\Entity\User\UserJobHistory; use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Export\FilterInterface; +use Chill\MainBundle\Form\Type\PickRollingDateType; +use Chill\MainBundle\Service\RollingDate\RollingDate; +use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelper; -use Doctrine\ORM\Query\Expr\Andx; +use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Contracts\Translation\TranslatorInterface; -use function in_array; class JobFilter implements FilterInterface { - public function __construct(protected TranslatorInterface $translator, private readonly TranslatableStringHelper $translatableStringHelper) {} + private const PREFIX = 'cal_filter_job'; + + public function __construct( + private readonly RollingDateConverter $rollingDateConverter, + protected TranslatorInterface $translator, + private readonly TranslatableStringHelper $translatableStringHelper + ) {} public function addRole(): ?string { @@ -33,21 +42,29 @@ class JobFilter implements FilterInterface public function alterQuery(QueryBuilder $qb, $data) { - if (!in_array('caluser', $qb->getAllAliases(), true)) { - $qb->join('cal.mainUser', 'caluser'); - } + $p = self::PREFIX; - $where = $qb->getDQLPart('where'); - $clause = $qb->expr()->in('caluser.userJob', ':job'); + $qb + ->leftJoin( + "cal.mainUser", + "{$p}_user" + ) + ->leftJoin( + UserJobHistory::class, + "{$p}_history", + Expr\Join::WITH, + $qb->expr()->eq("{$p}_history.user", "{$p}_user") + ) + ->andWhere($qb->expr()->in("{$p}_history.job", ":{$p}_job")) + ->andWhere( + "{$p}_history.startDate <= :{$p}_at AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > :{$p}_at)" + ) + ->setParameters([ + ["{$p}_job", $data["job"]], + ["{$p}_at", $this->rollingDateConverter->convert($data["job_at"])] + ]) + ; - if ($where instanceof Andx) { - $where->add($clause); - } else { - $where = $qb->expr()->andX($clause); - } - - $qb->add('where', $where); - $qb->setParameter('job', $data['job']); } public function applyOn(): string @@ -57,18 +74,24 @@ class JobFilter implements FilterInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('job', EntityType::class, [ - 'class' => UserJob::class, - 'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize( - $j->getLabel() - ), - 'multiple' => true, - 'expanded' => true, - ]); + $builder + ->add('job', EntityType::class, [ + 'class' => UserJob::class, + 'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize( + $j->getLabel() + ), + 'multiple' => true, + 'expanded' => true, + ]) + ->add('job_at', PickRollingDateType::class, [ + 'label' => 'export.calendar.agent_job.Calc date', + ]); } public function getFormDefaultData(): array { - return []; + return [ + 'job_at' => new RollingDate(RollingDate::T_TODAY), + ]; } public function describeAction($data, $format = 'string'): array diff --git a/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php b/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php index a30638d0d..30f732f9b 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php +++ b/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php @@ -13,18 +13,27 @@ namespace Chill\CalendarBundle\Export\Filter; use Chill\CalendarBundle\Export\Declarations; use Chill\MainBundle\Entity\Scope; +use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\FilterInterface; +use Chill\MainBundle\Form\Type\PickRollingDateType; +use Chill\MainBundle\Service\RollingDate\RollingDate; +use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelper; -use Doctrine\ORM\Query\Expr\Andx; +use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Contracts\Translation\TranslatorInterface; -use function in_array; class ScopeFilter implements FilterInterface { - public function __construct(protected TranslatorInterface $translator, private readonly TranslatableStringHelper $translatableStringHelper) {} + private const PREFIX = 'cal_filter_scope'; + + public function __construct( + private RollingDateConverter $rollingDateConverter, + protected TranslatorInterface $translator, + private readonly TranslatableStringHelper $translatableStringHelper + ) {} public function addRole(): ?string { @@ -33,45 +42,52 @@ class ScopeFilter implements FilterInterface public function alterQuery(QueryBuilder $qb, $data) { - if (!in_array('caluser', $qb->getAllAliases(), true)) { - $qb->join('cal.mainUser', 'caluser'); - } + $p = self::PREFIX; - $where = $qb->getDQLPart('where'); - $clause = $qb->expr()->in('caluser.mainScope', ':scope'); - - if ($where instanceof Andx) { - $where->add($clause); - } else { - $where = $qb->expr()->andX($clause); - } - - $qb->add('where', $where); - $qb->setParameter('scope', $data['scope']); + $qb + ->leftJoin("cal.mainUser", "{$p}_user") + ->leftJoin( + UserScopeHistory::class, + "{$p}_history", + Expr\Join::WITH, + $qb->expr()->eq("{$p}_history.user", "{$p}_user") + ) + ->andWhere($qb->expr()->in("{$p}_history.scope", ":{$p}_scope")) + ->andWhere( + "{$p}_history.startDate <= :{$p}_at AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > :{$p}_at)" + ) + ->setParameters([ + ["{$p}_scope", $data["scope"]], + ["{$p}_at", $this->rollingDateConverter->convert($data['scope_at'])] + ]); } - public function applyOn() + public function applyOn(): string { return Declarations::CALENDAR_TYPE; } public function buildForm(FormBuilderInterface $builder) { - $builder->add('scope', EntityType::class, [ - 'class' => Scope::class, - 'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize( - $s->getName() - ), - 'multiple' => true, - 'expanded' => true, - ]); + $builder + ->add('scope', EntityType::class, [ + 'class' => Scope::class, + 'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize( + $s->getName() + ), + 'multiple' => true, + 'expanded' => true, + ]) + ->add('scope_at', PickRollingDateType::class, [ + 'label' => 'export.calendar.agent_scope.Calc date', + ]); } public function getFormDefaultData(): array { - return []; + return ['scope_at' => new RollingDate(RollingDate::T_TODAY)]; } - public function describeAction($data, $format = 'string') + public function describeAction($data, $format = 'string'): array { $scopes = []; @@ -86,7 +102,7 @@ class ScopeFilter implements FilterInterface ]]; } - public function getTitle() + public function getTitle(): string { return 'Filter calendars by agent scope'; } diff --git a/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/JobFilterTest.php b/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/JobFilterTest.php index 42629896c..c1305036c 100644 --- a/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/JobFilterTest.php +++ b/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/JobFilterTest.php @@ -21,6 +21,7 @@ namespace Chill\CalendarBundle\Tests\Export\Filter; use Chill\CalendarBundle\Entity\Calendar; use Chill\CalendarBundle\Export\Filter\JobFilter; use Chill\MainBundle\Entity\UserJob; +use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Test\Export\AbstractFilterTest; use Doctrine\ORM\EntityManagerInterface; @@ -62,7 +63,16 @@ final class JobFilterTest extends AbstractFilterTest ->setMaxResults(1) ->getResult(); - yield ['job' => $array]; + $data = []; + + foreach ($array as $a) { + $data[] = [ + 'job' => $a, + 'job_at' => new RollingDate(RollingDate::T_FIXED_DATE, \DateTimeImmutable::createFromFormat('Y-m-d', '2020-01-01')), + ]; + } + + return $data; } 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..5d54a091e 100644 --- a/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/ScopeFilterTest.php +++ b/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/ScopeFilterTest.php @@ -21,6 +21,7 @@ namespace Chill\CalendarBundle\Tests\Export\Filter; use Chill\CalendarBundle\Entity\Calendar; use Chill\CalendarBundle\Export\Filter\ScopeFilter; use Chill\MainBundle\Entity\Scope; +use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Test\Export\AbstractFilterTest; use Doctrine\ORM\EntityManagerInterface; @@ -67,6 +68,7 @@ final class ScopeFilterTest extends AbstractFilterTest foreach ($array as $a) { $data[] = [ 'scope' => $a, + 'scope_at' => new RollingDate(RollingDate::T_FIXED_DATE, \DateTimeImmutable::createFromFormat('Y-m-d', '2020-01-01')), ]; } diff --git a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml index 20e9604db..0da92fd72 100644 --- a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml @@ -117,7 +117,7 @@ Group calendars by cancel reason: Grouper les rendez-vous par motif d'annulation Group calendars by month and year: Grouper les rendez-vous par mois et année Group calendars by urgency: Grouper les rendez-vous par urgent ou non -export.aggregator.calendar: +export.calendar: agent_job: Calc date: Date de calcul du métier de l'agent agent_scope: From 9db0011b2ee87526e57e5963048f6390f2d54daf Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 27 Sep 2023 11:53:12 +0200 Subject: [PATCH 20/62] [export] fix acp ReferrerScopeAggregator query + unit test TO CHECK: logic in alterQuery. calc_date is same for 2 histories ? --- .../Export/Aggregator/JobAggregator.php | 1 + .../Export/Aggregator/ScopeAggregator.php | 1 + .../Export/Filter/JobFilter.php | 1 + .../Export/Filter/ScopeFilter.php | 1 + .../ReferrerScopeAggregator.php | 73 ++++++++++++------- .../ReferrerScopeAggregatorTest.php | 1 - 6 files changed, 49 insertions(+), 29 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php index 4de1f863b..6a7d4cf5d 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php +++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php @@ -72,6 +72,7 @@ final readonly class JobAggregator implements AggregatorInterface { $builder->add('job_at', PickRollingDateType::class, [ 'label' => 'export.calendar.agent_job.Calc date', + 'required' => true, ]); } diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php index 9e395de80..f7c71951e 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php +++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php @@ -74,6 +74,7 @@ final readonly class ScopeAggregator implements AggregatorInterface { $builder->add('scope_at', PickRollingDateType::class, [ 'label' => 'export.calendar.agent_scope.Calc date', + 'required' => true, ]); } public function getFormDefaultData(): array diff --git a/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php b/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php index ae36fe2f0..da0cb5225 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php +++ b/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php @@ -85,6 +85,7 @@ class JobFilter implements FilterInterface ]) ->add('job_at', PickRollingDateType::class, [ 'label' => 'export.calendar.agent_job.Calc date', + 'required' => true, ]); } public function getFormDefaultData(): array diff --git a/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php b/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php index 30f732f9b..e89f00b52 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php +++ b/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php @@ -80,6 +80,7 @@ class ScopeFilter implements FilterInterface ]) ->add('scope_at', PickRollingDateType::class, [ 'label' => 'export.calendar.agent_scope.Calc date', + 'required' => true, ]); } public function getFormDefaultData(): array diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php index 7810df3f8..801e5d799 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators; +use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\AggregatorInterface; use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\ScopeRepositoryInterface; @@ -18,15 +19,20 @@ use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\PersonBundle\Export\Declarations; +use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; use LogicException; use Symfony\Component\Form\FormBuilderInterface; -class ReferrerScopeAggregator implements AggregatorInterface +readonly class ReferrerScopeAggregator implements AggregatorInterface { - private const SCOPE_KEY = 'acp_agg_refscope_user_history_ref_scope_name'; + private const PREFIX = 'acp_agg_referrer_scope'; - public function __construct(private readonly ScopeRepositoryInterface $scopeRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper, private readonly RollingDateConverterInterface $rollingDateConverter) {} + public function __construct( + private ScopeRepositoryInterface $scopeRepository, + private TranslatableStringHelperInterface $translatableStringHelper, + private RollingDateConverterInterface $rollingDateConverter + ) {} public function addRole(): ?string { @@ -35,48 +41,59 @@ class ReferrerScopeAggregator implements AggregatorInterface public function alterQuery(QueryBuilder $qb, $data) { - $userHistory = 'acp_agg_refscope_user_history'; - $ref = 'acp_agg_refscope_user_history_ref'; - $scopeName = self::SCOPE_KEY; - $dateCalc = 'acp_agg_refscope_user_history_date_calc'; + $p = self::PREFIX; $qb - ->leftJoin('acp.userHistories', $userHistory) - ->leftJoin($userHistory . '.user', $ref) + ->leftJoin("acp.userHistories", "{$p}_userHistory") + ->leftJoin("{$p}_userHistory.user", "{$p}_user") + ->leftJoin( + UserScopeHistory::class, + "{$p}_scopeHistory", + Expr\Join::WITH, + $qb->expr()->eq("{$p}_scopeHistory.user", "{$p}_user") + ) ->andWhere( $qb->expr()->orX( - $qb->expr()->isNull($userHistory), + $qb->expr()->isNull("{$p}_userHistory"), $qb->expr()->andX( - $qb->expr()->lte($userHistory . '.startDate', ':' . $dateCalc), + $qb->expr()->lte("{$p}_userHistory.startDate", ":{$p}_date_calc"), $qb->expr()->orX( - $qb->expr()->isNull($userHistory . '.endDate'), - $qb->expr()->gt($userHistory . '.endDate', ':' . $dateCalc) + $qb->expr()->isNull("{$p}_userHistory.endDate"), + $qb->expr()->gt("{$p}_userHistory.endDate", ":{$p}_date_calc") ) ) ) ) + ->andWhere( + $qb->expr()->andX( + $qb->expr()->lte("{$p}_scopeHistory.startDate", ":{$p}_date_calc"), + $qb->expr()->orX( + $qb->expr()->isNull("{$p}_scopeHistory.endDate"), + $qb->expr()->gt("{$p}_scopeHistory.endDate", ":{$p}_date_calc") + ) + ) + ) ->setParameter( - $dateCalc, + "{$p}_date_calc", $this->rollingDateConverter->convert($data['date_calc']) - ); - - // add groups - $qb - ->addSelect('IDENTITY(' . $ref . '.mainScope) AS ' . $scopeName) - ->addGroupBy($scopeName); + ) + ->addSelect("IDENTITY({$p}_scopeHistory.scope) AS {$p}_scope_name") + ->addGroupBy("{$p}_scope_name"); } - public function applyOn() + public function applyOn(): string { return Declarations::ACP_TYPE; } public function buildForm(FormBuilderInterface $builder) { - $builder->add('date_calc', PickRollingDateType::class, [ - 'label' => 'export.aggregator.course.by_user_scope.Computation date for referrer', - 'required' => true, - ]); + $builder + ->add('date_calc', PickRollingDateType::class, [ + 'label' => 'export.aggregator.course.by_user_scope.Computation date for referrer', + 'required' => true, + ]) + ; } public function getFormDefaultData(): array { @@ -104,12 +121,12 @@ class ReferrerScopeAggregator implements AggregatorInterface }; } - public function getQueryKeys($data) + public function getQueryKeys($data): array { - return [self::SCOPE_KEY]; + return [self::PREFIX . '_scope_name']; } - public function getTitle() + public function getTitle(): string { return 'export.aggregator.course.by_user_scope.Group course by referrer\'s scope'; } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregatorTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregatorTest.php index 6e17b2059..c69e775be 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregatorTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregatorTest.php @@ -71,7 +71,6 @@ final class ReferrerScopeAggregatorTest extends AbstractAggregatorTest $em->createQueryBuilder() ->select('count(acp.id)') ->from(AccompanyingPeriod::class, 'acp') - ->join('acp.scopes', 'acpscope'), ]; } } From 8b7600e09f0a648826353b5cc4c24cfaaab025dc Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 27 Sep 2023 13:30:33 +0200 Subject: [PATCH 21/62] [export] fix acp UserJobAggregator query + unit test --- .../ReferrerScopeAggregator.php | 6 +- .../UserJobAggregator.php | 59 +++++++++++++++---- .../UserJobAggregatorTest.php | 5 +- .../translations/messages.fr.yml | 6 +- 4 files changed, 58 insertions(+), 18 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php index 801e5d799..abd9feffb 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php @@ -77,8 +77,8 @@ readonly class ReferrerScopeAggregator implements AggregatorInterface "{$p}_date_calc", $this->rollingDateConverter->convert($data['date_calc']) ) - ->addSelect("IDENTITY({$p}_scopeHistory.scope) AS {$p}_scope_name") - ->addGroupBy("{$p}_scope_name"); + ->addSelect("IDENTITY({$p}_scopeHistory.scope) AS {$p}_select") + ->addGroupBy("{$p}_select"); } public function applyOn(): string @@ -123,7 +123,7 @@ readonly class ReferrerScopeAggregator implements AggregatorInterface public function getQueryKeys($data): array { - return [self::PREFIX . '_scope_name']; + return [self::PREFIX . '_select']; } public function getTitle(): string diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php index 883635a1e..bd65b555d 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php @@ -11,17 +11,27 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators; +use Chill\MainBundle\Entity\User\UserJobHistory; 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\Export\Declarations; +use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; -use function in_array; final readonly class UserJobAggregator implements AggregatorInterface { - public function __construct(private UserJobRepository $jobRepository, private TranslatableStringHelper $translatableStringHelper) {} + private const PREFIX = 'acp_agg_user_job'; + + public function __construct( + private RollingDateConverter $rollingDateConverter, + private UserJobRepository $jobRepository, + private TranslatableStringHelper $translatableStringHelper + ) {} public function addRole(): ?string { @@ -30,12 +40,31 @@ final readonly class UserJobAggregator implements AggregatorInterface public function alterQuery(QueryBuilder $qb, $data) { - if (!in_array('acpuser', $qb->getAllAliases(), true)) { - $qb->leftJoin('acp.user', 'acpuser'); - } + $p = self::PREFIX; - $qb->addSelect('IDENTITY(acpuser.userJob) AS job_aggregator'); - $qb->addGroupBy('job_aggregator'); + $qb + ->leftJoin("acp.user", "{$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") + ) + ) + ) + ->addSelect("IDENTITY({$p}_history.job) AS {$p}_select") + ->setParameter( + "{$p}_at", + $this->rollingDateConverter->convert($data['job_at']) + ) + ->addGroupBy("{$p}_select"); } public function applyOn(): string @@ -45,11 +74,15 @@ final readonly class UserJobAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - // no form + $builder + ->add('job_at', PickRollingDateType::class, [ + 'label' => 'export.acp.referrer_job.Calc date', + 'required' => true + ]); } public function getFormDefaultData(): array { - return []; + return ['job_at' => new RollingDate(RollingDate::T_TODAY)]; } public function getLabels($key, array $values, $data) @@ -63,7 +96,9 @@ final readonly class UserJobAggregator implements AggregatorInterface return ''; } - $j = $this->jobRepository->find($value); + if (null === $j = $this->jobRepository->find($value)) { + return ''; + } return $this->translatableStringHelper->localize( $j->getLabel() @@ -73,11 +108,11 @@ final readonly class UserJobAggregator implements AggregatorInterface public function getQueryKeys($data): array { - return ['job_aggregator']; + return [self::PREFIX . '_select']; } public function getTitle(): string { - return 'Group by user job'; + return 'export.acp.referrer_job.Group by user job'; } } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregatorTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregatorTest.php index 3b692f782..77d1fdfcc 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregatorTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregatorTest.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Chill\PersonBundle\Tests\Export\Aggregator\AccompanyingCourseAggregators; +use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Test\Export\AbstractAggregatorTest; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators\UserJobAggregator; @@ -39,7 +40,9 @@ final class UserJobAggregatorTest extends AbstractAggregatorTest public function getFormData(): array { return [ - [], + [ + 'job_at' => new RollingDate(RollingDate::T_TODAY) + ], ]; } diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index 0a8371f38..0dd982ae4 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -460,12 +460,14 @@ Filtered by person having an activity between %date_from% and %date_to% with rea ## accompanying course filters/aggr Filter by user scope: Filtrer les parcours par service du référent "Filtered by user main scope: only %scope%": "Filtré par service du référent: uniquement %scope%" - Group course by scope: Grouper les parcours par service Filter by user job: Filtrer les parcours par métier du référent "Filtered by user job: only %job%": "Filtré par métier du référent: uniquement %job%" -Group by user job: Grouper les parcours par métier du référent + +export.acp.referrer_job: + Group by user job: Grouper les parcours par métier du référent + Calc date: Date de calcul du métier du référent Filter by social issue: Filtrer les parcours par problématiques sociales Accepted socialissues: Problématiques sociales From 7c25ca8dd4f37fced9325f25fb328e9aef3896c9 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 27 Sep 2023 13:57:42 +0200 Subject: [PATCH 22/62] [export] fix acpw socialWork agent JobAggregator query + unit test --- .../SocialWorkAggregators/JobAggregator.php | 57 +++++++++++++++---- .../UserJobAggregatorTest.php | 2 +- .../JobAggregatorTest.php | 5 +- .../translations/messages.fr.yml | 13 +++-- 4 files changed, 59 insertions(+), 18 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php index ab1048144..1837a4a9b 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php @@ -11,17 +11,28 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Aggregator\SocialWorkAggregators; +use Chill\MainBundle\Entity\User\UserJobHistory; 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\Export\Declarations; +use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; use function in_array; final readonly class JobAggregator implements AggregatorInterface { - public function __construct(private UserJobRepository $jobRepository, private TranslatableStringHelper $translatableStringHelper) {} + private const PREFIX = 'acp_work_action_agg_user_job'; + + public function __construct( + private RollingDateConverter $rollingDateConverter, + private UserJobRepository $jobRepository, + private TranslatableStringHelper $translatableStringHelper + ) {} public function addRole(): ?string { @@ -30,12 +41,31 @@ final readonly class JobAggregator 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('IDENTITY(acpwuser.userJob) as job_aggregator') - ->addGroupBy('job_aggregator'); + $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") + ) + ) + ) + ->addSelect("IDENTITY({$p}_history.job) as {$p}_select") + ->setParameter( + "{$p}_at", + $this->rollingDateConverter->convert($data['job_at']) + ) + ->addGroupBy("{$p}_select"); } public function applyOn(): string @@ -45,11 +75,14 @@ final readonly class JobAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - // no form + $builder->add('job_at', PickRollingDateType::class, [ + 'label' => 'export.acpw.agent_job:Calc Date', + 'required' => true + ]); } public function getFormDefaultData(): array { - return []; + return ['job_at' => new RollingDate(RollingDate::T_TODAY)]; } public function getLabels($key, array $values, $data) @@ -63,7 +96,9 @@ final readonly class JobAggregator implements AggregatorInterface return ''; } - $j = $this->jobRepository->find($value); + if (null === $j = $this->jobRepository->find($value)) { + return ''; + } return $this->translatableStringHelper->localize( $j->getLabel() @@ -73,11 +108,11 @@ final readonly class JobAggregator implements AggregatorInterface public function getQueryKeys($data): array { - return ['job_aggregator']; + return [self::PREFIX . '_select']; } public function getTitle(): string { - return 'Group by treating agent job'; + return 'export.acpw.agent_job:Group by treating agent job'; } } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregatorTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregatorTest.php index 77d1fdfcc..cd070aca8 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregatorTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregatorTest.php @@ -41,7 +41,7 @@ final class UserJobAggregatorTest extends AbstractAggregatorTest { return [ [ - 'job_at' => new RollingDate(RollingDate::T_TODAY) + 'job_at' => new RollingDate(RollingDate::T_FIXED_DATE, \DateTimeImmutable::createFromFormat('Y-m-d', '2020-01-01')), ], ]; } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/JobAggregatorTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/JobAggregatorTest.php index 39cc20083..5a20fc3b1 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/JobAggregatorTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/JobAggregatorTest.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; use Chill\PersonBundle\Export\Aggregator\SocialWorkAggregators\JobAggregator; @@ -39,7 +40,9 @@ 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')), + ], ]; } diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index 0dd982ae4..d6f6eef4d 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -465,10 +465,6 @@ Group course by scope: Grouper les parcours par service Filter by user job: Filtrer les parcours par métier du référent "Filtered by user job: only %job%": "Filtré par métier du référent: uniquement %job%" -export.acp.referrer_job: - Group by user job: Grouper les parcours par métier du référent - Calc date: Date de calcul du métier du référent - Filter by social issue: Filtrer les parcours par problématiques sociales Accepted socialissues: Problématiques sociales "Filtered by socialissues: only %socialissues%": "Filtré par problématique sociale: uniquement %socialissues%" @@ -608,7 +604,6 @@ Filter by scope: Filtrer par service Filter by treating agent job: Filtrer les actions par métier de l'agent traitant "Filtered by treating agent job: only %jobs%": "Filtré par métier de l'agent traitant: uniquement %jobs%" -Group by treating agent job: Grouper les actions par métier de l'agent traitant Filter by treating agent: Filtrer les actions par agent traitant Accepted agents: Agent traitant @@ -1004,6 +999,14 @@ notification: personId: Identifiant de l'usager export: + acp: + referrer_job: + Group by user job: Grouper les parcours par métier du référent + Calc date: Date de calcul du métier du référent + acpw: + agent_job: + Group by treating agent job: Grouper les actions par métier de l'agent traitant + Calc date: Date de calcul du métier de l'agent traitant export: acp_stats: avg_duration: Moyenne de la durée de participation de chaque usager concerné From 0953faedc45f22e48d49af2d53fd0b48c6a36d3b Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 27 Sep 2023 14:14:08 +0200 Subject: [PATCH 23/62] [export] fix acpw socialWork agent ScopeAggregator query + unit test --- .../SocialWorkAggregators/ScopeAggregator.php | 57 +++++++++++++++---- .../ScopeAggregatorTest.php | 5 +- .../translations/messages.fr.yml | 4 +- 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php index bdfd3326f..5cea8daf2 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php @@ -11,17 +11,28 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Aggregator\SocialWorkAggregators; +use Chill\MainBundle\Entity\User\UserScopeHistory; 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\Export\Declarations; +use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; use function in_array; final readonly class ScopeAggregator implements AggregatorInterface { - public function __construct(private ScopeRepository $scopeRepository, private TranslatableStringHelper $translatableStringHelper) {} + private const PREFIX = 'acp_work_action_agg_user_scope'; + + public function __construct( + private RollingDateConverter $rollingDateConverter, + private ScopeRepository $scopeRepository, + private TranslatableStringHelper $translatableStringHelper + ) {} public function addRole(): ?string { @@ -30,12 +41,31 @@ final readonly class ScopeAggregator 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('IDENTITY(acpwuser.mainScope) as scope_aggregator'); - $qb->addGroupBy('scope_aggregator'); + $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") + ) + ) + ) + ->addSelect("IDENTITY({$p}_history.scope) as {$p}_select") + ->setParameter( + "{$p}_at", + $this->rollingDateConverter->convert($data['scope_at']) + ) + ->addGroupBy("{$p}_select"); } public function applyOn(): string @@ -45,11 +75,14 @@ final readonly class ScopeAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - // no form + $builder->add('scope_at', PickRollingDateType::class, [ + 'label' => 'export.acpw.agent_scope.Calc date', + 'required' => true, + ]); } public function getFormDefaultData(): array { - return []; + return ['scope_at' => new RollingDate(RollingDate::T_TODAY)]; } public function getLabels($key, array $values, $data) @@ -63,7 +96,9 @@ final readonly class ScopeAggregator implements AggregatorInterface return ''; } - $s = $this->scopeRepository->find($value); + if (null === $s = $this->scopeRepository->find($value)) { + return ''; + } return $this->translatableStringHelper->localize( $s->getName() @@ -73,11 +108,11 @@ final readonly class ScopeAggregator implements AggregatorInterface public function getQueryKeys($data): array { - return ['scope_aggregator']; + return [self::PREFIX . '_select']; } public function getTitle(): string { - return 'Group by treating agent scope'; + return 'export.acpw.agent_scope.Group by treating agent scope'; } } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/ScopeAggregatorTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/ScopeAggregatorTest.php index 9a31d88bc..0bb9fba13 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/ScopeAggregatorTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Aggregator/SocialWorkAggregators/ScopeAggregatorTest.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; use Chill\PersonBundle\Export\Aggregator\SocialWorkAggregators\ScopeAggregator; @@ -39,7 +40,9 @@ 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')), + ], ]; } diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index d6f6eef4d..a14ea3ed7 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -598,7 +598,6 @@ Filter by current evaluations: Filtrer les évaluations en cours ## social actions filters/aggr 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%" -Group by treating agent scope: Grouper les actions par service de l'agent traitant Filter by scope: Filtrer par service @@ -1007,6 +1006,9 @@ export: agent_job: Group by treating agent job: Grouper les actions par métier de l'agent traitant Calc date: Date de calcul du métier de l'agent traitant + agent_scope: + Group by treating agent scope: Grouper les actions par service de l'agent traitant + Calc date: Date de calcul du service de l'agent traitant export: acp_stats: avg_duration: Moyenne de la durée de participation de chaque usager concerné From e738bf0f5ecea120b6f8f0b01939fa0e881efce7 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 27 Sep 2023 14:40:30 +0200 Subject: [PATCH 24/62] [export] fix translations in message yaml tree --- .../ScopeAggregator.php | 2 +- .../UserJobAggregator.php | 4 +- .../SocialWorkAggregators/JobAggregator.php | 4 +- .../SocialWorkAggregators/ScopeAggregator.php | 4 +- .../UserJobFilter.php | 6 +-- .../translations/messages.fr.yml | 42 ++++++++++++------- 6 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeAggregator.php index 1f164a45e..c8f73f635 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeAggregator.php @@ -80,6 +80,6 @@ final readonly class ScopeAggregator implements AggregatorInterface public function getTitle(): string { - return 'Group course by scope'; + return 'export.aggregator.course.by_scope.Group course by scope'; } } diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php index bd65b555d..80e65664e 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php @@ -76,7 +76,7 @@ final readonly class UserJobAggregator implements AggregatorInterface { $builder ->add('job_at', PickRollingDateType::class, [ - 'label' => 'export.acp.referrer_job.Calc date', + 'label' => 'export.aggregator.course.by_user_job.Calc date', 'required' => true ]); } @@ -113,6 +113,6 @@ final readonly class UserJobAggregator implements AggregatorInterface public function getTitle(): string { - return 'export.acp.referrer_job.Group by user job'; + return 'export.aggregator.course.by_user_job.Group by user job'; } } diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php index 1837a4a9b..e7a1f25bb 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php @@ -76,7 +76,7 @@ final readonly class JobAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { $builder->add('job_at', PickRollingDateType::class, [ - 'label' => 'export.acpw.agent_job:Calc Date', + 'label' => 'export.aggregator.course_work.by_agent_job.Calc date', 'required' => true ]); } @@ -113,6 +113,6 @@ final readonly class JobAggregator implements AggregatorInterface public function getTitle(): string { - return 'export.acpw.agent_job:Group by treating agent job'; + return 'export.aggregator.course_work.by_agent_job.Group by treating agent job'; } } diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php index 5cea8daf2..606bb05e5 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php @@ -76,7 +76,7 @@ final readonly class ScopeAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { $builder->add('scope_at', PickRollingDateType::class, [ - 'label' => 'export.acpw.agent_scope.Calc date', + 'label' => 'export.aggregator.course_work.by_agent_scope.Calc date', 'required' => true, ]); } @@ -113,6 +113,6 @@ final readonly class ScopeAggregator implements AggregatorInterface public function getTitle(): string { - return 'export.acpw.agent_scope.Group by treating agent scope'; + return 'export.aggregator.course_work.by_agent_scope.Group by treating agent scope'; } } diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php index 082231cfc..c4b7abfcf 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php @@ -82,7 +82,7 @@ class UserJobFilter implements FilterInterface 'label' => 'Job', ]) ->add('date_calc', PickRollingDateType::class, [ - 'label' => 'export.filter.course.by_user_scope.Computation date for referrer', + 'label' => 'export.filter.course.by_user_job.Computation date for referrer', 'required' => true, ]); } @@ -94,7 +94,7 @@ class UserJobFilter implements FilterInterface public function describeAction($data, $format = 'string') { return [ - 'Filtered by user job: only %job%', [ + 'export.filter.course.by_user_job.Filtered by user job: only %job%', [ '%job%' => implode( ', ', array_map( @@ -108,6 +108,6 @@ class UserJobFilter implements FilterInterface public function getTitle() { - return 'Filter by user job'; + return 'export.filter.course.by_user_job.Filter by user job'; } } diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index a14ea3ed7..a850afc35 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -460,10 +460,6 @@ Filtered by person having an activity between %date_from% and %date_to% with rea ## accompanying course filters/aggr Filter by user scope: Filtrer les parcours par service du référent "Filtered by user main scope: only %scope%": "Filtré par service du référent: uniquement %scope%" -Group course by scope: Grouper les parcours par service - -Filter by user job: Filtrer les parcours par métier du référent -"Filtered by user job: only %job%": "Filtré par métier du référent: uniquement %job%" Filter by social issue: Filtrer les parcours par problématiques sociales Accepted socialissues: Problématiques sociales @@ -998,29 +994,20 @@ notification: personId: Identifiant de l'usager export: - acp: - referrer_job: - Group by user job: Grouper les parcours par métier du référent - Calc date: Date de calcul du métier du référent - acpw: - agent_job: - Group by treating agent job: Grouper les actions par métier de l'agent traitant - Calc date: Date de calcul du métier de l'agent traitant - agent_scope: - Group by treating agent scope: Grouper les actions par service de l'agent traitant - Calc date: Date de calcul du service de l'agent traitant export: acp_stats: avg_duration: Moyenne de la durée de participation de chaque usager concerné count_participations: Nombre de participations distinctes count_persons: Nombre d'usagers concernés distincts count_acps: Nombre de parcours distincts + nb_household_with_course: Count households with accompanying course: Nombre de ménages impliqués dans un parcours Count households: Nombre de ménages Count accompanying periods: Nombre de parcours Count household with accompanying course by various parameters.: Compte le nombre de ménages impliqués dans un parcours selon différents filtres. Date of calculation of household members: Date à laquelle les membres du ménages sont comptabilisés + aggregator: person: by_household_composition: @@ -1039,6 +1026,9 @@ export: Group course by referrer's scope: Grouper les parcours par service du référent Computation date for referrer: Date à laquelle le référent était actif Referrer's scope: Service du référent de parcours + by_user_job: + Group by user job: Grouper les parcours par métier du référent + Calc date: Date de calcul du métier du référent duration: day: Durée du parcours en jours week: Durée du parcours en semaines @@ -1057,12 +1047,22 @@ export: by_scope_working: title: Grouper les parcours par service de l'intervenant scope: Service de l'intervenant + by_scope: + Group course by scope: Grouper les parcours par service + course_work: by_current_action: Current action ?: Action en cours ? Group by current actions: Grouper les actions en cours Current action: Action en cours Not current action: Action terminée + by_agent_scope: + Group by treating agent scope: Grouper les actions par service de l'agent traitant + Calc date: Date de calcul du service de l'agent traitant + by_agent_job: + Group by treating agent job: Grouper les actions par métier de l'agent traitant + Calc date: Date de calcul du métier de l'agent traitant + eval: by_end_date: Has end date ?: Évaluation en cours ? @@ -1081,6 +1081,7 @@ export: filter: by_geog_unit: Filtered by person's geographical unit (based on address) computed at %datecalc%, only %units%: Filtré par unité géographique (sur base de l'adresse), calculé le %datecalc%, seulement %units% + person: by_composition: Filter by household composition: Filtrer les usagers par composition du ménage @@ -1139,6 +1140,11 @@ export: Calculation date: Date de la localisation creator_job: 'Filtered by creator job: only %jobs%': 'Filtré par métier du créateur: seulement %jobs%' + by_user_job: + Filter by user job: Filtrer les parcours par métier du référent + "Filtered by user job: only %job%": "Filtré par métier du référent: uniquement %job%" + Computation date for referrer: Date à laquelle le référent était actif + work: start_between_dates: title: Filtre les actions d'accompagnement dont la date d'ouverture est entre deux dates @@ -1154,12 +1160,14 @@ export: keep_null: Conserver les actions dont la date de fin n'est pas indiquée (actions en cours) keep_null_help: Si coché, les actions dont la date de fin est vide seront prises en compte. Si non coché, elles ne seront pas comptabilisée. Only where start date is between %startDate% and %endDate%: Seulement les actions dont la date de fin est entre le %startDate% et le %endDate% + list: person_with_acp: List peoples having an accompanying period: Liste des usagers ayant un parcours d'accompagnement List peoples having an accompanying period with period details: Liste des usagers concernés avec détail de chaque parcours Create a list of people having an accompaying periods, according to various filters.: Génère une liste des usagers ayant un parcours d'accompagnement, selon différents critères liés au parcours ou à l'usager Create a list of people having an accompaying periods with details of period, according to various filters.: Génère une liste des usagers ayant un parcours d'accompagnement, selon différents critères liés au parcours ou à l'usager. Ajoute les détails du parcours à la liste. + acp: List of accompanying periods: Liste des parcours d'accompagnements Generate a list of accompanying periods, filtered on different parameters.: Génère une liste des parcours d'accompagnement, filtrée sur différents paramètres. @@ -1198,6 +1206,7 @@ export: socialIssues: Problématiques sociales requestorPerson: Demandeur (personne) requestorThirdParty: Demandeur (tiers) + eval: List of evaluations: Liste des évaluations Generate a list of evaluations, filtered on different parameters: Génère une liste des évaluations, filtrée sur différents paramètres. @@ -1227,6 +1236,7 @@ export: createdBy: Créé par updatedBy: Modifié par timeSpent: Temps de rédaction (minutes) + acpw: List of accompanying period works: Liste des actions List description: Génère une liste des actions d'accompagnement, filtrée sur différents paramètres. @@ -1256,6 +1266,7 @@ export: resultsTitle: Résultats evaluationsId: Identifiants des évaluations evaluationsTitle: Évaluations + household: List household associated with accompanying period title: Liste des ménages impliqués dans un parcours List description: Génère la liste des ménages, filtrée selon divers paramètres. @@ -1269,6 +1280,7 @@ export: compositionNumberOfChildren: Nombre d'enfants dans la composition compositionComment: Commentaire sur la composition compositionType: Type de composition + acpaddress_fieldscountry: Pays # addressHelper effect social_action: From f225a83a3e79fdbfbaadc1f640b89c25967a0fc7 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 27 Sep 2023 15:00:46 +0200 Subject: [PATCH 25/62] [export] fix acp userJob Filter query + unit test (partial) --- .../UserJobFilter.php | 56 ++++++++++++------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php index c4b7abfcf..4f0d368d5 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters; +use Chill\MainBundle\Entity\User\UserJobHistory; use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Form\Type\PickRollingDateType; @@ -22,19 +23,16 @@ use Chill\PersonBundle\Export\Declarations; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Security\Core\Security; class UserJobFilter implements FilterInterface { - private const A = 'acp_ujob_filter_uhistory'; + private const PREFIX = 'acp_filter_user_job'; - private const AU = 'acp_ujob_filter_uhistory_user'; - - private const P = 'acp_ujob_filter_date'; - - private const PJ = 'acp_ujob_filter_job'; - - public function __construct(private readonly TranslatableStringHelper $translatableStringHelper, private readonly UserJobRepositoryInterface $userJobRepository, private readonly RollingDateConverterInterface $rollingDateConverter) {} + public function __construct( + private readonly TranslatableStringHelper $translatableStringHelper, + private readonly UserJobRepositoryInterface $userJobRepository, + private readonly RollingDateConverterInterface $rollingDateConverter + ) {} public function addRole(): ?string { @@ -43,26 +41,42 @@ class UserJobFilter implements FilterInterface public function alterQuery(QueryBuilder $qb, $data) { + $p = self::PREFIX; + $qb - ->join('acp.userHistories', self::A) + ->leftJoin("acp.userHistories", "{$p}_userHistory") + ->leftJoin("{$p}_userHistory.user", "{$p}_user") + ->leftJoin( + UserJobHistory::class, + "{$p}_jobHistory", + $qb->expr()->eq("{$p}_jobHistory", "{$p}_user") + ) ->andWhere( $qb->expr()->andX( - $qb->expr()->lte(self::A . '.startDate', ':' . self::P), + $qb->expr()->lte("{$p}_userHistory.startDate", ":{$p}_date"), $qb->expr()->orX( - $qb->expr()->isNull(self::A . '.endDate'), - $qb->expr()->gt(self::A . '.endDate', ':' . self::P) + $qb->expr()->isNull("{$p}_userHistory" . ".endDate"), + $qb->expr()->gt("{$p}_userHistory.endDate", ":{$p}_date") ) ) ) - ->setParameter( - self::P, - $this->rollingDateConverter->convert($data['date_calc']) - ) - ->join(self::A . '.user', self::AU) ->andWhere( - $qb->expr()->in(self::AU . '.userJob', ':' . self::PJ) + $qb->expr()->andX( + $qb->expr()->lte("{$p}_jobHistory.startDate", ":{$p}_date"), + $qb->expr()->orX( + $qb->expr()->isNull("{$p}_jobHistory" . ".endDate"), + $qb->expr()->gt("{$p}_jobHistory.endDate", ":{$p}_date") + ) + ) ) - ->setParameter(self::PJ, $data['jobs']); + ->andWhere( + $qb->expr()->in("{$p}_jobHistory.job", ":{$p}_job") + ) + ->setParameters([ + ["{$p}_job", $data["jobs"]], + ["{$p}_date", $this->rollingDateConverter->convert($data["date_calc"])] + ]) + ; } public function applyOn() @@ -106,7 +120,7 @@ class UserJobFilter implements FilterInterface ]; } - public function getTitle() + public function getTitle():string { return 'export.filter.course.by_user_job.Filter by user job'; } From 9b272e9b9ec21b0d3114061973abcc09c7287e87 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 27 Sep 2023 15:22:02 +0200 Subject: [PATCH 26/62] [export] fix acp user Scope Filter query + unit test (partial) --- .../UserScopeFilter.php | 73 ++++++++++--------- .../translations/messages.fr.yml | 5 +- 2 files changed, 42 insertions(+), 36 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php index 5a08eadc1..38450a1a0 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php @@ -12,7 +12,7 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters; use Chill\MainBundle\Entity\Scope; -use Chill\MainBundle\Entity\User; +use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\ScopeRepositoryInterface; @@ -20,22 +20,20 @@ use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface; use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\PersonBundle\Export\Declarations; +use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Security\Core\Security; class UserScopeFilter implements FilterInterface { - private const A = 'acp_uscope_filter_uhistory'; + private const PREFIX = 'acp_filter_main_scope'; - private const AU = 'acp_uscope_filter_uhistory_user'; - - private const P = 'acp_uscope_filter_date'; - - private const PS = 'acp_uscope_filter_scopes'; - - public function __construct(private readonly ScopeRepositoryInterface $scopeRepository, private readonly Security $security, private readonly TranslatableStringHelper $translatableStringHelper, private readonly RollingDateConverterInterface $rollingDateConverter) {} + public function __construct( + private readonly ScopeRepositoryInterface $scopeRepository, + private readonly TranslatableStringHelper $translatableStringHelper, + private readonly RollingDateConverterInterface $rollingDateConverter + ) {} public function addRole(): ?string { @@ -44,29 +42,46 @@ class UserScopeFilter implements FilterInterface public function alterQuery(QueryBuilder $qb, $data) { + $p = self::PREFIX; + $qb - ->join('acp.userHistories', self::A) + ->join("acp.userHistories", "{$p}_userHistory") + ->join("{$p}_userHistory.user", "{$p}_user") + ->join( + UserScopeHistory::class, + "{$p}_scopeHistory", + Expr\Join::WITH, + $qb->expr()->eq("{$p}_scopeHistory", "{$p}_user") + ) ->andWhere( $qb->expr()->andX( - $qb->expr()->lte(self::A . '.startDate', ':' . self::P), + $qb->expr()->lte("{$p}_userHistory.startDate", ":{$p}_date"), $qb->expr()->orX( - $qb->expr()->isNull(self::A . '.endDate'), - $qb->expr()->gt(self::A . '.endDate', ':' . self::P) + $qb->expr()->isNull("{$p}_userHistory.endDate"), + $qb->expr()->gt("{$p}_userHistory.endDate", ":{$p}_date") ) ) ) - ->setParameter( - self::P, - $this->rollingDateConverter->convert($data['date_calc']) - ) - ->join(self::A . '.user', self::AU) ->andWhere( - $qb->expr()->in(self::AU . '.mainScope', ':' . self::PS) + $qb->expr()->andX( + $qb->expr()->lte("{$p}_scopeHistory.startDate", ":{$p}_date"), + $qb->expr()->orX( + $qb->expr()->isNull("{$p}_scopeHistory.endDate"), + $qb->expr()->gt("{$p}_scopeHistory.endDate", ":{$p}_date") + ) + ) ) - ->setParameter(self::PS, $data['scopes']); + ->andWhere( + $qb->expr()->in("{$p}_scopeHistory.scope", ":{$p}_scopes") + ) + ->setParameters([ + ["{$p}_scopes", $data["scopes"]], + ["{$p}_date", $this->rollingDateConverter->convert($data["date_calc"])] + ]) + ; } - public function applyOn() + public function applyOn(): string { return Declarations::ACP_TYPE; } @@ -94,7 +109,7 @@ class UserScopeFilter implements FilterInterface public function describeAction($data, $format = 'string') { return [ - 'Filtered by user main scope: only %scope%', [ + 'export.filter.course.by_user_scope.Filtered by user main scope: only %scope%', [ '%scope%' => implode( ', ', array_map( @@ -106,16 +121,8 @@ class UserScopeFilter implements FilterInterface ]; } - public function getTitle() + public function getTitle():string { - return 'Filter by user scope'; - } - - private function getUserMainScope(): Scope - { - /** @var User $user */ - $user = $this->security->getUser(); - - return $user->getMainScope(); + return 'export.filter.course.by_user_scope.Filter by user scope'; } } diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index a850afc35..22b0c4096 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -458,9 +458,6 @@ Filtered by person having an activity between %date_from% and %date_to% with rea ## accompanying course filters/aggr -Filter by user scope: Filtrer les parcours par service du référent -"Filtered by user main scope: only %scope%": "Filtré par service du référent: uniquement %scope%" - Filter by social issue: Filtrer les parcours par problématiques sociales Accepted socialissues: Problématiques sociales "Filtered by socialissues: only %socialissues%": "Filtré par problématique sociale: uniquement %socialissues%" @@ -1131,6 +1128,8 @@ export: 'Filtered by steps: only %step% and between %date_from% and %date_to%': 'Filtré par statut: seulement %step%, entre %date_from% et %date_to%' by_user_scope: Computation date for referrer: Date à laquelle le référent était actif + Filter by user scope: Filtrer les parcours par service du référent + "Filtered by user main scope: only %scope%": "Filtré par service du référent: uniquement %scope%" by_referrer: Computation date for referrer: Date à laquelle le référent était actif having_temporarily: From bc69f83c37e5428101bd0e02838c55693b2e84f1 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 27 Sep 2023 15:57:31 +0200 Subject: [PATCH 27/62] [export] fix acpw socialWork agent JobFilter query + unit test (partial) --- .../Filter/SocialWorkFilters/JobFilter.php | 82 +++++++++++++------ .../SocialWorkFilters/JobFilterTest.php | 4 +- .../translations/messages.fr.yml | 7 +- 3 files changed, 62 insertions(+), 31 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php index 91c48b22b..7eaa1fc74 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php @@ -11,10 +11,15 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Filter\SocialWorkFilters; +use Chill\MainBundle\Entity\User\UserJobHistory; use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Export\FilterInterface; +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\Export\Declarations; +use Doctrine\ORM\Query\Expr; use Doctrine\ORM\Query\Expr\Andx; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; @@ -24,7 +29,13 @@ use function in_array; class JobFilter implements FilterInterface { - public function __construct(protected TranslatorInterface $translator, private readonly TranslatableStringHelper $translatableStringHelper) {} + private const PREFIX = 'acp_work_action_filter_user_job'; + + public function __construct( + private readonly RollingDateConverter $rollingDateConverter, + protected TranslatorInterface $translator, + private readonly TranslatableStringHelper $translatableStringHelper + ) {} public function addRole(): ?string { @@ -33,42 +44,59 @@ class JobFilter 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.userJob', ':job'); - - if ($where instanceof Andx) { - $where->add($clause); - } else { - $where = $qb->expr()->andX($clause); - } - - $qb->add('where', $where); - $qb->setParameter('job', $data['job']); + $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'])] + ]); } - public function applyOn() + public function applyOn(): string { return Declarations::SOCIAL_WORK_ACTION_TYPE; } public function buildForm(FormBuilderInterface $builder) { - $builder->add('job', EntityType::class, [ - 'class' => UserJob::class, - 'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize( - $j->getLabel() - ), - 'multiple' => true, - 'expanded' => true, - ]); + $builder + ->add('job', EntityType::class, [ + 'class' => UserJob::class, + 'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize( + $j->getLabel() + ), + 'multiple' => true, + 'expanded' => true, + ]) + ->add('job_at', PickRollingDateType::class, [ + 'label' => 'export.filter.work.by_user_job.Calc date', + 'required' => true, + ]) + ; } public function getFormDefaultData(): array { - return []; + return ['job_at' => new RollingDate(RollingDate::T_TODAY)]; } public function describeAction($data, $format = 'string') @@ -81,13 +109,13 @@ class JobFilter implements FilterInterface ); } - return ['Filtered by treating agent job: only %jobs%', [ + return ['export.filter.work.by_user_job.Filtered by treating agent job: only %jobs%', [ '%jobs%' => implode(', ', $userjobs), ]]; } public function getTitle(): string { - return 'Filter by treating agent job'; + return 'export.filter.work.by_user_job.Filter by treating agent job'; } } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/JobFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/JobFilterTest.php index 890222b5b..f5836c18c 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/JobFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/JobFilterTest.php @@ -12,6 +12,7 @@ declare(strict_types=1); namespace Chill\PersonBundle\Tests\Export\Filter\SocialWorkFilters; use Chill\MainBundle\Entity\UserJob; +use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Test\Export\AbstractFilterTest; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork; use Chill\PersonBundle\Export\Filter\SocialWorkFilters\JobFilter; @@ -49,7 +50,8 @@ final class JobFilterTest extends AbstractFilterTest return [ [ - 'job' => new ArrayCollection($jobs) + '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/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index 22b0c4096..9f4915f78 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -594,9 +594,6 @@ Filter by treating agent scope: Filtrer les actions par service de l'agent trait Filter by scope: Filtrer par service -Filter by treating agent job: Filtrer les actions par métier de l'agent traitant -"Filtered by treating agent job: only %jobs%": "Filtré par métier de l'agent traitant: uniquement %jobs%" - 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%" @@ -1159,6 +1156,10 @@ export: keep_null: Conserver les actions dont la date de fin n'est pas indiquée (actions en cours) keep_null_help: Si coché, les actions dont la date de fin est vide seront prises en compte. Si non coché, elles ne seront pas comptabilisée. Only where start date is between %startDate% and %endDate%: Seulement les actions dont la date de fin est entre le %startDate% et le %endDate% + by_user_job: + Filter by treating agent job: Filtrer les actions par métier de l'agent traitant + "Filtered by treating agent job: only %jobs%": "Filtré par métier de l'agent traitant: uniquement %jobs%" + Calc date: Date de calcul du métier de l'agent traitant list: person_with_acp: From aeb0d5eab851674b9deb2b85d4b7dfd60ebfc740 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 27 Sep 2023 16:13:11 +0200 Subject: [PATCH 28/62] [export] fix acpw socialWork agent ScopeFilter query + unit test (partial) --- .../UserJobFilter.php | 2 +- .../UserScopeFilter.php | 2 +- .../Filter/SocialWorkFilters/ScopeFilter.php | 86 ++++++++++++------- .../SocialWorkFilters/ScopeFilterTest.php | 4 +- .../translations/messages.fr.yml | 7 +- 5 files changed, 65 insertions(+), 36 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php index 4f0d368d5..65acb56e5 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php @@ -120,7 +120,7 @@ class UserJobFilter implements FilterInterface ]; } - public function getTitle():string + public function getTitle(): string { return 'export.filter.course.by_user_job.Filter by user job'; } diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php index 38450a1a0..d530e0bd2 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php @@ -121,7 +121,7 @@ class UserScopeFilter implements FilterInterface ]; } - public function getTitle():string + public function getTitle(): string { return 'export.filter.course.by_user_scope.Filter by user scope'; } diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php index f25897a7e..5f15ccbaa 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php @@ -12,19 +12,28 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Filter\SocialWorkFilters; use Chill\MainBundle\Entity\Scope; +use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\FilterInterface; +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\Export\Declarations; -use Doctrine\ORM\Query\Expr\Andx; +use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Contracts\Translation\TranslatorInterface; -use function in_array; class ScopeFilter implements FilterInterface { - public function __construct(protected TranslatorInterface $translator, private readonly TranslatableStringHelper $translatableStringHelper) {} + private const PREFIX = 'acp_work_action_filter_user_scope'; + + public function __construct( + private readonly RollingDateConverter $rollingDateConverter, + protected TranslatorInterface $translator, + private readonly TranslatableStringHelper $translatableStringHelper + ) {} public function addRole(): ?string { @@ -33,21 +42,32 @@ class ScopeFilter 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.mainScope', ':scope'); - - if ($where instanceof Andx) { - $where->add($clause); - } else { - $where = $qb->expr()->andX($clause); - } - - $qb->add('where', $where); - $qb->setParameter('scope', $data['scope']); + $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'])] + ]); } public function applyOn() @@ -57,21 +77,27 @@ class ScopeFilter implements FilterInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('scope', EntityType::class, [ - 'class' => Scope::class, - 'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize( - $s->getName() - ), - 'multiple' => true, - 'expanded' => true, - ]); + $builder + ->add('scope', EntityType::class, [ + 'class' => Scope::class, + 'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize( + $s->getName() + ), + 'multiple' => true, + 'expanded' => true, + ]) + ->add('scope_at', PickRollingDateType::class, [ + 'label' => 'export.filter.work.by_user_scope.Calc date', + 'required' => true, + ]) + ; } public function getFormDefaultData(): array { - return []; + return ['scope_at' => new RollingDate(RollingDate::T_TODAY)]; } - public function describeAction($data, $format = 'string') + public function describeAction($data, $format = 'string'): array { $scopes = []; @@ -81,13 +107,13 @@ class ScopeFilter implements FilterInterface ); } - return ['Filtered by treating agent scope: only %scopes%', [ + return ['export.filter.work.by_user_scope.Filtered by treating agent scope: only %scopes%', [ '%scopes%' => implode(', ', $scopes), ]]; } - public function getTitle() + public function getTitle(): string { - return 'Filter by treating agent scope'; + return 'export.filter.work.by_user_scope.Filter by treating agent scope'; } } diff --git a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ScopeFilterTest.php b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ScopeFilterTest.php index 1ff6c6d6e..f2ffce2e4 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ScopeFilterTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Export/Filter/SocialWorkFilters/ScopeFilterTest.php @@ -12,6 +12,7 @@ declare(strict_types=1); namespace Chill\PersonBundle\Tests\Export\Filter\SocialWorkFilters; use Chill\MainBundle\Entity\Scope; +use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Test\Export\AbstractFilterTest; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork; use Chill\PersonBundle\Export\Filter\SocialWorkFilters\ScopeFilter; @@ -48,7 +49,8 @@ final class ScopeFilterTest extends AbstractFilterTest return [ [ - 'scope' => $scopes + 'scope' => $scopes, + 'scope_at' => new RollingDate(RollingDate::T_FIXED_DATE, \DateTimeImmutable::createFromFormat('Y-m-d', '2020-01-01')) ] ]; } diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index 9f4915f78..bfecd6559 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -589,9 +589,6 @@ Filter by current evaluations: Filtrer les évaluations en cours 'Filtered by geographic unit: computed at %date%, only in %units%': 'Filtré par unité géographique: adresse le %date%, seulement les unités %units%' ## social actions filters/aggr -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%" - Filter by scope: Filtrer par service Filter by treating agent: Filtrer les actions par agent traitant @@ -1160,6 +1157,10 @@ export: Filter by treating agent job: Filtrer les actions par métier de l'agent traitant "Filtered by treating agent job: only %jobs%": "Filtré par métier de l'agent traitant: uniquement %jobs%" Calc date: Date de calcul du métier de l'agent traitant + by_user_scope: + 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 list: person_with_acp: From 2100d45671efbf5789d13c904230ce18f6513db2 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 27 Sep 2023 16:18:33 +0200 Subject: [PATCH 29/62] fix phpstan error --- .../Export/Filter/AccompanyingCourseFilters/UserJobFilter.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php index 65acb56e5..c221d0280 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php @@ -20,6 +20,7 @@ use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface; use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\PersonBundle\Export\Declarations; +use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\FormBuilderInterface; @@ -49,7 +50,8 @@ class UserJobFilter implements FilterInterface ->leftJoin( UserJobHistory::class, "{$p}_jobHistory", - $qb->expr()->eq("{$p}_jobHistory", "{$p}_user") + Expr\Join::WITH, + $qb->expr()->eq("{$p}_jobHistory.user", "{$p}_user") ) ->andWhere( $qb->expr()->andX( From e4cf07c7b3c2c1456677f182e4b98d574e69ebd6 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 27 Sep 2023 16:20:10 +0200 Subject: [PATCH 30/62] rector fix error --- src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php b/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php index e89f00b52..e8171dbf2 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php +++ b/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php @@ -30,7 +30,7 @@ class ScopeFilter implements FilterInterface private const PREFIX = 'cal_filter_scope'; public function __construct( - private RollingDateConverter $rollingDateConverter, + private readonly RollingDateConverter $rollingDateConverter, protected TranslatorInterface $translator, private readonly TranslatableStringHelper $translatableStringHelper ) {} From 4460db1dc4a07b6d60df2a6f02f44ed91147ce89 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 27 Sep 2023 16:48:27 +0200 Subject: [PATCH 31/62] Fix syntax error --- src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php | 4 ++-- src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php | 4 ++-- .../Export/Filter/AccompanyingCourseFilters/UserJobFilter.php | 4 ++-- .../Filter/AccompanyingCourseFilters/UserScopeFilter.php | 4 ++-- .../Export/Filter/SocialWorkFilters/JobFilter.php | 4 ++-- .../Export/Filter/SocialWorkFilters/ScopeFilter.php | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php b/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php index da0cb5225..34e973bce 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php +++ b/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php @@ -60,8 +60,8 @@ class JobFilter implements FilterInterface "{$p}_history.startDate <= :{$p}_at AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > :{$p}_at)" ) ->setParameters([ - ["{$p}_job", $data["job"]], - ["{$p}_at", $this->rollingDateConverter->convert($data["job_at"])] + "{$p}_job" => $data["job"], + "{$p}_at" => $this->rollingDateConverter->convert($data["job_at"]) ]) ; diff --git a/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php b/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php index e8171dbf2..7f578ac86 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php +++ b/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php @@ -57,8 +57,8 @@ class ScopeFilter implements FilterInterface "{$p}_history.startDate <= :{$p}_at AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > :{$p}_at)" ) ->setParameters([ - ["{$p}_scope", $data["scope"]], - ["{$p}_at", $this->rollingDateConverter->convert($data['scope_at'])] + "{$p}_scope" => $data["scope"], + "{$p}_at" => $this->rollingDateConverter->convert($data['scope_at']) ]); } diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php index c221d0280..e31e51ccc 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php @@ -75,8 +75,8 @@ class UserJobFilter implements FilterInterface $qb->expr()->in("{$p}_jobHistory.job", ":{$p}_job") ) ->setParameters([ - ["{$p}_job", $data["jobs"]], - ["{$p}_date", $this->rollingDateConverter->convert($data["date_calc"])] + "{$p}_job" => $data["jobs"], + "{$p}_date" => $this->rollingDateConverter->convert($data["date_calc"]) ]) ; } diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php index d530e0bd2..607e442eb 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php @@ -75,8 +75,8 @@ class UserScopeFilter implements FilterInterface $qb->expr()->in("{$p}_scopeHistory.scope", ":{$p}_scopes") ) ->setParameters([ - ["{$p}_scopes", $data["scopes"]], - ["{$p}_date", $this->rollingDateConverter->convert($data["date_calc"])] + "{$p}_scopes" => $data["scopes"], + "{$p}_date" => $this->rollingDateConverter->convert($data["date_calc"]) ]) ; } diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php index 7eaa1fc74..a05e4b1d2 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php @@ -67,8 +67,8 @@ class JobFilter implements FilterInterface $qb->expr()->in("{$p}_history.job", ":{$p}_job") ) ->setParameters([ - ["{$p}_job", $data["job"]], - ["{$p}_at", $this->rollingDateConverter->convert($data['job_at'])] + "{$p}_job" => $data["job"], + "{$p}_at" => $this->rollingDateConverter->convert($data['job_at']) ]); } diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php index 5f15ccbaa..465569198 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php @@ -65,8 +65,8 @@ class ScopeFilter implements FilterInterface $qb->expr()->in("{$p}_history.scope", ":{$p}_scope") ) ->setParameters([ - ["{$p}_scope", $data["scope"]], - ["{$p}_at", $this->rollingDateConverter->convert($data['scope_at'])] + "{$p}_scope" => $data["scope"], + "{$p}_at" => $this->rollingDateConverter->convert($data['scope_at']) ]); } From 3aa10927d79a6572b4f60c4a9e0defb1827dfd1d Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Thu, 28 Sep 2023 12:06:09 +0200 Subject: [PATCH 32/62] [export] fix 4 job/scope aggregators in activity and aside activity --- .../Aggregator/ActivityUsersJobAggregator.php | 60 ++++++++++++++----- .../ActivityUsersScopeAggregator.php | 59 +++++++++++++----- .../translations/messages.fr.yml | 13 ++-- .../Export/Aggregator/ByUserJobAggregator.php | 55 +++++++++++++---- .../Aggregator/ByUserScopeAggregator.php | 57 +++++++++++++----- .../src/translations/messages.fr.yml | 8 ++- 6 files changed, 192 insertions(+), 60 deletions(-) diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php index 6f05d88f6..8e2b41025 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php @@ -12,15 +12,26 @@ declare(strict_types=1); namespace Chill\ActivityBundle\Export\Aggregator; use Chill\ActivityBundle\Export\Declarations; +use Chill\MainBundle\Entity\User\UserJobHistory; +use Chill\MainBundle\Export\AggregatorInterface; +use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\UserJobRepositoryInterface; +use Chill\MainBundle\Service\RollingDate\RollingDate; +use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; +use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; -use function in_array; -class ActivityUsersJobAggregator implements \Chill\MainBundle\Export\AggregatorInterface +class ActivityUsersJobAggregator implements AggregatorInterface { - public function __construct(private readonly UserJobRepositoryInterface $userJobRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper) {} + private const PREFIX = 'act_agg_user_job'; + + public function __construct( + private readonly RollingDateConverter $rollingDateConverter, + private readonly UserJobRepositoryInterface $userJobRepository, + private readonly TranslatableStringHelperInterface $translatableStringHelper + ) {} public function addRole(): ?string { @@ -29,27 +40,48 @@ class ActivityUsersJobAggregator implements \Chill\MainBundle\Export\AggregatorI public function alterQuery(QueryBuilder $qb, $data) { - if (!in_array('actusers', $qb->getAllAliases(), true)) { - $qb->leftJoin('activity.users', 'actusers'); - } + $p = self::PREFIX; $qb - ->addSelect('IDENTITY(actusers.userJob) AS activity_users_job_aggregator') - ->addGroupBy('activity_users_job_aggregator'); + ->leftJoin("activity.users", "{$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") + ) + ) + ) + ->addSelect("IDENTITY({$p}_history.job) AS {$p}_select") + ->setParameter( + "{$p}_at", $this->rollingDateConverter->convert($data['job_at']) + ) + ->addGroupBy("{$p}_select"); } - public function applyOn() + public function applyOn(): string { return Declarations::ACTIVITY; } public function buildForm(FormBuilderInterface $builder) { - // nothing to add in the form + $builder->add('job_at', PickRollingDateType::class, [ + 'label' => 'export.aggregator.activity.by_user_job.Calc date', + 'required' => true + ]); + } public function getFormDefaultData(): array { - return []; + return ['job_at' => new RollingDate(RollingDate::T_TODAY)]; } public function getLabels($key, array $values, $data) @@ -73,11 +105,11 @@ class ActivityUsersJobAggregator implements \Chill\MainBundle\Export\AggregatorI public function getQueryKeys($data): array { - return ['activity_users_job_aggregator']; + return [self::PREFIX . '_select']; } - public function getTitle() + public function getTitle(): string { - return 'Aggregate by users job'; + return 'export.aggregator.activity.by_user_job.Aggregate by users job'; } } diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php index a29458dc7..3d05af976 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php @@ -12,15 +12,26 @@ declare(strict_types=1); namespace Chill\ActivityBundle\Export\Aggregator; use Chill\ActivityBundle\Export\Declarations; +use Chill\MainBundle\Entity\User\UserScopeHistory; +use Chill\MainBundle\Export\AggregatorInterface; +use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\ScopeRepositoryInterface; +use Chill\MainBundle\Service\RollingDate\RollingDate; +use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; +use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; -use function in_array; -class ActivityUsersScopeAggregator implements \Chill\MainBundle\Export\AggregatorInterface +class ActivityUsersScopeAggregator implements AggregatorInterface { - public function __construct(private readonly ScopeRepositoryInterface $scopeRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper) {} + private const PREFIX = 'act_agg_user_scope'; + + public function __construct( + private readonly RollingDateConverter $rollingDateConverter, + private readonly ScopeRepositoryInterface $scopeRepository, + private readonly TranslatableStringHelperInterface $translatableStringHelper + ) {} public function addRole(): ?string { @@ -29,27 +40,47 @@ class ActivityUsersScopeAggregator implements \Chill\MainBundle\Export\Aggregato public function alterQuery(QueryBuilder $qb, $data) { - if (!in_array('actusers', $qb->getAllAliases(), true)) { - $qb->leftJoin('activity.users', 'actusers'); - } + $p = self::PREFIX; $qb - ->addSelect('IDENTITY(actusers.mainScope) AS activity_users_main_scope_aggregator') - ->addGroupBy('activity_users_main_scope_aggregator'); + ->leftJoin("activity.users", "{$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") + ) + ) + ) + ->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select") + ->setParameter( + "{$p}_at", $this->rollingDateConverter->convert($data['scope_at']) + ) + ->addGroupBy("{$p}_select"); } - public function applyOn() + public function applyOn(): string { return Declarations::ACTIVITY; } public function buildForm(FormBuilderInterface $builder) { - // nothing to add in the form + $builder->add('scope_at', PickRollingDateType::class, [ + 'label' => 'export.aggregator.activity.by_user_scope.Calc date', + 'required' => true, + ]); } public function getFormDefaultData(): array { - return []; + return ['scope_at' => new RollingDate(RollingDate::T_TODAY)]; } public function getLabels($key, array $values, $data) @@ -73,11 +104,11 @@ class ActivityUsersScopeAggregator implements \Chill\MainBundle\Export\Aggregato public function getQueryKeys($data): array { - return ['activity_users_main_scope_aggregator']; + return [self::PREFIX . '_select']; } - public function getTitle() + public function getTitle(): string { - return 'Aggregate by users scope'; + return 'export.aggregator.activity.by_user_scope.Aggregate by users scope'; } } diff --git a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml index ef2494f57..b824b7a56 100644 --- a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml @@ -306,10 +306,6 @@ Aggregate by activity user: Grouper les échanges par référent Aggregate by activity users: Grouper les échanges par utilisateurs participants Aggregate by activity type: Grouper les échanges par type Aggregate by activity reason: Grouper les échanges par sujet -Aggregate by users scope: Grouper les échanges par service principal de l'utilisateur -Users 's scope: Service principal des utilisateurs participants à l'échange -Aggregate by users job: Grouper les échanges par métier des utilisateurs participants -Users 's job: Métier des utilisateurs participants à l'échange Group activity by locationtype: Grouper les échanges par type de localisation Group activity by date: Grouper les échanges par date @@ -391,6 +387,15 @@ export: by_location: Activity Location: Localisation de l'échange Title: Grouper les échanges par localisation de l'échange + by_user_job: + Users 's job: Métier des utilisateurs participants à l'échange + Aggregate by users job: Grouper les échanges par métier des utilisateurs participants + Calc date: Date de calcul du métier des participants + by_user_scope: + Users 's scope: Service principal des utilisateurs participants à l'échange + Aggregate by users scope: Grouper les échanges par service principal de l'utilisateur + Calc date: Date de calcul du service principal de l'utilisateur + generic_doc: filter: diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php index 474f0a49f..4be1aa669 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php @@ -12,9 +12,14 @@ declare(strict_types=1); namespace Chill\AsideActivityBundle\Export\Aggregator; use Chill\AsideActivityBundle\Export\Declarations; +use Chill\MainBundle\Entity\User\UserJobHistory; use Chill\MainBundle\Export\AggregatorInterface; +use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\UserJobRepositoryInterface; +use Chill\MainBundle\Service\RollingDate\RollingDate; +use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; +use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; @@ -22,7 +27,13 @@ use function in_array; class ByUserJobAggregator implements AggregatorInterface { - public function __construct(private readonly UserJobRepositoryInterface $userJobRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper) {} + private const PREFIX = 'aside_act_agg_user_job'; + + public function __construct( + private readonly RollingDateConverter $rollingDateConverter, + private readonly UserJobRepositoryInterface $userJobRepository, + private readonly TranslatableStringHelperInterface $translatableStringHelper + ) {} public function addRole(): ?string { @@ -31,27 +42,47 @@ class ByUserJobAggregator implements AggregatorInterface public function alterQuery(QueryBuilder $qb, $data) { - if (!in_array('aside_user', $qb->getAllAliases(), true)) { - $qb->leftJoin('aside.agent', 'aside_user'); - } + $p = self::PREFIX; $qb - ->addSelect('IDENTITY(aside_user.userJob) AS aside_activity_user_job_aggregator') - ->addGroupBy('aside_activity_user_job_aggregator'); + ->leftJoin("aside.agent", "{$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") + ) + ) + ) + ->addSelect("IDENTITY({$p}_history.job) AS {$p}_select") + ->setParameter( + "{$p}_at", $this->rollingDateConverter->convert($data['job_at']) + ) + ->addGroupBy("{$p}_select"); } - public function applyOn() + public function applyOn(): string { return Declarations::ASIDE_ACTIVITY_TYPE; } public function buildForm(FormBuilderInterface $builder) { - // nothing to add in the form + $builder->add('job_at', PickRollingDateType::class, [ + 'label' => 'export.aggregator.by_user_job.Calc date', + 'required' => true + ]); } public function getFormDefaultData(): array { - return []; + return ['job_at' => new RollingDate(RollingDate::T_TODAY)]; } public function getLabels($key, array $values, $data) @@ -75,11 +106,11 @@ class ByUserJobAggregator implements AggregatorInterface public function getQueryKeys($data): array { - return ['aside_activity_user_job_aggregator']; + return [self::PREFIX . '_select']; } - public function getTitle() + public function getTitle(): string { - return 'export.aggregator.Aggregate by user job'; + return 'export.aggregator.by_user_job.Aggregate by user job'; } } diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php index 03646fab4..fc8a8cbab 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php @@ -12,17 +12,26 @@ declare(strict_types=1); namespace Chill\AsideActivityBundle\Export\Aggregator; use Chill\AsideActivityBundle\Export\Declarations; +use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\AggregatorInterface; +use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\ScopeRepositoryInterface; +use Chill\MainBundle\Service\RollingDate\RollingDate; +use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; +use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; -use function in_array; - class ByUserScopeAggregator implements AggregatorInterface { - public function __construct(private readonly ScopeRepositoryInterface $scopeRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper) {} + private const PREFIX = 'aside_act_agg_user_scope'; + + public function __construct( + private readonly RollingDateConverter $rollingDateConverter, + private readonly ScopeRepositoryInterface $scopeRepository, + private readonly TranslatableStringHelperInterface $translatableStringHelper + ) {} public function addRole(): ?string { @@ -31,27 +40,47 @@ class ByUserScopeAggregator implements AggregatorInterface public function alterQuery(QueryBuilder $qb, $data) { - if (!in_array('aside_user', $qb->getAllAliases(), true)) { - $qb->leftJoin('aside.agent', 'aside_user'); - } + $p = self::PREFIX; $qb - ->addSelect('IDENTITY(aside_user.mainScope) AS aside_activity_user_scope_aggregator') - ->addGroupBy('aside_activity_user_scope_aggregator'); + ->leftJoin("aside.agent", "{$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") + ) + ) + ) + ->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select") + ->setParameter( + "{$p}_at", $this->rollingDateConverter->convert($data['scope_at']) + ) + ->addGroupBy("{$p}_select"); } - public function applyOn() + public function applyOn(): string { return Declarations::ASIDE_ACTIVITY_TYPE; } public function buildForm(FormBuilderInterface $builder) { - // nothing to add in the form + $builder->add('scope_at', PickRollingDateType::class, [ + 'label' => 'export.aggregator.by_user_scope.Calc date', + 'required' => true, + ]); } public function getFormDefaultData(): array { - return []; + return ['scope_at' => new RollingDate(RollingDate::T_TODAY)]; } public function getLabels($key, array $values, $data) @@ -75,11 +104,11 @@ class ByUserScopeAggregator implements AggregatorInterface public function getQueryKeys($data): array { - return ['aside_activity_user_scope_aggregator']; + return [self::PREFIX . '_select']; } - public function getTitle() + public function getTitle(): string { - return 'export.aggregator.Aggregate by user scope'; + return 'export.aggregator.by_user_scope.Aggregate by user scope'; } } diff --git a/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml b/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml index 6028193db..69f4e8736 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml +++ b/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml @@ -209,8 +209,12 @@ export: aggregator: Group by aside activity type: Grouper les activités annexes par type d'activité Aside activity type: Type d'activité annexe - Aggregate by user job: Grouper les activités annexes par métier des utilisateurs - Aggregate by user scope: Grouper les activités annexes par service des utilisateurs + by_user_job: + Aggregate by user job: Grouper les activités annexes par métier des utilisateurs + Calc date: Date de calcul du métier des utilisateurs + by_user_scope: + Aggregate by user scope: Grouper les activités annexes par service des utilisateurs + Calc date: Date de calcul du service des utilisateurs Aside activity location: Localisation des activités annexe Group by aside activity location: Grouper les activités annexes par localisation Aside activity localisation: Localisation From bea21d45fc3b033fd37c0e8509a8d9ea5e0686ed Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Thu, 28 Sep 2023 12:27:53 +0200 Subject: [PATCH 33/62] [export] fix 2 job/scope aggregators in activity and acp --- .../Aggregator/CreatorScopeAggregator.php | 53 +++++++++++++++---- .../translations/messages.fr.yml | 4 +- .../CreatorJobAggregator.php | 53 +++++++++++++++---- .../translations/messages.fr.yml | 3 +- 4 files changed, 89 insertions(+), 24 deletions(-) diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php index 581614832..5841cb20f 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php @@ -12,16 +12,26 @@ declare(strict_types=1); namespace Chill\ActivityBundle\Export\Aggregator; use Chill\ActivityBundle\Export\Declarations; +use Chill\MainBundle\Entity\User\UserScopeHistory; 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 Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; -use function in_array; class CreatorScopeAggregator implements AggregatorInterface { - public function __construct(private readonly ScopeRepository $scopeRepository, private readonly TranslatableStringHelper $translatableStringHelper) {} + private const PREFIX = 'acp_agg_creator_scope'; + + public function __construct( + private readonly RollingDateConverter $rollingDateConverter, + private readonly ScopeRepository $scopeRepository, + private readonly TranslatableStringHelper $translatableStringHelper + ) {} public function addRole(): ?string { @@ -30,12 +40,30 @@ class CreatorScopeAggregator implements AggregatorInterface public function alterQuery(QueryBuilder $qb, $data) { - if (!in_array('actcreator', $qb->getAllAliases(), true)) { - $qb->leftJoin('activity.createdBy', 'actcreator'); - } + $p = self::PREFIX; - $qb->addSelect('IDENTITY(actcreator.mainScope) AS creatorscope_aggregator'); - $qb->addGroupBy('creatorscope_aggregator'); + $qb + ->leftJoin("activity.createdBy", "{$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") + ) + ) + ) + ->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select") + ->setParameter( + "{$p}_at", $this->rollingDateConverter->convert($data['scope_at']) + ) + ->addGroupBy("{$p}_select"); } public function applyOn(): string @@ -45,11 +73,14 @@ class CreatorScopeAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - // no form + $builder->add('scope_at', PickRollingDateType::class, [ + 'label' => 'export.aggregator.activity.by_creator_scope.Calc date', + 'required' => true, + ]); } public function getFormDefaultData(): array { - return []; + return ['scope_at' => new RollingDate(RollingDate::T_TODAY)]; } public function getLabels($key, array $values, $data) @@ -73,11 +104,11 @@ class CreatorScopeAggregator implements AggregatorInterface public function getQueryKeys($data): array { - return ['creatorscope_aggregator']; + return ['_select']; } public function getTitle(): string { - return 'Group activity by creator scope'; + return 'export.aggregator.activity.by_creator_scope.Group activity by creator scope'; } } diff --git a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml index b824b7a56..ef9a1b45e 100644 --- a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml @@ -316,7 +316,6 @@ for week: Semaine by year: Par année in year: En Group activity by creator: Grouper les échanges par créateur de l'échange -Group activity by creator scope: Grouper les échanges par service du créateur de l'échange Group activity by linked thirdparties: Grouper les échanges par tiers impliqué Accepted thirdparty: Tiers impliqué Group activity by linked socialaction: Grouper les échanges par action liée @@ -395,6 +394,9 @@ export: Users 's scope: Service principal des utilisateurs participants à l'échange Aggregate by users scope: Grouper les échanges par service principal de l'utilisateur Calc date: Date de calcul du service principal de l'utilisateur + 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 generic_doc: diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php index b07da6871..c9d8cbde8 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php @@ -11,17 +11,27 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators; +use Chill\MainBundle\Entity\User\UserJobHistory; 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\Export\Declarations; +use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; -use function in_array; class CreatorJobAggregator implements AggregatorInterface { - public function __construct(private readonly UserJobRepository $jobRepository, private readonly TranslatableStringHelper $translatableStringHelper) {} + private const PREFIX = 'acp_agg_creator_job'; + + public function __construct( + private readonly RollingDateConverter $rollingDateConverter, + private readonly UserJobRepository $jobRepository, + private readonly TranslatableStringHelper $translatableStringHelper + ) {} public function addRole(): ?string { @@ -30,12 +40,30 @@ class CreatorJobAggregator implements AggregatorInterface public function alterQuery(QueryBuilder $qb, $data) { - if (!in_array('acp_creator', $qb->getAllAliases(), true)) { - $qb->leftJoin('acp.createdBy', 'acp_creator'); - } + $p = self::PREFIX; - $qb->addSelect('IDENTITY(acp_creator.userJob) AS acp_creator_job_aggregator') - ->addGroupBy('acp_creator_job_aggregator'); + $qb + ->leftJoin("acp.createdBy", "{$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") + ) + ) + ) + ->addSelect("IDENTITY({$p}_history.job) AS {$p}_select") + ->setParameter( + "{$p}_at", $this->rollingDateConverter->convert($data['job_at']) + ) + ->addGroupBy("{$p}_select"); } public function applyOn(): string @@ -45,11 +73,14 @@ class CreatorJobAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - // No form needed + $builder->add('job_at', PickRollingDateType::class, [ + 'label' => 'export.aggregator.course.by_creator_job.Calc date', + 'required' => true + ]); } public function getFormDefaultData(): array { - return []; + return ['job_at' => new RollingDate(RollingDate::T_TODAY)]; } public function getLabels($key, array $values, $data) @@ -71,11 +102,11 @@ class CreatorJobAggregator implements AggregatorInterface public function getQueryKeys($data): array { - return ['acp_creator_job_aggregator']; + return [self::PREFIX . '_select']; } public function getTitle(): string { - return 'Group by creator job'; + return 'export.aggregator.course.by_creator_job.Group by creator job'; } } diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index bfecd6559..1a240422b 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -573,7 +573,6 @@ Filter by creator: Filtrer les parcours par créateur 'Filtered by creator: only %creators%': 'Filtré par créateur: uniquement %creators%' Filter by creator job: Filtrer les parcours par métier du créateur 'Filtered by creator job: only %jobs%': 'Filtré par métier du créateur: uniquement %jobs%' -Group by creator job: Grouper les parcours par métier du créateur Filter actions without end date: Filtre les actions sans date de fin (ouvertes) Filtered actions without end date: 'Filtré: uniquement les actions sans date de fin (ouvertes)' @@ -1029,6 +1028,8 @@ export: Number of actions: Nombre d'actions by_creator_job: Creator's job: Métier du créateur + Group by creator job: Grouper les parcours par métier du créateur + Calc date: Date de calcul du métier du créateur by_user_working: title: Grouper les parcours par intervenant user: Intervenant From 1973a4b849a802a8a18f0a782fb2bbaa3394bc2d Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Thu, 28 Sep 2023 12:55:50 +0200 Subject: [PATCH 34/62] [export] fix 2 job/scope aggregators in acp --- .../JobWorkingOnCourseAggregator.php | 93 +++++++++++------- .../ScopeWorkingOnCourseAggregator.php | 94 ++++++++++++------- .../translations/messages.fr.yml | 2 + 3 files changed, 118 insertions(+), 71 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php index 46489069d..39a9fda83 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php @@ -11,8 +11,12 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators; +use Chill\MainBundle\Entity\User\UserJobHistory; use Chill\MainBundle\Export\AggregatorInterface; +use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\UserJobRepositoryInterface; +use Chill\MainBundle\Service\RollingDate\RollingDate; +use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodInfo; use Chill\PersonBundle\Export\Declarations; @@ -22,21 +26,69 @@ use Symfony\Component\Form\FormBuilderInterface; final readonly class JobWorkingOnCourseAggregator implements AggregatorInterface { - private const COLUMN_NAME = 'user_working_on_course_job_id'; + private const PREFIX = 'acp_agg_user_job_working_on_course'; public function __construct( + private RollingDateConverter $rollingDateConverter, private UserJobRepositoryInterface $userJobRepository, private TranslatableStringHelperInterface $translatableStringHelper, ) {} + public function addRole(): ?string + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + $p = self::PREFIX; + + $qb + ->leftJoin( + AccompanyingPeriodInfo::class, + "acpinfo", + Join::WITH, + $qb->expr()->eq( "IDENTITY(acpinfo.accompanyingPeriod)", "acp.id") + ) + ->leftJoin("acpinfo.user", "{$p}_user") + ->leftJoin( + UserJobHistory::class, + "{$p}_history", + 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']) + ) + ->addGroupBy("{$p}_select"); + } + + public function applyOn(): string + { + return Declarations::ACP_TYPE; + } + public function buildForm(FormBuilderInterface $builder) { - // nothing to add here + $builder->add('job_at', PickRollingDateType::class, [ + 'label' => 'export.aggregator.course.by_job_working.Calc date', + 'required' => true + ]); } public function getFormDefaultData(): array { - return []; + return ['job_at' => new RollingDate(RollingDate::T_TODAY)]; } public function getLabels($key, array $values, $data): \Closure @@ -58,42 +110,13 @@ final readonly class JobWorkingOnCourseAggregator implements AggregatorInterface }; } - public function getQueryKeys($data) + public function getQueryKeys($data): array { - return [self::COLUMN_NAME]; + return [self::PREFIX . '_select']; } - public function getTitle() + public function getTitle(): string { return 'export.aggregator.course.by_job_working.title'; } - - public function addRole(): ?string - { - return null; - } - - public function alterQuery(QueryBuilder $qb, $data) - { - if (!in_array('acpinfo', $qb->getAllAliases(), true)) { - $qb->leftJoin( - AccompanyingPeriodInfo::class, - 'acpinfo', - Join::WITH, - 'acp.id = IDENTITY(acpinfo.accompanyingPeriod)' - ); - } - - if (!in_array('acpinfo_user', $qb->getAllAliases(), true)) { - $qb->leftJoin('acpinfo.user', 'acpinfo_user'); - } - - $qb->addSelect('IDENTITY(acpinfo_user.userJob) AS ' . self::COLUMN_NAME); - $qb->addGroupBy(self::COLUMN_NAME); - } - - public function applyOn() - { - return Declarations::ACP_TYPE; - } } diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php index a5b2f10f0..8b2529be9 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php @@ -11,9 +11,12 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators; +use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\AggregatorInterface; +use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\ScopeRepositoryInterface; -use Chill\MainBundle\Repository\UserJobRepositoryInterface; +use Chill\MainBundle\Service\RollingDate\RollingDate; +use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodInfo; use Chill\PersonBundle\Export\Declarations; @@ -23,21 +26,69 @@ use Symfony\Component\Form\FormBuilderInterface; final readonly class ScopeWorkingOnCourseAggregator implements AggregatorInterface { - private const COLUMN_NAME = 'user_working_on_course_scope_id'; + private const PREFIX = 'acp_agg_user_scope_working_on_course'; public function __construct( + private RollingDateConverter $rollingDateConverter, private ScopeRepositoryInterface $scopeRepository, private TranslatableStringHelperInterface $translatableStringHelper, ) {} + public function addRole(): ?string + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data) + { + $p = self::PREFIX; + + $qb + ->leftJoin( + AccompanyingPeriodInfo::class, + "acpinfo", + Join::WITH, + $qb->expr()->eq("IDENTITY(acpinfo.accompanyingPeriod)", "acp.id") + ) + ->leftJoin("acpinfo.user", "{$p}_user") + ->leftJoin( + UserScopeHistory::class, + "{$p}_history", + 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']) + ) + ->addGroupBy("{$p}_select"); + } + + public function applyOn(): string + { + return Declarations::ACP_TYPE; + } + public function buildForm(FormBuilderInterface $builder) { - // nothing to add here + $builder->add('scope_at', PickRollingDateType::class, [ + 'label' => 'export.aggregator.course.by_scope_working.Calc date', + 'required' => true, + ]); } public function getFormDefaultData(): array { - return []; + return ['scope_at' => new RollingDate(RollingDate::T_TODAY)]; } public function getLabels($key, array $values, $data): \Closure @@ -59,42 +110,13 @@ final readonly class ScopeWorkingOnCourseAggregator implements AggregatorInterfa }; } - public function getQueryKeys($data) + public function getQueryKeys($data): array { - return [self::COLUMN_NAME]; + return [self::PREFIX. '_select']; } - public function getTitle() + public function getTitle(): string { return 'export.aggregator.course.by_scope_working.title'; } - - public function addRole(): ?string - { - return null; - } - - public function alterQuery(QueryBuilder $qb, $data) - { - if (!in_array('acpinfo', $qb->getAllAliases(), true)) { - $qb->leftJoin( - AccompanyingPeriodInfo::class, - 'acpinfo', - Join::WITH, - 'acp.id = IDENTITY(acpinfo.accompanyingPeriod)' - ); - } - - if (!in_array('acpinfo_user', $qb->getAllAliases(), true)) { - $qb->leftJoin('acpinfo.user', 'acpinfo_user'); - } - - $qb->addSelect('IDENTITY(acpinfo_user.mainScope) AS ' . self::COLUMN_NAME); - $qb->addGroupBy(self::COLUMN_NAME); - } - - public function applyOn() - { - return Declarations::ACP_TYPE; - } } diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index 1a240422b..f1a2ccdf0 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -1036,9 +1036,11 @@ export: by_job_working: title: Grouper les parcours par métier de l'intervenant job: Métier de l'intervenant + Calc date: Date de calcul du métier de l'intervenant by_scope_working: title: Grouper les parcours par service de l'intervenant scope: Service de l'intervenant + Calc date: Date de calcul du service de l'intervenant by_scope: Group course by scope: Grouper les parcours par service From 8c44e9207973bb9d4a0e71d9215c3d06d5d5c86f Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Thu, 28 Sep 2023 15:46:46 +0200 Subject: [PATCH 35/62] [export] fix 2 job/scope filters aside activity --- .../src/Export/Filter/ByUserJobFilter.php | 63 ++++++++++++------ .../src/Export/Filter/ByUserScopeFilter.php | 64 +++++++++++++------ .../src/translations/messages.fr.yml | 12 ++-- 3 files changed, 97 insertions(+), 42 deletions(-) diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php index 5cff1b0e3..a97fcb1c1 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php @@ -13,8 +13,12 @@ namespace Chill\AsideActivityBundle\Export\Filter; use Chill\AsideActivityBundle\Entity\AsideActivity; use Chill\AsideActivityBundle\Export\Declarations; +use Chill\MainBundle\Entity\User\UserJobHistory; use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Export\FilterInterface; +use Chill\MainBundle\Form\Type\PickRollingDateType; +use Chill\MainBundle\Service\RollingDate\RollingDate; +use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; @@ -22,7 +26,12 @@ use Symfony\Component\Form\FormBuilderInterface; class ByUserJobFilter implements FilterInterface { - public function __construct(private readonly TranslatableStringHelperInterface $translatableStringHelper) {} + private const PREFIX = 'aside_act_filter_user_job'; + + public function __construct( + private readonly RollingDateConverter $rollingDateConverter, + private readonly TranslatableStringHelperInterface $translatableStringHelper + ) {} public function addRole(): ?string { @@ -31,38 +40,49 @@ class ByUserJobFilter implements FilterInterface public function alterQuery(QueryBuilder $qb, $data) { + $p = self::PREFIX; + $qb ->andWhere( $qb->expr()->exists( - 'SELECT 1 FROM ' . AsideActivity::class . ' aside_activity_user_job_filter_act - JOIN aside_activity_user_job_filter_act.agent aside_activity_user_job_filter_user WHERE aside_activity_user_job_filter_user.userJob IN (:aside_activity_user_job_filter_jobs) AND aside_activity_user_job_filter_act = aside' + "SELECT 1 FROM " . AsideActivity::class . " {$p}_act " + . "JOIN {$p}_act.agent {$p}_user " + . "JOIN " . UserJobHistory::class . " {$p}_history WITH {$p}_history.user = {$p}_user " + . "WHERE {$p}_act = aside " + . "AND {$p}_history.startDate <= :{$p}_at " + . "AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > :{$p}_at) " + . "AND {$p}_history.job IN ( :{$p}_jobs )" ) ) - ->setParameter('aside_activity_user_job_filter_jobs', $data['jobs']); + ->setParameters([ + "{$p}_jobs" => $data["jobs"], + "{$p}_at" => $this->rollingDateConverter->convert($data["job_at"]) + ]); } - public function applyOn() + public function applyOn(): string { return Declarations::ASIDE_ACTIVITY_TYPE; } public function buildForm(FormBuilderInterface $builder) { - $builder->add('jobs', EntityType::class, [ - 'class' => UserJob::class, - 'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize($j->getLabel()), - 'multiple' => true, - 'expanded' => true, - ]); - } - public function getFormDefaultData(): array - { - return []; + $builder + ->add('jobs', EntityType::class, [ + 'class' => UserJob::class, + 'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize($j->getLabel()), + 'multiple' => true, + 'expanded' => true, + ]) + ->add('job_at', PickRollingDateType::class, [ + 'label' => 'export.filter.by_user_job.Calc date', + 'required' => true + ]); } - public function describeAction($data, $format = 'string') + public function describeAction($data, $format = 'string'): array { - return ['export.filter.Filtered aside activities by user jobs: only %jobs%', [ + return ['export.filter.by_user_job.Filtered aside activities by user jobs: only %jobs%', [ '%jobs%' => implode( ', ', array_map( @@ -73,8 +93,13 @@ class ByUserJobFilter implements FilterInterface ]]; } - public function getTitle() + public function getFormDefaultData(): array { - return 'export.filter.Filter by user jobs'; + return ['job_at' => new RollingDate(RollingDate::T_TODAY)]; + } + + public function getTitle(): string + { + return 'export.filter.by_user_job.Filter by user jobs'; } } diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php index 22930183e..9c75d0ed8 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php @@ -14,8 +14,12 @@ namespace Chill\AsideActivityBundle\Export\Filter; use Chill\AsideActivityBundle\Entity\AsideActivity; use Chill\AsideActivityBundle\Export\Declarations; use Chill\MainBundle\Entity\Scope; +use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\FilterInterface; +use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\ScopeRepositoryInterface; +use Chill\MainBundle\Service\RollingDate\RollingDate; +use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; @@ -23,7 +27,13 @@ use Symfony\Component\Form\FormBuilderInterface; class ByUserScopeFilter implements FilterInterface { - public function __construct(private readonly ScopeRepositoryInterface $scopeRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper) {} + private const PREFIX = 'aside_act_filter_user_scope'; + + public function __construct( + private readonly RollingDateConverter $rollingDateConverter, + private readonly ScopeRepositoryInterface $scopeRepository, + private readonly TranslatableStringHelperInterface $translatableStringHelper + ) {} public function addRole(): ?string { @@ -32,39 +42,50 @@ class ByUserScopeFilter implements FilterInterface public function alterQuery(QueryBuilder $qb, $data) { + $p = self::PREFIX; + $qb ->andWhere( $qb->expr()->exists( - 'SELECT 1 FROM ' . AsideActivity::class . ' aside_activity_user_scope_filter_act - JOIN aside_activity_user_scope_filter_act.agent aside_activity_user_scope_filter_user WHERE aside_activity_user_scope_filter_user.mainScope IN (:aside_activity_user_scope_filter_scopes) AND aside_activity_user_scope_filter_act = aside ' + "SELECT 1 FROM " . AsideActivity::class . " {$p}_act " + . "JOIN {$p}_act.agent {$p}_user " + . "JOIN " . UserScopeHistory::class . " {$p}_history WITH {$p}_history.user = {$p}_user " + . "WHERE {$p}_act = aside " + . "AND {$p}_history.startDate <= :{$p}_at " + . "AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > :{$p}_at) " + . "AND {$p}_history.scope IN ( :{$p}_scopes )" ) ) - ->setParameter('aside_activity_user_scope_filter_scopes', $data['scopes']); + ->setParameters([ + "{$p}_scopes" => $data["scopes"], + "{$p}_at" => $this->rollingDateConverter->convert($data["scope_at"]) + ]); } - public function applyOn() + public function applyOn(): string { return Declarations::ASIDE_ACTIVITY_TYPE; } public function buildForm(FormBuilderInterface $builder) { - $builder->add('scopes', EntityType::class, [ - 'class' => Scope::class, - 'choices' => $this->scopeRepository->findAllActive(), - 'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()), - 'multiple' => true, - 'expanded' => true, - ]); - } - public function getFormDefaultData(): array - { - return []; + $builder + ->add('scopes', EntityType::class, [ + 'class' => Scope::class, + 'choices' => $this->scopeRepository->findAllActive(), + 'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()), + 'multiple' => true, + 'expanded' => true, + ]) + ->add('scope_at', PickRollingDateType::class, [ + 'label' => 'export.filter.by_user_scope.Calc date', + 'required' => true, + ]); } public function describeAction($data, $format = 'string') { - return ['export.filter.Filtered aside activities by user scope: only %scopes%', [ + return ['export.filter.by_user_scope.Filtered aside activities by user scope: only %scopes%', [ '%scopes%' => implode( ', ', array_map( @@ -75,8 +96,13 @@ class ByUserScopeFilter implements FilterInterface ]]; } - public function getTitle() + public function getFormDefaultData(): array { - return 'export.filter.Filter by user scope'; + return ['scope_at' => new RollingDate(RollingDate::T_TODAY)]; + } + + public function getTitle(): string + { + return 'export.filter.by_user_scope.Filter by user scope'; } } diff --git a/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml b/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml index 69f4e8736..fe895e223 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml +++ b/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml @@ -200,10 +200,14 @@ export: Aside activities before this date: Actvitités annexes avant cette date 'Filtered aside activity by user: only %users%': "Filtré par utilisateur: uniquement %users%" Filter aside activity by user: Filtrer par utilisateur - 'Filtered aside activities by user jobs: only %jobs%': "Filtré par métier des utilisateurs: uniquement %jobs%" - Filter by user jobs: Filtrer les activités annexes par métier des utilisateurs - 'Filtered aside activities by user scope: only %scopes%': "Filtré par service des utilisateur: uniquement %scopes%" - Filter by user scope: Filtrer les activités annexes par service d'utilisateur + by_user_job: + 'Filtered aside activities by user jobs: only %jobs%': "Filtré par métier des utilisateurs: uniquement %jobs%" + Filter by user jobs: Filtrer les activités annexes par métier des utilisateurs + Calc date: Date de calcul du métier des utilisateurs + by_user_scope: + 'Filtered aside activities by user scope: only %scopes%': "Filtré par service des utilisateurs: uniquement %scopes%" + Filter by user scope: Filtrer les activités annexes par service d'utilisateur + Calc date: Date de calcul du service des utilisateurs Filter by aside activity location: Filtrer les activités annexes par localisation 'Filtered by aside activity location: only %location%': "Filtré par localisation: uniquement %location%" aggregator: From f025b0d1843d2b71276e22248cccdbc871f32f06 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Thu, 28 Sep 2023 16:54:33 +0200 Subject: [PATCH 36/62] [export] fix 4 job/scope filters in activity and acp --- .../Export/Filter/UserScopeFilter.php | 93 ++++++++++++------- .../Export/Filter/UsersJobFilter.php | 60 ++++++++---- .../Export/Filter/UsersScopeFilter.php | 69 ++++++++++---- .../translations/messages.fr.yml | 13 ++- .../CreatorJobFilter.php | 80 +++++++++++----- .../translations/messages.fr.yml | 6 +- 6 files changed, 223 insertions(+), 98 deletions(-) diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/UserScopeFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/UserScopeFilter.php index a887eb201..ad7585d71 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/UserScopeFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/UserScopeFilter.php @@ -13,17 +13,25 @@ namespace Chill\ActivityBundle\Export\Filter; use Chill\ActivityBundle\Export\Declarations; use Chill\MainBundle\Entity\Scope; +use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\FilterInterface; +use Chill\MainBundle\Form\Type\PickRollingDateType; +use Chill\MainBundle\Service\RollingDate\RollingDate; +use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelper; -use Doctrine\ORM\Query\Expr\Andx; +use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\FormBuilderInterface; -use function in_array; class UserScopeFilter implements FilterInterface { - public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) {} + private const PREFIX = 'acp_act_filter_user_scope'; // creator ? cfr translation + + public function __construct( + private readonly RollingDateConverter $rollingDateConverter, + private readonly TranslatableStringHelper $translatableStringHelper + ) {} public function addRole(): ?string { @@ -32,22 +40,32 @@ class UserScopeFilter implements FilterInterface public function alterQuery(QueryBuilder $qb, $data) { - if (!in_array('actuser', $qb->getAllAliases(), true)) { - $qb->join('activity.user', 'actuser'); - } + $p = self::PREFIX; - $where = $qb->getDQLPart('where'); - - $clause = $qb->expr()->in('actuser.mainScope', ':userscope'); - - if ($where instanceof Andx) { - $where->add($clause); - } else { - $where = $qb->expr()->andX($clause); - } - - $qb->add('where', $where); - $qb->setParameter('userscope', $data['accepted_userscope']); + $qb + ->leftJoin("activity.user", "{$p}_user") // createdBy ? cfr translation + ->leftJoin( + UserScopeHistory::class, + "{$p}_history", + 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["scopes"], + "{$p}_at" => $this->rollingDateConverter->convert($data["scope_at"]) + ]); } public function applyOn(): string @@ -57,37 +75,46 @@ class UserScopeFilter implements FilterInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('accepted_userscope', EntityType::class, [ - 'class' => Scope::class, - 'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize( - $s->getName() - ), - 'multiple' => true, - 'expanded' => true, - ]); - } - public function getFormDefaultData(): array - { - return []; + $builder + ->add('scopes', EntityType::class, [ + 'class' => Scope::class, + 'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize( + $s->getName() + ), + 'multiple' => true, + 'expanded' => true, + ]) + ->add('scope_at', PickRollingDateType::class, [ + 'label' => 'export.filter.activity.course.by_user_scope.Calc date', + 'required' => true, + ]); } public function describeAction($data, $format = 'string'): array { $scopes = []; - foreach ($data['accepted_userscope'] as $s) { + foreach ($data['scopes'] as $s) { $scopes[] = $this->translatableStringHelper->localize( $s->getName() ); } - return ['Filtered activity by userscope: only %scopes%', [ + return ['export.filter.activity.course.by_user_scope.Filtered activity by userscope: only %scopes%', [ '%scopes%' => implode(', ', $scopes), ]]; } + public function getFormDefaultData(): array + { + return [ + 'scopes' => [], + 'scope_at' => new RollingDate(RollingDate::T_TODAY) + ]; + } + public function getTitle(): string { - return 'Filter activity by userscope'; + return 'export.filter.activity.course.by_user_scope.Filter activity by userscope'; } } diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/UsersJobFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/UsersJobFilter.php index 69f743987..4185ad4e9 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/UsersJobFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/UsersJobFilter.php @@ -13,8 +13,12 @@ namespace Chill\ActivityBundle\Export\Filter; use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Export\Declarations; +use Chill\MainBundle\Entity\User\UserJobHistory; use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Export\FilterInterface; +use Chill\MainBundle\Form\Type\PickRollingDateType; +use Chill\MainBundle\Service\RollingDate\RollingDate; +use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; @@ -22,7 +26,12 @@ use Symfony\Component\Form\FormBuilderInterface; class UsersJobFilter implements FilterInterface { - public function __construct(private readonly TranslatableStringHelperInterface $translatableStringHelper) {} + private const PREFIX = 'act_filter_user_job'; + + public function __construct( + private readonly RollingDateConverter $rollingDateConverter, + private readonly TranslatableStringHelperInterface $translatableStringHelper + ) {} public function addRole(): ?string { @@ -31,14 +40,24 @@ class UsersJobFilter implements FilterInterface public function alterQuery(QueryBuilder $qb, $data) { + $p = self::PREFIX; + $qb ->andWhere( $qb->expr()->exists( - 'SELECT 1 FROM ' . Activity::class . ' activity_users_job_filter_act - JOIN activity_users_job_filter_act.users users WHERE users.userJob IN (:activity_users_job_filter_jobs) AND activity_users_job_filter_act = activity ' + "SELECT 1 FROM " . Activity::class . " {$p}_act " + . "JOIN {$p}_act.users {$p}_user " + . "JOIN " . UserJobHistory::class . " {$p}_history WITH {$p}_history.user = {$p}_user " + . "WHERE {$p}_act = activity " + . "AND {$p}_history.startDate <= :{$p}_at " + . "AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > :{$p}_at) " + . "AND {$p}_history.job IN ( :{$p}_jobs )" ) ) - ->setParameter('activity_users_job_filter_jobs', $data['jobs']); + ->setParameters([ + "{$p}_jobs" => $data["jobs"], + "{$p}_at" => $this->rollingDateConverter->convert($data["job_at"]) + ]); } public function applyOn() @@ -48,21 +67,22 @@ class UsersJobFilter implements FilterInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('jobs', EntityType::class, [ - 'class' => UserJob::class, - 'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize($j->getLabel()), - 'multiple' => true, - 'expanded' => true, - ]); - } - public function getFormDefaultData(): array - { - return []; + $builder + ->add('jobs', EntityType::class, [ + 'class' => UserJob::class, + 'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize($j->getLabel()), + 'multiple' => true, + 'expanded' => true, + ]) + ->add('job_at', PickRollingDateType::class, [ + 'label' => 'export.filter.activity.by_users_job.Calc date', + 'required' => true + ]); } public function describeAction($data, $format = 'string') { - return ['export.filter.activity.by_usersjob.Filtered activity by users job: only %jobs%', [ + return ['export.filter.activity.by_users_job.Filtered activity by users job: only %jobs%', [ '%jobs%' => implode( ', ', array_map( @@ -73,8 +93,16 @@ class UsersJobFilter implements FilterInterface ]]; } + public function getFormDefaultData(): array + { + return [ + 'jobs' => [], + 'job_at' => new RollingDate(RollingDate::T_TODAY) + ]; + } + public function getTitle() { - return 'export.filter.activity.by_usersjob.Filter by users job'; + return 'export.filter.activity.by_users_job.Filter by users job'; } } diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/UsersScopeFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/UsersScopeFilter.php index 02c3229a7..e2c4ca1e0 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/UsersScopeFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/UsersScopeFilter.php @@ -14,8 +14,12 @@ namespace Chill\ActivityBundle\Export\Filter; use Chill\ActivityBundle\Entity\Activity; use Chill\ActivityBundle\Export\Declarations; use Chill\MainBundle\Entity\Scope; +use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\FilterInterface; +use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\ScopeRepositoryInterface; +use Chill\MainBundle\Service\RollingDate\RollingDate; +use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; @@ -23,7 +27,13 @@ use Symfony\Component\Form\FormBuilderInterface; class UsersScopeFilter implements FilterInterface { - public function __construct(private readonly ScopeRepositoryInterface $scopeRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper) {} + private const PREFIX = 'act_filter_user_scope'; + + public function __construct( + private readonly RollingDateConverter $rollingDateConverter, + private readonly ScopeRepositoryInterface $scopeRepository, + private readonly TranslatableStringHelperInterface $translatableStringHelper + ) {} public function addRole(): ?string { @@ -32,39 +42,50 @@ class UsersScopeFilter implements FilterInterface public function alterQuery(QueryBuilder $qb, $data) { + $p = self::PREFIX; + $qb ->andWhere( $qb->expr()->exists( - 'SELECT 1 FROM ' . Activity::class . ' activity_users_scope_filter_act - JOIN activity_users_scope_filter_act.users users WHERE users.mainScope IN (:activity_users_scope_filter_scopes) AND activity_users_scope_filter_act = activity ' + "SELECT 1 FROM " . Activity::class . " {$p}_act " + . "JOIN {$p}_act.users {$p}_user " + . "JOIN " . UserScopeHistory::class . " {$p}_history WITH {$p}_history.user = {$p}_user " + . "WHERE {$p}_act = activity " + . "AND {$p}_history.startDate <= :{$p}_at " + . "AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > :{$p}_at) " + . "AND {$p}_history.scope IN ( :{$p}_scopes )" ) ) - ->setParameter('activity_users_scope_filter_scopes', $data['scopes']); + ->setParameters([ + "{$p}_scopes" => $data["scopes"], + "{$p}_at" => $this->rollingDateConverter->convert($data["scope_at"]) + ]); } - public function applyOn() + public function applyOn(): string { return Declarations::ACTIVITY; } public function buildForm(FormBuilderInterface $builder) { - $builder->add('scopes', EntityType::class, [ - 'class' => Scope::class, - 'choices' => $this->scopeRepository->findAllActive(), - 'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()), - 'multiple' => true, - 'expanded' => true, - ]); - } - public function getFormDefaultData(): array - { - return []; + $builder + ->add('scopes', EntityType::class, [ + 'class' => Scope::class, + 'choices' => $this->scopeRepository->findAllActive(), + 'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()), + 'multiple' => true, + 'expanded' => true, + ]) + ->add('scope_at', PickRollingDateType::class, [ + 'label' => 'export.filter.activity.by_users_scope.Calc date', + 'required' => true, + ]); } - public function describeAction($data, $format = 'string') + public function describeAction($data, $format = 'string'): array { - return ['export.filter.activity.by_usersscope.Filtered activity by users scope: only %scopes%', [ + return ['export.filter.activity.by_users_scope.Filtered activity by users scope: only %scopes%', [ '%scopes%' => implode( ', ', array_map( @@ -75,8 +96,16 @@ class UsersScopeFilter implements FilterInterface ]]; } - public function getTitle() + public function getFormDefaultData(): array { - return 'export.filter.activity.by_usersscope.Filter by users scope'; + return [ + 'scopes' => [], + 'scope_at' => new RollingDate(RollingDate::T_TODAY) + ]; + } + + public function getTitle(): string + { + return 'export.filter.activity.by_users_scope.Filter by users scope'; } } diff --git a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml index ef9a1b45e..2576b9bf4 100644 --- a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml @@ -287,8 +287,6 @@ Filter activity by creator: Filtrer les échanges par créateur de l'échange 'Filtered activity by users: only %users%': "Filtré par utilisateurs participants: uniquement %users%" 'Filtered activity by creator: only %users%': "Filtré par créateur: uniquement %users%" Creators: Créateurs -Filter activity by userscope: Filtrer les échanges par service du créateur -'Filtered activity by userscope: only %scopes%': "Filtré par service du créateur: uniquement %scopes%" Accepted userscope: Services Filter acp which has no activity: Filtrer les parcours qui n’ont pas d’échange @@ -362,18 +360,25 @@ export: filter: activity: - by_usersjob: + by_users_job: Filter by users job: Filtrer les échanges par métier d'au moins un utilisateur participant 'Filtered activity by users job: only %jobs%': 'Filtré par métier d''au moins un utilisateur participant: seulement %jobs%' - by_usersscope: + Calc date: Date de calcul du métier de l'utilisateur + by_users_scope: Filter by users scope: Filtrer les échanges par services d'au moins un utilisateur participant 'Filtered activity by users scope: only %scopes%': 'Filtré par service d''au moins un utilisateur participant: seulement %scopes%' + Calc date: Date de calcul du service de l'utilisateur course_having_activity_between_date: Title: Filtre les parcours ayant reçu un échange entre deux dates Receiving an activity after: Ayant reçu un échange après le Receiving an activity before: Ayant reçu un échange avant le acp_by_activity_type: 'acp_containing_at_least_one_%activitytypes%': 'Parcours filtrés: uniquement ceux qui contiennent au moins un échange d''un des types suivants: %activitytypes%' + course: + by_user_scope: + Filter activity by userscope: Filtrer les échanges par service du créateur + 'Filtered activity by userscope: only %scopes%': "Filtré par service du créateur: uniquement %scopes%" + Calc date: Date de calcul du service du créateur aggregator: diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php index eca8a299a..f9b652eeb 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php @@ -11,19 +11,29 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters; +use Chill\MainBundle\Entity\User\UserJobHistory; use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Export\FilterInterface; +use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\UserJobRepositoryInterface; +use Chill\MainBundle\Service\RollingDate\RollingDate; +use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\PersonBundle\Export\Declarations; +use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\FormBuilderInterface; -use function in_array; class CreatorJobFilter implements FilterInterface { - public function __construct(private readonly TranslatableStringHelper $translatableStringHelper, private readonly UserJobRepositoryInterface $userJobRepository) {} + private const PREFIX = 'acp_filter_creator_job'; + + public function __construct( + private readonly RollingDateConverter $rollingDateConverter, + private readonly TranslatableStringHelper $translatableStringHelper, + private readonly UserJobRepositoryInterface $userJobRepository + ) {} public function addRole(): ?string { @@ -32,13 +42,30 @@ class CreatorJobFilter implements FilterInterface public function alterQuery(QueryBuilder $qb, $data) { - if (!in_array('acp_creator', $qb->getAllAliases(), true)) { - $qb->join('acp.createdBy', 'acp_creator'); - } + $p = self::PREFIX; $qb - ->andWhere($qb->expr()->in('acp_creator.userJob', ':creator_job')) - ->setParameter('creator_job', $data['creator_job']); + ->join("acp.createdBy", "{$p}_user") + ->leftJoin( + UserJobHistory::class, + "{$p}_history", + 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}_jobs")) + ->setParameters([ + "{$p}_jobs" => $data["creator_job"], + "{$p}_at" => $this->rollingDateConverter->convert($data["job_at"]) + ]); } public function applyOn(): string @@ -48,20 +75,21 @@ class CreatorJobFilter implements FilterInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('creator_job', EntityType::class, [ - 'class' => UserJob::class, - 'choices' => $this->userJobRepository->findAllActive(), - 'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize( - $j->getLabel() - ), - 'multiple' => true, - 'expanded' => true, - 'label' => 'Job', - ]); - } - public function getFormDefaultData(): array - { - return []; + $builder + ->add('creator_job', EntityType::class, [ + 'class' => UserJob::class, + 'choices' => $this->userJobRepository->findAllActive(), + 'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize( + $j->getLabel() + ), + 'multiple' => true, + 'expanded' => true, + 'label' => 'Job', + ]) + ->add('job_at', PickRollingDateType::class, [ + 'label' => 'export.filter.course.creator_job.Calc date', + 'required' => true + ]); } public function describeAction($data, $format = 'string'): array @@ -79,8 +107,16 @@ class CreatorJobFilter implements FilterInterface ]]; } + public function getFormDefaultData(): array + { + return [ + 'creator_job' => [], + 'job_at' => new RollingDate(RollingDate::T_TODAY) + ]; + } + public function getTitle(): string { - return 'Filter by creator job'; + return 'export.filter.course.creator_job.Filter by creator job'; } } diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index f1a2ccdf0..08027db7e 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -571,8 +571,6 @@ Filtered acp which has no actions: 'Filtré: uniquement les parcours qui n''ont Group by number of actions: Grouper les parcours par nombre d’actions Filter by creator: Filtrer les parcours par créateur 'Filtered by creator: only %creators%': 'Filtré par créateur: uniquement %creators%' -Filter by creator job: Filtrer les parcours par métier du créateur -'Filtered by creator job: only %jobs%': 'Filtré par métier du créateur: uniquement %jobs%' Filter actions without end date: Filtre les actions sans date de fin (ouvertes) Filtered actions without end date: 'Filtré: uniquement les actions sans date de fin (ouvertes)' @@ -1135,7 +1133,9 @@ export: Having a person's location: Ayant une localisation auprès d'un usager Calculation date: Date de la localisation creator_job: - 'Filtered by creator job: only %jobs%': 'Filtré par métier du créateur: seulement %jobs%' + Filter by creator job: Filtrer les parcours par métier du créateur + 'Filtered by creator job: only %jobs%': "Filtré par métier du créateur: uniquement %jobs%" + Calc date: Date de calcul du métier du créateur by_user_job: Filter by user job: Filtrer les parcours par métier du référent "Filtered by user job: only %job%": "Filtré par métier du référent: uniquement %job%" From eddcfc39213b1ef643b8b0a1f46136d5b82b9e64 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Thu, 28 Sep 2023 16:57:08 +0200 Subject: [PATCH 37/62] cs-fixer --- .../Export/Aggregator/ActivityUsersJobAggregator.php | 3 ++- .../Export/Aggregator/ActivityUsersScopeAggregator.php | 3 ++- .../Export/Aggregator/CreatorScopeAggregator.php | 3 ++- .../src/Export/Aggregator/ByUserJobAggregator.php | 3 ++- .../src/Export/Aggregator/ByUserScopeAggregator.php | 3 ++- .../AccompanyingCourseAggregators/CreatorJobAggregator.php | 3 ++- .../JobWorkingOnCourseAggregator.php | 5 +++-- .../ScopeWorkingOnCourseAggregator.php | 3 ++- 8 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php index 8e2b41025..7c7428b45 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php @@ -61,7 +61,8 @@ class ActivityUsersJobAggregator implements AggregatorInterface ) ->addSelect("IDENTITY({$p}_history.job) AS {$p}_select") ->setParameter( - "{$p}_at", $this->rollingDateConverter->convert($data['job_at']) + "{$p}_at", + $this->rollingDateConverter->convert($data['job_at']) ) ->addGroupBy("{$p}_select"); } diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php index 3d05af976..7c02e929f 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php @@ -61,7 +61,8 @@ class ActivityUsersScopeAggregator implements AggregatorInterface ) ->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select") ->setParameter( - "{$p}_at", $this->rollingDateConverter->convert($data['scope_at']) + "{$p}_at", + $this->rollingDateConverter->convert($data['scope_at']) ) ->addGroupBy("{$p}_select"); } diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php index 5841cb20f..ce00d81bd 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php @@ -61,7 +61,8 @@ class CreatorScopeAggregator implements AggregatorInterface ) ->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select") ->setParameter( - "{$p}_at", $this->rollingDateConverter->convert($data['scope_at']) + "{$p}_at", + $this->rollingDateConverter->convert($data['scope_at']) ) ->addGroupBy("{$p}_select"); } diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php index 4be1aa669..be54e2251 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php @@ -63,7 +63,8 @@ class ByUserJobAggregator implements AggregatorInterface ) ->addSelect("IDENTITY({$p}_history.job) AS {$p}_select") ->setParameter( - "{$p}_at", $this->rollingDateConverter->convert($data['job_at']) + "{$p}_at", + $this->rollingDateConverter->convert($data['job_at']) ) ->addGroupBy("{$p}_select"); } diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php index fc8a8cbab..ad2000a6c 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php @@ -61,7 +61,8 @@ class ByUserScopeAggregator implements AggregatorInterface ) ->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select") ->setParameter( - "{$p}_at", $this->rollingDateConverter->convert($data['scope_at']) + "{$p}_at", + $this->rollingDateConverter->convert($data['scope_at']) ) ->addGroupBy("{$p}_select"); } diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php index c9d8cbde8..81e5e78dc 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php @@ -61,7 +61,8 @@ class CreatorJobAggregator implements AggregatorInterface ) ->addSelect("IDENTITY({$p}_history.job) AS {$p}_select") ->setParameter( - "{$p}_at", $this->rollingDateConverter->convert($data['job_at']) + "{$p}_at", + $this->rollingDateConverter->convert($data['job_at']) ) ->addGroupBy("{$p}_select"); } diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php index 39a9fda83..ccc108cd0 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php @@ -48,7 +48,7 @@ final readonly class JobWorkingOnCourseAggregator implements AggregatorInterface AccompanyingPeriodInfo::class, "acpinfo", Join::WITH, - $qb->expr()->eq( "IDENTITY(acpinfo.accompanyingPeriod)", "acp.id") + $qb->expr()->eq("IDENTITY(acpinfo.accompanyingPeriod)", "acp.id") ) ->leftJoin("acpinfo.user", "{$p}_user") ->leftJoin( @@ -68,7 +68,8 @@ final readonly class JobWorkingOnCourseAggregator implements AggregatorInterface ) ->addSelect("IDENTITY({$p}_history.job) AS {$p}_select") ->setParameter( - "{$p}_at", $this->rollingDateConverter->convert($data['job_at']) + "{$p}_at", + $this->rollingDateConverter->convert($data['job_at']) ) ->addGroupBy("{$p}_select"); } diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php index 8b2529be9..08bddabb5 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php @@ -68,7 +68,8 @@ final readonly class ScopeWorkingOnCourseAggregator implements AggregatorInterfa ) ->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select") ->setParameter( - "{$p}_at", $this->rollingDateConverter->convert($data['scope_at']) + "{$p}_at", + $this->rollingDateConverter->convert($data['scope_at']) ) ->addGroupBy("{$p}_select"); } From 84ba626fb5d09a4e7a805032a8c7e9970cd89579 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Fri, 29 Sep 2023 09:35:52 +0200 Subject: [PATCH 38/62] add missing form child in getFormDefaultData() + sort methods try to resolve 2 last unit tests errors on ci (no errors in local) --- .../Aggregator/ActivityUsersJobAggregator.php | 1 + .../Aggregator/ActivityUsersScopeAggregator.php | 1 + .../Export/Aggregator/CreatorScopeAggregator.php | 1 + .../src/Export/Aggregator/ByUserJobAggregator.php | 1 + .../Export/Aggregator/ByUserScopeAggregator.php | 1 + .../src/Export/Filter/ByUserJobFilter.php | 5 ++++- .../src/Export/Filter/ByUserScopeFilter.php | 5 ++++- .../Export/Filter/JobFilter.php | 14 ++++++++------ .../Export/Filter/ScopeFilter.php | 12 ++++++++---- .../CreatorJobAggregator.php | 1 + .../UserJobAggregator.php | 1 + .../SocialWorkAggregators/JobAggregator.php | 1 + .../SocialWorkAggregators/ScopeAggregator.php | 1 + .../AccompanyingCourseFilters/UserJobFilter.php | 12 ++++++++---- .../AccompanyingCourseFilters/UserScopeFilter.php | 12 ++++++++---- .../Export/Filter/SocialWorkFilters/JobFilter.php | 12 ++++++++---- .../Filter/SocialWorkFilters/ScopeFilter.php | 12 ++++++++---- 17 files changed, 65 insertions(+), 28 deletions(-) diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php index 7c7428b45..5696a9780 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php @@ -80,6 +80,7 @@ class ActivityUsersJobAggregator implements AggregatorInterface ]); } + public function getFormDefaultData(): array { return ['job_at' => new RollingDate(RollingDate::T_TODAY)]; diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php index 7c02e929f..41ef1934e 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php @@ -79,6 +79,7 @@ class ActivityUsersScopeAggregator implements AggregatorInterface 'required' => true, ]); } + public function getFormDefaultData(): array { return ['scope_at' => new RollingDate(RollingDate::T_TODAY)]; diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php index ce00d81bd..de8fea079 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php @@ -79,6 +79,7 @@ class CreatorScopeAggregator implements AggregatorInterface 'required' => true, ]); } + public function getFormDefaultData(): array { return ['scope_at' => new RollingDate(RollingDate::T_TODAY)]; diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php index be54e2251..a7a7e403e 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php @@ -81,6 +81,7 @@ class ByUserJobAggregator implements AggregatorInterface 'required' => true ]); } + public function getFormDefaultData(): array { return ['job_at' => new RollingDate(RollingDate::T_TODAY)]; diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php index ad2000a6c..168d38433 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php @@ -79,6 +79,7 @@ class ByUserScopeAggregator implements AggregatorInterface 'required' => true, ]); } + public function getFormDefaultData(): array { return ['scope_at' => new RollingDate(RollingDate::T_TODAY)]; diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php index a97fcb1c1..867eca230 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php @@ -95,7 +95,10 @@ class ByUserJobFilter implements FilterInterface public function getFormDefaultData(): array { - return ['job_at' => new RollingDate(RollingDate::T_TODAY)]; + return [ + 'jobs' => [], + 'job_at' => new RollingDate(RollingDate::T_TODAY) + ]; } public function getTitle(): string diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php index 9c75d0ed8..ce6905378 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php @@ -98,7 +98,10 @@ class ByUserScopeFilter implements FilterInterface public function getFormDefaultData(): array { - return ['scope_at' => new RollingDate(RollingDate::T_TODAY)]; + return [ + 'scopes' => [], + 'scope_at' => new RollingDate(RollingDate::T_TODAY) + ]; } public function getTitle(): string diff --git a/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php b/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php index 34e973bce..11a26eea6 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php +++ b/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php @@ -88,12 +88,6 @@ class JobFilter implements FilterInterface 'required' => true, ]); } - public function getFormDefaultData(): array - { - return [ - 'job_at' => new RollingDate(RollingDate::T_TODAY), - ]; - } public function describeAction($data, $format = 'string'): array { @@ -110,6 +104,14 @@ class JobFilter implements FilterInterface ]]; } + public function getFormDefaultData(): array + { + return [ + 'job' => [], + 'job_at' => new RollingDate(RollingDate::T_TODAY), + ]; + } + public function getTitle(): string { return 'Filter calendars by agent job'; diff --git a/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php b/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php index 7f578ac86..5a310c38b 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php +++ b/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php @@ -83,10 +83,6 @@ class ScopeFilter implements FilterInterface 'required' => true, ]); } - public function getFormDefaultData(): array - { - return ['scope_at' => new RollingDate(RollingDate::T_TODAY)]; - } public function describeAction($data, $format = 'string'): array { @@ -103,6 +99,14 @@ class ScopeFilter implements FilterInterface ]]; } + public function getFormDefaultData(): array + { + return [ + 'scope' => [], + 'scope_at' => new RollingDate(RollingDate::T_TODAY) + ]; + } + public function getTitle(): string { return 'Filter calendars by agent scope'; diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php index 81e5e78dc..50c4e6f9b 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php @@ -79,6 +79,7 @@ class CreatorJobAggregator implements AggregatorInterface 'required' => true ]); } + public function getFormDefaultData(): array { return ['job_at' => new RollingDate(RollingDate::T_TODAY)]; diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php index 80e65664e..65b2dc38b 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php @@ -80,6 +80,7 @@ final readonly class UserJobAggregator implements AggregatorInterface 'required' => true ]); } + public function getFormDefaultData(): array { return ['job_at' => new RollingDate(RollingDate::T_TODAY)]; diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php index e7a1f25bb..6012bbcab 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/JobAggregator.php @@ -80,6 +80,7 @@ final readonly class JobAggregator implements AggregatorInterface 'required' => true ]); } + public function getFormDefaultData(): array { return ['job_at' => new RollingDate(RollingDate::T_TODAY)]; diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php index 606bb05e5..b6c799079 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ScopeAggregator.php @@ -80,6 +80,7 @@ final readonly class ScopeAggregator implements AggregatorInterface 'required' => true, ]); } + public function getFormDefaultData(): array { return ['scope_at' => new RollingDate(RollingDate::T_TODAY)]; diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php index e31e51ccc..56c16fd73 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php @@ -102,10 +102,6 @@ class UserJobFilter implements FilterInterface 'required' => true, ]); } - public function getFormDefaultData(): array - { - return ['date_calc' => new RollingDate(RollingDate::T_TODAY)]; - } public function describeAction($data, $format = 'string') { @@ -122,6 +118,14 @@ class UserJobFilter implements FilterInterface ]; } + public function getFormDefaultData(): array + { + return [ + 'jobs' => [], + 'date_calc' => new RollingDate(RollingDate::T_TODAY) + ]; + } + public function getTitle(): string { return 'export.filter.course.by_user_job.Filter by user job'; diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php index 607e442eb..1d2ccf839 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php @@ -101,10 +101,6 @@ class UserScopeFilter implements FilterInterface 'required' => true, ]); } - public function getFormDefaultData(): array - { - return ['date_calc' => new RollingDate(RollingDate::T_TODAY)]; - } public function describeAction($data, $format = 'string') { @@ -121,6 +117,14 @@ class UserScopeFilter implements FilterInterface ]; } + public function getFormDefaultData(): array + { + return [ + 'scopes' => [], + 'date_calc' => new RollingDate(RollingDate::T_TODAY) + ]; + } + public function getTitle(): string { return 'export.filter.course.by_user_scope.Filter by user scope'; diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php index a05e4b1d2..2ad01c3ff 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/JobFilter.php @@ -94,10 +94,6 @@ class JobFilter implements FilterInterface ]) ; } - public function getFormDefaultData(): array - { - return ['job_at' => new RollingDate(RollingDate::T_TODAY)]; - } public function describeAction($data, $format = 'string') { @@ -114,6 +110,14 @@ class JobFilter implements FilterInterface ]]; } + public function getFormDefaultData(): array + { + return [ + 'job' => [], + 'job_at' => new RollingDate(RollingDate::T_TODAY) + ]; + } + public function getTitle(): string { return 'export.filter.work.by_user_job.Filter by treating agent job'; diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php index 465569198..c5041aa6c 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/SocialWorkFilters/ScopeFilter.php @@ -92,10 +92,6 @@ class ScopeFilter implements FilterInterface ]) ; } - public function getFormDefaultData(): array - { - return ['scope_at' => new RollingDate(RollingDate::T_TODAY)]; - } public function describeAction($data, $format = 'string'): array { @@ -112,6 +108,14 @@ class ScopeFilter implements FilterInterface ]]; } + public function getFormDefaultData(): array + { + return [ + 'scope' => [], + 'scope_at' => new RollingDate(RollingDate::T_TODAY) + ]; + } + public function getTitle(): string { return 'export.filter.work.by_user_scope.Filter by treating agent scope'; From 31fc7fffe9c7c7db344acf1658120549360e853d Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 3 Oct 2023 14:19:45 +0200 Subject: [PATCH 39/62] [export] fix calendar filters/aggregators + tests: 'at' based on calendar date --- .../Export/Aggregator/JobAggregator.php | 36 +++++++---------- .../Export/Aggregator/ScopeAggregator.php | 39 ++++++++----------- .../Export/Filter/JobFilter.php | 37 +++++++----------- .../Export/Filter/ScopeFilter.php | 29 +++++++------- .../Export/Aggregator/JobAggregatorTest.php | 5 +-- .../Export/Aggregator/ScopeAggregatorTest.php | 5 +-- .../Tests/Export/Filter/JobFilterTest.php | 2 - .../Tests/Export/Filter/ScopeFilterTest.php | 2 - .../translations/messages.fr.yml | 24 ++++++------ 9 files changed, 74 insertions(+), 105 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php index 6a7d4cf5d..acef258fa 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php +++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php @@ -14,13 +14,10 @@ namespace Chill\CalendarBundle\Export\Aggregator; use Chill\CalendarBundle\Export\Declarations; use Chill\MainBundle\Entity\User\UserJobHistory; 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\RollingDateConverterInterface; use Chill\MainBundle\Templating\TranslatableStringHelper; use Closure; -use Doctrine\ORM\Query\Expr; +use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; @@ -29,7 +26,6 @@ final readonly class JobAggregator implements AggregatorInterface private const PREFIX = 'cal_agg_job'; public function __construct( - private RollingDateConverterInterface $rollingDateConverter, private UserJobRepository $jobRepository, private TranslatableStringHelper $translatableStringHelper ) {} @@ -44,22 +40,24 @@ final readonly class JobAggregator implements AggregatorInterface $p = self::PREFIX; $qb - ->leftJoin( - 'cal.mainUser', - "{$p}_user" - ) + ->leftJoin('cal.mainUser', "{$p}_user") ->leftJoin( UserJobHistory::class, "{$p}_history", - Expr\Join::WITH, + Join::WITH, $qb->expr()->eq("{$p}_history.user", "{$p}_user") ) - ->andWhere("{$p}_history.startDate <= :{$p}_at AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > :{$p}_at)") - ->addSelect("IDENTITY({$p}_history.job) AS {$p}_select") - ->setParameter( - "{$p}_at", - $this->rollingDateConverter->convert($data['job_at']) + // job_at based on cal.startDate + ->andWhere( + $qb->expr()->andX( + $qb->expr()->lte("{$p}_history.startDate", "cal.startDate"), + $qb->expr()->orX( + $qb->expr()->isNull("{$p}_history.endDate"), + $qb->expr()->gt("{$p}_history.endDate", "cal.startDate") + ) + ) ) + ->addSelect("IDENTITY({$p}_history.job) AS {$p}_select") ->addGroupBy("{$p}_select"); } @@ -70,15 +68,11 @@ final readonly class JobAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('job_at', PickRollingDateType::class, [ - 'label' => 'export.calendar.agent_job.Calc date', - 'required' => true, - ]); } public function getFormDefaultData(): array { - return ['job_at' => new RollingDate(RollingDate::T_TODAY)]; + return []; } public function getLabels($key, array $values, $data): Closure @@ -109,6 +103,6 @@ final readonly class JobAggregator implements AggregatorInterface public function getTitle(): string { - return 'Group calendars by agent job'; + return 'export.aggregator.calendar.agent_job.Group calendars by agent job'; } } diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php index f7c71951e..ec1c91dc9 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php +++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php @@ -14,24 +14,18 @@ namespace Chill\CalendarBundle\Export\Aggregator; use Chill\CalendarBundle\Export\Declarations; use Chill\MainBundle\Entity\User\UserScopeHistory; 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\RollingDateConverterInterface; use Chill\MainBundle\Templating\TranslatableStringHelper; use Closure; -use Doctrine\ORM\Query\Expr; +use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; -use PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Exp; use Symfony\Component\Form\FormBuilderInterface; -use function in_array; final readonly class ScopeAggregator implements AggregatorInterface { private const PREFIX = "cal_agg_scope"; public function __construct( - private RollingDateConverterInterface $rollingDateConverter, private ScopeRepository $scopeRepository, private TranslatableStringHelper $translatableStringHelper ) {} @@ -46,22 +40,24 @@ final readonly class ScopeAggregator implements AggregatorInterface $p = self::PREFIX; $qb - ->leftJoin( - "cal.mainUser", - "{$p}_user" - ) + ->leftJoin("cal.mainUser", "{$p}_user") ->leftJoin( UserScopeHistory::class, "{$p}_history", - Expr\Join::WITH, + Join::WITH, $qb->expr()->eq("{$p}_history.user", "{$p}_user") ) - ->andWhere("{$p}_history.startDate <= :{$p}_at AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > :{$p}_at)") - ->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select") - ->setParameter( - "{$p}_at", - $this->rollingDateConverter->convert($data['scope_at']) + // scope_at based on cal.startDate + ->andWhere( + $qb->expr()->andX( + $qb->expr()->lte("{$p}_history.startDate", "cal.startDate"), + $qb->expr()->orX( + $qb->expr()->isNull("{$p}_history.endDate"), + $qb->expr()->gt("{$p}_history.endDate", "cal.startDate") + ) + ) ) + ->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select") ->addGroupBy("{$p}_select"); } @@ -72,14 +68,11 @@ final readonly class ScopeAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('scope_at', PickRollingDateType::class, [ - 'label' => 'export.calendar.agent_scope.Calc date', - 'required' => true, - ]); } + public function getFormDefaultData(): array { - return ['scope_at' => new RollingDate(RollingDate::T_TODAY)]; + return []; } public function getLabels($key, array $values, $data): Closure @@ -110,6 +103,6 @@ final readonly class ScopeAggregator implements AggregatorInterface public function getTitle(): string { - return 'Group calendars by agent scope'; + return 'export.aggregator.calendar.agent_scope.Group calendars by agent scope'; } } diff --git a/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php b/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php index 11a26eea6..1b666019b 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php +++ b/src/Bundle/ChillCalendarBundle/Export/Filter/JobFilter.php @@ -15,11 +15,8 @@ use Chill\CalendarBundle\Export\Declarations; use Chill\MainBundle\Entity\User\UserJobHistory; use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Export\FilterInterface; -use Chill\MainBundle\Form\Type\PickRollingDateType; -use Chill\MainBundle\Service\RollingDate\RollingDate; -use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelper; -use Doctrine\ORM\Query\Expr; +use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\FormBuilderInterface; @@ -30,7 +27,6 @@ class JobFilter implements FilterInterface private const PREFIX = 'cal_filter_job'; public function __construct( - private readonly RollingDateConverter $rollingDateConverter, protected TranslatorInterface $translator, private readonly TranslatableStringHelper $translatableStringHelper ) {} @@ -45,25 +41,27 @@ class JobFilter implements FilterInterface $p = self::PREFIX; $qb - ->leftJoin( - "cal.mainUser", - "{$p}_user" - ) + ->leftJoin("cal.mainUser", "{$p}_user") ->leftJoin( UserJobHistory::class, "{$p}_history", - Expr\Join::WITH, + Join::WITH, $qb->expr()->eq("{$p}_history.user", "{$p}_user") ) - ->andWhere($qb->expr()->in("{$p}_history.job", ":{$p}_job")) + // job_at based on cal.startDate ->andWhere( - "{$p}_history.startDate <= :{$p}_at AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > :{$p}_at)" + $qb->expr()->andX( + $qb->expr()->lte("{$p}_history.startDate", "cal.startDate"), + $qb->expr()->orX( + $qb->expr()->isNull("{$p}_history.endDate"), + $qb->expr()->gt("{$p}_history.endDate", "cal.startDate") + ) + ) ) + ->andWhere($qb->expr()->in("{$p}_history.job", ":{$p}_job")) ->setParameters([ "{$p}_job" => $data["job"], - "{$p}_at" => $this->rollingDateConverter->convert($data["job_at"]) - ]) - ; + ]); } @@ -82,10 +80,6 @@ class JobFilter implements FilterInterface ), 'multiple' => true, 'expanded' => true, - ]) - ->add('job_at', PickRollingDateType::class, [ - 'label' => 'export.calendar.agent_job.Calc date', - 'required' => true, ]); } @@ -99,7 +93,7 @@ class JobFilter implements FilterInterface ); } - return ['Filtered by agent job: only %jobs%', [ + return ['export.filter.calendar.agent_job.Filtered by agent job: only %jobs%', [ '%jobs%' => implode(', ', $userJobs), ]]; } @@ -108,12 +102,11 @@ class JobFilter implements FilterInterface { return [ 'job' => [], - 'job_at' => new RollingDate(RollingDate::T_TODAY), ]; } public function getTitle(): string { - return 'Filter calendars by agent job'; + return 'export.filter.calendar.agent_job.Filter calendars by agent job'; } } diff --git a/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php b/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php index 5a310c38b..61ec8d50d 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php +++ b/src/Bundle/ChillCalendarBundle/Export/Filter/ScopeFilter.php @@ -15,11 +15,8 @@ use Chill\CalendarBundle\Export\Declarations; use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\FilterInterface; -use Chill\MainBundle\Form\Type\PickRollingDateType; -use Chill\MainBundle\Service\RollingDate\RollingDate; -use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelper; -use Doctrine\ORM\Query\Expr; +use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\FormBuilderInterface; @@ -30,7 +27,6 @@ class ScopeFilter implements FilterInterface private const PREFIX = 'cal_filter_scope'; public function __construct( - private readonly RollingDateConverter $rollingDateConverter, protected TranslatorInterface $translator, private readonly TranslatableStringHelper $translatableStringHelper ) {} @@ -49,16 +45,22 @@ class ScopeFilter implements FilterInterface ->leftJoin( UserScopeHistory::class, "{$p}_history", - Expr\Join::WITH, + Join::WITH, $qb->expr()->eq("{$p}_history.user", "{$p}_user") ) - ->andWhere($qb->expr()->in("{$p}_history.scope", ":{$p}_scope")) + // scope_at based on cal.startDate ->andWhere( - "{$p}_history.startDate <= :{$p}_at AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > :{$p}_at)" + $qb->expr()->andX( + $qb->expr()->lte("{$p}_history.startDate", "cal.startDate"), + $qb->expr()->orX( + $qb->expr()->isNull("{$p}_history.endDate"), + $qb->expr()->gt("{$p}_history.endDate", "cal.startDate") + ) + ) ) + ->andWhere($qb->expr()->in("{$p}_history.scope", ":{$p}_scope")) ->setParameters([ "{$p}_scope" => $data["scope"], - "{$p}_at" => $this->rollingDateConverter->convert($data['scope_at']) ]); } @@ -77,10 +79,6 @@ class ScopeFilter implements FilterInterface ), 'multiple' => true, 'expanded' => true, - ]) - ->add('scope_at', PickRollingDateType::class, [ - 'label' => 'export.calendar.agent_scope.Calc date', - 'required' => true, ]); } @@ -94,7 +92,7 @@ class ScopeFilter implements FilterInterface ); } - return ['Filtered by agent scope: only %scopes%', [ + return ['export.filter.calendar.agent_scope.Filtered by agent scope: only %scopes%', [ '%scopes%' => implode(', ', $scopes), ]]; } @@ -103,12 +101,11 @@ class ScopeFilter implements FilterInterface { return [ 'scope' => [], - 'scope_at' => new RollingDate(RollingDate::T_TODAY) ]; } public function getTitle(): string { - return 'Filter calendars by agent scope'; + return 'export.filter.calendar.agent_scope.Filter calendars by agent scope'; } } diff --git a/src/Bundle/ChillCalendarBundle/Tests/Export/Aggregator/JobAggregatorTest.php b/src/Bundle/ChillCalendarBundle/Tests/Export/Aggregator/JobAggregatorTest.php index 838f8b988..094567fa7 100644 --- a/src/Bundle/ChillCalendarBundle/Tests/Export/Aggregator/JobAggregatorTest.php +++ b/src/Bundle/ChillCalendarBundle/Tests/Export/Aggregator/JobAggregatorTest.php @@ -20,7 +20,6 @@ namespace Chill\CalendarBundle\Tests\Export\Aggregator; use Chill\CalendarBundle\Entity\Calendar; use Chill\CalendarBundle\Export\Aggregator\JobAggregator; -use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Test\Export\AbstractAggregatorTest; use Doctrine\ORM\EntityManagerInterface; @@ -47,9 +46,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')), - ] + [] ]; } diff --git a/src/Bundle/ChillCalendarBundle/Tests/Export/Aggregator/ScopeAggregatorTest.php b/src/Bundle/ChillCalendarBundle/Tests/Export/Aggregator/ScopeAggregatorTest.php index 43900d53a..c9a2b9e5c 100644 --- a/src/Bundle/ChillCalendarBundle/Tests/Export/Aggregator/ScopeAggregatorTest.php +++ b/src/Bundle/ChillCalendarBundle/Tests/Export/Aggregator/ScopeAggregatorTest.php @@ -20,7 +20,6 @@ namespace Chill\CalendarBundle\Tests\Export\Aggregator; use Chill\CalendarBundle\Entity\Calendar; use Chill\CalendarBundle\Export\Aggregator\ScopeAggregator; -use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Test\Export\AbstractAggregatorTest; use Doctrine\ORM\EntityManagerInterface; @@ -47,9 +46,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')), - ], + [], ]; } diff --git a/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/JobFilterTest.php b/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/JobFilterTest.php index c1305036c..a395062db 100644 --- a/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/JobFilterTest.php +++ b/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/JobFilterTest.php @@ -21,7 +21,6 @@ namespace Chill\CalendarBundle\Tests\Export\Filter; use Chill\CalendarBundle\Entity\Calendar; use Chill\CalendarBundle\Export\Filter\JobFilter; use Chill\MainBundle\Entity\UserJob; -use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Test\Export\AbstractFilterTest; use Doctrine\ORM\EntityManagerInterface; @@ -68,7 +67,6 @@ final class JobFilterTest extends AbstractFilterTest foreach ($array as $a) { $data[] = [ 'job' => $a, - 'job_at' => new RollingDate(RollingDate::T_FIXED_DATE, \DateTimeImmutable::createFromFormat('Y-m-d', '2020-01-01')), ]; } diff --git a/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/ScopeFilterTest.php b/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/ScopeFilterTest.php index 5d54a091e..eef7d1362 100644 --- a/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/ScopeFilterTest.php +++ b/src/Bundle/ChillCalendarBundle/Tests/Export/Filter/ScopeFilterTest.php @@ -21,7 +21,6 @@ namespace Chill\CalendarBundle\Tests\Export\Filter; use Chill\CalendarBundle\Entity\Calendar; use Chill\CalendarBundle\Export\Filter\ScopeFilter; use Chill\MainBundle\Entity\Scope; -use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Test\Export\AbstractFilterTest; use Doctrine\ORM\EntityManagerInterface; @@ -68,7 +67,6 @@ final class ScopeFilterTest extends AbstractFilterTest foreach ($array as $a) { $data[] = [ 'scope' => $a, - 'scope_at' => new RollingDate(RollingDate::T_FIXED_DATE, \DateTimeImmutable::createFromFormat('Y-m-d', '2020-01-01')), ]; } diff --git a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml index 0da92fd72..d157683e0 100644 --- a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml @@ -99,29 +99,31 @@ Get the sum of appointment durations according to various filters: Calcule la so 'Filtered by agent: only %agents%': "Filtré par agents: uniquement %agents%" Filter calendars by agent: Filtrer les rendez-vous par agents -Filter calendars by agent job: Filtrer les rendez-vous par métiers des agents -'Filtered by agent job: only %jobs%': 'Filtré par métiers des agents: uniquement les %jobs%' -Filter calendars by agent scope: Filtrer les rendez-vous par services des agents -'Filtered by agent scope: only %scopes%': 'Filtré par services des agents: uniquement les services %scopes%' Filter calendars between certain dates: Filtrer les rendez-vous par date du rendez-vous 'Filtered by calendars between %dateFrom% and %dateTo%': 'Filtré par rendez-vous entre %dateFrom% et %dateTo%' 'Filtered by calendar range: only %calendarRange%': 'Filtré par rendez-vous par plage de disponibilité: uniquement les %calendarRange%' Filter by calendar range: Filtrer par rendez-vous dans une plage de disponibilité ou non Group calendars by agent: Grouper les rendez-vous par agent -Group calendars by agent job: Grouper les rendez-vous par métier de l'agent -Group calendars by agent scope: Grouper les rendez-vous par service de l'agent Group calendars by location type: Grouper les rendez-vous par type de localisation Group calendars by location: Grouper les rendez-vous par lieu de rendez-vous Group calendars by cancel reason: Grouper les rendez-vous par motif d'annulation Group calendars by month and year: Grouper les rendez-vous par mois et année Group calendars by urgency: Grouper les rendez-vous par urgent ou non -export.calendar: - agent_job: - Calc date: Date de calcul du métier de l'agent - agent_scope: - Calc date: Date de calcul du service de l'agent +export: + aggregator.calendar: + agent_job: + Group calendars by agent job: Grouper les rendez-vous par métier de l'agent + agent_scope: + Group calendars by agent scope: Grouper les rendez-vous par service de l'agent + filter.calendar: + agent_job: + Filter calendars by agent job: Filtrer les rendez-vous par métiers des agents (utilisateurs principaux) + 'Filtered by agent job: only %jobs%': 'Filtré par métiers des agents (utilisateurs principaux): uniquement les %jobs%' + agent_scope: + Filter calendars by agent scope: Filtrer les rendez-vous par services des agents (utilisateurs principaux) + 'Filtered by agent scope: only %scopes%': 'Filtré par services des agents (utilisateurs principaux): uniquement les services %scopes%' Scope: Service Job: Métier From 6e48d036d7ff21efb173e555a561059d7a5c38e9 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 3 Oct 2023 14:43:25 +0200 Subject: [PATCH 40/62] [export] fix aside activity filters/aggregators: 'at' based on aside date --- .../Export/Aggregator/ByUserJobAggregator.php | 25 +++++-------------- .../Aggregator/ByUserScopeAggregator.php | 22 ++++------------ .../src/Export/Filter/ByUserJobFilter.php | 15 +++-------- .../src/Export/Filter/ByUserScopeFilter.php | 15 +++-------- .../src/translations/messages.fr.yml | 4 --- 5 files changed, 17 insertions(+), 64 deletions(-) diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php index a7a7e403e..6ea912eed 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php @@ -14,23 +14,17 @@ namespace Chill\AsideActivityBundle\Export\Aggregator; use Chill\AsideActivityBundle\Export\Declarations; use Chill\MainBundle\Entity\User\UserJobHistory; use Chill\MainBundle\Export\AggregatorInterface; -use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\UserJobRepositoryInterface; -use Chill\MainBundle\Service\RollingDate\RollingDate; -use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; -use Doctrine\ORM\Query\Expr; +use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; -use function in_array; - class ByUserJobAggregator implements AggregatorInterface { private const PREFIX = 'aside_act_agg_user_job'; public function __construct( - private readonly RollingDateConverter $rollingDateConverter, private readonly UserJobRepositoryInterface $userJobRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper ) {} @@ -49,23 +43,20 @@ class ByUserJobAggregator implements AggregatorInterface ->leftJoin( UserJobHistory::class, "{$p}_history", - Expr\Join::WITH, + Join::WITH, $qb->expr()->eq("{$p}_history.user", "{$p}_user") ) + // job_at based on aside.date ->andWhere( $qb->expr()->andX( - $qb->expr()->lte("{$p}_history.startDate", ":{$p}_at"), + $qb->expr()->lte("{$p}_history.startDate", "aside.date"), $qb->expr()->orX( $qb->expr()->isNull("{$p}_history.endDate"), - $qb->expr()->gt("{$p}_history.endDate", ":{$p}_at") + $qb->expr()->gt("{$p}_history.endDate", "aside.date") ) ) ) ->addSelect("IDENTITY({$p}_history.job) AS {$p}_select") - ->setParameter( - "{$p}_at", - $this->rollingDateConverter->convert($data['job_at']) - ) ->addGroupBy("{$p}_select"); } @@ -76,15 +67,11 @@ class ByUserJobAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('job_at', PickRollingDateType::class, [ - 'label' => 'export.aggregator.by_user_job.Calc date', - 'required' => true - ]); } 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/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php index 168d38433..3d55884b4 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php @@ -14,12 +14,9 @@ namespace Chill\AsideActivityBundle\Export\Aggregator; use Chill\AsideActivityBundle\Export\Declarations; use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\AggregatorInterface; -use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\ScopeRepositoryInterface; -use Chill\MainBundle\Service\RollingDate\RollingDate; -use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; -use Doctrine\ORM\Query\Expr; +use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; @@ -28,7 +25,6 @@ class ByUserScopeAggregator implements AggregatorInterface private const PREFIX = 'aside_act_agg_user_scope'; public function __construct( - private readonly RollingDateConverter $rollingDateConverter, private readonly ScopeRepositoryInterface $scopeRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper ) {} @@ -47,23 +43,19 @@ class ByUserScopeAggregator implements AggregatorInterface ->leftJoin( UserScopeHistory::class, "{$p}_history", - Expr\Join::WITH, + Join::WITH, $qb->expr()->eq("{$p}_history.user", "{$p}_user") ) ->andWhere( $qb->expr()->andX( - $qb->expr()->lte("{$p}_history.startDate", ":{$p}_at"), + $qb->expr()->lte("{$p}_history.startDate", "aside.date"), $qb->expr()->orX( $qb->expr()->isNull("{$p}_history.endDate"), - $qb->expr()->gt("{$p}_history.endDate", ":{$p}_at") + $qb->expr()->gt("{$p}_history.endDate", "aside.date") ) ) ) ->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select") - ->setParameter( - "{$p}_at", - $this->rollingDateConverter->convert($data['scope_at']) - ) ->addGroupBy("{$p}_select"); } @@ -74,15 +66,11 @@ class ByUserScopeAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('scope_at', PickRollingDateType::class, [ - 'label' => 'export.aggregator.by_user_scope.Calc date', - 'required' => true, - ]); } 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/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php index 867eca230..d76d6d126 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserJobFilter.php @@ -16,9 +16,6 @@ use Chill\AsideActivityBundle\Export\Declarations; use Chill\MainBundle\Entity\User\UserJobHistory; use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Export\FilterInterface; -use Chill\MainBundle\Form\Type\PickRollingDateType; -use Chill\MainBundle\Service\RollingDate\RollingDate; -use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; @@ -29,7 +26,6 @@ class ByUserJobFilter implements FilterInterface private const PREFIX = 'aside_act_filter_user_job'; public function __construct( - private readonly RollingDateConverter $rollingDateConverter, private readonly TranslatableStringHelperInterface $translatableStringHelper ) {} @@ -49,14 +45,14 @@ class ByUserJobFilter implements FilterInterface . "JOIN {$p}_act.agent {$p}_user " . "JOIN " . UserJobHistory::class . " {$p}_history WITH {$p}_history.user = {$p}_user " . "WHERE {$p}_act = aside " - . "AND {$p}_history.startDate <= :{$p}_at " - . "AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > :{$p}_at) " + // job_at based on aside.date + . "AND {$p}_history.startDate <= aside.date " + . "AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > aside.date) " . "AND {$p}_history.job IN ( :{$p}_jobs )" ) ) ->setParameters([ "{$p}_jobs" => $data["jobs"], - "{$p}_at" => $this->rollingDateConverter->convert($data["job_at"]) ]); } @@ -73,10 +69,6 @@ class ByUserJobFilter implements FilterInterface 'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize($j->getLabel()), 'multiple' => true, 'expanded' => true, - ]) - ->add('job_at', PickRollingDateType::class, [ - 'label' => 'export.filter.by_user_job.Calc date', - 'required' => true ]); } @@ -97,7 +89,6 @@ class ByUserJobFilter implements FilterInterface { return [ 'jobs' => [], - 'job_at' => new RollingDate(RollingDate::T_TODAY) ]; } diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php index ce6905378..7df450bde 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Filter/ByUserScopeFilter.php @@ -16,10 +16,7 @@ use Chill\AsideActivityBundle\Export\Declarations; use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\FilterInterface; -use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\ScopeRepositoryInterface; -use Chill\MainBundle\Service\RollingDate\RollingDate; -use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; @@ -30,7 +27,6 @@ class ByUserScopeFilter implements FilterInterface private const PREFIX = 'aside_act_filter_user_scope'; public function __construct( - private readonly RollingDateConverter $rollingDateConverter, private readonly ScopeRepositoryInterface $scopeRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper ) {} @@ -51,14 +47,14 @@ class ByUserScopeFilter implements FilterInterface . "JOIN {$p}_act.agent {$p}_user " . "JOIN " . UserScopeHistory::class . " {$p}_history WITH {$p}_history.user = {$p}_user " . "WHERE {$p}_act = aside " - . "AND {$p}_history.startDate <= :{$p}_at " - . "AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > :{$p}_at) " + // scope_at based on aside.date + . "AND {$p}_history.startDate <= aside.date " + . "AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > aside.date) " . "AND {$p}_history.scope IN ( :{$p}_scopes )" ) ) ->setParameters([ "{$p}_scopes" => $data["scopes"], - "{$p}_at" => $this->rollingDateConverter->convert($data["scope_at"]) ]); } @@ -76,10 +72,6 @@ class ByUserScopeFilter implements FilterInterface 'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()), 'multiple' => true, 'expanded' => true, - ]) - ->add('scope_at', PickRollingDateType::class, [ - 'label' => 'export.filter.by_user_scope.Calc date', - 'required' => true, ]); } @@ -100,7 +92,6 @@ class ByUserScopeFilter implements FilterInterface { return [ 'scopes' => [], - 'scope_at' => new RollingDate(RollingDate::T_TODAY) ]; } diff --git a/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml b/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml index fe895e223..0a324d2cd 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml +++ b/src/Bundle/ChillAsideActivityBundle/src/translations/messages.fr.yml @@ -203,11 +203,9 @@ export: by_user_job: 'Filtered aside activities by user jobs: only %jobs%': "Filtré par métier des utilisateurs: uniquement %jobs%" Filter by user jobs: Filtrer les activités annexes par métier des utilisateurs - Calc date: Date de calcul du métier des utilisateurs by_user_scope: 'Filtered aside activities by user scope: only %scopes%': "Filtré par service des utilisateurs: uniquement %scopes%" Filter by user scope: Filtrer les activités annexes par service d'utilisateur - Calc date: Date de calcul du service des utilisateurs Filter by aside activity location: Filtrer les activités annexes par localisation 'Filtered by aside activity location: only %location%': "Filtré par localisation: uniquement %location%" aggregator: @@ -215,10 +213,8 @@ export: Aside activity type: Type d'activité annexe by_user_job: Aggregate by user job: Grouper les activités annexes par métier des utilisateurs - Calc date: Date de calcul du métier des utilisateurs by_user_scope: Aggregate by user scope: Grouper les activités annexes par service des utilisateurs - Calc date: Date de calcul du service des utilisateurs Aside activity location: Localisation des activités annexe Group by aside activity location: Grouper les activités annexes par localisation Aside activity localisation: Localisation From fa3fc2c781156365ef6ff4ab89d27ad1aaa9e055 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 3 Oct 2023 15:24:41 +0200 Subject: [PATCH 41/62] [export] fix activity filters/aggregators + tests: 'at' based on activity date --- .../Aggregator/ActivityUsersJobAggregator.php | 20 ++++------------ .../ActivityUsersScopeAggregator.php | 19 ++++----------- .../Aggregator/CreatorScopeAggregator.php | 23 +++++-------------- .../Export/Filter/UserScopeFilter.php | 19 ++++++--------- .../Export/Filter/UsersJobFilter.php | 15 +++--------- .../Export/Filter/UsersScopeFilter.php | 15 +++--------- .../Export/Filter/UserScopeFilterTest.php | 2 +- .../translations/messages.fr.yml | 14 +++-------- 8 files changed, 31 insertions(+), 96 deletions(-) diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php index 5696a9780..da851f8f2 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php @@ -14,10 +14,7 @@ namespace Chill\ActivityBundle\Export\Aggregator; use Chill\ActivityBundle\Export\Declarations; use Chill\MainBundle\Entity\User\UserJobHistory; use Chill\MainBundle\Export\AggregatorInterface; -use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\UserJobRepositoryInterface; -use Chill\MainBundle\Service\RollingDate\RollingDate; -use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; @@ -28,7 +25,6 @@ class ActivityUsersJobAggregator implements AggregatorInterface private const PREFIX = 'act_agg_user_job'; public function __construct( - private readonly RollingDateConverter $rollingDateConverter, private readonly UserJobRepositoryInterface $userJobRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper ) {} @@ -50,20 +46,17 @@ class ActivityUsersJobAggregator implements AggregatorInterface Expr\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", ":{$p}_at"), + $qb->expr()->lte("{$p}_history.startDate", "activity.date"), $qb->expr()->orX( $qb->expr()->isNull("{$p}_history.endDate"), - $qb->expr()->gt("{$p}_history.endDate", ":{$p}_at") + $qb->expr()->gt("{$p}_history.endDate", "activity.date") ) ) ) ->addSelect("IDENTITY({$p}_history.job) AS {$p}_select") - ->setParameter( - "{$p}_at", - $this->rollingDateConverter->convert($data['job_at']) - ) ->addGroupBy("{$p}_select"); } @@ -74,16 +67,11 @@ class ActivityUsersJobAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('job_at', PickRollingDateType::class, [ - 'label' => 'export.aggregator.activity.by_user_job.Calc date', - 'required' => true - ]); - } 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/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php index 41ef1934e..b9f1e4874 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php @@ -14,10 +14,7 @@ namespace Chill\ActivityBundle\Export\Aggregator; use Chill\ActivityBundle\Export\Declarations; use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\AggregatorInterface; -use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\ScopeRepositoryInterface; -use Chill\MainBundle\Service\RollingDate\RollingDate; -use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; @@ -28,7 +25,6 @@ class ActivityUsersScopeAggregator implements AggregatorInterface private const PREFIX = 'act_agg_user_scope'; public function __construct( - private readonly RollingDateConverter $rollingDateConverter, private readonly ScopeRepositoryInterface $scopeRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper ) {} @@ -50,20 +46,17 @@ class ActivityUsersScopeAggregator implements AggregatorInterface Expr\Join::WITH, $qb->expr()->eq("{$p}_history.user", "{$p}_user") ) + // scope_at based on activity.date ->andWhere( $qb->expr()->andX( - $qb->expr()->lte("{$p}_history.startDate", ":{$p}_at"), + $qb->expr()->lte("{$p}_history.startDate", "activity.date"), $qb->expr()->orX( $qb->expr()->isNull("{$p}_history.endDate"), - $qb->expr()->gt("{$p}_history.endDate", ":{$p}_at") + $qb->expr()->gt("{$p}_history.endDate", "activity.date") ) ) ) ->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select") - ->setParameter( - "{$p}_at", - $this->rollingDateConverter->convert($data['scope_at']) - ) ->addGroupBy("{$p}_select"); } @@ -74,15 +67,11 @@ class ActivityUsersScopeAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('scope_at', PickRollingDateType::class, [ - 'label' => 'export.aggregator.activity.by_user_scope.Calc date', - 'required' => true, - ]); } 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/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php index de8fea079..9bce69131 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php @@ -14,12 +14,9 @@ namespace Chill\ActivityBundle\Export\Aggregator; use Chill\ActivityBundle\Export\Declarations; use Chill\MainBundle\Entity\User\UserScopeHistory; 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 Doctrine\ORM\Query\Expr; +use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; @@ -28,7 +25,6 @@ class CreatorScopeAggregator implements AggregatorInterface private const PREFIX = 'acp_agg_creator_scope'; public function __construct( - private readonly RollingDateConverter $rollingDateConverter, private readonly ScopeRepository $scopeRepository, private readonly TranslatableStringHelper $translatableStringHelper ) {} @@ -47,23 +43,20 @@ class CreatorScopeAggregator implements AggregatorInterface ->leftJoin( UserScopeHistory::class, "{$p}_history", - Expr\Join::WITH, + Join::WITH, $qb->expr()->eq("{$p}_history.user", "{$p}_user") ) + // scope_at based on activity.date ->andWhere( $qb->expr()->andX( - $qb->expr()->lte("{$p}_history.startDate", ":{$p}_at"), + $qb->expr()->lte("{$p}_history.startDate", "activity.date"), $qb->expr()->orX( $qb->expr()->isNull("{$p}_history.endDate"), - $qb->expr()->gt("{$p}_history.endDate", ":{$p}_at") + $qb->expr()->gt("{$p}_history.endDate", "activity.date") ) ) ) ->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select") - ->setParameter( - "{$p}_at", - $this->rollingDateConverter->convert($data['scope_at']) - ) ->addGroupBy("{$p}_select"); } @@ -74,15 +67,11 @@ class CreatorScopeAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('scope_at', PickRollingDateType::class, [ - 'label' => 'export.aggregator.activity.by_creator_scope.Calc date', - 'required' => true, - ]); } 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/ChillActivityBundle/Export/Filter/UserScopeFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/UserScopeFilter.php index ad7585d71..f942fd6d6 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/UserScopeFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/UserScopeFilter.php @@ -50,21 +50,21 @@ class UserScopeFilter implements FilterInterface Join::WITH, $qb->expr()->eq("{$p}_history.user", "{$p}_user") ) + // scope_at based on activity.date ->andWhere( $qb->expr()->andX( - $qb->expr()->lte("{$p}_history.startDate", ":{$p}_at"), + $qb->expr()->lte("{$p}_history.startDate", "activity.date"), $qb->expr()->orX( $qb->expr()->isNull("{$p}_history.endDate"), - $qb->expr()->gt("{$p}_history.endDate", ":{$p}_at") + $qb->expr()->gt("{$p}_history.endDate", "activity.date") ) ) ) ->andWhere( - $qb->expr()->in("{$p}_history.scope", ":{$p}_scope") + $qb->expr()->in("{$p}_history.scope", ":{$p}_scopes") ) ->setParameters([ - "{$p}_scope" => $data["scopes"], - "{$p}_at" => $this->rollingDateConverter->convert($data["scope_at"]) + "{$p}_scopes" => $data["scopes"], ]); } @@ -83,10 +83,6 @@ class UserScopeFilter implements FilterInterface ), 'multiple' => true, 'expanded' => true, - ]) - ->add('scope_at', PickRollingDateType::class, [ - 'label' => 'export.filter.activity.course.by_user_scope.Calc date', - 'required' => true, ]); } @@ -100,7 +96,7 @@ class UserScopeFilter implements FilterInterface ); } - return ['export.filter.activity.course.by_user_scope.Filtered activity by userscope: only %scopes%', [ + return ['export.filter.activity.by_creator_scope.Filtered activity by user scope: only %scopes%', [ '%scopes%' => implode(', ', $scopes), ]]; } @@ -109,12 +105,11 @@ class UserScopeFilter implements FilterInterface { return [ 'scopes' => [], - 'scope_at' => new RollingDate(RollingDate::T_TODAY) ]; } public function getTitle(): string { - return 'export.filter.activity.course.by_user_scope.Filter activity by userscope'; + return 'export.filter.activity.by_creator_scope.Filter activity by user scope'; } } diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/UsersJobFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/UsersJobFilter.php index 4185ad4e9..b49397521 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/UsersJobFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/UsersJobFilter.php @@ -16,9 +16,6 @@ use Chill\ActivityBundle\Export\Declarations; use Chill\MainBundle\Entity\User\UserJobHistory; use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Export\FilterInterface; -use Chill\MainBundle\Form\Type\PickRollingDateType; -use Chill\MainBundle\Service\RollingDate\RollingDate; -use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; @@ -29,7 +26,6 @@ class UsersJobFilter implements FilterInterface private const PREFIX = 'act_filter_user_job'; public function __construct( - private readonly RollingDateConverter $rollingDateConverter, private readonly TranslatableStringHelperInterface $translatableStringHelper ) {} @@ -49,14 +45,14 @@ class UsersJobFilter implements FilterInterface . "JOIN {$p}_act.users {$p}_user " . "JOIN " . UserJobHistory::class . " {$p}_history WITH {$p}_history.user = {$p}_user " . "WHERE {$p}_act = activity " - . "AND {$p}_history.startDate <= :{$p}_at " - . "AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > :{$p}_at) " + // job_at based on activity.date + . "AND {$p}_history.startDate <= activity.date " + . "AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > activity.date) " . "AND {$p}_history.job IN ( :{$p}_jobs )" ) ) ->setParameters([ "{$p}_jobs" => $data["jobs"], - "{$p}_at" => $this->rollingDateConverter->convert($data["job_at"]) ]); } @@ -73,10 +69,6 @@ class UsersJobFilter implements FilterInterface 'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize($j->getLabel()), 'multiple' => true, 'expanded' => true, - ]) - ->add('job_at', PickRollingDateType::class, [ - 'label' => 'export.filter.activity.by_users_job.Calc date', - 'required' => true ]); } @@ -97,7 +89,6 @@ class UsersJobFilter implements FilterInterface { return [ 'jobs' => [], - 'job_at' => new RollingDate(RollingDate::T_TODAY) ]; } diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/UsersScopeFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/UsersScopeFilter.php index e2c4ca1e0..3391f92cf 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/UsersScopeFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/UsersScopeFilter.php @@ -16,10 +16,7 @@ use Chill\ActivityBundle\Export\Declarations; use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\FilterInterface; -use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\ScopeRepositoryInterface; -use Chill\MainBundle\Service\RollingDate\RollingDate; -use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; @@ -30,7 +27,6 @@ class UsersScopeFilter implements FilterInterface private const PREFIX = 'act_filter_user_scope'; public function __construct( - private readonly RollingDateConverter $rollingDateConverter, private readonly ScopeRepositoryInterface $scopeRepository, private readonly TranslatableStringHelperInterface $translatableStringHelper ) {} @@ -51,14 +47,14 @@ class UsersScopeFilter implements FilterInterface . "JOIN {$p}_act.users {$p}_user " . "JOIN " . UserScopeHistory::class . " {$p}_history WITH {$p}_history.user = {$p}_user " . "WHERE {$p}_act = activity " - . "AND {$p}_history.startDate <= :{$p}_at " - . "AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > :{$p}_at) " + // scope_at based on activity.date + . "AND {$p}_history.startDate <= activity.date " + . "AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > activity.date) " . "AND {$p}_history.scope IN ( :{$p}_scopes )" ) ) ->setParameters([ "{$p}_scopes" => $data["scopes"], - "{$p}_at" => $this->rollingDateConverter->convert($data["scope_at"]) ]); } @@ -76,10 +72,6 @@ class UsersScopeFilter implements FilterInterface 'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()), 'multiple' => true, 'expanded' => true, - ]) - ->add('scope_at', PickRollingDateType::class, [ - 'label' => 'export.filter.activity.by_users_scope.Calc date', - 'required' => true, ]); } @@ -100,7 +92,6 @@ class UsersScopeFilter implements FilterInterface { return [ 'scopes' => [], - 'scope_at' => new RollingDate(RollingDate::T_TODAY) ]; } diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/UserScopeFilterTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/UserScopeFilterTest.php index cc165c6ac..0e38e92a6 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Filter/UserScopeFilterTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Filter/UserScopeFilterTest.php @@ -53,7 +53,7 @@ final class UserScopeFilterTest extends AbstractFilterTest foreach ($array as $a) { $data[] = [ - 'accepted_userscope' => $a, + 'scopes' => $a, ]; } diff --git a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml index 2576b9bf4..3496f7a52 100644 --- a/src/Bundle/ChillActivityBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillActivityBundle/translations/messages.fr.yml @@ -363,23 +363,18 @@ export: by_users_job: Filter by users job: Filtrer les échanges par métier d'au moins un utilisateur participant 'Filtered activity by users job: only %jobs%': 'Filtré par métier d''au moins un utilisateur participant: seulement %jobs%' - Calc date: Date de calcul du métier de l'utilisateur by_users_scope: Filter by users scope: Filtrer les échanges par services d'au moins un utilisateur participant 'Filtered activity by users scope: only %scopes%': 'Filtré par service d''au moins un utilisateur participant: seulement %scopes%' - Calc date: Date de calcul du service de l'utilisateur course_having_activity_between_date: Title: Filtre les parcours ayant reçu un échange entre deux dates Receiving an activity after: Ayant reçu un échange après le Receiving an activity before: Ayant reçu un échange avant le acp_by_activity_type: 'acp_containing_at_least_one_%activitytypes%': 'Parcours filtrés: uniquement ceux qui contiennent au moins un échange d''un des types suivants: %activitytypes%' - course: - by_user_scope: - Filter activity by userscope: Filtrer les échanges par service du créateur - 'Filtered activity by userscope: only %scopes%': "Filtré par service du créateur: uniquement %scopes%" - Calc date: Date de calcul du service du créateur - + by_creator_scope: + Filter activity by user scope: Filtrer les échanges par service du créateur de l'échange + 'Filtered activity by user scope: only %scopes%': "Filtré par service du créateur: uniquement %scopes%" aggregator: activity: @@ -394,16 +389,13 @@ export: by_user_job: Users 's job: Métier des utilisateurs participants à l'échange Aggregate by users job: Grouper les échanges par métier des utilisateurs participants - Calc date: Date de calcul du métier des participants by_user_scope: Users 's scope: Service principal des utilisateurs participants à l'échange Aggregate by users scope: Grouper les échanges par service principal de l'utilisateur - Calc date: Date de calcul du service principal de l'utilisateur 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 - generic_doc: filter: keys: From c00c26c3e55302ecfa344bb7f588a388d6e68319 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Thu, 28 Sep 2023 17:21:24 +0200 Subject: [PATCH 42/62] [export] fix 2 job/scope 'WorkingOnCourse' filters in acp --- .../JobWorkingOnCourseAggregator.php | 15 +-- .../ScopeWorkingOnCourseAggregator.php | 15 +-- .../JobWorkingOnCourseFilter.php | 100 ++++++++++-------- .../ScopeWorkingOnCourseFilter.php | 96 ++++++++--------- .../translations/messages.fr.yml | 2 + 5 files changed, 112 insertions(+), 116 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php index ccc108cd0..a58f6dcaa 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php @@ -57,20 +57,17 @@ final readonly class JobWorkingOnCourseAggregator implements AggregatorInterface Join::WITH, $qb->expr()->eq("{$p}_history.user", "{$p}_user") ) + // job_at based on _info.infoDate ->andWhere( $qb->expr()->andX( - $qb->expr()->lte("{$p}_history.startDate", ":{$p}_at"), + $qb->expr()->lte("{$p}_history.startDate", "acpinfo.infoDate"), $qb->expr()->orX( $qb->expr()->isNull("{$p}_history.endDate"), - $qb->expr()->gt("{$p}_history.endDate", ":{$p}_at") + $qb->expr()->gt("{$p}_history.endDate", "acpinfo.infoDate") ) ) ) ->addSelect("IDENTITY({$p}_history.job) AS {$p}_select") - ->setParameter( - "{$p}_at", - $this->rollingDateConverter->convert($data['job_at']) - ) ->addGroupBy("{$p}_select"); } @@ -81,15 +78,11 @@ final readonly class JobWorkingOnCourseAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('job_at', PickRollingDateType::class, [ - 'label' => 'export.aggregator.course.by_job_working.Calc date', - 'required' => true - ]); } public function getFormDefaultData(): array { - return ['job_at' => new RollingDate(RollingDate::T_TODAY)]; + return []; } public function getLabels($key, array $values, $data): \Closure diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php index 08bddabb5..e45f7d479 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php @@ -57,20 +57,17 @@ final readonly class ScopeWorkingOnCourseAggregator implements AggregatorInterfa Join::WITH, $qb->expr()->eq("{$p}_history.user", "{$p}_user") ) + // scope_at based on _info.infoDate ->andWhere( $qb->expr()->andX( - $qb->expr()->lte("{$p}_history.startDate", ":{$p}_at"), + $qb->expr()->lte("{$p}_history.startDate", "acpinfo.infoDate"), $qb->expr()->orX( $qb->expr()->isNull("{$p}_history.endDate"), - $qb->expr()->gt("{$p}_history.endDate", ":{$p}_at") + $qb->expr()->gt("{$p}_history.endDate", "acpinfo.infoDate") ) ) ) ->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select") - ->setParameter( - "{$p}_at", - $this->rollingDateConverter->convert($data['scope_at']) - ) ->addGroupBy("{$p}_select"); } @@ -81,15 +78,11 @@ final readonly class ScopeWorkingOnCourseAggregator implements AggregatorInterfa public function buildForm(FormBuilderInterface $builder) { - $builder->add('scope_at', PickRollingDateType::class, [ - 'label' => 'export.aggregator.course.by_scope_working.Calc date', - 'required' => true, - ]); } public function getFormDefaultData(): array { - return ['scope_at' => new RollingDate(RollingDate::T_TODAY)]; + return []; } public function getLabels($key, array $values, $data): \Closure diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/JobWorkingOnCourseFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/JobWorkingOnCourseFilter.php index 142cfd307..393a726fc 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/JobWorkingOnCourseFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/JobWorkingOnCourseFilter.php @@ -11,17 +11,15 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters; -use Chill\MainBundle\Entity\User; +use Chill\MainBundle\Entity\User\UserJobHistory; use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Form\Type\PickRollingDateType; -use Chill\MainBundle\Form\Type\PickUserDynamicType; use Chill\MainBundle\Repository\UserJobRepositoryInterface; use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface; -use Chill\MainBundle\Templating\Entity\UserRender; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; -use Chill\PersonBundle\Entity\AccompanyingPeriod; +use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodInfo; use Chill\PersonBundle\Export\Declarations; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; @@ -34,12 +32,50 @@ use Symfony\Component\Form\FormBuilderInterface; */ readonly class JobWorkingOnCourseFilter implements FilterInterface { + private const PREFIX = 'acp_filter_user_job_working_on_course'; + public function __construct( private UserJobRepositoryInterface $userJobRepository, private RollingDateConverterInterface $rollingDateConverter, private TranslatableStringHelperInterface $translatableStringHelper, ) {} + public function addRole(): ?string + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data): void + { + $p = self::PREFIX; + + $qb + ->andWhere( + $qb->expr()->exists( + "SELECT 1 FROM " . AccompanyingPeriodInfo::class . " {$p}_info " + . "JOIN {$p}_info.user {$p}_user " + . "JOIN " . UserJobHistory::class . " {$p}_history WITH {$p}_history.user = {$p}_user " + . "WHERE IDENTITY({$p}_info.accompanyingPeriod) = acp.id " + . "AND {$p}_history.job IN (:{$p}_jobs) " + // job_at based on _info.infoDate + . "AND {$p}_history.startDate <= {$p}_info.infoDate " + . "AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > {$p}_info.infoDate) " + . "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']) + ]) + ; + } + + public function applyOn(): string + { + return Declarations::ACP_TYPE; + } + public function buildForm(FormBuilderInterface $builder): void { $jobs = $this->userJobRepository->findAllActive(); @@ -59,23 +95,14 @@ readonly class JobWorkingOnCourseFilter implements FilterInterface ->add('end_date', PickRollingDateType::class, [ 'label' => 'export.filter.course.by_job_working.Job working before' ]) + //->add('job_at', PickRollingDateType::class, [ + // 'label' => 'bla', + // 'help' => 'bli', + // 'required' => false, + //]) ; } - public function getFormDefaultData(): array - { - return [ - 'jobs' => [], - 'start_date' => new RollingDate(RollingDate::T_YEAR_CURRENT_START), - 'end_date' => new RollingDate(RollingDate::T_TODAY), - ]; - } - - public function getTitle(): string - { - return 'export.filter.course.by_job_working.title'; - } - public function describeAction($data, $format = 'string'): array { return [ @@ -93,37 +120,18 @@ readonly class JobWorkingOnCourseFilter implements FilterInterface ]; } - public function addRole(): ?string + public function getFormDefaultData(): array { - return null; + return [ + 'jobs' => [], + 'start_date' => new RollingDate(RollingDate::T_YEAR_CURRENT_START), + 'end_date' => new RollingDate(RollingDate::T_TODAY), + //'job_at' => null, + ]; } - public function alterQuery(QueryBuilder $qb, $data): void + public function getTitle(): string { - $ai_alias = 'jobs_working_on_course_filter_acc_info'; - $ai_user_alias = 'jobs_working_on_course_filter_user'; - $ai_jobs = 'jobs_working_on_course_filter_jobs'; - $start = 'acp_jobs_work_on_start'; - $end = 'acp_jobs_work_on_end'; - - $qb - ->andWhere( - $qb->expr()->exists( - "SELECT 1 FROM " . AccompanyingPeriod\AccompanyingPeriodInfo::class . " {$ai_alias} JOIN {$ai_alias}.user {$ai_user_alias} " . - "WHERE IDENTITY({$ai_alias}.accompanyingPeriod) = acp.id - AND {$ai_user_alias}.userJob IN (:{$ai_jobs}) - AND {$ai_alias}.infoDate >= :{$start} and {$ai_alias}.infoDate < :{$end} - " - ) - ) - ->setParameter($ai_jobs, $data['jobs']) - ->setParameter($start, $this->rollingDateConverter->convert($data['start_date'])) - ->setParameter($end, $this->rollingDateConverter->convert($data['end_date'])) - ; - } - - public function applyOn(): string - { - return Declarations::ACP_TYPE; + return 'export.filter.course.by_job_working.title'; } } diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ScopeWorkingOnCourseFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ScopeWorkingOnCourseFilter.php index 6aef4e3da..97f592c3d 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ScopeWorkingOnCourseFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/ScopeWorkingOnCourseFilter.php @@ -12,18 +12,14 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters; use Chill\MainBundle\Entity\Scope; -use Chill\MainBundle\Entity\User; -use Chill\MainBundle\Entity\UserJob; +use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Form\Type\PickRollingDateType; -use Chill\MainBundle\Form\Type\PickUserDynamicType; use Chill\MainBundle\Repository\ScopeRepositoryInterface; -use Chill\MainBundle\Repository\UserJobRepositoryInterface; use Chill\MainBundle\Service\RollingDate\RollingDate; use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface; -use Chill\MainBundle\Templating\Entity\UserRender; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; -use Chill\PersonBundle\Entity\AccompanyingPeriod; +use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodInfo; use Chill\PersonBundle\Export\Declarations; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; @@ -36,12 +32,50 @@ use Symfony\Component\Form\FormBuilderInterface; */ readonly class ScopeWorkingOnCourseFilter implements FilterInterface { + private const PREFIX = 'acp_filter_user_scope_working_on_course'; + public function __construct( private ScopeRepositoryInterface $scopeRepository, private RollingDateConverterInterface $rollingDateConverter, private TranslatableStringHelperInterface $translatableStringHelper, ) {} + public function addRole(): ?string + { + return null; + } + + public function alterQuery(QueryBuilder $qb, $data): void + { + $p = self::PREFIX; + + $qb + ->andWhere( + $qb->expr()->exists( + "SELECT 1 FROM " . AccompanyingPeriodInfo::class . " {$p}_info " + . "JOIN {$p}_info.user {$p}_user " + . "JOIN " . UserScopeHistory::class . " {$p}_history WITH {$p}_history.user = {$p}_user " + . "WHERE IDENTITY({$p}_info.accompanyingPeriod) = acp.id " + . "AND {$p}_history.scope IN ( :{$p}_scopes ) " + // scope_at based on _info.infoDate + . "AND {$p}_history.startDate <= {$p}_info.infoDate " + . "AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > {$p}_info.infoDate) " + . "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"]) + ]) + ; + } + + public function applyOn(): string + { + return Declarations::ACP_TYPE; + } + public function buildForm(FormBuilderInterface $builder): void { $scopes = $this->scopeRepository->findAllActive(); @@ -64,20 +98,6 @@ readonly class ScopeWorkingOnCourseFilter implements FilterInterface ; } - public function getFormDefaultData(): array - { - return [ - 'scopes' => [], - 'start_date' => new RollingDate(RollingDate::T_YEAR_CURRENT_START), - 'end_date' => new RollingDate(RollingDate::T_TODAY), - ]; - } - - public function getTitle(): string - { - return 'export.filter.course.by_scope_working.title'; - } - public function describeAction($data, $format = 'string'): array { return [ @@ -95,37 +115,17 @@ readonly class ScopeWorkingOnCourseFilter implements FilterInterface ]; } - public function addRole(): ?string + public function getFormDefaultData(): array { - return null; + return [ + 'scopes' => [], + 'start_date' => new RollingDate(RollingDate::T_YEAR_CURRENT_START), + 'end_date' => new RollingDate(RollingDate::T_TODAY), + ]; } - public function alterQuery(QueryBuilder $qb, $data): void + public function getTitle(): string { - $ai_alias = 'scopes_working_on_course_filter_acc_info'; - $ai_user_alias = 'scopes_working_on_course_filter_user'; - $ai_scopes = 'scopes_working_on_course_filter_scopes'; - $start = 'acp_scopes_work_on_start'; - $end = 'acp_scopes_work_on_end'; - - $qb - ->andWhere( - $qb->expr()->exists( - "SELECT 1 FROM " . AccompanyingPeriod\AccompanyingPeriodInfo::class . " {$ai_alias} JOIN {$ai_alias}.user {$ai_user_alias} " . - "WHERE IDENTITY({$ai_alias}.accompanyingPeriod) = acp.id - AND {$ai_user_alias}.mainScope IN (:{$ai_scopes}) - AND {$ai_alias}.infoDate >= :{$start} and {$ai_alias}.infoDate < :{$end} - " - ) - ) - ->setParameter($ai_scopes, $data['scopes']) - ->setParameter($start, $this->rollingDateConverter->convert($data['start_date'])) - ->setParameter($end, $this->rollingDateConverter->convert($data['end_date'])) - ; - } - - public function applyOn(): string - { - return Declarations::ACP_TYPE; + return 'export.filter.course.by_scope_working.title'; } } diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index 08027db7e..fadfbdc51 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -1108,11 +1108,13 @@ export: 'Filtered by job working on course: only %jobs%, between %start_date% and %end_date%': 'Filtré par métier des intervenants sur le parcours: seulement %jobs%, entre le %start_date% et le %end_date%' Job working after: Intervention après le Job working before: Intervention avant le + Calc date: by_scope_working: title: Filtrer les parcours par service de l'intervenant, entre deux dates 'Filtered by scope working on course: only %scopes%, between %start_date% and %end_date%': 'Filtré par service des intervenants sur le parcours: seulement %scopes%, entre le %start_date% et le %end_date%' Scope working after: Intervention après le Scope working before: Intervention avant le + Calc date: by_step: Filter by step: Filtrer les parcours par statut du parcours Filter by step between dates: Filtrer les parcours par statut du parcours entre deux dates From c6a06ebaf9a630781906b4149c06250d0a986fac Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 3 Oct 2023 19:29:58 +0200 Subject: [PATCH 43/62] [export] fix 6 job/scope agg/filters in acp (queries with 2 history) --- .../CreatorJobAggregator.php | 49 ++++++++--------- .../ReferrerScopeAggregator.php | 54 +++++++------------ .../UserJobAggregator.php | 51 +++++++++--------- .../CreatorJobFilter.php | 44 +++++++-------- .../UserJobFilter.php | 52 ++++++++---------- .../UserScopeFilter.php | 52 ++++++++---------- .../translations/messages.fr.yml | 6 --- 7 files changed, 135 insertions(+), 173 deletions(-) diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php index 50c4e6f9b..707f2a36a 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php @@ -13,13 +13,11 @@ namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators; use Chill\MainBundle\Entity\User\UserJobHistory; 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\Export\Declarations; use Doctrine\ORM\Query\Expr; +use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; @@ -28,7 +26,6 @@ class CreatorJobAggregator implements AggregatorInterface private const PREFIX = 'acp_agg_creator_job'; public function __construct( - private readonly RollingDateConverter $rollingDateConverter, private readonly UserJobRepository $jobRepository, private readonly TranslatableStringHelper $translatableStringHelper ) {} @@ -43,27 +40,35 @@ class CreatorJobAggregator implements AggregatorInterface $p = self::PREFIX; $qb - ->leftJoin("acp.createdBy", "{$p}_user") ->leftJoin( - UserJobHistory::class, - "{$p}_history", - Expr\Join::WITH, - $qb->expr()->eq("{$p}_history.user", "{$p}_user") - ) - ->andWhere( + "acp.userHistories", "{$p}_userHistory", + Join::WITH, $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") + $qb->expr()->eq("{$p}_userHistory.accompanyingPeriod", "acp.id"), + $qb->expr()->andX( + $qb->expr()->gte("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.startDate"), + $qb->expr()->orX( + $qb->expr()->isNull("{$p}_userHistory.endDate"), + $qb->expr()->lt("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.endDate") + ) ) ) ) - ->addSelect("IDENTITY({$p}_history.job) AS {$p}_select") - ->setParameter( - "{$p}_at", - $this->rollingDateConverter->convert($data['job_at']) + ->leftJoin( + UserJobHistory::class,"{$p}_jobHistory", + Expr\Join::WITH, + $qb->expr()->andX( + $qb->expr()->eq("{$p}_jobHistory.user", "{$p}_userHistory.createdBy"), // et si il est null ? + $qb->expr()->andX( + $qb->expr()->lte("{$p}_jobHistory.startDate", "{$p}_userHistory.startDate"), + $qb->expr()->orX( + $qb->expr()->isNull("{$p}_jobHistory.endDate"), + $qb->expr()->gt("{$p}_jobHistory.endDate", "{$p}_userHistory.startDate") + ) + ) + ) ) + ->addSelect("IDENTITY({$p}_jobHistory.job) AS {$p}_select") ->addGroupBy("{$p}_select"); } @@ -74,15 +79,11 @@ class CreatorJobAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - $builder->add('job_at', PickRollingDateType::class, [ - 'label' => 'export.aggregator.course.by_creator_job.Calc date', - 'required' => true - ]); } 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/AccompanyingCourseAggregators/ReferrerScopeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php index abd9feffb..743144fbf 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php @@ -13,13 +13,10 @@ namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators; use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\AggregatorInterface; -use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\ScopeRepositoryInterface; -use Chill\MainBundle\Service\RollingDate\RollingDate; -use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\PersonBundle\Export\Declarations; -use Doctrine\ORM\Query\Expr; +use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; use LogicException; use Symfony\Component\Form\FormBuilderInterface; @@ -31,7 +28,6 @@ readonly class ReferrerScopeAggregator implements AggregatorInterface public function __construct( private ScopeRepositoryInterface $scopeRepository, private TranslatableStringHelperInterface $translatableStringHelper, - private RollingDateConverterInterface $rollingDateConverter ) {} public function addRole(): ?string @@ -44,40 +40,35 @@ readonly class ReferrerScopeAggregator implements AggregatorInterface $p = self::PREFIX; $qb - ->leftJoin("acp.userHistories", "{$p}_userHistory") - ->leftJoin("{$p}_userHistory.user", "{$p}_user") ->leftJoin( - UserScopeHistory::class, - "{$p}_scopeHistory", - Expr\Join::WITH, - $qb->expr()->eq("{$p}_scopeHistory.user", "{$p}_user") - ) - ->andWhere( - $qb->expr()->orX( - $qb->expr()->isNull("{$p}_userHistory"), + "acp.userHistories", "{$p}_userHistory", + Join::WITH, + $qb->expr()->andX( + $qb->expr()->eq("{$p}_userHistory.accompanyingPeriod", "acp.id"), $qb->expr()->andX( - $qb->expr()->lte("{$p}_userHistory.startDate", ":{$p}_date_calc"), + $qb->expr()->gte("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.startDate"), $qb->expr()->orX( $qb->expr()->isNull("{$p}_userHistory.endDate"), - $qb->expr()->gt("{$p}_userHistory.endDate", ":{$p}_date_calc") + $qb->expr()->lt("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.endDate") ) ) ) ) - ->andWhere( + ->leftJoin( + UserScopeHistory::class,"{$p}_scopeHistory", + Join::WITH, $qb->expr()->andX( - $qb->expr()->lte("{$p}_scopeHistory.startDate", ":{$p}_date_calc"), - $qb->expr()->orX( - $qb->expr()->isNull("{$p}_scopeHistory.endDate"), - $qb->expr()->gt("{$p}_scopeHistory.endDate", ":{$p}_date_calc") + $qb->expr()->eq("{$p}_scopeHistory.user", "{$p}_userHistory.user"), + $qb->expr()->andX( + $qb->expr()->lte("{$p}_scopeHistory.startDate", "{$p}_userHistory.startDate"), + $qb->expr()->orX( + $qb->expr()->isNull("{$p}_scopeHistory.endDate"), + $qb->expr()->gt("{$p}_scopeHistory.endDate", "{$p}_userHistory.startDate") + ) ) ) ) - ->setParameter( - "{$p}_date_calc", - $this->rollingDateConverter->convert($data['date_calc']) - ) - ->addSelect("IDENTITY({$p}_scopeHistory.scope) AS {$p}_select") + ->addSelect("IDENTITY({$p}_sh.scope) AS {$p}_select") ->addGroupBy("{$p}_select"); } @@ -88,16 +79,11 @@ readonly class ReferrerScopeAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - $builder - ->add('date_calc', PickRollingDateType::class, [ - 'label' => 'export.aggregator.course.by_user_scope.Computation date for referrer', - 'required' => true, - ]) - ; } + public function getFormDefaultData(): array { - return ['date_calc' => new RollingDate(RollingDate::T_TODAY)]; + return []; } public function getLabels($key, array $values, $data) diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php index 65b2dc38b..76612cac2 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php @@ -13,13 +13,10 @@ namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators; use Chill\MainBundle\Entity\User\UserJobHistory; 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\Export\Declarations; -use Doctrine\ORM\Query\Expr; +use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; @@ -28,7 +25,6 @@ final readonly class UserJobAggregator implements AggregatorInterface private const PREFIX = 'acp_agg_user_job'; public function __construct( - private RollingDateConverter $rollingDateConverter, private UserJobRepository $jobRepository, private TranslatableStringHelper $translatableStringHelper ) {} @@ -43,27 +39,35 @@ final readonly class UserJobAggregator implements AggregatorInterface $p = self::PREFIX; $qb - ->leftJoin("acp.user", "{$p}_user") ->leftJoin( - UserJobHistory::class, - "{$p}_history", - Expr\Join::WITH, - $qb->expr()->eq("{$p}_history.user", "{$p}_user") - ) - ->andWhere( + "acp.userHistories", "{$p}_userHistory", + Join::WITH, $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") + $qb->expr()->eq("{$p}_userHistory.accompanyingPeriod", "acp.id"), + $qb->expr()->andX( + $qb->expr()->gte("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.startDate"), + $qb->expr()->orX( + $qb->expr()->isNull("{$p}_userHistory.endDate"), + $qb->expr()->lt("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.endDate") + ) ) ) ) - ->addSelect("IDENTITY({$p}_history.job) AS {$p}_select") - ->setParameter( - "{$p}_at", - $this->rollingDateConverter->convert($data['job_at']) + ->leftJoin( + UserJobHistory::class, "{$p}_jobHistory", + Join::WITH, + $qb->expr()->andX( + $qb->expr()->eq("{$p}_jobHistory.user", "{$p}_userHistory.user"), + $qb->expr()->andX( + $qb->expr()->lte("{$p}_jobHistory.startDate", "{$p}_userHistory.startDate"), + $qb->expr()->orX( + $qb->expr()->isNull("{$p}_jobHistory.endDate"), + $qb->expr()->gt("{$p}_jobHistory.endDate", "{$p}_userHistory.startDate") + ) + ) + ) ) + ->addSelect("IDENTITY({$p}_jobHistory.job) AS {$p}_select") ->addGroupBy("{$p}_select"); } @@ -74,16 +78,11 @@ final readonly class UserJobAggregator implements AggregatorInterface public function buildForm(FormBuilderInterface $builder) { - $builder - ->add('job_at', PickRollingDateType::class, [ - 'label' => 'export.aggregator.course.by_user_job.Calc date', - 'required' => true - ]); } 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/Filter/AccompanyingCourseFilters/CreatorJobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php index f9b652eeb..29eed0a68 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php @@ -14,10 +14,7 @@ namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters; use Chill\MainBundle\Entity\User\UserJobHistory; use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Export\FilterInterface; -use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\UserJobRepositoryInterface; -use Chill\MainBundle\Service\RollingDate\RollingDate; -use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\PersonBundle\Export\Declarations; use Doctrine\ORM\Query\Expr\Join; @@ -30,7 +27,6 @@ class CreatorJobFilter implements FilterInterface private const PREFIX = 'acp_filter_creator_job'; public function __construct( - private readonly RollingDateConverter $rollingDateConverter, private readonly TranslatableStringHelper $translatableStringHelper, private readonly UserJobRepositoryInterface $userJobRepository ) {} @@ -45,26 +41,37 @@ class CreatorJobFilter implements FilterInterface $p = self::PREFIX; $qb - ->join("acp.createdBy", "{$p}_user") - ->leftJoin( - UserJobHistory::class, - "{$p}_history", + ->join( + "acp.userHistories", "{$p}_userHistory", 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") + $qb->expr()->eq("{$p}_userHistory.accompanyingPeriod", "acp.id"), + $qb->expr()->andX( + $qb->expr()->gte("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.startDate"), + $qb->expr()->orX( + $qb->expr()->isNull("{$p}_userHistory.endDate"), + $qb->expr()->lt("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.endDate") + ) + ) + ) + ) + ->leftJoin( + UserJobHistory::class,"{$p}_history", + Join::WITH, + $qb->expr()->andX( + $qb->expr()->eq("{$p}_history.user", "{$p}_userHistory.createdBy"), + $qb->expr()->andX( + $qb->expr()->lte("{$p}_history.startDate", "{$p}_userHistory.startDate"), + $qb->expr()->orX( + $qb->expr()->isNull("{$p}_history.endDate"), + $qb->expr()->gt("{$p}_history.endDate", "{$p}_userHistory.startDate") + ) ) ) ) ->andWhere($qb->expr()->in("{$p}_history.job", ":{$p}_jobs")) ->setParameters([ "{$p}_jobs" => $data["creator_job"], - "{$p}_at" => $this->rollingDateConverter->convert($data["job_at"]) ]); } @@ -85,10 +92,6 @@ class CreatorJobFilter implements FilterInterface 'multiple' => true, 'expanded' => true, 'label' => 'Job', - ]) - ->add('job_at', PickRollingDateType::class, [ - 'label' => 'export.filter.course.creator_job.Calc date', - 'required' => true ]); } @@ -111,7 +114,6 @@ class CreatorJobFilter implements FilterInterface { return [ 'creator_job' => [], - 'job_at' => new RollingDate(RollingDate::T_TODAY) ]; } diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php index 56c16fd73..215b48677 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php @@ -14,13 +14,10 @@ namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters; use Chill\MainBundle\Entity\User\UserJobHistory; use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Export\FilterInterface; -use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\UserJobRepositoryInterface; -use Chill\MainBundle\Service\RollingDate\RollingDate; -use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface; use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\PersonBundle\Export\Declarations; -use Doctrine\ORM\Query\Expr; +use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\FormBuilderInterface; @@ -32,7 +29,6 @@ class UserJobFilter implements FilterInterface public function __construct( private readonly TranslatableStringHelper $translatableStringHelper, private readonly UserJobRepositoryInterface $userJobRepository, - private readonly RollingDateConverterInterface $rollingDateConverter ) {} public function addRole(): ?string @@ -45,38 +41,37 @@ class UserJobFilter implements FilterInterface $p = self::PREFIX; $qb - ->leftJoin("acp.userHistories", "{$p}_userHistory") - ->leftJoin("{$p}_userHistory.user", "{$p}_user") ->leftJoin( - UserJobHistory::class, - "{$p}_jobHistory", - Expr\Join::WITH, - $qb->expr()->eq("{$p}_jobHistory.user", "{$p}_user") - ) - ->andWhere( + "acp.userHistories", "{$p}_userHistory", + Join::WITH, $qb->expr()->andX( - $qb->expr()->lte("{$p}_userHistory.startDate", ":{$p}_date"), - $qb->expr()->orX( - $qb->expr()->isNull("{$p}_userHistory" . ".endDate"), - $qb->expr()->gt("{$p}_userHistory.endDate", ":{$p}_date") + $qb->expr()->eq("{$p}_userHistory.accompanyingPeriod", "acp.id"), + $qb->expr()->andX( + $qb->expr()->gte("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.startDate"), + $qb->expr()->orX( + $qb->expr()->isNull("{$p}_userHistory.endDate"), + $qb->expr()->lt("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.endDate") + ) ) ) ) - ->andWhere( + ->leftJoin( + UserJobHistory::class, "{$p}_jobHistory", + Join::WITH, $qb->expr()->andX( - $qb->expr()->lte("{$p}_jobHistory.startDate", ":{$p}_date"), - $qb->expr()->orX( - $qb->expr()->isNull("{$p}_jobHistory" . ".endDate"), - $qb->expr()->gt("{$p}_jobHistory.endDate", ":{$p}_date") + $qb->expr()->eq("{$p}_jobHistory.user", "{$p}_userHistory.user"), + $qb->expr()->andX( + $qb->expr()->lte("{$p}_jobHistory.startDate", "{$p}_userHistory.startDate"), + $qb->expr()->orX( + $qb->expr()->isNull("{$p}_jobHistory" . ".endDate"), + $qb->expr()->gt("{$p}_jobHistory.endDate", "{$p}_userHistory.startDate") + ) ) ) ) - ->andWhere( - $qb->expr()->in("{$p}_jobHistory.job", ":{$p}_job") - ) + ->andWhere($qb->expr()->in("{$p}_jobHistory.job", ":{$p}_job")) ->setParameters([ "{$p}_job" => $data["jobs"], - "{$p}_date" => $this->rollingDateConverter->convert($data["date_calc"]) ]) ; } @@ -96,10 +91,6 @@ class UserJobFilter implements FilterInterface 'expanded' => true, 'choice_label' => fn (UserJob $job) => $this->translatableStringHelper->localize($job->getLabel()), 'label' => 'Job', - ]) - ->add('date_calc', PickRollingDateType::class, [ - 'label' => 'export.filter.course.by_user_job.Computation date for referrer', - 'required' => true, ]); } @@ -122,7 +113,6 @@ class UserJobFilter implements FilterInterface { return [ 'jobs' => [], - 'date_calc' => new RollingDate(RollingDate::T_TODAY) ]; } diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php index 1d2ccf839..789019eb5 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php @@ -14,13 +14,10 @@ namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters; use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\FilterInterface; -use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\ScopeRepositoryInterface; -use Chill\MainBundle\Service\RollingDate\RollingDate; -use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface; use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\PersonBundle\Export\Declarations; -use Doctrine\ORM\Query\Expr; +use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\FormBuilderInterface; @@ -32,7 +29,6 @@ class UserScopeFilter implements FilterInterface public function __construct( private readonly ScopeRepositoryInterface $scopeRepository, private readonly TranslatableStringHelper $translatableStringHelper, - private readonly RollingDateConverterInterface $rollingDateConverter ) {} public function addRole(): ?string @@ -45,38 +41,37 @@ class UserScopeFilter implements FilterInterface $p = self::PREFIX; $qb - ->join("acp.userHistories", "{$p}_userHistory") - ->join("{$p}_userHistory.user", "{$p}_user") ->join( - UserScopeHistory::class, - "{$p}_scopeHistory", - Expr\Join::WITH, - $qb->expr()->eq("{$p}_scopeHistory", "{$p}_user") - ) - ->andWhere( + "acp.userHistories", "{$p}_userHistory", + Join::WITH, $qb->expr()->andX( - $qb->expr()->lte("{$p}_userHistory.startDate", ":{$p}_date"), - $qb->expr()->orX( - $qb->expr()->isNull("{$p}_userHistory.endDate"), - $qb->expr()->gt("{$p}_userHistory.endDate", ":{$p}_date") + $qb->expr()->eq("{$p}_userHistory.accompanyingPeriod", "acp.id"), + $qb->expr()->andX( + $qb->expr()->gte("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.startDate"), + $qb->expr()->orX( + $qb->expr()->isNull("{$p}_userHistory.endDate"), + $qb->expr()->lt("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.endDate") + ) ) ) ) - ->andWhere( + ->join( + UserScopeHistory::class, "{$p}_scopeHistory", + Join::WITH, $qb->expr()->andX( - $qb->expr()->lte("{$p}_scopeHistory.startDate", ":{$p}_date"), - $qb->expr()->orX( - $qb->expr()->isNull("{$p}_scopeHistory.endDate"), - $qb->expr()->gt("{$p}_scopeHistory.endDate", ":{$p}_date") + $qb->expr()->eq("{$p}_scopeHistory.user", "{$p}_userHistory.user"), + $qb->expr()->andX( + $qb->expr()->lte("{$p}_scopeHistory.startDate", "{$p}_userHistory.startDate"), + $qb->expr()->orX( + $qb->expr()->isNull("{$p}_scopeHistory.endDate"), + $qb->expr()->gt("{$p}_scopeHistory.endDate", "{$p}_userHistory.startDate") + ) ) ) ) - ->andWhere( - $qb->expr()->in("{$p}_scopeHistory.scope", ":{$p}_scopes") - ) + ->andWhere($qb->expr()->in("{$p}_scopeHistory.scope", ":{$p}_scopes")) ->setParameters([ "{$p}_scopes" => $data["scopes"], - "{$p}_date" => $this->rollingDateConverter->convert($data["date_calc"]) ]) ; } @@ -95,10 +90,6 @@ class UserScopeFilter implements FilterInterface 'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()), 'multiple' => true, 'expanded' => true, - ]) - ->add('date_calc', PickRollingDateType::class, [ - 'label' => 'export.filter.course.by_user_scope.Computation date for referrer', - 'required' => true, ]); } @@ -121,7 +112,6 @@ class UserScopeFilter implements FilterInterface { return [ 'scopes' => [], - 'date_calc' => new RollingDate(RollingDate::T_TODAY) ]; } diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index fadfbdc51..639de0443 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -1012,11 +1012,9 @@ export: Computation date for referrer: Date à laquelle le référent était actif by_user_scope: Group course by referrer's scope: Grouper les parcours par service du référent - Computation date for referrer: Date à laquelle le référent était actif Referrer's scope: Service du référent de parcours by_user_job: Group by user job: Grouper les parcours par métier du référent - Calc date: Date de calcul du métier du référent duration: day: Durée du parcours en jours week: Durée du parcours en semaines @@ -1027,7 +1025,6 @@ export: by_creator_job: Creator's job: Métier du créateur Group by creator job: Grouper les parcours par métier du créateur - Calc date: Date de calcul du métier du créateur by_user_working: title: Grouper les parcours par intervenant user: Intervenant @@ -1124,7 +1121,6 @@ export: date_to: Statuts acquis avant cette date 'Filtered by steps: only %step% and between %date_from% and %date_to%': 'Filtré par statut: seulement %step%, entre %date_from% et %date_to%' by_user_scope: - Computation date for referrer: Date à laquelle le référent était actif Filter by user scope: Filtrer les parcours par service du référent "Filtered by user main scope: only %scope%": "Filtré par service du référent: uniquement %scope%" by_referrer: @@ -1137,11 +1133,9 @@ export: creator_job: Filter by creator job: Filtrer les parcours par métier du créateur 'Filtered by creator job: only %jobs%': "Filtré par métier du créateur: uniquement %jobs%" - Calc date: Date de calcul du métier du créateur by_user_job: Filter by user job: Filtrer les parcours par métier du référent "Filtered by user job: only %job%": "Filtré par métier du référent: uniquement %job%" - Computation date for referrer: Date à laquelle le référent était actif work: start_between_dates: From d6a104458503f26030b077cc30dd71b47c5e8776 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Tue, 3 Oct 2023 15:38:59 +0200 Subject: [PATCH 44/62] just mark other uses with mainScope and userJob !! --- .../src/Export/Export/ListAsideActivity.php | 2 +- .../ChillMainBundle/Controller/UserExportController.php | 8 ++++---- src/Bundle/ChillMainBundle/Repository/UserRepository.php | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php index 53e66c6c3..f01c3efc2 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Export/ListAsideActivity.php @@ -190,7 +190,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(agent.mainScope) 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/ChillMainBundle/Controller/UserExportController.php b/src/Bundle/ChillMainBundle/Controller/UserExportController.php index 450be8dd7..04778dfae 100644 --- a/src/Bundle/ChillMainBundle/Controller/UserExportController.php +++ b/src/Bundle/ChillMainBundle/Controller/UserExportController.php @@ -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/Repository/UserRepository.php b/src/Bundle/ChillMainBundle/Repository/UserRepository.php index 230a2b925..a59ddc399 100644 --- a/src/Bundle/ChillMainBundle/Repository/UserRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/UserRepository.php @@ -108,7 +108,7 @@ final readonly class UserRepository implements UserRepositoryInterface LEFT JOIN u.mainScope mainScope LEFT JOIN u.userJob userJob ORDER BY u.label - DQL); + DQL); /// mainScope userJob $query = $this->entityManager->createQuery($dql) ->setHydrationMode(AbstractQuery::HYDRATE_ARRAY) From 15e23087edb9d1d4f5cf4f93ed0eb8d2cf1589a3 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 4 Oct 2023 09:45:15 +0200 Subject: [PATCH 45/62] cs-fixer, phpstan et rector --- .../Export/Aggregator/ActivityUsersJobAggregator.php | 4 +--- .../Export/Aggregator/ActivityUsersScopeAggregator.php | 4 +--- .../Export/Aggregator/CreatorScopeAggregator.php | 4 +--- .../Export/Filter/UserScopeFilter.php | 4 ---- .../src/Export/Aggregator/ByUserJobAggregator.php | 4 +--- .../src/Export/Aggregator/ByUserScopeAggregator.php | 4 +--- .../Export/Aggregator/JobAggregator.php | 4 +--- .../Export/Aggregator/ScopeAggregator.php | 4 +--- .../CreatorJobAggregator.php | 10 +++++----- .../JobWorkingOnCourseAggregator.php | 8 +------- .../ReferrerScopeAggregator.php | 10 +++++----- .../ScopeWorkingOnCourseAggregator.php | 8 +------- .../UserJobAggregator.php | 10 +++++----- .../AccompanyingCourseFilters/CreatorJobFilter.php | 6 ++++-- .../Filter/AccompanyingCourseFilters/UserJobFilter.php | 6 ++++-- .../AccompanyingCourseFilters/UserScopeFilter.php | 6 ++++-- 16 files changed, 36 insertions(+), 60 deletions(-) diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php index da851f8f2..af4ed7352 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersJobAggregator.php @@ -65,9 +65,7 @@ class ActivityUsersJobAggregator implements AggregatorInterface return Declarations::ACTIVITY; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php index b9f1e4874..aeb021cf1 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUsersScopeAggregator.php @@ -65,9 +65,7 @@ class ActivityUsersScopeAggregator implements AggregatorInterface return Declarations::ACTIVITY; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php b/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php index 9bce69131..2c053b035 100644 --- a/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php +++ b/src/Bundle/ChillActivityBundle/Export/Aggregator/CreatorScopeAggregator.php @@ -65,9 +65,7 @@ class CreatorScopeAggregator implements AggregatorInterface return Declarations::ACTIVITY; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillActivityBundle/Export/Filter/UserScopeFilter.php b/src/Bundle/ChillActivityBundle/Export/Filter/UserScopeFilter.php index f942fd6d6..ec87ce954 100644 --- a/src/Bundle/ChillActivityBundle/Export/Filter/UserScopeFilter.php +++ b/src/Bundle/ChillActivityBundle/Export/Filter/UserScopeFilter.php @@ -15,9 +15,6 @@ use Chill\ActivityBundle\Export\Declarations; use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\FilterInterface; -use Chill\MainBundle\Form\Type\PickRollingDateType; -use Chill\MainBundle\Service\RollingDate\RollingDate; -use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelper; use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\QueryBuilder; @@ -29,7 +26,6 @@ class UserScopeFilter implements FilterInterface private const PREFIX = 'acp_act_filter_user_scope'; // creator ? cfr translation public function __construct( - private readonly RollingDateConverter $rollingDateConverter, private readonly TranslatableStringHelper $translatableStringHelper ) {} diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php index 6ea912eed..ae4fb8477 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserJobAggregator.php @@ -65,9 +65,7 @@ class ByUserJobAggregator implements AggregatorInterface return Declarations::ASIDE_ACTIVITY_TYPE; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php index 3d55884b4..6c9690791 100644 --- a/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php +++ b/src/Bundle/ChillAsideActivityBundle/src/Export/Aggregator/ByUserScopeAggregator.php @@ -64,9 +64,7 @@ class ByUserScopeAggregator implements AggregatorInterface return Declarations::ASIDE_ACTIVITY_TYPE; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php index acef258fa..189d70130 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php +++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/JobAggregator.php @@ -66,9 +66,7 @@ final readonly class JobAggregator implements AggregatorInterface return Declarations::CALENDAR_TYPE; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php b/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php index ec1c91dc9..5412a15d1 100644 --- a/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php +++ b/src/Bundle/ChillCalendarBundle/Export/Aggregator/ScopeAggregator.php @@ -66,9 +66,7 @@ final readonly class ScopeAggregator implements AggregatorInterface return Declarations::CALENDAR_TYPE; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php index 707f2a36a..f6a84cd3a 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php @@ -41,7 +41,8 @@ class CreatorJobAggregator implements AggregatorInterface $qb ->leftJoin( - "acp.userHistories", "{$p}_userHistory", + "acp.userHistories", + "{$p}_userHistory", Join::WITH, $qb->expr()->andX( $qb->expr()->eq("{$p}_userHistory.accompanyingPeriod", "acp.id"), @@ -55,7 +56,8 @@ class CreatorJobAggregator implements AggregatorInterface ) ) ->leftJoin( - UserJobHistory::class,"{$p}_jobHistory", + UserJobHistory::class, + "{$p}_jobHistory", Expr\Join::WITH, $qb->expr()->andX( $qb->expr()->eq("{$p}_jobHistory.user", "{$p}_userHistory.createdBy"), // et si il est null ? @@ -77,9 +79,7 @@ class CreatorJobAggregator implements AggregatorInterface return Declarations::ACP_TYPE; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php index a58f6dcaa..ad38b4a6b 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/JobWorkingOnCourseAggregator.php @@ -13,10 +13,7 @@ namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators; use Chill\MainBundle\Entity\User\UserJobHistory; use Chill\MainBundle\Export\AggregatorInterface; -use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\UserJobRepositoryInterface; -use Chill\MainBundle\Service\RollingDate\RollingDate; -use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodInfo; use Chill\PersonBundle\Export\Declarations; @@ -29,7 +26,6 @@ final readonly class JobWorkingOnCourseAggregator implements AggregatorInterface private const PREFIX = 'acp_agg_user_job_working_on_course'; public function __construct( - private RollingDateConverter $rollingDateConverter, private UserJobRepositoryInterface $userJobRepository, private TranslatableStringHelperInterface $translatableStringHelper, ) {} @@ -76,9 +72,7 @@ final readonly class JobWorkingOnCourseAggregator implements AggregatorInterface return Declarations::ACP_TYPE; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php index 743144fbf..4687d4ce3 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php @@ -41,7 +41,8 @@ readonly class ReferrerScopeAggregator implements AggregatorInterface $qb ->leftJoin( - "acp.userHistories", "{$p}_userHistory", + "acp.userHistories", + "{$p}_userHistory", Join::WITH, $qb->expr()->andX( $qb->expr()->eq("{$p}_userHistory.accompanyingPeriod", "acp.id"), @@ -55,7 +56,8 @@ readonly class ReferrerScopeAggregator implements AggregatorInterface ) ) ->leftJoin( - UserScopeHistory::class,"{$p}_scopeHistory", + UserScopeHistory::class, + "{$p}_scopeHistory", Join::WITH, $qb->expr()->andX( $qb->expr()->eq("{$p}_scopeHistory.user", "{$p}_userHistory.user"), @@ -77,9 +79,7 @@ readonly class ReferrerScopeAggregator implements AggregatorInterface return Declarations::ACP_TYPE; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php index e45f7d479..fbc4947bf 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ScopeWorkingOnCourseAggregator.php @@ -13,10 +13,7 @@ namespace Chill\PersonBundle\Export\Aggregator\AccompanyingCourseAggregators; use Chill\MainBundle\Entity\User\UserScopeHistory; use Chill\MainBundle\Export\AggregatorInterface; -use Chill\MainBundle\Form\Type\PickRollingDateType; use Chill\MainBundle\Repository\ScopeRepositoryInterface; -use Chill\MainBundle\Service\RollingDate\RollingDate; -use Chill\MainBundle\Service\RollingDate\RollingDateConverter; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodInfo; use Chill\PersonBundle\Export\Declarations; @@ -29,7 +26,6 @@ final readonly class ScopeWorkingOnCourseAggregator implements AggregatorInterfa private const PREFIX = 'acp_agg_user_scope_working_on_course'; public function __construct( - private RollingDateConverter $rollingDateConverter, private ScopeRepositoryInterface $scopeRepository, private TranslatableStringHelperInterface $translatableStringHelper, ) {} @@ -76,9 +72,7 @@ final readonly class ScopeWorkingOnCourseAggregator implements AggregatorInterfa return Declarations::ACP_TYPE; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php index 76612cac2..60923ccb2 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php @@ -40,7 +40,8 @@ final readonly class UserJobAggregator implements AggregatorInterface $qb ->leftJoin( - "acp.userHistories", "{$p}_userHistory", + "acp.userHistories", + "{$p}_userHistory", Join::WITH, $qb->expr()->andX( $qb->expr()->eq("{$p}_userHistory.accompanyingPeriod", "acp.id"), @@ -54,7 +55,8 @@ final readonly class UserJobAggregator implements AggregatorInterface ) ) ->leftJoin( - UserJobHistory::class, "{$p}_jobHistory", + UserJobHistory::class, + "{$p}_jobHistory", Join::WITH, $qb->expr()->andX( $qb->expr()->eq("{$p}_jobHistory.user", "{$p}_userHistory.user"), @@ -76,9 +78,7 @@ final readonly class UserJobAggregator implements AggregatorInterface return Declarations::ACP_TYPE; } - public function buildForm(FormBuilderInterface $builder) - { - } + public function buildForm(FormBuilderInterface $builder) {} public function getFormDefaultData(): array { diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php index 29eed0a68..8b197e82e 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php @@ -42,7 +42,8 @@ class CreatorJobFilter implements FilterInterface $qb ->join( - "acp.userHistories", "{$p}_userHistory", + "acp.userHistories", + "{$p}_userHistory", Join::WITH, $qb->expr()->andX( $qb->expr()->eq("{$p}_userHistory.accompanyingPeriod", "acp.id"), @@ -56,7 +57,8 @@ class CreatorJobFilter implements FilterInterface ) ) ->leftJoin( - UserJobHistory::class,"{$p}_history", + UserJobHistory::class, + "{$p}_history", Join::WITH, $qb->expr()->andX( $qb->expr()->eq("{$p}_history.user", "{$p}_userHistory.createdBy"), diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php index 215b48677..a1e96608a 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php @@ -42,7 +42,8 @@ class UserJobFilter implements FilterInterface $qb ->leftJoin( - "acp.userHistories", "{$p}_userHistory", + "acp.userHistories", + "{$p}_userHistory", Join::WITH, $qb->expr()->andX( $qb->expr()->eq("{$p}_userHistory.accompanyingPeriod", "acp.id"), @@ -56,7 +57,8 @@ class UserJobFilter implements FilterInterface ) ) ->leftJoin( - UserJobHistory::class, "{$p}_jobHistory", + UserJobHistory::class, + "{$p}_jobHistory", Join::WITH, $qb->expr()->andX( $qb->expr()->eq("{$p}_jobHistory.user", "{$p}_userHistory.user"), diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php index 789019eb5..c3e2f598b 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php @@ -42,7 +42,8 @@ class UserScopeFilter implements FilterInterface $qb ->join( - "acp.userHistories", "{$p}_userHistory", + "acp.userHistories", + "{$p}_userHistory", Join::WITH, $qb->expr()->andX( $qb->expr()->eq("{$p}_userHistory.accompanyingPeriod", "acp.id"), @@ -56,7 +57,8 @@ class UserScopeFilter implements FilterInterface ) ) ->join( - UserScopeHistory::class, "{$p}_scopeHistory", + UserScopeHistory::class, + "{$p}_scopeHistory", Join::WITH, $qb->expr()->andX( $qb->expr()->eq("{$p}_scopeHistory.user", "{$p}_userHistory.user"), From b4e5618e0096539b5d7c0ed706e422b55163922c Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 4 Oct 2023 10:06:46 +0200 Subject: [PATCH 46/62] fix phpunit tests errors --- .../ACPAggregators/BySocialActionAggregatorTest.php | 2 +- .../ACPAggregators/BySocialIssueAggregatorTest.php | 2 +- .../AccompanyingCourseAggregators/CreatorJobAggregator.php | 4 ++-- .../ReferrerScopeAggregator.php | 6 +++--- .../AccompanyingCourseAggregators/UserJobAggregator.php | 4 ++-- .../Filter/AccompanyingCourseFilters/CreatorJobFilter.php | 4 ++-- .../Filter/AccompanyingCourseFilters/UserJobFilter.php | 4 ++-- .../Filter/AccompanyingCourseFilters/UserScopeFilter.php | 4 ++-- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ACPAggregators/BySocialActionAggregatorTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ACPAggregators/BySocialActionAggregatorTest.php index e7d3f50ab..657c9441e 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ACPAggregators/BySocialActionAggregatorTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ACPAggregators/BySocialActionAggregatorTest.php @@ -12,7 +12,7 @@ declare(strict_types=1); namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators; use Chill\ActivityBundle\Entity\Activity; -use Chill\ActivityBundle\Export\Aggregator\BySocialActionAggregator; +use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\BySocialActionAggregator; use Chill\MainBundle\Test\Export\AbstractAggregatorTest; use Doctrine\ORM\EntityManagerInterface; diff --git a/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ACPAggregators/BySocialIssueAggregatorTest.php b/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ACPAggregators/BySocialIssueAggregatorTest.php index 471c6ad21..86c999cf3 100644 --- a/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ACPAggregators/BySocialIssueAggregatorTest.php +++ b/src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/ACPAggregators/BySocialIssueAggregatorTest.php @@ -12,7 +12,7 @@ declare(strict_types=1); namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators; use Chill\ActivityBundle\Entity\Activity; -use Chill\ActivityBundle\Export\Aggregator\BySocialIssueAggregator; +use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\BySocialIssueAggregator; use Chill\MainBundle\Test\Export\AbstractAggregatorTest; use Doctrine\ORM\EntityManagerInterface; diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php index f6a84cd3a..8dee2e5f0 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/CreatorJobAggregator.php @@ -47,10 +47,10 @@ class CreatorJobAggregator implements AggregatorInterface $qb->expr()->andX( $qb->expr()->eq("{$p}_userHistory.accompanyingPeriod", "acp.id"), $qb->expr()->andX( - $qb->expr()->gte("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.startDate"), + $qb->expr()->gte("COALESCE(acp.closingDate, CURRENT_TIMESTAMP())", "{$p}_userHistory.startDate"), $qb->expr()->orX( $qb->expr()->isNull("{$p}_userHistory.endDate"), - $qb->expr()->lt("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.endDate") + $qb->expr()->lt("COALESCE(acp.closingDate, CURRENT_TIMESTAMP())", "{$p}_userHistory.endDate") ) ) ) diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php index 4687d4ce3..664d3f77e 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php @@ -47,10 +47,10 @@ readonly class ReferrerScopeAggregator implements AggregatorInterface $qb->expr()->andX( $qb->expr()->eq("{$p}_userHistory.accompanyingPeriod", "acp.id"), $qb->expr()->andX( - $qb->expr()->gte("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.startDate"), + $qb->expr()->gte("COALESCE(acp.closingDate, CURRENT_TIMESTAMP())", "{$p}_userHistory.startDate"), $qb->expr()->orX( $qb->expr()->isNull("{$p}_userHistory.endDate"), - $qb->expr()->lt("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.endDate") + $qb->expr()->lt("COALESCE(acp.closingDate, CURRENT_TIMESTAMP())", "{$p}_userHistory.endDate") ) ) ) @@ -70,7 +70,7 @@ readonly class ReferrerScopeAggregator implements AggregatorInterface ) ) ) - ->addSelect("IDENTITY({$p}_sh.scope) AS {$p}_select") + ->addSelect("IDENTITY({$p}_scopeHistory.scope) AS {$p}_select") ->addGroupBy("{$p}_select"); } diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php index 60923ccb2..ff3c0a3b2 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/UserJobAggregator.php @@ -46,10 +46,10 @@ final readonly class UserJobAggregator implements AggregatorInterface $qb->expr()->andX( $qb->expr()->eq("{$p}_userHistory.accompanyingPeriod", "acp.id"), $qb->expr()->andX( - $qb->expr()->gte("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.startDate"), + $qb->expr()->gte("COALESCE(acp.closingDate, CURRENT_TIMESTAMP())", "{$p}_userHistory.startDate"), $qb->expr()->orX( $qb->expr()->isNull("{$p}_userHistory.endDate"), - $qb->expr()->lt("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.endDate") + $qb->expr()->lt("COALESCE(acp.closingDate, CURRENT_TIMESTAMP())", "{$p}_userHistory.endDate") ) ) ) diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php index 8b197e82e..7053654df 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/CreatorJobFilter.php @@ -48,10 +48,10 @@ class CreatorJobFilter implements FilterInterface $qb->expr()->andX( $qb->expr()->eq("{$p}_userHistory.accompanyingPeriod", "acp.id"), $qb->expr()->andX( - $qb->expr()->gte("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.startDate"), + $qb->expr()->gte("COALESCE(acp.closingDate, CURRENT_TIMESTAMP())", "{$p}_userHistory.startDate"), $qb->expr()->orX( $qb->expr()->isNull("{$p}_userHistory.endDate"), - $qb->expr()->lt("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.endDate") + $qb->expr()->lt("COALESCE(acp.closingDate, CURRENT_TIMESTAMP())", "{$p}_userHistory.endDate") ) ) ) diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php index a1e96608a..04d1b2cb8 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserJobFilter.php @@ -48,10 +48,10 @@ class UserJobFilter implements FilterInterface $qb->expr()->andX( $qb->expr()->eq("{$p}_userHistory.accompanyingPeriod", "acp.id"), $qb->expr()->andX( - $qb->expr()->gte("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.startDate"), + $qb->expr()->gte("COALESCE(acp.closingDate, CURRENT_TIMESTAMP())", "{$p}_userHistory.startDate"), $qb->expr()->orX( $qb->expr()->isNull("{$p}_userHistory.endDate"), - $qb->expr()->lt("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.endDate") + $qb->expr()->lt("COALESCE(acp.closingDate, CURRENT_TIMESTAMP())", "{$p}_userHistory.endDate") ) ) ) diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php index c3e2f598b..2abad7823 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingCourseFilters/UserScopeFilter.php @@ -48,10 +48,10 @@ class UserScopeFilter implements FilterInterface $qb->expr()->andX( $qb->expr()->eq("{$p}_userHistory.accompanyingPeriod", "acp.id"), $qb->expr()->andX( - $qb->expr()->gte("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.startDate"), + $qb->expr()->gte("COALESCE(acp.closingDate, CURRENT_TIMESTAMP())", "{$p}_userHistory.startDate"), $qb->expr()->orX( $qb->expr()->isNull("{$p}_userHistory.endDate"), - $qb->expr()->lt("COALESCE(acp.endDate, CURRENT_TIMESTAMP)", "{$p}_userHistory.endDate") + $qb->expr()->lt("COALESCE(acp.closingDate, CURRENT_TIMESTAMP())", "{$p}_userHistory.endDate") ) ) ) From c526973475160db020a90ffda3785382087f49fe Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 4 Oct 2023 12:13:10 +0200 Subject: [PATCH 47/62] [admin][templates] move job/scope history in an unique template and display history for a given user --- .../Controller/UserJobHistoryController.php | 29 ------- .../UserJobScopeHistoriesController.php | 43 ++++++++++ .../Controller/UserScopeHistoryController.php | 29 ------- .../ChillMainExtension.php | 26 ------ .../Resources/views/Scope/history.html.twig | 51 ------------ .../Resources/views/Scope/index.html.twig | 3 - .../Resources/views/User/edit.html.twig | 12 ++- .../Resources/views/User/history.html.twig | 81 +++++++++++++++++++ .../Resources/views/UserJob/history.html.twig | 51 ------------ .../Resources/views/UserJob/index.html.twig | 3 - .../translations/messages.fr.yml | 43 +++++----- .../HouseholdCompositionController.php | 12 ++- 12 files changed, 167 insertions(+), 216 deletions(-) delete mode 100644 src/Bundle/ChillMainBundle/Controller/UserJobHistoryController.php create mode 100644 src/Bundle/ChillMainBundle/Controller/UserJobScopeHistoriesController.php delete mode 100644 src/Bundle/ChillMainBundle/Controller/UserScopeHistoryController.php delete mode 100644 src/Bundle/ChillMainBundle/Resources/views/Scope/history.html.twig create mode 100644 src/Bundle/ChillMainBundle/Resources/views/User/history.html.twig delete mode 100644 src/Bundle/ChillMainBundle/Resources/views/UserJob/history.html.twig diff --git a/src/Bundle/ChillMainBundle/Controller/UserJobHistoryController.php b/src/Bundle/ChillMainBundle/Controller/UserJobHistoryController.php deleted file mode 100644 index eb181f252..000000000 --- a/src/Bundle/ChillMainBundle/Controller/UserJobHistoryController.php +++ /dev/null @@ -1,29 +0,0 @@ -addOrderBy('e.startDate', 'DESC') - ->addOrderBy('e.user', 'ASC') - ; - - return parent::orderQuery($action, $query, $request, $paginator); - } -} diff --git a/src/Bundle/ChillMainBundle/Controller/UserJobScopeHistoriesController.php b/src/Bundle/ChillMainBundle/Controller/UserJobScopeHistoriesController.php new file mode 100644 index 000000000..4014e0593 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Controller/UserJobScopeHistoriesController.php @@ -0,0 +1,43 @@ +getUserJobHistories(); + $scopeHistories = $user->getMainScopeHistories(); + + + return new Response( + $this->engine->render('@ChillMain/User/history.html.twig', [ + 'user' => $user, + 'jobHistories' => $jobHistories, + 'scopeHistories' => $scopeHistories, + ] + )); + } +} diff --git a/src/Bundle/ChillMainBundle/Controller/UserScopeHistoryController.php b/src/Bundle/ChillMainBundle/Controller/UserScopeHistoryController.php deleted file mode 100644 index 2d425456f..000000000 --- a/src/Bundle/ChillMainBundle/Controller/UserScopeHistoryController.php +++ /dev/null @@ -1,29 +0,0 @@ -addOrderBy('e.startDate', 'DESC') - ->addOrderBy('e.user', 'ASC') - ; - - return parent::orderQuery($action, $query, $request, $paginator); - } -} diff --git a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php index 80febcae9..4d81c3980 100644 --- a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php +++ b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php @@ -375,32 +375,6 @@ class ChillMainExtension extends Extension implements ], ], ], - [ - 'class' => UserJobHistory::class, - 'controller' => UserJobHistoryController::class, - 'name' => 'admin_user_job_history', - 'base_path' => '/admin/main/user-job-history', - 'base_role' => 'ROLE_ADMIN', - 'actions' => [ - 'index' => [ - 'role' => 'ROLE_ADMIN', - 'template' => '@ChillMain/UserJob/history.html.twig', - ], - ], - ], - [ - 'class' => UserScopeHistory::class, - 'controller' => UserScopeHistoryController::class, - 'name' => 'admin_user_scope_history', - 'base_path' => '/admin/main/user-scope-history', - 'base_role' => 'ROLE_ADMIN', - 'actions' => [ - 'index' => [ - 'role' => 'ROLE_ADMIN', - 'template' => '@ChillMain/Scope/history.html.twig', - ], - ], - ], [ 'class' => User::class, 'controller' => UserController::class, diff --git a/src/Bundle/ChillMainBundle/Resources/views/Scope/history.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Scope/history.html.twig deleted file mode 100644 index b7d4d6d18..000000000 --- a/src/Bundle/ChillMainBundle/Resources/views/Scope/history.html.twig +++ /dev/null @@ -1,51 +0,0 @@ -{% extends '@ChillMain/CRUD/Admin/index.html.twig' %} - -{% block admin_content %} - {% embed '@ChillMain/CRUD/_index.html.twig' %} - - {% block table_entities_thead_tr %} - {{ 'crud.admin_user_scope_history.index.start'|trans }} - {{ 'crud.admin_user_scope_history.index.end'|trans }} - {{ 'crud.admin_user_scope_history.index.user'|trans }} - {{ 'crud.admin_user_scope_history.index.scope'|trans }} - {% endblock %} - - {% block table_entities_tbody %} - {% for entity in entities %} - - {{ entity.startDate|format_datetime('medium') }} - - {% if entity.endDate is not null %} - {{ entity.endDate|format_datetime('medium') }} - {% else %} - {{ "crud.admin_user_scope_history.index.today"|trans }} - {% endif %} - - {{ entity.user.usernameCanonical }} - - {% if entity.scope %} - {{ entity.scope.name|localize_translatable_string }} - {% else %} - {{ 'crud.admin_user_scope_history.index.undefined'|trans }} - {% endif %} - - - {% endfor %} - {% endblock %} - - {% block actions_before %} -
    • - {{'Back to the admin'|trans }} -
    • - {% endblock %} - - {% block list_actions %} - - {% endblock %} - {% endembed %} -{% endblock %} - diff --git a/src/Bundle/ChillMainBundle/Resources/views/Scope/index.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Scope/index.html.twig index ac52afa30..38493201e 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Scope/index.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Scope/index.html.twig @@ -48,9 +48,6 @@
    • {{'Back to the admin'|trans}}
    • -
    • - {{ 'crud.admin_user_scope_history.Show scope history'|trans }} -
    • {{ 'Create a new circle'|trans }}
    • diff --git a/src/Bundle/ChillMainBundle/Resources/views/User/edit.html.twig b/src/Bundle/ChillMainBundle/Resources/views/User/edit.html.twig index 4ac863ee6..4c90915ed 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/User/edit.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/User/edit.html.twig @@ -1,7 +1,8 @@ -{% extends '@ChillMain/Admin/layoutWithVerticalMenu.html.twig' %} +{% extends '@ChillMain/CRUD/Admin/index.html.twig' %} {% block admin_content -%} {% embed '@ChillMain/CRUD/_edit_content.html.twig' %} + {% block crud_content_after_form %} {% if access_permissions_group_list %}

      {{ 'Permissions granted'|trans }}

      @@ -54,5 +55,14 @@ {% endblock %} {% block content_form_actions_save_and_show %}{% endblock %} + + {% block content_form_actions_view %} +
    • + + {{ 'admin.users.job_scope_histories.Show history'|trans }} + +
    • + {% endblock %} + {% endembed %} {% endblock %} diff --git a/src/Bundle/ChillMainBundle/Resources/views/User/history.html.twig b/src/Bundle/ChillMainBundle/Resources/views/User/history.html.twig new file mode 100644 index 000000000..ec38ec388 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/User/history.html.twig @@ -0,0 +1,81 @@ +{% extends '@ChillMain/Admin/layoutWithVerticalMenu.html.twig' %} + +{% block title %}{{ 'admin.users.job_scope_histories.index.histories'|trans }}{% endblock title %} + +{% block admin_content %} +

      {{ user.usernameCanonical }}

      +

      {{ 'admin.users.job_scope_histories.index.histories'|trans }}

      + +

      {{ 'admin.users.job_scope_histories.index.job_history.title'|trans }}

      + + + + + + + + + + {% for entity in jobHistories|reverse %} + + + + + + {% endfor %} + +
      {{ 'admin.users.job_scope_histories.index.job_history.start'|trans }}{{ 'admin.users.job_scope_histories.index.job_history.end'|trans }}{{ 'admin.users.job_scope_histories.index.job_history.job'|trans }}
      {{ entity.startDate|format_datetime('medium') }} + {% if entity.endDate is not null %} + {{ entity.endDate|format_datetime('medium') }} + {% else %} + {{ "admin.users.job_scope_histories.index.job_history.today"|trans }} + {% endif %} + + {% if entity.job %} + {{ entity.job.label|localize_translatable_string }} + {% else %} + {{ 'admin.users.job_scope_histories.index.job_history.undefined'|trans }} + {% endif %} +
      + +

      {{ 'admin.users.job_scope_histories.index.scope_history.title'|trans }}

      + + + + + + + + + + {% for entity in scopeHistories|reverse %} + + + + + + {% endfor %} + +
      {{ 'admin.users.job_scope_histories.index.scope_history.start'|trans }}{{ 'admin.users.job_scope_histories.index.scope_history.end'|trans }}{{ 'admin.users.job_scope_histories.index.scope_history.scope'|trans }}
      {{ entity.startDate|format_datetime('medium') }} + {% if entity.endDate is not null %} + {{ entity.endDate|format_datetime('medium') }} + {% else %} + {{ "admin.users.job_scope_histories.index.scope_history.today"|trans }} + {% endif %} + + {% if entity.scope %} + {{ entity.scope.name|localize_translatable_string }} + {% else %} + {{ 'admin.users.job_scope_histories.index.scope_history.undefined'|trans }} + {% endif %} +
      + + + +{% endblock %} diff --git a/src/Bundle/ChillMainBundle/Resources/views/UserJob/history.html.twig b/src/Bundle/ChillMainBundle/Resources/views/UserJob/history.html.twig deleted file mode 100644 index a0adf3e30..000000000 --- a/src/Bundle/ChillMainBundle/Resources/views/UserJob/history.html.twig +++ /dev/null @@ -1,51 +0,0 @@ -{% extends '@ChillMain/CRUD/Admin/index.html.twig' %} - -{% block admin_content %} - {% embed '@ChillMain/CRUD/_index.html.twig' %} - - {% block table_entities_thead_tr %} - {{ 'crud.admin_user_job_history.index.start'|trans }} - {{ 'crud.admin_user_job_history.index.end'|trans }} - {{ 'crud.admin_user_job_history.index.user'|trans }} - {{ 'crud.admin_user_job_history.index.job'|trans }} - {% endblock %} - - {% block table_entities_tbody %} - {% for entity in entities %} - - {{ entity.startDate|format_datetime('medium') }} - - {% if entity.endDate is not null %} - {{ entity.endDate|format_datetime('medium') }} - {% else %} - {{ "crud.admin_user_job_history.index.today"|trans }} - {% endif %} - - {{ entity.user.usernameCanonical }} - - {% if entity.job %} - {{ entity.job.label|localize_translatable_string }} - {% else %} - {{ 'crud.admin_user_job_history.index.undefined'|trans }} - {% endif %} - - - {% endfor %} - {% endblock %} - - {% block actions_before %} -
    • - {{'Back to the admin'|trans }} -
    • - {% endblock %} - - {% block list_actions %} - - {% endblock %} - {% endembed %} -{% endblock %} - diff --git a/src/Bundle/ChillMainBundle/Resources/views/UserJob/index.html.twig b/src/Bundle/ChillMainBundle/Resources/views/UserJob/index.html.twig index 7ec15f14d..a0c66ccdc 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/UserJob/index.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/UserJob/index.html.twig @@ -37,9 +37,6 @@
    • {{'Back to the admin'|trans }}
    • -
    • - {{ 'crud.admin_user_job_history.Show job history'|trans }} -
    • {% endblock %} {% endembed %} diff --git a/src/Bundle/ChillMainBundle/translations/messages.fr.yml b/src/Bundle/ChillMainBundle/translations/messages.fr.yml index 05a02bde1..28615bc75 100644 --- a/src/Bundle/ChillMainBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillMainBundle/translations/messages.fr.yml @@ -389,28 +389,6 @@ crud: add_new: Créer title_new: Nouveau métier title_edit: Modifier un métier - admin_user_job_history: - index: - title: Historique des métiers - start: Du - end: Jusque - today: en cours - undefined: non défini - user: Utilisateur - job: Métier - Show job history: Voir l'historique - Back to user job: Revenir aux métiers - admin_user_scope_history: - index: - title: Historique des cercles - start: Du - end: Jusque - today: en cours - undefined: non défini - user: Utilisateur - scope: Cercle - Show scope history: Voir l'historique - Back to user scope: Revenir aux cercles main_location_type: index: title: Liste des types de localisations @@ -673,3 +651,24 @@ admin: center_name: Centre permissionsGroup_id: Identifiant du groupe de permissions permissionsGroup_name: Groupe de permissions + job_scope_histories: + Show history: Voir l'historique + index: + histories: Historique des services et des métiers + Back to user job: Revenir à l'utilisateur + job_history: + title: Historique des métiers + start: Du + end: Jusque + today: en cours + undefined: non défini + user: Utilisateur + job: Métier + scope_history: + title: Historique des services + start: Du + end: Jusque + today: en cours + undefined: non défini + user: Utilisateur + scope: Service diff --git a/src/Bundle/ChillPersonBundle/Controller/HouseholdCompositionController.php b/src/Bundle/ChillPersonBundle/Controller/HouseholdCompositionController.php index 1b85daea8..3e0ab7add 100644 --- a/src/Bundle/ChillPersonBundle/Controller/HouseholdCompositionController.php +++ b/src/Bundle/ChillPersonBundle/Controller/HouseholdCompositionController.php @@ -36,7 +36,17 @@ use Symfony\Contracts\Translation\TranslatorInterface; class HouseholdCompositionController extends AbstractController { - public function __construct(private readonly Security $security, private readonly HouseholdCompositionRepository $householdCompositionRepository, private readonly HouseholdRepository $householdRepository, private readonly PaginatorFactory $paginatorFactory, private readonly FormFactoryInterface $formFactory, private readonly EntityManagerInterface $entityManager, private readonly TranslatorInterface $translator, private readonly \Twig\Environment $engine, private readonly UrlGeneratorInterface $urlGenerator) {} + public function __construct( + private readonly Security $security, + private readonly HouseholdCompositionRepository $householdCompositionRepository, + private readonly HouseholdRepository $householdRepository, + private readonly PaginatorFactory $paginatorFactory, + private readonly FormFactoryInterface $formFactory, + private readonly EntityManagerInterface $entityManager, + private readonly TranslatorInterface $translator, + private readonly \Twig\Environment $engine, + private readonly UrlGeneratorInterface $urlGenerator + ) {} /** * @Route("/{_locale}/person/household/{household_id}/composition/{composition_id}/delete", name="chill_person_household_composition_delete") From 0b6b25fd95b7d87e3f391f7e6e3e6a3cfd5539c1 Mon Sep 17 00:00:00 2001 From: Mathieu Jaumotte Date: Wed, 4 Oct 2023 12:47:23 +0200 Subject: [PATCH 48/62] improve histories order since User entity --- .../UserJobScopeHistoriesController.php | 20 ++++++------ src/Bundle/ChillMainBundle/Entity/User.php | 32 +++++++++++++++++++ .../Resources/views/User/history.html.twig | 4 +-- 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/Bundle/ChillMainBundle/Controller/UserJobScopeHistoriesController.php b/src/Bundle/ChillMainBundle/Controller/UserJobScopeHistoriesController.php index 4014e0593..55d7aceb7 100644 --- a/src/Bundle/ChillMainBundle/Controller/UserJobScopeHistoriesController.php +++ b/src/Bundle/ChillMainBundle/Controller/UserJobScopeHistoriesController.php @@ -28,16 +28,18 @@ class UserJobScopeHistoriesController extends AbstractController */ public function indexAction(User $user): Response { - $jobHistories = $user->getUserJobHistories(); - $scopeHistories = $user->getMainScopeHistories(); - + $jobHistories = $user->getUserJobHistoriesOrdered(); + $scopeHistories = $user->getMainScopeHistoriesOrdered(); return new Response( - $this->engine->render('@ChillMain/User/history.html.twig', [ - 'user' => $user, - 'jobHistories' => $jobHistories, - 'scopeHistories' => $scopeHistories, - ] - )); + $this->engine->render( + '@ChillMain/User/history.html.twig', + [ + 'user' => $user, + 'jobHistories' => $jobHistories, + 'scopeHistories' => $scopeHistories, + ] + ) + ); } } diff --git a/src/Bundle/ChillMainBundle/Entity/User.php b/src/Bundle/ChillMainBundle/Entity/User.php index 64f0e18f6..33c8be166 100644 --- a/src/Bundle/ChillMainBundle/Entity/User.php +++ b/src/Bundle/ChillMainBundle/Entity/User.php @@ -283,6 +283,22 @@ class User implements UserInterface, \Stringable return $this->scopeHistories; } + /** + * @return ArrayCollection|UserScopeHistory[] + */ + public function getMainScopeHistoriesOrdered(): ArrayCollection + { + $scopeHistories = $this->getMainScopeHistories(); + + $sortedScopeHistories = $scopeHistories->toArray(); + + usort($sortedScopeHistories, function ($a, $b) { + return $a->getStartDate() < $b->getStartDate() ? 1 : -1; + }); + + return new ArrayCollection($sortedScopeHistories); + } + /** * @return string */ @@ -321,6 +337,22 @@ class User implements UserInterface, \Stringable return $this->jobHistories; } + /** + * @return ArrayCollection|UserJobHistory[] + */ + public function getUserJobHistoriesOrdered(): ArrayCollection + { + $jobHistories = $this->getUserJobHistories(); + + $sortedJobHistories = $jobHistories->toArray(); + + usort($sortedJobHistories, function ($a, $b) { + return $a->getStartDate() < $b->getStartDate() ? 1 : -1; + }); + + return new ArrayCollection($sortedJobHistories); + } + /** * @return string */ diff --git a/src/Bundle/ChillMainBundle/Resources/views/User/history.html.twig b/src/Bundle/ChillMainBundle/Resources/views/User/history.html.twig index ec38ec388..eb1e0e461 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/User/history.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/User/history.html.twig @@ -16,7 +16,7 @@ - {% for entity in jobHistories|reverse %} + {% for entity in jobHistories %} {{ entity.startDate|format_datetime('medium') }} @@ -48,7 +48,7 @@ - {% for entity in scopeHistories|reverse %} + {% for entity in scopeHistories %} {{ entity.startDate|format_datetime('medium') }} From 239372270e61c47cba23a7809f1c7ed49614a6db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Thu, 5 Oct 2023 09:33:23 +0200 Subject: [PATCH 49/62] Update schema to store accompanying period work referrer history --- .../AccompanyingPeriodWork.php | 38 ++++-- .../AccompanyingPeriodWorkReferrerHistory.php | 125 ++++++++++++++++++ .../migrations/Version20231004142738.php | 85 ++++++++++++ 3 files changed, 234 insertions(+), 14 deletions(-) create mode 100644 src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkReferrerHistory.php create mode 100644 src/Bundle/ChillPersonBundle/migrations/Version20231004142738.php diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php index afbb91963..611f1763e 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php @@ -26,6 +26,7 @@ use DateTimeImmutable; use DateTimeInterface; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; +use Doctrine\Common\Collections\ReadableCollection; use Doctrine\ORM\Mapping as ORM; use LogicException; use Symfony\Component\Serializer\Annotation as Serializer; @@ -154,14 +155,11 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues private PrivateCommentEmbeddable $privateComment; /** - * @var Collection - * @ORM\ManyToMany(targetEntity=User::class) + * @var Collection + * @ORM\OneToMany(targetEntity=AccompanyingPeriodWorkReferrerHistory::class, cascade={"persist", "remove"}, mappedBy="accompanyingPeriodWork") * @ORM\JoinTable(name="chill_person_accompanying_period_work_referrer") - * @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"}) - * @Serializer\Groups({"accompanying_period_work:edit"}) - * @Serializer\Groups({"accompanying_period_work:create"}) */ - private Collection $referrers; + private Collection $referrersHistory; /** * @var Collection @@ -220,7 +218,7 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues $this->thirdParties = new ArrayCollection(); $this->persons = new ArrayCollection(); $this->accompanyingPeriodWorkEvaluations = new ArrayCollection(); - $this->referrers = new ArrayCollection(); + $this->referrersHistory = new ArrayCollection(); } public function addAccompanyingPeriodWorkEvaluation(AccompanyingPeriodWorkEvaluation $evaluation): self @@ -254,8 +252,9 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues public function addReferrer(User $referrer): self { - if (!$this->referrers->contains($referrer)) { - $this->referrers[] = $referrer; + if (!$this->getReferrers()->contains($referrer)) { + $this->referrersHistory[] = + new AccompanyingPeriodWorkReferrerHistory($this, $referrer, new DateTimeImmutable('today')); } return $this; @@ -351,15 +350,18 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues } /** - * @return Collection|User[] + * @return ReadableCollection + * @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"}) + * @Serializer\Groups({"accompanying_period_work:edit"}) + * @Serializer\Groups({"accompanying_period_work:create"}) */ - public function getReferrers(): Collection + public function getReferrers(): ReadableCollection { - return $this->referrers; + return $this->referrersHistory->map(fn (AccompanyingPeriodWorkReferrerHistory $h) => $h->getUser()); } /** - * @return Collection|Result[] + * @return Collection */ public function getResults(): Collection { @@ -434,7 +436,15 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues public function removeReferrer(User $referrer): self { - $this->referrers->removeElement($referrer); + foreach ($this->referrersHistory as $history) { + if ($history->isOpen() && $referrer === $history->getUser()) { + $history->setEndDate(new DateTimeImmutable('today')); + + if ($history->isDateRangeEmpty()) { + $history->removeAccompanyingPeriodWork(); + } + } + } return $this; } diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkReferrerHistory.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkReferrerHistory.php new file mode 100644 index 000000000..48b75d3e4 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWorkReferrerHistory.php @@ -0,0 +1,125 @@ +accompanyingPeriodWork = $accompanyingPeriodWork; + } + + public function getId(): ?int + { + return $this->id; + } + + public function getEndDate(): ?\DateTimeImmutable + { + return $this->endDate; + } + + public function setEndDate(?\DateTimeImmutable $endDate): AccompanyingPeriodWorkReferrerHistory + { + $this->endDate = $endDate; + return $this; + } + + public function getAccompanyingPeriodWork(): AccompanyingPeriodWork + { + return $this->accompanyingPeriodWork; + } + + public function getUser(): User + { + return $this->user; + } + + public function getStartDate(): \DateTimeImmutable + { + return $this->startDate; + } + + /** + * to be used when the history is removed (when startDate = endDate) + * + * @return self + */ + public function removeAccompanyingPeriodWork(): self + { + $this->accompanyingPeriodWork = null; + + return $this; + } + + /** + * @return bool true if the endDate is null + */ + public function isOpen(): bool + { + return null === $this->getEndDate(); + } + + /** + * return true if the date range is empty (start date and end date are equal). + * + * @return bool true if the start date and end date are equal. + */ + public function isDateRangeEmpty(): bool + { + return $this->getStartDate()->format('Y-m-d') === $this->getEndDate()?->format('Y-m-d'); + } +} diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20231004142738.php b/src/Bundle/ChillPersonBundle/migrations/Version20231004142738.php new file mode 100644 index 000000000..0c9840fff --- /dev/null +++ b/src/Bundle/ChillPersonBundle/migrations/Version20231004142738.php @@ -0,0 +1,85 @@ +addSql('CREATE SEQUENCE chill_person_accompanying_period_work_referrer_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP CONSTRAINT fk_3619f5ebb99f6060'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP CONSTRAINT FK_3619F5EBA76ED395'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP CONSTRAINT chill_person_accompanying_period_work_referrer_pkey'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD id INT NOT NULL DEFAULT nextval(\'chill_person_accompanying_period_work_referrer_id_seq\')'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD endDate DATE DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD startDate DATE DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ALTER accompanyingperiodwork_id DROP NOT NULL'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ALTER user_id DROP NOT NULL'); + $this->addSql('COMMENT ON COLUMN chill_person_accompanying_period_work_referrer.endDate IS \'(DC2Type:date_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_person_accompanying_period_work_referrer.startDate IS \'(DC2Type:date_immutable)\''); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD CONSTRAINT FK_3619F5EBC55C1209 FOREIGN KEY (accompanyingPeriodWork_id) REFERENCES chill_person_accompanying_period_work (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD CONSTRAINT FK_3619F5EBA76ED395 FOREIGN KEY (user_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD PRIMARY KEY (id)'); + $this->addSql('ALTER INDEX idx_3619f5ebb99f6060 RENAME TO IDX_3619F5EBC55C1209'); + + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD createdAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL;'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD updatedAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL;'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD createdBy_id INT DEFAULT NULL;'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD updatedBy_id INT DEFAULT NULL;'); + $this->addSql('COMMENT ON COLUMN chill_person_accompanying_period_work_referrer.endDate IS \'(DC2Type:date_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_person_accompanying_period_work_referrer.startDate IS \'(DC2Type:date_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_person_accompanying_period_work_referrer.createdAt IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_person_accompanying_period_work_referrer.updatedAt IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD CONSTRAINT FK_3619F5EB3174800F FOREIGN KEY (createdBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE;'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD CONSTRAINT FK_3619F5EB65FF1AEC FOREIGN KEY (updatedBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE;'); + $this->addSql('CREATE INDEX IDX_3619F5EB3174800F ON chill_person_accompanying_period_work_referrer (createdBy_id);'); + $this->addSql('CREATE INDEX IDX_3619F5EB65FF1AEC ON chill_person_accompanying_period_work_referrer (updatedBy_id);'); + + // set a default date on startDate + $this->addSql('UPDATE chill_person_accompanying_period_work_referrer r SET startdate=w.startdate FROM chill_person_accompanying_period_work w WHERE w.id = r.accompanyingperiodwork_id'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ALTER startDate SET NOT NULL'); + + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD CONSTRAINT cpapwr_start_date_before_end CHECK (startdate <= enddate OR enddate IS NULL)'); + + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer + ADD CONSTRAINT acc_period_work_ref_history_not_overlaps + EXCLUDE USING GIST (accompanyingperiodwork_id with =, user_id with =, tsrange(startdate, enddate) with &&) + DEFERRABLE INITIALLY DEFERRED'); + } + + public function down(Schema $schema): void + { + $this->addSql('DROP SEQUENCE chill_person_accompanying_period_work_referrer_id_seq CASCADE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP CONSTRAINT FK_3619F5EBC55C1209'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP CONSTRAINT fk_3619f5eba76ed395'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP CONSTRAINT cpapwr_start_date_before_end'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP CONSTRAINT acc_period_work_ref_history_not_overlaps'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP CONSTRAINT chill_person_accompanying_period_work_referrer_pkey'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP id'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP endDate'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer DROP startDate'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ALTER user_id SET NOT NULL'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ALTER accompanyingPeriodWork_id SET NOT NULL'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD CONSTRAINT fk_3619f5ebb99f6060 FOREIGN KEY (accompanyingperiodwork_id) REFERENCES chill_person_accompanying_period_work (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD CONSTRAINT fk_3619f5eba76ed395 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD PRIMARY KEY (accompanyingperiodwork_id, user_id)'); + $this->addSql('ALTER INDEX idx_3619f5ebc55c1209 RENAME TO idx_3619f5ebb99f6060'); + } +} From 363785b7794f845c92f6d8cd148ca8d6ec38e9c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Thu, 5 Oct 2023 09:33:23 +0200 Subject: [PATCH 50/62] Update schema to store accompanying period work referrer history --- .../AccompanyingPeriodWork.php | 13 ++- .../AccompanyingPeriodWorkReferrerHistory.php | 21 ++-- .../AccompanyingPeriodWorkTest.php | 96 +++++++++++++++++++ 3 files changed, 115 insertions(+), 15 deletions(-) create mode 100644 src/Bundle/ChillPersonBundle/Tests/Entity/AccompanyingPeriod/AccompanyingPeriodWorkTest.php diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php index 611f1763e..bf87bf7ee 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php @@ -156,7 +156,7 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues /** * @var Collection - * @ORM\OneToMany(targetEntity=AccompanyingPeriodWorkReferrerHistory::class, cascade={"persist", "remove"}, mappedBy="accompanyingPeriodWork") + * @ORM\OneToMany(targetEntity=AccompanyingPeriodWorkReferrerHistory::class, cascade={"persist", "remove"}, mappedBy="accompanyingPeriodWork", orphanRemoval=true) * @ORM\JoinTable(name="chill_person_accompanying_period_work_referrer") */ private Collection $referrersHistory; @@ -357,9 +357,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 +450,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/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')); + } +} From 978db5a5c5172fa85cbc22984bc23ff9c69b2d0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 11 Oct 2023 15:14:27 +0200 Subject: [PATCH 51/62] update some queries in the interface to take into account history of user's scope and user's job --- .../Repository/ActivityACLAwareRepository.php | 34 +++++++-- .../Controller/UserExportController.php | 8 +-- .../Repository/UserRepository.php | 71 +++++++++++-------- .../EntityInfo/ViewEntityInfoManager.php | 6 +- .../AccompanyingPeriodWork.php | 1 - ...mpanyingPeriodWorkEvaluationRepository.php | 5 +- .../AccompanyingPeriodWorkRepository.php | 12 ++-- ...kEndQueryPartForAccompanyingPeriodInfo.php | 2 +- ...ionQueryPartForAccompanyingPeriodInfo.php} | 13 ++-- ...nMaxQueryPartForAccompanyingPeriodInfo.php | 2 +- ...tartQueryPartForAccompanyingPeriodInfo.php | 4 +- ...rrerQueryPartForAccompanyingPeriodInfo.php | 64 +++++++++++++++++ ...tartQueryPartForAccompanyingPeriodInfo.php | 2 +- .../Tests/Repository/UserRepositoryTest.php | 43 +++++++++++ 14 files changed, 210 insertions(+), 57 deletions(-) rename src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/{AccompanyingPeriodWorkEvaluationWarningDateQueryPartForAccompanyingPeriodInfo.php => AccompanyingPeriodWorkEvaluationCreationQueryPartForAccompanyingPeriodInfo.php} (73%) create mode 100644 src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkNewReferrerQueryPartForAccompanyingPeriodInfo.php create mode 100644 src/Bundle/ChillPersonBundle/Tests/Repository/UserRepositoryTest.php diff --git a/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php b/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php index f9db5c158..6babecc55 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); @@ -175,13 +196,14 @@ final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepos public function findUserJobByAssociated(Person|AccompanyingPeriod $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/ChillMainBundle/Controller/UserExportController.php b/src/Bundle/ChillMainBundle/Controller/UserExportController.php index 04778dfae..450be8dd7 100644 --- a/src/Bundle/ChillMainBundle/Controller/UserExportController.php +++ b/src/Bundle/ChillMainBundle/Controller/UserExportController.php @@ -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/Repository/UserRepository.php b/src/Bundle/ChillMainBundle/Repository/UserRepository.php index a59ddc399..222dae2b5 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,58 @@ 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 + LEFT JOIN chill_main_user_scope_history userScopeHistory ON u.id = userScopeHistory.user_id + 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 + WHERE + tstzrange(userScopeHistory.startdate, userScopeHistory.enddate) @> NOW() + AND + tstzrange(userJobHistory.startdate, userJobHistory.enddate) @> NOW() + 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/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/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php index bf87bf7ee..0c17276ae 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php @@ -157,7 +157,6 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues /** * @var Collection * @ORM\OneToMany(targetEntity=AccompanyingPeriodWorkReferrerHistory::class, cascade={"persist", "remove"}, mappedBy="accompanyingPeriodWork", orphanRemoval=true) - * @ORM\JoinTable(name="chill_person_accompanying_period_work_referrer") */ private Collection $referrersHistory; 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/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/Repository/UserRepositoryTest.php b/src/Bundle/ChillPersonBundle/Tests/Repository/UserRepositoryTest.php new file mode 100644 index 000000000..c7d8e67cc --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Repository/UserRepositoryTest.php @@ -0,0 +1,43 @@ +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); + } + self::assertGreaterThan(0, $i); + } +} From 21524f052e9d1193fec32424c7a41b3f480c2760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Thu, 12 Oct 2023 09:53:18 +0200 Subject: [PATCH 52/62] Create a custom dql function to build json object (JSON_BUILD_OBJECT) --- .../ChillMainExtension.php | 2 + .../Doctrine/DQL/JsonBuildObject.php | 53 ++++++++++++++++ .../Doctrine/DQL/JsonBuildObjectTest.php | 61 +++++++++++++++++++ .../Export/ListAccompanyingPeriodWork.php | 33 +++++++++- 4 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 src/Bundle/ChillMainBundle/Doctrine/DQL/JsonBuildObject.php create mode 100644 src/Bundle/ChillMainBundle/Tests/Doctrine/DQL/JsonBuildObjectTest.php 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/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/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/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 ' From 63e9d1a96f7d69e25c235de1e1bfe972f4bc7de9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 16 Oct 2023 10:58:00 +0200 Subject: [PATCH 53/62] [export] add a filter and aggregator on activity: by creator job --- .../unreleased/Feature-20231011-155115.yaml | 5 + .../Aggregator/CreatorScopeAggregator.php | 2 +- .../Export/Aggregator/JobScopeAggregator.php | 104 ++++++++++++++++++ .../Aggregator/JobScopeAggregatorTest.php | 60 ++++++++++ .../config/services/export.yaml | 4 + 5 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 .changes/unreleased/Feature-20231011-155115.yaml create mode 100644 src/Bundle/ChillActivityBundle/Export/Aggregator/JobScopeAggregator.php create mode 100644 src/Bundle/ChillActivityBundle/Tests/Export/Aggregator/JobScopeAggregatorTest.php 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/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/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 } From 68d28f3e28c4f33ea031f90090d47f07021fa36e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 16 Oct 2023 10:58:41 +0200 Subject: [PATCH 54/62] Fix filtres and scopes to take into account job and scope when the refferrer is add to the accompanying period work --- .../Export/Export/ListActivityHelper.php | 6 +- .../translations/messages.fr.yml | 3 + .../src/Export/Export/ListAsideActivity.php | 7 +- .../Export/Export/ListAsideActivityTest.php | 43 +++++++++ src/Bundle/ChillMainBundle/Entity/User.php | 8 +- .../Export/Helper/ExportAddressHelper.php | 4 +- .../Export/Helper/UserHelper.php | 90 ++++++++++++++----- .../Resources/views/Entity/user.html.twig | 8 +- .../Templating/Entity/UserRender.php | 15 +++- .../SocialWorkAggregators/JobAggregator.php | 39 +++----- .../ReferrerAggregator.php | 2 +- .../SocialWorkAggregators/ScopeAggregator.php | 39 +++----- .../Export/Export/ListEvaluation.php | 6 +- .../Filter/SocialWorkFilters/JobFilter.php | 38 ++------ .../Filter/SocialWorkFilters/ScopeFilter.php | 37 ++------ .../Helper/ListAccompanyingPeriodHelper.php | 15 ++-- .../JobAggregatorTest.php | 5 +- .../ScopeAggregatorTest.php | 5 +- .../Export/ListAccompanyingPeriodTest.php | 53 +++++++++++ .../Export/ListAccompanyingPeriodWorkTest.php | 49 ++++++++++ .../Export/Export/ListEvaluationTest.php | 49 ++++++++++ .../SocialWorkFilters/JobFilterTest.php | 1 - .../SocialWorkFilters/ScopeFilterTest.php | 1 - .../translations/messages.fr.yml | 2 + 24 files changed, 352 insertions(+), 173 deletions(-) create mode 100644 src/Bundle/ChillAsideActivityBundle/src/Tests/Export/Export/ListAsideActivityTest.php create mode 100644 src/Bundle/ChillPersonBundle/Tests/Export/Export/ListAccompanyingPeriodTest.php create mode 100644 src/Bundle/ChillPersonBundle/Tests/Export/Export/ListAccompanyingPeriodWorkTest.php create mode 100644 src/Bundle/ChillPersonBundle/Tests/Export/Export/ListEvaluationTest.php 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/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/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/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/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/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/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/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..3bec8730b 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ReferrerAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ReferrerAggregator.php @@ -65,7 +65,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]); }; } 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/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/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/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/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/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/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/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index 639de0443..542471149 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -1187,7 +1187,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 From 51a4ffca2e1d1c777ecf1286b57d9f5adf541127 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 16 Oct 2023 11:59:49 +0200 Subject: [PATCH 55/62] Fix cs with new cs rules (php-cs-fixer version 3.35) --- .../Repository/ActivityACLAwareRepository.php | 2 +- .../Repository/ChargeRepository.php | 2 +- .../Repository/ResourceRepository.php | 4 ++-- .../Connector/MSGraph/MSUserAbsenceReader.php | 2 +- .../MSGraph/MSUserAbsenceReaderInterface.php | 2 +- .../CustomFields/CustomFieldChoice.php | 2 +- .../Entity/CustomFieldsGroup.php | 2 +- .../Controller/ParticipationController.php | 16 ++++++++-------- src/Bundle/ChillEventBundle/Entity/Event.php | 2 +- .../Command/LoadPostalCodesCommand.php | 2 +- .../Controller/PasswordController.php | 4 ++-- .../ChillMainBundle/Doctrine/DQL/Extract.php | 2 +- .../ChillMainBundle/Doctrine/DQL/JsonExtract.php | 2 +- .../ChillMainBundle/Doctrine/DQL/ToChar.php | 2 +- .../ChillMainBundle/Export/ExportFormHelper.php | 4 ++-- .../ChillMainBundle/Export/ExportManager.php | 8 ++++---- .../Authorization/AuthorizationHelper.php | 8 ++++---- .../AuthorizationHelperInterface.php | 2 +- .../Resolver/ScopeResolverDispatcher.php | 2 +- .../DiscriminatedObjectDenormalizer.php | 2 +- .../Doctrine/DQL/AddressPart.php | 2 +- .../Entity/AccompanyingPeriod.php | 2 +- .../Entity/AccompanyingPeriod/Resource.php | 2 +- src/Bundle/ChillPersonBundle/Entity/Person.php | 2 +- .../Entity/SocialWork/SocialAction.php | 6 +++--- .../Entity/SocialWork/SocialIssue.php | 2 +- .../JobWorkingOnCourseAggregator.php | 2 +- .../ScopeWorkingOnCourseAggregator.php | 2 +- .../UserWorkingOnCourseAggregator.php | 2 +- .../PersonAggregators/CenterAggregator.php | 2 +- .../AccompanyingPeriodWorkNormalizer.php | 2 +- .../AccompanyingPeriodACLAwareRepositoryTest.php | 2 +- .../DataFixtures/ORM/LoadReports.php | 2 +- .../Authorization/AuthorizationEvent.php | 2 +- .../ChillWopiBundle/src/Controller/Convert.php | 2 +- 35 files changed, 53 insertions(+), 53 deletions(-) diff --git a/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php b/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php index 6babecc55..d61e0999e 100644 --- a/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php +++ b/src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php @@ -193,7 +193,7 @@ 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.job)') 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/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/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/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/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/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/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/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/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/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/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/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()); } } From b65f76262a16cdd8267b61caa2d179017e87a2c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 16 Oct 2023 13:06:25 +0200 Subject: [PATCH 56/62] Refactor filters and aggregators of "acpwusers" for using the acpw referrer history instead --- exports_alias_conventions.csv | 63 ------------------- exports_alias_conventions.md | 1 - .../Tests/Export/Filter/JobFilterTest.php | 15 ++--- .../Tests/Export/Filter/ScopeFilterTest.php | 15 ++--- .../ReferrerAggregator.php | 35 ++++++++--- .../SocialWorkFilters/ReferrerFilter.php | 58 ++++++++++------- .../ReferrerAggregatorTest.php | 6 +- .../SocialWorkFilters/ReferrerFilterTest.php | 6 ++ .../translations/messages+intl-icu.fr.yaml | 6 +- .../translations/messages.fr.yml | 13 ++-- 10 files changed, 101 insertions(+), 117 deletions(-) delete mode 100644 exports_alias_conventions.csv 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/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/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ReferrerAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/SocialWorkAggregators/ReferrerAggregator.php index 3bec8730b..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) @@ -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/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/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/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/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 542471149..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: From efcb903d10ee0335a4c76fb4fa6d1e3a940ee83a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 16 Oct 2023 13:13:24 +0200 Subject: [PATCH 57/62] Fix direct kernel deprecation in AccompanyingCourseApiControllerTest --- .../AccompanyingCourseApiControllerTest.php | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) 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)"); } From 304bf4258b0fe023cc2103e4c187ba75d1d52994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 16 Oct 2023 14:28:04 +0200 Subject: [PATCH 58/62] Remove usage of setParameters in various filters --- .../Export/Filter/UserScopeFilter.php | 7 ++++--- .../Export/Filter/UsersJobFilter.php | 7 ++++--- .../Export/Filter/UsersScopeFilter.php | 7 ++++--- .../src/Export/Filter/ByUserJobFilter.php | 7 ++++--- .../src/Export/Filter/ByUserScopeFilter.php | 7 ++++--- .../Export/Filter/JobFilter.php | 12 ++++++------ .../Export/Filter/ScopeFilter.php | 7 ++++--- .../AccompanyingCourseFilters/CreatorJobFilter.php | 7 ++++--- .../JobWorkingOnCourseFilter.php | 14 +++++++++----- .../ScopeWorkingOnCourseFilter.php | 14 +++++++++----- .../AccompanyingCourseFilters/UserJobFilter.php | 7 ++++--- .../AccompanyingCourseFilters/UserScopeFilter.php | 7 ++++--- 12 files changed, 60 insertions(+), 43 deletions(-) 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/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/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/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"], + ) ; } From 93b189b091cf7c286ac74a5607959c1b48b68ec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 16 Oct 2023 14:43:46 +0200 Subject: [PATCH 59/62] DX: Fix HouseholdApiControllerTest.php --- .../Tests/Controller/HouseholdApiControllerTest.php | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) 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(); } From c62495a280675bedbe8da450a594f6dc97c83d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 16 Oct 2023 16:20:09 +0200 Subject: [PATCH 60/62] Fix export of all users and mapping of columns in user csv export (admin zone) --- .../ChillMainBundle/Controller/UserExportController.php | 2 +- src/Bundle/ChillMainBundle/Repository/UserRepository.php | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Bundle/ChillMainBundle/Controller/UserExportController.php b/src/Bundle/ChillMainBundle/Controller/UserExportController.php index 450be8dd7..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', diff --git a/src/Bundle/ChillMainBundle/Repository/UserRepository.php b/src/Bundle/ChillMainBundle/Repository/UserRepository.php index 222dae2b5..17775f475 100644 --- a/src/Bundle/ChillMainBundle/Repository/UserRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/UserRepository.php @@ -109,15 +109,12 @@ final readonly class UserRepository implements UserRepositoryInterface 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 - LEFT JOIN chill_main_user_scope_history userScopeHistory ON u.id = userScopeHistory.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 - WHERE - tstzrange(userScopeHistory.startdate, userScopeHistory.enddate) @> NOW() - AND - tstzrange(userJobHistory.startdate, userJobHistory.enddate) @> NOW() + ORDER BY u.label, u.id SQL); $query = $this->connection->prepare($sql); From 0df93fb7030138a112d86190d1d58ac61ba9e64f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 16 Oct 2023 17:19:28 +0200 Subject: [PATCH 61/62] DX: Fix test for PersonMoveTest.php --- .../Tests/Action/Remove/PersonMoveTest.php | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) 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"]; From dd47ddc268b21a2ac0ce8c60366774d551d03c65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 16 Oct 2023 17:26:15 +0200 Subject: [PATCH 62/62] DX: Fix user repository test --- .../ChillPersonBundle/Tests/Repository/UserRepositoryTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Bundle/ChillPersonBundle/Tests/Repository/UserRepositoryTest.php b/src/Bundle/ChillPersonBundle/Tests/Repository/UserRepositoryTest.php index c7d8e67cc..5a99b8e4c 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Repository/UserRepositoryTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Repository/UserRepositoryTest.php @@ -37,6 +37,7 @@ class UserRepositoryTest extends KernelTestCase $i = 0; foreach ($userIterator as $u) { self::assertIsArray($u); + $i++; } self::assertGreaterThan(0, $i); }