diff --git a/CHANGELOG.md b/CHANGELOG.md index 15c8ae4de..57372ed35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to ## Unreleased +* [person] AccompanyingPeriodWork: add referrers to work, add doctrine event listener to add logged user to referrers collection and display a referrers list in work list (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/502) * [person] AccompanyingPeriodWorkEvaluation: fix circular reference when serialising (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/495) * [person] order accompanying period by opening date in search persons, person and household period lists (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/493) * [parcours] autosave of the pinned comment for draft accompanying course (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/477) diff --git a/src/Bundle/ChillMainBundle/Resources/views/Menu/verticalMenu.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Menu/verticalMenu.html.twig index 51be6c2c3..e15e64374 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Menu/verticalMenu.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Menu/verticalMenu.html.twig @@ -27,7 +27,7 @@ {% for menu in menus %} - {{ menu.label|upper }} + {{ menu.label|trans|upper }} {% endfor %} diff --git a/src/Bundle/ChillMainBundle/Resources/views/User/index.html.twig b/src/Bundle/ChillMainBundle/Resources/views/User/index.html.twig index 53bd89482..5a558b6a0 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/User/index.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/User/index.html.twig @@ -1,60 +1,62 @@ {% extends '@ChillMain/Admin/Permission/layout_crud_permission_index.html.twig' %} {% block admin_content -%} - {% embed '@ChillMain/CRUD/_index.html.twig' %} - {% block table_entities_thead_tr %} - {{ 'crud.admin_user.index.is_active'|trans }} - {{ 'crud.admin_user.index.usernames'|trans }} - {{ 'crud.admin_user.index.mains'|trans }} -   - {% endblock %} - {% block table_entities_tbody %} - {% for entity in entities %} - - + +

{{"Users"|trans}}

+ {% for entity in entities %} +
+
+
+
+ {{ entity.label }} {% if entity.isEnabled %} {% else %} {% endif %} - - - {{ entity.username }} -
- {{ entity.label }} -
- {{ entity.email }} - - +
+
{{ entity.email }}
+
+
+
+ login: {{ entity.username|e('html_attr') }} +
+
{% if entity.userJob %} - {{ entity.userJob.label|localize_translatable_string }} -
+ {{ entity.userJob.label|localize_translatable_string }} {% endif %} +
+
+
+
{% if entity.mainScope %} - {{ entity.mainScope.name|localize_translatable_string }} -
+ {{ entity.mainScope.name|localize_translatable_string }} {% endif %} {% if entity.mainCenter %} - {{ entity.mainCenter.name }} + , {{ entity.mainCenter.name }} {% endif %} - - -
    +
+
+
+
    +
  • + +
  • +
  • + +
  • + {% if is_granted('ROLE_ALLOWED_TO_SWITCH') %}
  • - +
  • -
  • - -
  • - {% if is_granted('ROLE_ALLOWED_TO_SWITCH') %} -
  • - -
  • - {% endif %} -
- - - {% endfor %} - {% endblock %} - {% endembed %} -{% endblock %} + {% endif %} + +
+
+ +
+ {% endfor %} + + {{ chill_pagination(paginator) }} + +{% endblock %} \ No newline at end of file diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php index ed00c8611..95ec008d9 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/AccompanyingPeriodWork.php @@ -142,6 +142,15 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues */ private Collection $persons; + /** + * @ORM\ManyToMany(targetEntity=User::class) + * @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; + /** * @ORM\ManyToMany(targetEntity=Result::class, inversedBy="accompanyingPeriodWorks") * @ORM\JoinTable(name="chill_person_accompanying_period_work_result") @@ -196,6 +205,7 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues $this->thirdParties = new ArrayCollection(); $this->persons = new ArrayCollection(); $this->accompanyingPeriodWorkEvaluations = new ArrayCollection(); + $this->referrers = new ArrayCollection(); } public function addAccompanyingPeriodWorkEvaluation(AccompanyingPeriodWorkEvaluation $evaluation): self @@ -227,6 +237,15 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues return $this; } + public function addReferrer(User $referrer): self + { + if (!$this->referrers->contains($referrer)) { + $this->referrers[] = $referrer; + } + + return $this; + } + public function addResult(Result $result): self { if (!$this->results->contains($result)) { @@ -308,6 +327,14 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues return $this->persons; } + /** + * @return Collection|User[] + */ + public function getReferrers(): Collection + { + return $this->referrers; + } + /** * @return Collection|Result[] */ @@ -382,6 +409,13 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues return $this; } + public function removeReferrer(User $referrer): self + { + $this->referrers->removeElement($referrer); + + return $this; + } + public function removeResult(Result $result): self { $this->results->removeElement($result); diff --git a/src/Bundle/ChillPersonBundle/EventListener/AccompanyingPeriodWorkEventListener.php b/src/Bundle/ChillPersonBundle/EventListener/AccompanyingPeriodWorkEventListener.php new file mode 100644 index 000000000..c9b11ea71 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/EventListener/AccompanyingPeriodWorkEventListener.php @@ -0,0 +1,30 @@ +security = $security; + } + + public function prePersistAccompanyingPeriodWork(AccompanyingPeriodWork $work): void + { + $work->addReferrer($this->security->getUser()); + } +} diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationRepository.php index 3178aa6e2..3273e3a7d 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationRepository.php @@ -87,9 +87,12 @@ class AccompanyingPeriodWorkEvaluationRepository implements ObjectRepository ->join('work.accompanyingPeriod', 'period') ->where( $qb->expr()->andX( - $qb->expr()->eq('period.user', ':user'), $qb->expr()->isNull('e.endDate'), - $qb->expr()->gte(':now', $qb->expr()->diff('e.maxDate', 'e.warningInterval')) + $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') + ) ) ) ->setParameters([ diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php index 9e67da458..dd27cf434 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php @@ -159,9 +159,12 @@ final class AccompanyingPeriodWorkRepository implements ObjectRepository ->join('w.accompanyingPeriod', 'period') ->where( $qb->expr()->andX( - $qb->expr()->eq('period.user', ':user'), $qb->expr()->gte('w.endDate', ':since'), - $qb->expr()->lte('w.startDate', ':until') + $qb->expr()->lte('w.startDate', ':until'), + $qb->expr()->orX( + $qb->expr()->eq('period.user', ':user'), + $qb->expr()->isMemberOf(':user', 'w.referrers') + ) ) ) ->setParameters([ diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/App.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/App.vue index 3920182c8..7f6cadca0 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/App.vue +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/App.vue @@ -151,6 +151,37 @@ +
+

{{ $t('referrers') }}

+ +
+

{{ $t('no_referrers') }}

+
+ +
+ +
+ + +
+

{{ $t('handling_thirdparty') }}

@@ -289,7 +320,6 @@ import PersonText from 'ChillPersonAssets/vuejs/_components/Entity/PersonText.vu import {buildLinkCreate} from 'ChillMainAssets/lib/entity-workflow/api.js'; import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods'; - const i18n = { messages: { fr: { @@ -322,6 +352,10 @@ const i18n = { available_evaluations_text: "Documents disponibles pour ajout :", no_evaluations_available: "Aucune évaluation disponible", no_goals_available: "Aucun objectif disponible", + referrers: "Agents traitants", + no_referrers: "Aucun agent traitant", + choose_referrers: "Choisir des agents traitants", + remove_referrer: "Enlever l'agent" } } }; @@ -370,6 +404,17 @@ export default { } }, }, + referrerPicker: { + key: 'referrer', + options: { + type: ['user'], + priority: null, + uniq: false, + button: { + display: false + } + }, + }, }; }, computed: { @@ -381,6 +426,7 @@ export default { 'personsReachables', 'handlingThirdParty', 'thirdParties', + 'referrers', 'isPosting', 'errors', 'templatesAvailablesForAction', @@ -389,6 +435,7 @@ export default { 'hasResultsForAction', 'hasHandlingThirdParty', 'hasThirdParties', + 'hasReferrers' ]), startDate: { get() { @@ -465,6 +512,14 @@ export default { removeThirdParty(t) { this.$store.commit('removeThirdParty', t); }, + addReferrers({selected, modal}) { + this.$store.commit('addReferrers', selected.map(r => r.result)); + this.$refs.referrerPicker.resetSearch(); + modal.showModal = false; + }, + removeReferrer(u) { + this.$store.commit('removeReferrer', u); + }, goToGenerateWorkflow({link}) { console.log('save before leave to generate workflow') const callback = (data) => { @@ -521,6 +576,7 @@ div#workEditor { "objectives objectives" "evaluations evaluations" "persons persons" + "referrers referrers" "handling handling" "tparties tparties" "errors errors"; @@ -543,6 +599,8 @@ div#workEditor { grid-area: handling; } #thirdParties { grid-area: tparties; } + #referrers { + grid-area: referrers; } #errors { grid-area: errors; } @@ -657,5 +715,4 @@ div#workEditor { } } - diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/store.js b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/store.js index 7f96843e5..f53c9d246 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/store.js +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/store.js @@ -31,6 +31,7 @@ const store = createStore({ .map(p => p.person), handlingThirdParty: window.accompanyingCourseWork.handlingThierParty, thirdParties: window.accompanyingCourseWork.thirdParties, + referrers: window.accompanyingCourseWork.referrers, isPosting: false, errors: [], }, @@ -54,6 +55,9 @@ const store = createStore({ hasHandlingThirdParty(state) { return state.handlingThirdParty !== null; }, + hasReferrers(state) { + return state.referrers.length > 0; + }, hasThirdParties(state) { return state.thirdParties.length > 0; }, @@ -82,6 +86,7 @@ const store = createStore({ }, results: state.resultsPicked.map(r => ({id: r.id, type: r.type})), thirdParties: state.thirdParties.map(t => ({id: t.id, type: t.type})), + referrers: state.referrers.map(t => ({id: t.id, type: t.type})), goals: state.goalsPicked.map(g => { let o = { type: g.type, @@ -302,6 +307,18 @@ const store = createStore({ state.thirdParties = state.thirdParties .filter(t => t.id !== thirdParty.id); }, + addReferrers(state, referrers) { + let ids = state.referrers.map(t => t.id); + let unexistings = referrers.filter(t => !ids.includes(t.id)); + + for (let i in unexistings) { + state.referrers.push(unexistings[i]); + } + }, + removeReferrer(state, user) { + state.referrers = state.referrers + .filter(u => u.id !== user.id); + }, setErrors(state, errors) { state.errors = errors; }, @@ -315,7 +332,6 @@ const store = createStore({ }, actions: { updateThirdParty({ commit }, payload) { - console.log(payload); commit('updateThirdParty', payload); }, getReachablesGoalsForAction({ getters, commit, dispatch }) { diff --git a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/_item.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/_item.html.twig index d7e4f4e96..6287b158d 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/_item.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/_item.html.twig @@ -28,11 +28,14 @@ {% if w.createdBy %}
-

{{ 'Referrer'|trans }}

+

{{ 'Referrers'|trans }}

- {{ w.createdBy|chill_entity_render_box }} + {% for u in w.referrers %} + {{ u|chill_entity_render_box }} + {% if not loop.last %}, {% endif %} + {% endfor %}

diff --git a/src/Bundle/ChillPersonBundle/Tests/Serializer/Normalizer/HouseholdNormalizerTest.php b/src/Bundle/ChillPersonBundle/Tests/Serializer/Normalizer/HouseholdNormalizerTest.php index ac015155b..c67e07b5e 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Serializer/Normalizer/HouseholdNormalizerTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Serializer/Normalizer/HouseholdNormalizerTest.php @@ -16,6 +16,7 @@ use Chill\PersonBundle\Entity\Household\HouseholdMember; use Chill\PersonBundle\Entity\Household\Position; use Chill\PersonBundle\Entity\Person; use DateTimeImmutable; +use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; @@ -25,17 +26,24 @@ use Symfony\Component\Serializer\Normalizer\NormalizerInterface; */ final class HouseholdNormalizerTest extends KernelTestCase { + private EntityManagerInterface $entityManager; + private ?NormalizerInterface $normalizer; + private array $toDelete; + protected function setUp(): void { self::bootKernel(); $this->normalizer = self::$container->get(NormalizerInterface::class); + $this->entityManager = self::$container->get(EntityManagerInterface::class); } public function testNormalizationRecursive() { $person = new Person(); + $person->setFirstName('ok')->setLastName('ok'); + $this->entityManager->persist($person); $member = new HouseholdMember(); $household = new Household(); $position = (new Position()) @@ -44,7 +52,8 @@ final class HouseholdNormalizerTest extends KernelTestCase $member->setPerson($person) ->setStartDate(new DateTimeImmutable('1 year ago')) - ->setEndDate(new DateTimeImmutable('1 month ago')); + ->setEndDate(new DateTimeImmutable('1 month ago')) + ->setPosition($position); $household->addMember($member); diff --git a/src/Bundle/ChillPersonBundle/config/services/doctrineEventListener.yaml b/src/Bundle/ChillPersonBundle/config/services/doctrineEventListener.yaml index f75243d02..dbf6fc16d 100644 --- a/src/Bundle/ChillPersonBundle/config/services/doctrineEventListener.yaml +++ b/src/Bundle/ChillPersonBundle/config/services/doctrineEventListener.yaml @@ -12,3 +12,13 @@ services: event: 'prePersist' entity: 'Chill\PersonBundle\Entity\PersonAltName' method: 'prePersistAltName' + + Chill\PersonBundle\EventListener\AccompanyingPeriodWorkEventListener: + autoconfigure: true + autowire: true + tags: + - + name: 'doctrine.orm.entity_listener' + event: 'prePersist' + entity: 'Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork' + method: 'prePersistAccompanyingPeriodWork' \ No newline at end of file diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20220310063629.php b/src/Bundle/ChillPersonBundle/migrations/Version20220310063629.php new file mode 100644 index 000000000..9e6f0c332 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/migrations/Version20220310063629.php @@ -0,0 +1,42 @@ +addSql('DROP TABLE chill_person_accompanying_period_work_referrer'); + } + + public function getDescription(): string + { + return 'Add referrers to AccompanyingPeriodWork'; + } + + public function up(Schema $schema): void + { + $this->addSql('CREATE TABLE chill_person_accompanying_period_work_referrer (accompanyingperiodwork_id INT NOT NULL, user_id INT NOT NULL, PRIMARY KEY(accompanyingperiodwork_id, user_id))'); + $this->addSql('CREATE INDEX IDX_3619F5EBB99F6060 ON chill_person_accompanying_period_work_referrer (accompanyingperiodwork_id)'); + $this->addSql('CREATE INDEX IDX_3619F5EBA76ED395 ON chill_person_accompanying_period_work_referrer (user_id)'); + $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('INSERT INTO chill_person_accompanying_period_work_referrer (accompanyingperiodwork_id, user_id) + SELECT id, createdby_id FROM postgres.public.chill_person_accompanying_period_work'); + } +} diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index 57fc039b8..bb5e5e846 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -214,6 +214,7 @@ No requestor: Pas de demandeur No resources: "Pas d'interlocuteurs privilégiés" Persons associated: Usagers concernés Referrer: Référent +Referrers: Référents Some peoples does not belong to any household currently. Add them to an household soon: Certaines personnes n'appartiennent à aucun ménage actuellement. Renseignez leur ménage dès que possible. Add to household now: Ajouter à un ménage Any resource for this accompanying course: Aucun interlocuteur privilégié pour ce parcours