diff --git a/.changes/header.tpl.md b/.changes/header.tpl.md new file mode 100644 index 000000000..df8faa7b2 --- /dev/null +++ b/.changes/header.tpl.md @@ -0,0 +1,6 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html), +and is generated by [Changie](https://github.com/miniscruff/changie). diff --git a/.changes/unreleased/.gitkeep b/.changes/unreleased/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/.changes/v2.0.0.md b/.changes/v2.0.0.md new file mode 100644 index 000000000..8d70ecba6 --- /dev/null +++ b/.changes/v2.0.0.md @@ -0,0 +1,677 @@ +## 2.0.0 + +* this is a release to relaunch our proceess of release with semantic versioning + +## Test releases + +### 2.0.0-beta3 + +* [person][export] Fixed: rename the alias for `accompanying_period` to `acp` in filter associated with person +* [activity][export] Feature: improve label for aliases in "Filter by activity type" +* [activity][export] DX/Feature: use of an `ActivityTypeRepositoryInterface` instead of the old-style EntityRepository +* [person][export] Fixed: some inconsistency with date filter on accompanying courses +* [person][export] Fixed: use left join for related entities in accompanying course aggregators +* [workflow] Feature: allow user to copy and send manually the access link for the workflow +* [workflow] Feature: show the email addresses that received an access link for the workflow +### 2.0.0-beta2 + +* [workflow]: Fixed: the notification is sent when the user is added to the first step. +* [budget] Feature: allow to desactivate some charges and resources, adding an `active` key in the configuration +* [person] Feature: on Evaluation, allow to configure an URL from the admin + +### 2022-06 + +* [workflow]: added pagination to workflow list page +* [homepage_widget]: null error on tasks widget fixed +* [person-thirdparty]: fix quick-add of names that consist of multiple parts (eg. De Vlieger) within onthefly modal person/thirdparty +* [search]: Order of birthdate fields changed in advanced search to avoid confusion. +* [workflow]: Constraint added to workflow (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/675) +* [social_action]: only show active objectives (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/625) +* [household]: Reposition and cut button for enfant hors menage have been deleted (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/620) +* [admin]: Add crud for composition type in admin (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/611) +* [social_action]: only show active objectives (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/625) + +## Test releases + +### 2022-05-30 + +* fix creating a new AccompanyingPeriodWorkEvaluationDocument when replacing the document (the workflow was lost) + +### 2022-05-27 + +* [storedobject] add title field on StoredObject entity + use it in activity documents (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/604) +* [main] add a "read more..." on comment embeddable when overflown (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/604) +* [person] add closing motive to closed acc course (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/603) +* [person] household filiation: fetch person info when unfolding person (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/586) +* [admin] repair edit of social action in the admin (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/601) +* [admin]: add select2 to Goal form type entity fields (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/702) +* [main] allow hide permissions group list menu (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/577) +* [main] allow hide change user password menu (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/577) +* [main] filter user jobs by active jobs (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/577) +* [main] add civility to User (entity, migration and form type) (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/577) +* [admin] refactorisation of the admin section: reorganisation of the menu, translations, form types, new entities (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/592) +* [admin] add admin section for languages and countries (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/596) +* [activity] activity admin: translations + remove label field for comment on admin activity type (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/587) +* [main] admin user_job: improvements (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/588) +* [address] can add extra address info even if noAddress (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/576) + + +### 2022-05-06 + +* [person] add civility when creating a person (with the on-the-fly component or in the php form) (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/557) +* [person] add address when creating a person (with the on-the-fly component or in the php form) (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/557) +* [person] add household creation API point (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/557) + +### 2021-04-29 + +* [person] prevent circular references in PersonDocGenNormalizer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/527) +* [person] add maritalStatusComment to PersonDocGenNormalizer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/582) +* Load relationships without gender in french fixtures +* Add command to remove old draft accompanying periods +* [parcours]: If users assings him/herself as referrer and job is not null. Update parcours job (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/578) + +### 2021-04-28 + +* [address] fix bug when editing address: update location and addressreferenceId + better update of the map in edition (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/593) +* [main] avoid address reference search on undefined post code (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/561) +* [person] prevent duplicate relationship in filiation/household graph (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/560) +* [Documents] Validate storedObject and allow for null data (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/565) +* [parcours]: Comments can be unpinned + edit/delete for all users that are allowed to edit parcours (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/566) + +### 2021-04-26 + +* [Datepickers] datepickers fixed when using keyboard to enter date (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/545) +* [social_action] Display 'agents traitants' in parcours resumé and social action list (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/568) +* [Person_search] Closed parcours shown within an accordeon that can be opened/closed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/574) + +### 2021-04-24 + +* [notification email on course designation] allow raw string in email content generation +* [Accompanying period work] list evaluations associated to a work by startDate, and then by id, from the most recent to older +* [Documents] Change wording 'créer' to 'enregistrer' (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/634) +* [Parcours]: The number of 'mes parcours' displayed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/572) +* [Hompage_widget]: Renaming of tabs and removal of social actions tab (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/570) +* [activity]: Ignore thirdparties when creating a social action via an activity (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/573) +* [parcours]: change wording of warning message and button when user is not associated to a household yet (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/590#note_918370943) +* [Accompanying period work evaluations] list documents associated to a work by creation date, and then by id, from the most recent to older +* [Course comment] add validationConstraint NotNull and NotBlank on comment content, to avoid sql error +* [Notifications] delay the sending of notificaiton to kernel.terminate +* [Notifications / Period user change] fix the sending of notification when user changes +* [Activity form] invert 'incoming' and 'receiving' in Activity form +* [Activity form] keep the same order for 'attendee' field in new and edit form +* [list with period] use "sameas" test operator to introduce requestor in list +* [notification email on course designation] allow raw string in email content generation +* [Accompanying period work] list evaluations associated to a work by startDate, and then by id, from the most recent to older +* [evaluation_document] changing date to datetime in order to display the time at which document was created (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/569) + + +### 2021-04-13 + +* [person] household address: add a form for editing the validFrom date (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/541) +* [person] householdmemberseditor: fix composition type bug in select form (vuejs) (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/543) +* [docgen] add more persons choices in docgen for course: amongst requestor (if person), resources of course (if person), and PersonResource (if person); +* [docgen] add a new context with a list of activities in course +* [docgen] add a comment in budget lines +* [notifications] allow to send a notification to an email address. The address receive an access link +* [adresses] add constraints in database to avoid errors later: postcode not null, and validfrom <= validto +* [accompanying work editor] add a label on document title input + +### 2021-04-07 + +* notification list: move action buttons outside of the toggle +* fix detecting of non-read notification +* filter users which are disabled in search user api +* order query for location and add pagination in list +* allow every person which has part for a workflow to see the workflow page +* able to see the workflow if the evaluation document has been deleted +* hardcode the list of supported mime types for edition with collabora +* list of accompanying course: allow to see the pinned comment in list_item + +### 2021-04-06 + +* [main] notification toggle read: correct js syntax for compilation in production (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/548) +* [parcours] Display of interlocuteurs changed to flex-table in parcours edit page to prevent cut-off of information (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/535) +* [activity] espace entre les boutons pour supprimer les documents + + +### continuous release in February and March + +* Creation of PickCivilityType, and implementation in PersonType and ThirdpartyType +* [person] Accompanying course evaluation documents: disable the WOPI edit link if mimetype not supported and if no keyInfos +(https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/585) +* [activity] display error messages above the form in creating a new location (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/481) +* [activity] show required field in activity edit/new by an asterix in the vuejs fields (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/494) +* [ACL] fix allow to see the course, event if the scope'course does not contains the scope's user +* [search] enforce limit of results for fetching rsults by search api https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/576 +* [activity] Fix delete button for document (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/554) +* [activity] Add return path the document generation (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/553) +* [person] add person ressource to person docgen normaliser (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/517) +* [person] AccompanyingCourseWorkEdit: fix deleting evaluation documents (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/546) +* [person] AccompanyingCourseWorkEdit: download existing documents (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/512) +* [person] AccompanyingCourseWorkEdit: replace document by a new one (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/511) +* [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) +* [main] filter user job in undispatch acc period to assign (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/472) +* [main] filter user job in undispatch acc period to assign (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/472) +* [person] Add url in accompanying period work evaluations entity and form (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/476) +* [person] Add document generation in admin and in person/{id}/document (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/464) +* [activity] do not override location if already exist (when validating new activity) (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/470) +* [parcours] Toggle emergency/intensity only by referrer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/442) +* [docstore] Add an API entrypoint for StoredObject (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/466) +* [person] Add the possibility of uploading existing documents to AccPeriodWorkEvaluationDocument (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/466) +* [person] Add title to AccPeriodWorkEvaluationDocument (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/466) +* [person] Order social issues by the field "ordering" (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/388) +* [Person/Household list] when listing other simultaneous members of an household, exclude the members on person, not on members (avoid to show two membersship with the same person) +* [draft periods] add a delete button (if acl granted) on each draft period listed on draft period page (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/463) +* [Person] Display suffixText in RenderPerson, PersonText.vue, RenderPersonBox.vue (was made for displaying "enfant confie") (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/441) +* [budget]: budget enabled for persons and households (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/469) +* [person] residential address: show residential address or info in PersonRenderBox, refactor Residential Address (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/439) +* [thirdparty] Add a contact to a thirdparty from within onTheFly (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/345) +* [documents] Improve flex-table item-col placement when long buttons and long metadata +* [thirdparty] Fix display of multiple contact badges so they wrap onto next line (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/482) +* [confidential] Fix position of toggle button so it does not cover text nor fall outside of box (no issue) +* [parcours] Fix edit of both thirdparty and contact name (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/474) +* [template] do not list inactive templates (for doc generator) +* [household] bugfix if position of member is null, renderbox no longer throws an error (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/480) +* [parcours] location cannot be removed if linked to a user (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/478) +* [person] email added to twig personRenderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/490) +* [activity] Only youngest descendant is kept for social issues and actions (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/471) +* [person] Add link to current household in person banner (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/484) +* [address] person badge in address history changed to open OnTheFly with all person info (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/489) +* [person] Change 'personne' with 'usager' and '&' with 'ET' (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/499) +* [thirdparty] Add parameter condition to display centers or not (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/500) +* [phonenumber] Remove placeholder in phonenumber field (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/496) +* [person_resource] separate create page created to avoid confusion (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/504) +* [contact] add contact button color changed plus the pipe at the side removed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/506) +* [thirdparty] For contacts show current civility/profession in edit form + fix saving of edited information (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/491) +* [household] create-edit household composition placed in separate page to avoid confusion (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/505) +* [blur] Improved positioning of toggle icon (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/486) +* [thirdparty] add firstname field to thirdparty 'child' or 'contact' types (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/508) +* [household] create-edit household composition placed in separate page to avoid confusion (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/505) +* [blur] Improved positioning of toggle icon (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/486) +* [parcours] List of parcours for a specific user so they can be reassigned in case of absence (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/509) +* [thirdparty] Thirdparty view page, english text translated (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/534) +* [social_action] Translation changed in evaluation section (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/512) +* [filiation] Possible to add person (or create onthefly) to add to filiation graph + add relation (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/519) +* [household] Within parcours listing page of household add create button (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/560) +* [person_resource] bugfix when adding thirdparty or freetext resource + prevent personOwner themselves to be added. (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/526) +* [aside_activity] style correction + sticky-form create button (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/529) +* [budget] order within the menu adjusted (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/592) +* [onthefly] fix create person. Bug was noticed in filiation (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/591) +* [parcours] Create document buttons made sticky (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/532) +* [person] Trailing guillemet removed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/530) +* [notification] Display of social action within workflow notification set to display block (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/537) +* [onthefly] trim trailing whitespace in email of person and thirdparty (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/542) + +* [action] Only youngest descendant is kept for social issues and actions (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/471) +## Test releases + +### test release 2022-02-21 + +* [notifications] Word 'un' changed to number '1' for notifications in user menu (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/483) +* [documents] 'gabarit' changed to 'modèle' (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/405) +* [person_resources] Menu name and order changed (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/460) +* workflow: fix sending notifications +* [thirdparty] Extend the thirdparty search to thirdparty children (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/448) +* [person]: AddPersons: allow creation of person or thirdparty only (no users) (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/422) +* [person]: AddPersons: allow creation of person or thirdparty depending on allowed types (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/422) +* [person]: AddPersons: add suggestion of name when creating new person or thirdparty (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/422) +* [main] Address: fix small bug: when modifying an address without street (isNoAddress), also check errors if street is an empty string as back-end change null value to empty string for street (and streetNumber) +* [main] Address: stronger client-side validation of addresses (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/449) +* [person] accompanying course: filter suggested entities by open participations (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/415) +[activity] can click through the cross icon for removing person in concerned group (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/476) +[activity] correct associated persons by considering only open participations (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/476) +* [person_resources]: Renderboxes used to display person/thirdparty info (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/465) +* [Household]: Add end date in HouseholdMember form for 'enfant hors menage' (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/434) +* [homepage_widget]: If no sender then display as 'notification automatique' (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/435) +* [parcours]: Order social activities and only display most recent three in parcours resumé (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/481) +* [3party]: 3party: redirect to parent when contact (child) is opened in view page +* [parcours / addresses]: launch an event when a person change address (either through changing household or because the household is associated to a new address). If the person is localising a course, the course location go back to a temporarily address. +* [thirdparty]: address/phonenumber/email/fonction displayed in thirdpartyrenderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/401) +* [thirdparty_contact]: in search results the 'qualité' is displayed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/465) +* [bug]: fix confidential toggle of address in thirdpartyrenderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/460) + + + +### test release 2022-02-14 + +* AddPersons: remove ul-li html tags from AddPersons (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/419) +* [doc-generator] do not set required fields for mainPerson, person1, person2 (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement#456) +* [doc-generation] add age and obele in the mainPerson, person1 and person2 list + add obele in person renderString if addAge (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/370) +* [person] accompanying course work: fix on-the-fly update of thirdParty +* fix normalisation of accompanying course requestor api (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/378) +* [person] add a returnPath when clicking on some Person or ThirdParty badge (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/427) +* [person] accompanying course work: fix on-the-fly update of thirdParty +* [on-the-fly] close modal only after validation +* [person] correct thirdparty PATCH url + add email and altnames in AddPerson and serializer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/433) +* change order for accompanying course work list +* [parcours]: Mes parcours brouillon added to user menu (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/440) +* [Documents]: List view adapted to display more information (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/414) +* [person]: style fix in parcours listing per person. (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/432) +* [parcours]: Only the referrer can toggle the intensity of the parcours (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/442) +* [household]: display address of current household (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/415) +* ajoute un ordre dans les localisation (api) +* [pick entity]: fix translations in modal (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/419) +* [homepage_widget]: fix translation on emergency badge (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/440) +* [person]: create person and household added to button dropdown (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/454) +* display full address in address.text in normalization. Adapt AddressRenderBox +* [address]: Correction residential address 'depuis le' (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/459) +* [Documents]: List view adapted to display more information (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/414) +* [Thirdparty_contact]: address blurred if confidential in view page (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/450) +* [thirdparty] Add a contact to a thirdparty from within onTheFly (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/345) + + +### test release 2021-02-01 + +* renommer "dossier numéro" en "parcours numéro" dans les résultats de recherche +* renomme date de début en date d'ouverture dans le formulaire parcours +* [homepage widget] improve content tables, improve counter pluralization with style on number +* [notification lists] add comments counter information +* [workflows] fix popover header with previous transition +* [parcours]: validation + message for closing parcours adjusted. +* [household]: household composition double edit button replaced by a delete action (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/426) +[fast_actions] improve fast-actions buttons override mechanism, fix https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/413 +[homepage widget] add vue homepage_widget with asynchone loading, give a global view resume of the user concerned actions, notifications, etc. +* [person]: Comment on marital status is possible even if marital status is not defined (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/421) +* [parcours]: In the list of person results the requestor is not displayed if defined as anonymous (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/424) +* [bugfix]: modal closes and newly created person/thirdparty is selected when multiple persons/thirdparties are created through the modal (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/429) +* [person_resource]: Onthefly button added to view person/thirdparty and badge differentiation for a contact-thirdparty (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/428) +* [workflow][notification] improve how notifications and workflows are 'attached' to entities: contextual list, counter, buttons and vue modal +* [AddAddress] disable multiselect search, and rely only on most pertinent Cities and Street computed backend +* [fast_actions] improve fast-actions buttons override mechanism, fix https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/413 +* [homepage widget] add vue homepage_widget with asynchone loading, give a global view resume of the user concerned actions, notifications, etc. +* [thirdparty] Add a contact to a thirdparty from within onTheFly (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/345) +* [homepage widget] add vue homepage_widget with asynchone loading, give a global view resume of the user concerned actions, notifications, etc. + + +### test release 2021-01-31 + +* [person] accompanying course: optimisation: do not fetch some resources for the banner (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/409) +* [person] accompanying course: close modal when edit participation (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/420) +* [person] accompanying course: treat validation error when editing on-the-fly entities (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/420) +* [activity] show activity attendee (présence) in the activity list (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/412) +* [activity] admin: change validation rule for social action visible field (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/413) +* [parcours]: component added to change the opening date of a parcours (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/411) +* [search]: listing of parcours display changed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/410) +* [user]: page with accompanying periods to which is user is referent (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/408) +* [person] age added to renderstring + renderbox/ vue component created to display person text (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/389) +* [household member editor] allow to push to existing household + + +### test release 2021-01-28 + +* [person] improve filiations vis graph: disable physics, use chill colors for persons-households-course, increase label of relations, remove labels on household arrows and other improvements (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/286, https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/362) +* [activity] Order activity by date and by id (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/364) +* [main] increase length of 4 Address fields (change to TEXT, no size limits) (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/277) +* [main] Add confidential option for address, in edit and view (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/165) +* [person] name suggestions within create person form when person is created departing from a search input (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/377) +* [person] Add residential address entity, form and list for each person +* [aside_activity]: dynamicUserPickerType used (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/399) +* dispatching list + + +### test release 2021-01-26 + +* [parcours] comments truncated if too long + link added (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/406) +* [person]: possibility to add person resources (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/382) +* [person ressources]: module added + + +### test release 2022-01-24 + +* [person] name suggestions within create person form when person is created departing from a search input (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/377) +* [notification: formulaire création] descend la box avec la description dans le bas du formulaire +* [notification for activity]: fix link to activity +* [notification] add "URGENT" before accompanying course with emergency = true +* [notification] add a "read more" button on system notification +* [notification] add `[Chill]` in the subject of each notification, automatically +* [notification] add a counter for notification in activity list and accompanying period list, and search results +* [parcours] bugfix if deathdate is not defined (eg. for a thirdparty) parcours is still displayed. Gave error before. +* [workflow] add breadcrumb to show steps +* [popover] add popover html popup mechanism (used by workflow breadcrumb) +* [templates] improve updatedBy macro in item metadatas +* [parcours]: bug fix when comment is pinned all other comments remain in the collection (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/385) +* [workflow] + * add My workflow section with my opened subscriptions + * apply workflow on documents, accompanyingCourseWork and Evaluations +* [wopi-link] a new vue component allow to open wopi link in a fullscreen chill-themed modal + +### test release 2022-01-19 +* vuejs: add dead information on all on-the-fly person render boxes, in vis graph and other templates (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/271) +* [thirdparty] fix bug in 3rd party view: types was replaced by thirdPartyTypes +* [main] location form type: fix unmapped address field (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/246) +* [activity] fix wrong import of js assets for adding and viewing documents in activity (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/83 & https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/176) +* [person]: space added between deathdate and age in twig renderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/380) +* [forms] dynamic picker types for user/person/thirdparty types created (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/386) + +### test release 2022-01-17 + +* [main] Add editableByUser field to locationType entity, adapt the admin template and add this condition in the location-type endpoint (see https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/297) +* [main] Add mainLocation field to User entity and add it in user form type +* rewrite page which allow to select activity +* [main] Add mainLocation field to User entity and add it in user form type +* [course list in person context] show full username/label for ref +* [accompanying period work] remove the possibility to generate document from an accompanying period work +* vuejs: add validation on required fields for AddPerson, Address and Location components +* vuejs: treat 422 validation errors in locations and AddPerson components +* [person]: space added between deathdate and age in twig renderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/380) + +## Test releases +* vuejs: add validation on required fields for AddPerson, Address and Location components +* vuejs: treat 422 validation errors in locations and AddPerson components +* [person]: space added between deathdate and age in twig renderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/380) + +### test release 2022-01-12 + +* fix thirdparty normalizer on telephone field: https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/322 + +### test release 2022-01-11 + +* vuejs: translate in French all multiselect widgets +* [address] define address lines according postal standards for France and Belgium (default) and change AddressRender, chill_entity_render_box and AddressRenderBox.vue +* [household] change translations (champs-libres/departement-de-la-vendee/accent-suivi-developpement#109) +* [household] add address i18n in household component (champs-libres/departement-de-la-vendee/accent-suivi-developpement#158) +* [household] add on the fly i18n in household component +* [household] redirect to the household page when a household is created from a person (champs-libres/departement-de-la-vendee/accent-suivi-developpement#175) +* [household] household member editor: display alert if some members have already an household (champs-libres/departement-de-la-vendee/accent-suivi-developpement#172) +* [household] household member editor: do not add in new members if the member is included in the members of household (champs-libres/departement-de-la-vendee/accent-suivi-developpement#123) +* [household] household member editor: remove markNoAddress button (champs-libres/departement-de-la-vendee/accent-suivi-developpement#109) +* [person]: ordering fields in add person (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/61) +* [person]: Add email and alt names in add person (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/61) +* [accompanyingCourse] Add a delete action and delete buttons to delete a accompanying course when step = DRAFT (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/64) +* [accompanyingCourse] Add a administrative location in the accompanying course, set the user current location as default, allow to select a location in a select field and do not allow to confirm the accompanying course if location is empty. +* [accompanyingCourse] Add the administrative location in the available variables for document generation +* AddAddress: optimize loading: wait for the user finish typing; +* UserPicker: fix bug with deprecated role +* docgen: add base context + tests +* docgen: add age for person +* [household menu] fix filiation order https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/265 +* [AddAddress]: optimize loading: wait for the user finish typing; +* [UserPicker]: fix bug with deprecated role +* [docgen]: add base context + tests +* [docgen]: add age for person +* [task]: fix dropdown menu style + fix bug in singleTaskController (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/338) +* Household: fix bug when moving person on the same day (see https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/281) +* Household: show date validFrom and validTo when moving +* address reference: add index for refid +* [accompanyingCourse_work] fix styles conflicts + fix bug with remove goal (remove goals one at a time) +* [accompanyingCourse] improve masonry on resume page, add origin +* [notification] new notification interface, can be associated to AccompanyingCourse/Period, Activities. + * List notifications, show, and comment in User section + * Notify button and contextual notification box on associated objects pages +* [accompanyingCourse] add a comment for each resource associated. A modal allow to save comment. Comment is displayed in on-the-fly show modal of the accompanyingCourse context (edit page + resume page). + +### test release 2021-12-14 + +* [asideactivity] creation of aside activity category fixed (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/262) +* [vendee/person] fix typo "situation professionelle" => "situation professionnelle" +* [main] add availableForUsers condition from locationType in the location API endpoint (champs-libres/departement-de-la-vendee/accent-suivi-developpement#248) +* [main] add the current location of the user as API point + add it in the activity location list (champs-libres/departement-de-la-vendee/accent-suivi-developpement#247) +* [activity] improve show/new/edit templates, fix SEE and SEE_DETAILS acl +* [badges] create specific badge for TMS, and make person/thirdparty badges clickable with on-the-fly modal in : + * concerned groups items (activity, calendar) + * accompanyingCourseWork lists + * accompanyingCourse lists +* [acompanyingCourse] add initial comment on Resume page +* [person] create button full width (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/330) + +### test release 2021-12-11 + +* [main] add order field to civility +* [main] change address format in case the country is France, in Address render box and address normalizer +* [person] add validator for accompanying period with a test on social issues (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/76) +* [activity] fix visibility for location +* [origin] fix origin: use correctly the translatable strings + * /!\ everyone must update the origin table. As there is only one row, execute `update chill_person_accompanying_period_origin set label = jsonb_build_object('fr', 'appel téléphonique');` +* [person] redirect bug fixed. +* [action] add an unrelated issue within action creation. +* [origin] fix origin: use correctly the translatable strings + * /!\ everyone must update the origin table. As there is only one row, execute `update chill_person_accompanying_period_origin set label = jsonb_build_object('fr', 'appel téléphonique');` +* [main] change order of civilities in civility fixtures (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/191) +* [person] set min attr in the minimum of children field (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/191) +* [person] add marital status date in person view (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/191) +* [person] show number of children + allow set number of children to null (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/191) +* [person] show acceptSMS option (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/191) +* [person] add death information in person render box in twig and vue render boxes (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/191) +* [asideactivity] creation of aside activity category fixed (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/262) +* [vendee/person] fix typo "situation professionelle" => "situation professionnelle" +* [accompanyingcourse_work] Changes in layout/behavior of edit form (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/321) +* [badge-entity] design coherency between pills badge-person and 3 kinds of badge-thirdparty +* [AddPersons] suggestions row are clickable, not only checkbox + +### test release 2021-12-06 + +* [main] address: use search API end points for getting postal code and reference address (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/316) +* [main] address: in edit mode, select the encoded values in multiselect for address reference and city (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/316) +* [person search] fix bug when using birthdate after and birthdate before +* [person search] increase pertinence when lastname begins with search pattern +* [activity/actions] Améliore la cohérence du design entre + * la page résumé d'un parcours (liste d'actions récentes et liste d'activités récentes) + * la page liste des actions + * la page liste des activités (contexte personne / contexte parcours) +* [household] field to edit wheter person is titulaire of household or not removed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/322) +* [activity] create work if a work with same social action is not associated to the activity +* [visgraph] improve and fix bugs on vis-network relationship graph +* [bugfix] posting of birth- and deathdate through api fixed. +* [suggestions] improve suggestions lists + +### Test release 2021-11-19 - bis + +* [household] do not allow to create two addresses on the same date +* [activity] handle case when there is no social action associated to social issue +* [activity] layout for issues / actions +* [activity][bugfix] in edit mode, the form will now load the social action list + + +### Test release 2021-11-29 + +* [person] suggest entities (person | thirdparty) when creating/editing the accompanying course (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/119) +* [activity] add custom validation on the Activity class, based on what is required from the ActivityType (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/188) +* [main] translate multiselect messages when selecting/creating address +* [main] set the coordinates of the city when creating a new address OR choosing "pas d'adresse complète" +* Use the user.label in accompanying course banner, instead of username; +* fix: show validation message when closing accompanying course; +* [thirdparty] link from modal to thirdparty detail page fixed (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/228) +* [assets] new asset to style suggestions lists (with add/remove item link) (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/258) +* [accompanyingCourseWorkEdit] improves hyphenation and line breaks for long badges +* [acompanyingCourse] improve Resume page + * complete all needed informations, + * actions and activities are clickables, + * better placement with js masonry blocks on top of content area, + * https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/101 + * https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/295 +* [activity/calendar] on show page, concerned groups of persons table adapt itself to isVisibles options +* [activity] remove the "plus" button in activity list +* [activity] check ACL on activity list in person context +* [list for accompanying course in person] filter list using ACL +* [validation] toasts are displayed for errors when modifying accompanying course (generalization required). +* [period] only the user can enable confidentiality +* add an endpoint for checking permissions. See https://gitlab.com/Chill-Projet/chill-bundles/-/merge_requests/232 +* [activity] for a new activity: suggest and create on-the-fly locations based on the accompanying course location + location of the suggested parties +* [calendar] for a new rdv: suggest and create on-the-fly locations based on the accompanying course location + location of the suggested parties +* [period] Validation added when period is confidential and confirmed -> user cannot be null. + + +## Test releases + +### Test release 2021-11-22 + +* [activity] delete admin_user_show in twig template because this route is not defined and should be defined +* [activity] suggest requestor, user and ressources for adding persons|user|3rdparty +* [calendar] suggest persons, professionals and invites for adding persons|3rdparty|user +* [activity] take into account the restrictions on person|thirdparties|users visibilities defined in ActivityType +* [main] Add currentLocation to the User entity + add a page for selecting this location + add in the user menu (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/133) +* [activity] add user current location as default location for a new activity (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/133) +* [task] Select2 field in task form to allow search for a user (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/167) +* remove "search by phone configuration option": search by phone is now executed by default +* remplacer le classement par ordre alphabétique par un classement par ordre de pertinence, qui tient compte: + * de la présence d'une string avec le nom de la ville; + * de la similarité; + * du fait que la recherche commence par une partie du mot recherché +* ajouter la recherche par numéro de téléphone directement dans la barre de recherche et dans le formulaire recherche avancée; +* ajouter la recherche par date de naissance directement dans la barre de recherche; +* ajouter la recherche par ville dans la recherche avancée +* ajouter un lien vers le ménage dans les résultats de recherche +* ajouter l'id du parcours dans les résultats de recherche +* ajouter le demandeur dans les résultats de recherche +* ajout d'un bouton "recherche avancée" sur la page d'accueil +* [person] create an accompanying course: add client-side validation if no origin (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/210) +* [person] fix bounds for computing current person address: the new address appears immediatly +* [docgen] create a normalizer and serializer for normalization on doc format +* [person normalization] the key center is now "centers" and is an array. Empty array if no center +* [accompanyingCourse] Ability to close accompanying course (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/296) +* [task] Select2 field in task form to allow search for a user (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/167) +* [list result] show all courses, except ones with period closed +* [accompanyingCourse] improve banner with small carousel to display slide social-issues or slide associated persons (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/69) + +### Test release 2021-11-15 + +* [main] fix adding multiple AddresseDeRelais (combine PickAddressType with ChillCollection) +* [person]: do not suggest the current household of the person (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/51) +* [person]: display other phone numbers in view + add message in case no others phone numbers (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/184) +* unnecessary whitespace removed from person banner after person-id + double parentheses removed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/290) +* [person]: delete accompanying period work, including related objects (cascade) (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/36) +* [address]: Display of incomplete address adjusted. +* [household]: improve relationship graph + * add form to create/edit/delete relationship link, + * improve graph refresh mechanism + * add feature to export canvas as image (png) +* [person suggest] In widget "add person", improve the pertinence of persons when one of the names starts with the pattern; +* [person] do not ask for center any more on person creation +* [3party] do not ask for center any more on 3party creation + +## Test releases + +### Test release 2021-11-08 + +* [person]: Display the name of a user when searching after a User (TMS) +* [person]: Add civility to the person +* [person]: Various improvements on the edit person form +* [person]: Set available_languages and available_countries as parameters for use in the edit person form +* [activity] Bugfix: documents can now be added to an activity. +* [tasks] improve tasks with filter order +* [tasks] refactor singleControllerTasks: limit the number of conditions from the context +* [validations] validation of accompanying period added: no duplicate participations or resources (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/60). +* [renderbox] If gender of person is not defined, no icon is displayed instead of neuter-icon (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/129). +* [confidential information] module added to blur confidential information (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/248). +* refactor `AuthorizationHelper` and `UserACLAwareRepository` to fix constructor, and separate logic for parent role helper into `ParentRoleHelper` +* [main]: filter location and locationType in backend: exclude NULL names, only active and availableToUsers +* [activity]: perform client-side validation & show/hide fields in the "new location" modal +* [person]: normalize person with CenterResolverDispatcher and handle case where center is null or multiple in PersonRenderBox +* [docstore] voter for PersonDocument and AccompanyingCourseDocument on the 2.0 way (using VoterHelperFactory) +* [docstore] add authorization check inside controller and menu +* [activity]: fix inheritance for role `ACTIVITY FULL` and add missing acl in menu +* [person] show current address in search results +* [person] show alt names in search results +* [admin]: links to activity admin section added again. +* [household]: endDate field deleted from household edit form. +* [household]: View accompanying periods of current and old household members. +* [tasks]: different layout for task list / my tasks, and fix link to tasks in alert or in warning +* [admin]: links to activity admin section added again. +* [household]: household addresses ordered by ValidFrom date and by id to show the last created address on top. +* [socialWorkAction]: display of social issue and parent issues + banner context added. +* [DBAL dependencies] Upgrade to DBAL 3.1 + +### Test release 2021-10-27 + +* [person]: delete double actions buttons on search person page +* [person]: accompanying course work: remove creation date display the list of work + handle case when end date is null +* [main]: Add new pages with a menu for managing location and location type in the admin +* [main]: Add some fixtures for location type +* [calendar]: Pass the location when transforming a calendar item (rdv) into an activity +* [calendar]: Add a user menu for "my calendar" + +### Test release 2021-10-18 + +* [3party]: french translation of contact and company +* [3party]: show parent in list +* [3party]: change color for badge "child" +* [3party]: fix address creation +* [household members editor] finalisation of editor +* [AccompanyingCourse banner]: replace translation referrer (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/70) +* [Location]: add location system in activity and RV (calendar). User can choose in location list or create a new location. +* [household]: add relationship page with dynamic data visualisation graph + +## Test releases + +### Test release 2021-10-11 + +* Address: zoom on postal code geometry + fix origin of manually entered postal code + +* in the Address vue component, order the postal code and street address by alphabetic and numeric order + +* add 3 new fields to PostalCode and adapt postal code command and fixtures + +* [Aside activity] Fixes for aside activity + + * categories with child + * fast creation buttons + * add ordering for types + +* [AccompanyingCourse Resume page] dashboard for AccompanyingCourseWork and for Activities; +* Improve badges behaviour with small screens; + +* [ThirdParty]: + + * third party list + * create a kind contact/institution when create a new thirdparty, and set contact embedded as kind=child; + * filter thirdparties in list + +* [FilterOrder]: add development kit for generating filter and ordering in list +* [Capitalization of names] person names are capitalized on creation, on prePersist event +* [On-The-Fly] modale works for showing, editing and creating person or thirdparty ; +* [AccompanyingCourse Resume page] associated persons list, can see household when hover, and with show on-the-fly modale when clicking person ; + +### test release 2021-10-04 + +* [Household editor][UI] Update how household suggestion and addresses are picked; + + See https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/80 +* [AddAddress] Handle address suggestion; +* [CenterType][Create a person] when overriding the ACL rules, allow to show a PickCenterType + when no centers are reachable by the default ACL. +* [Household] Show comment event if no address are associated with the household; +* [Person results] Add requestor into search results: + + * a badge "requestor" is shown into search results; + * periods where the person is only requestor (without participating) are also shown; + + Issues: + + * https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/13 + * https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/199 +* [Person form] "accept sms" not required: + + https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/37 + https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/221 + +* [Household editor] suggest only temporarily addresses; + See https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/82 +* On-The-Fly modale works for showing, editing and creating person and thirdparty ; +* AccompanyingCourse Resume page: list associated persons by household, see household when hover, and show on-the-fly modale when clicking on person ; +* [AddAddress] Handle address suggestion; +* [AddAddress][Entity address]: add a link between address and address reference; +* [Household editor] suggest household by comparing the temporary addresses from courses; + + See https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/81 +* On-The-Fly modale works for showing, editing and creating person and thirdparty + + +## Test released + + + +## Stable releases + +No stable releases for v2+ + diff --git a/.changes/v2.1.0.md b/.changes/v2.1.0.md new file mode 100644 index 000000000..ade83aee0 --- /dev/null +++ b/.changes/v2.1.0.md @@ -0,0 +1,17 @@ +## v2.1.0 - 2023-06-12 + +### Feature + +* [docgen] allow to pick a third party when generating a document in context Activity, AccompanyingPeriod + +### Fixed + +* ([#111](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/111)) List of "my accompanying periods": separate the active and closed periods in two different lists, and show the inactive_long and inactive_short periods + +### Security + +* ([#105](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/105)) Rights are checked for display of 'accompanying period' tab in household menu. Rights are also checked for creation of 'accompanying period' from within household context + +### DX + +* Add methods to RegroupmentRepository and fullfill Center / Regroupment Doctrine mapping diff --git a/.changie.yaml b/.changie.yaml new file mode 100644 index 000000000..83fd9770a --- /dev/null +++ b/.changie.yaml @@ -0,0 +1,34 @@ +changesDir: .changes +unreleasedDir: unreleased +headerPath: header.tpl.md +changelogPath: CHANGELOG.md +versionExt: md +versionFormat: '## {{.Version}} - {{.Time.Format "2006-01-02"}}' +kindFormat: '### {{.Kind}}' +changeFormat: >- + * {{ if not (eq .Custom.Issue "") }}([#{{ .Custom.Issue }}](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/{{ .Custom.Issue }})) {{- end }}{{.Body}} +custom: + - key: Issue + label: Issue number (on chill-bundles repository) (optional) + optional: true + type: int + minInt: 1 +body: + # allow multiline messages + block: true +kinds: + - label: Feature + auto: minor + - label: Deprecated + auto: minor + - label: Fixed + auto: patch + - label: Security + auto: patch + - label: DX + auto: patch +newlines: + afterChangelogHeader: 1 + beforeChangelogVersion: 1 + endOfVersion: 1 +envPrefix: CHANGIE_ diff --git a/CHANGELOG.md b/CHANGELOG.md index b2f951479..f10f12f9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,16 +1,37 @@ # Changelog - All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to +adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html), +and is generated by [Changie](https://github.com/miniscruff/changie). -* [Semantic Versioning](https://semver.org/spec/v2.0.0.html) for stable releases; -* date versioning for test releases -## Unreleased +## v2.1.0 - 2023-06-12 + +### Feature + +* [docgen] allow to pick a third party when generating a document in context Activity, AccompanyingPeriod + +### Fixed + +* ([#111](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/111)) List of "my accompanying periods": separate the active and closed periods in two different lists, and show the inactive_long and inactive_short periods + +### Security + +* ([#105](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/105)) Rights are checked for display of 'accompanying period' tab in household menu. Rights are also checked for creation of 'accompanying period' from within household context + +### DX + +* Add methods to RegroupmentRepository and fullfill Center / Regroupment Doctrine mapping + +## 2.0.0 + +* this is a release to relaunch our proceess of release with semantic versioning + +## Test releases + +### 2.0.0-beta3 - * [person][export] Fixed: rename the alias for `accompanying_period` to `acp` in filter associated with person * [activity][export] Feature: improve label for aliases in "Filter by activity type" * [activity][export] DX/Feature: use of an `ActivityTypeRepositoryInterface` instead of the old-style EntityRepository @@ -18,9 +39,6 @@ and this project adheres to * [person][export] Fixed: use left join for related entities in accompanying course aggregators * [workflow] Feature: allow user to copy and send manually the access link for the workflow * [workflow] Feature: show the email addresses that received an access link for the workflow - -## Test releases - ### 2.0.0-beta2 * [workflow]: Fixed: the notification is sent when the user is added to the first step. diff --git a/src/Bundle/ChillActivityBundle/Service/DocGenerator/ActivityContext.php b/src/Bundle/ChillActivityBundle/Service/DocGenerator/ActivityContext.php index 624859eda..a20ca365b 100644 --- a/src/Bundle/ChillActivityBundle/Service/DocGenerator/ActivityContext.php +++ b/src/Bundle/ChillActivityBundle/Service/DocGenerator/ActivityContext.php @@ -24,6 +24,9 @@ use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Repository\PersonRepository; use Chill\PersonBundle\Templating\Entity\PersonRenderInterface; +use Chill\ThirdPartyBundle\Entity\ThirdParty; +use Chill\ThirdPartyBundle\Templating\Entity\ThirdPartyRender; +use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; @@ -55,6 +58,10 @@ class ActivityContext implements private TranslatorInterface $translator; + private ThirdPartyRender $thirdPartyRender; + + private ThirdPartyRepository $thirdPartyRepository; + public function __construct( DocumentCategoryRepository $documentCategoryRepository, NormalizerInterface $normalizer, @@ -63,7 +70,9 @@ class ActivityContext implements PersonRenderInterface $personRender, PersonRepository $personRepository, TranslatorInterface $translator, - BaseContextData $baseContextData + BaseContextData $baseContextData, + ThirdPartyRender $thirdPartyRender, + ThirdPartyRepository $thirdPartyRepository ) { $this->documentCategoryRepository = $documentCategoryRepository; $this->normalizer = $normalizer; @@ -73,6 +82,8 @@ class ActivityContext implements $this->personRepository = $personRepository; $this->translator = $translator; $this->baseContextData = $baseContextData; + $this->thirdPartyRender = $thirdPartyRender; + $this->thirdPartyRepository = $thirdPartyRepository; } public function adminFormReverseTransform(array $data): array @@ -89,6 +100,8 @@ class ActivityContext implements 'person1Label' => $data['person1Label'] ?? $this->translator->trans('docgen.person 1'), 'person2' => $data['person2'] ?? false, 'person2Label' => $data['person2Label'] ?? $this->translator->trans('docgen.person 2'), + 'thirdParty' => $data['thirdParty'] ?? false, + 'thirdPartyLabel' => $data['thirdPartyLabel'] ?? $this->translator->trans('thirdParty'), ]; } @@ -118,6 +131,14 @@ class ActivityContext implements ->add('person2Label', TextType::class, [ 'label' => 'person 2 label', 'required' => true, + ]) + ->add('thirdParty', CheckboxType::class, [ + 'required' => false, + 'label' => 'docgen.Ask for thirdParty', + ]) + ->add('thirdPartyLabel', TextType::class, [ + 'label' => 'docgen.thirdParty label', + 'required' => true, ]); } @@ -143,6 +164,20 @@ class ActivityContext implements ]); } } + + $thirdParties = $entity->getThirdParties(); + if ($options['thirdParty'] ?? false) { + $builder->add('thirdParty', EntityType::class, [ + 'class' => ThirdParty::class, + 'choices' => $thirdParties, + 'choice_label' => fn (ThirdParty $p) => $this->thirdPartyRender->renderString($p, []), + 'multiple' => false, + 'required' => false, + 'expanded' => true, + 'label' => $options['thirdPartyLabel'], + 'placeholder' => $this->translator->trans('Any third party selected'), + ]); + } } public function contextGenerationDataDenormalize(DocGeneratorTemplate $template, $entity, array $data): array @@ -157,6 +192,12 @@ class ActivityContext implements } } + if (null !== ($id = ($data['thirdParty'] ?? null))) { + $denormalized['thirdParty'] = $this->thirdPartyRepository->find($id); + } else { + $denormalized['thirdParty'] = null; + } + return $denormalized; } @@ -165,9 +206,11 @@ class ActivityContext implements $normalized = []; foreach (['mainPerson', 'person1', 'person2'] as $k) { - $normalized[$k] = null === $data[$k] ? null : $data[$k]->getId(); + $normalized[$k] = ($data[$k] ?? null)?->getId(); } + $normalized['thirdParty'] = ($data['thirdParty'] ?? null)?->getId(); + return $normalized; } @@ -196,6 +239,13 @@ class ActivityContext implements } } + if ($options['thirdParty']) { + $data['thirdParty'] = $this->normalizer->normalize($contextGenerationData['thirdParty'], 'docgen', [ + 'docgen:expects' => ThirdParty::class, + 'groups' => 'docgen:read' + ]); + } + return $data; } @@ -235,7 +285,7 @@ class ActivityContext implements { $options = $template->getOptions(); - return $options['mainPerson'] || $options['person1'] || $options['person2']; + return $options['mainPerson'] || $options['person1'] || $options['person2'] || $options ['thirdParty']; } public function storeGenerated(DocGeneratorTemplate $template, StoredObject $storedObject, object $entity, array $contextGenerationData): void diff --git a/src/Bundle/ChillActivityBundle/Service/DocGenerator/ListActivitiesByAccompanyingPeriodContext.php b/src/Bundle/ChillActivityBundle/Service/DocGenerator/ListActivitiesByAccompanyingPeriodContext.php index 3da451f2e..045d09beb 100644 --- a/src/Bundle/ChillActivityBundle/Service/DocGenerator/ListActivitiesByAccompanyingPeriodContext.php +++ b/src/Bundle/ChillActivityBundle/Service/DocGenerator/ListActivitiesByAccompanyingPeriodContext.php @@ -140,26 +140,36 @@ class ListActivitiesByAccompanyingPeriodContext implements return $normalized; } + /** + * @return list + */ private function filterActivitiesByUser(array $activities, User $user): array { - return array_filter( - $activities, - function ($activity) use ($user) { - $activityUsernames = array_map(static fn ($user) => $user['username'], $activity['users'] ?? []); - return in_array($user->getUsername(), $activityUsernames, true); - } + return array_values( + array_filter( + $activities, + function ($activity) use ($user) { + $activityUsernames = array_map(static fn ($user) => $user['username'], $activity['users'] ?? []); + return in_array($user->getUsername(), $activityUsernames, true); + } + ) ); } + /** + * @return list + */ private function filterWorksByUser(array $works, User $user): array { - return array_filter( - $works, - function ($work) use ($user) { - $workUsernames = array_map(static fn ($user) => $user['username'], $work['referrers'] ?? []); + return array_values( + array_filter( + $works, + function ($work) use ($user) { + $workUsernames = array_map(static fn ($user) => $user['username'], $work['referrers'] ?? []); - return in_array($user->getUsername(), $workUsernames, true); - } + return in_array($user->getUsername(), $workUsernames, true); + } + ) ); } diff --git a/src/Bundle/ChillBudgetBundle/Calculator/CalculatorResult.php b/src/Bundle/ChillBudgetBundle/Calculator/CalculatorResult.php index 380e641a6..2a67486f0 100644 --- a/src/Bundle/ChillBudgetBundle/Calculator/CalculatorResult.php +++ b/src/Bundle/ChillBudgetBundle/Calculator/CalculatorResult.php @@ -21,7 +21,7 @@ class CalculatorResult public $label; - public $result; + public float $result; public $type; } diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/DownloadButton.vue b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/DownloadButton.vue index b22035bee..10985fdff 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/DownloadButton.vue +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/DownloadButton.vue @@ -1,52 +1,90 @@ diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/helpers.ts b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/helpers.ts index 5b61a108d..c0b0fa940 100644 --- a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/helpers.ts +++ b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/helpers.ts @@ -149,16 +149,21 @@ async function download_and_decrypt_doc(urlGenerator: string, keyData: JsonWebKe } if (iv.length === 0) { + console.log('returning document immediatly'); return rawResponse.blob(); } + console.log('start decrypting doc'); + const rawBuffer = await rawResponse.arrayBuffer(); try { const key = await window.crypto.subtle .importKey('jwk', keyData, { name: algo }, false, ['decrypt']); + console.log('key created'); const decrypted = await window.crypto.subtle .decrypt({ name: algo, iv: iv }, key, rawBuffer); + console.log('doc decrypted'); return Promise.resolve(new Blob([decrypted])); } catch (e) { diff --git a/src/Bundle/ChillMainBundle/Entity/Center.php b/src/Bundle/ChillMainBundle/Entity/Center.php index 5ca051ec0..0d5402409 100644 --- a/src/Bundle/ChillMainBundle/Entity/Center.php +++ b/src/Bundle/ChillMainBundle/Entity/Center.php @@ -48,12 +48,19 @@ class Center implements HasCenterInterface */ private string $name = ''; + /** + * @var Collection + * @ORM\ManyToMany(targetEntity=Regroupment::class, mappedBy="centers") + */ + private Collection $regroupments; + /** * Center constructor. */ public function __construct() { - $this->groupCenters = new \Doctrine\Common\Collections\ArrayCollection(); + $this->groupCenters = new ArrayCollection(); + $this->regroupments = new ArrayCollection(); } /** @@ -106,6 +113,14 @@ class Center implements HasCenterInterface return $this->name; } + /** + * @return Collection + */ + public function getRegroupments(): Collection + { + return $this->regroupments; + } + /** * @param $name * diff --git a/src/Bundle/ChillMainBundle/Entity/Regroupment.php b/src/Bundle/ChillMainBundle/Entity/Regroupment.php index 96953abf5..c5d9525cf 100644 --- a/src/Bundle/ChillMainBundle/Entity/Regroupment.php +++ b/src/Bundle/ChillMainBundle/Entity/Regroupment.php @@ -22,11 +22,12 @@ use Doctrine\ORM\Mapping as ORM; class Regroupment { /** - * @var Center * @ORM\ManyToMany( - * targetEntity=Center::class + * targetEntity=Center::class, + * inversedBy="regroupments" * ) * @ORM\Id + * @var Collection
*/ private Collection $centers; @@ -52,6 +53,26 @@ class Regroupment $this->centers = new ArrayCollection(); } + public function addCenter(Center $center): self + { + if (!$this->centers->contains($center)) { + $this->centers->add($center); + $center->getRegroupments()->add($this); + } + + return $this; + } + + public function removeCenter(Center $center): self + { + if ($this->centers->contains($center)) { + $this->centers->removeElement($center); + $center->getRegroupments()->removeElement($this); + } + + return $this; + } + public function getCenters(): Collection { return $this->centers; diff --git a/src/Bundle/ChillMainBundle/Form/RegroupmentType.php b/src/Bundle/ChillMainBundle/Form/RegroupmentType.php index bc8e6684f..22814598a 100644 --- a/src/Bundle/ChillMainBundle/Form/RegroupmentType.php +++ b/src/Bundle/ChillMainBundle/Form/RegroupmentType.php @@ -31,7 +31,7 @@ class RegroupmentType extends AbstractType ->add('centers', EntityType::class, [ 'class' => Center::class, 'multiple' => true, - 'attr' => ['class' => 'select2'], + 'expanded' => true, ]) ->add('isActive', CheckboxType::class, [ 'label' => 'Actif ?', diff --git a/src/Bundle/ChillMainBundle/Repository/RegroupmentRepository.php b/src/Bundle/ChillMainBundle/Repository/RegroupmentRepository.php index a28f2f341..c115d5d98 100644 --- a/src/Bundle/ChillMainBundle/Repository/RegroupmentRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/RegroupmentRepository.php @@ -14,6 +14,8 @@ namespace Chill\MainBundle\Repository; use Chill\MainBundle\Entity\Regroupment; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; +use Doctrine\ORM\NonUniqueResultException; +use Doctrine\ORM\NoResultException; use Doctrine\Persistence\ObjectRepository; final class RegroupmentRepository implements ObjectRepository @@ -59,6 +61,30 @@ final class RegroupmentRepository implements ObjectRepository return $this->repository->findOneBy($criteria, $orderBy); } + /** + * @throws NonUniqueResultException + * @throws NoResultException + */ + public function findOneByName(string $name): ?Regroupment + { + return $this->repository->createQueryBuilder('r') + ->where('LOWER(r.name) = LOWER(:searched)') + ->setParameter('searched', $name) + ->getQuery() + ->getSingleResult(); + } + + /** + * @return array + */ + public function findRegroupmentAssociatedToNoCenter(): array + { + return $this->repository->createQueryBuilder('r') + ->where('SIZE(r.centers) = 0') + ->getQuery() + ->getResult(); + } + public function getClassName() { return Regroupment::class; diff --git a/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Events/UserRefEventSubscriber.php b/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Events/UserRefEventSubscriber.php index 8d7249928..50e7dcabb 100644 --- a/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Events/UserRefEventSubscriber.php +++ b/src/Bundle/ChillPersonBundle/AccompanyingPeriod/Events/UserRefEventSubscriber.php @@ -51,7 +51,10 @@ class UserRefEventSubscriber implements EventSubscriberInterface public function onStateEntered(EnteredEvent $enteredEvent): void { - if ($enteredEvent->getMarking()->has(AccompanyingPeriod::STEP_CONFIRMED)) { + if ( + $enteredEvent->getMarking()->has(AccompanyingPeriod::STEP_CONFIRMED) + and $enteredEvent->getTransition()->getName() === 'confirm' + ) { $this->onPeriodConfirmed($enteredEvent->getSubject()); } } diff --git a/src/Bundle/ChillPersonBundle/Controller/UserAccompanyingPeriodController.php b/src/Bundle/ChillPersonBundle/Controller/UserAccompanyingPeriodController.php index 658fdb7be..1b67014b3 100644 --- a/src/Bundle/ChillPersonBundle/Controller/UserAccompanyingPeriodController.php +++ b/src/Bundle/ChillPersonBundle/Controller/UserAccompanyingPeriodController.php @@ -12,9 +12,11 @@ declare(strict_types=1); namespace Chill\PersonBundle\Controller; use Chill\MainBundle\Pagination\PaginatorFactory; +use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Repository\AccompanyingPeriodRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; class UserAccompanyingPeriodController extends AbstractController @@ -32,12 +34,24 @@ class UserAccompanyingPeriodController extends AbstractController /** * @Route("/{_locale}/person/accompanying-periods/my", name="chill_person_accompanying_period_user") */ - public function listAction(Request $request) + public function listAction(Request $request): Response { - $total = $this->accompanyingPeriodRepository->countBy(['user' => $this->getUser(), 'step' => ['CONFIRMED', 'CLOSED']]); + $active = $request->query->getBoolean('active', true); + $steps = match ($active) { + true => [ + AccompanyingPeriod::STEP_CONFIRMED, + AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG, + AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT, + ], + false => [ + AccompanyingPeriod::STEP_CLOSED, + ] + }; + + $total = $this->accompanyingPeriodRepository->countBy(['user' => $this->getUser(), 'step' => $steps]); $pagination = $this->paginatorFactory->create($total); $accompanyingPeriods = $this->accompanyingPeriodRepository->findBy( - ['user' => $this->getUser(), 'step' => ['CONFIRMED', 'CLOSED']], + ['user' => $this->getUser(), 'step' => $steps], ['openingDate' => 'DESC'], $pagination->getItemsPerPage(), $pagination->getCurrentPageFirstItemNumber() @@ -46,13 +60,14 @@ class UserAccompanyingPeriodController extends AbstractController return $this->render('@ChillPerson/AccompanyingPeriod/user_periods_list.html.twig', [ 'accompanyingPeriods' => $accompanyingPeriods, 'pagination' => $pagination, + 'active' => $active, ]); } /** * @Route("/{_locale}/person/accompanying-periods/my/drafts", name="chill_person_accompanying_period_draft_user") */ - public function listDraftsAction(Request $request) + public function listDraftsAction(): Response { $total = $this->accompanyingPeriodRepository->countBy(['user' => $this->getUser(), 'step' => 'DRAFT']); $pagination = $this->paginatorFactory->create($total); diff --git a/src/Bundle/ChillPersonBundle/Menu/HouseholdMenuBuilder.php b/src/Bundle/ChillPersonBundle/Menu/HouseholdMenuBuilder.php index 074c27027..13291bdd1 100644 --- a/src/Bundle/ChillPersonBundle/Menu/HouseholdMenuBuilder.php +++ b/src/Bundle/ChillPersonBundle/Menu/HouseholdMenuBuilder.php @@ -12,7 +12,9 @@ declare(strict_types=1); namespace Chill\PersonBundle\Menu; use Chill\MainBundle\Routing\LocalMenuBuilderInterface; +use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter; use Knp\Menu\MenuItem; +use Symfony\Component\Security\Core\Security; use Symfony\Contracts\Translation\TranslatorInterface; class HouseholdMenuBuilder implements LocalMenuBuilderInterface @@ -22,9 +24,12 @@ class HouseholdMenuBuilder implements LocalMenuBuilderInterface */ protected $translator; - public function __construct(TranslatorInterface $translator) + private Security $security; + + public function __construct(TranslatorInterface $translator, Security $security) { $this->translator = $translator; + $this->security = $security; } public function buildMenu($menuId, MenuItem $menu, array $parameters): void @@ -53,12 +58,14 @@ class HouseholdMenuBuilder implements LocalMenuBuilderInterface ], ]) ->setExtras(['order' => 17]); - $menu->addChild($this->translator->trans('household.Accompanying period'), [ - 'route' => 'chill_person_household_accompanying_period', - 'routeParameters' => [ - 'household_id' => $household->getId(), - ], ]) - ->setExtras(['order' => 20]); + if ($this->security->isGranted(AccompanyingPeriodVoter::SEE, $parameters['household'])) { + $menu->addChild($this->translator->trans('household.Accompanying period'), [ + 'route' => 'chill_person_household_accompanying_period', + 'routeParameters' => [ + 'household_id' => $household->getId(), + ],]) + ->setExtras(['order' => 20]); + } $menu->addChild($this->translator->trans('household.Addresses'), [ 'route' => 'chill_person_household_addresses', diff --git a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/_list_item.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/_list_item.html.twig index 6c7fbf7c0..47b8c8a15 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/_list_item.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/_list_item.html.twig @@ -16,11 +16,13 @@
{% if period.step == 'DRAFT' %} - {{- 'Draft'|trans|upper -}} - {% elseif period.step == 'CONFIRMED' %} - {{- 'Confirmed'|trans|upper -}} - {% else %} - {{- 'Closed'|trans|upper -}} + {{ 'course.draft'|trans }} + {% elseif period.step == 'CLOSED' %} + {{ 'course.closed'|trans }} + {% elseif period.step == 'CONFIRMED_INACTIVE_SHORT' %} + {{ 'course.inactive_short'|trans }} + {% elseif period.step == 'CONFIRMED_INACTIVE_LONG' %} + {{ 'course.inactive_long'|trans }} {% endif %}
diff --git a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/user_periods_list.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/user_periods_list.html.twig index 031e0728c..38e055378 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/user_periods_list.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/user_periods_list.html.twig @@ -17,6 +17,15 @@

{{ 'My accompanying periods'|trans }}

+ +

{{ 'Number of periods'|trans }}: {{ pagination.totalItems }}

diff --git a/src/Bundle/ChillPersonBundle/Resources/views/Household/accompanying_period.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/Household/accompanying_period.html.twig index acd251735..c734eee8e 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/Household/accompanying_period.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/Household/accompanying_period.html.twig @@ -40,13 +40,14 @@ {{ 'Household summary'|trans }} - {# TODO: add ACL to check if user is allowed to edit household? #} -
  • - - {{ 'Create an accompanying period'|trans }} - -
  • + {% if is_granted('CHILL_PERSON_HOUSEHOLD_EDIT', household) %} +
  • + + {{ 'Create an accompanying period'|trans }} + +
  • + {% endif %}
    diff --git a/src/Bundle/ChillPersonBundle/Service/DocGenerator/AccompanyingPeriodContext.php b/src/Bundle/ChillPersonBundle/Service/DocGenerator/AccompanyingPeriodContext.php index a42765c12..4f6235930 100644 --- a/src/Bundle/ChillPersonBundle/Service/DocGenerator/AccompanyingPeriodContext.php +++ b/src/Bundle/ChillPersonBundle/Service/DocGenerator/AccompanyingPeriodContext.php @@ -22,10 +22,14 @@ use Chill\DocStoreBundle\Entity\StoredObject; use Chill\DocStoreBundle\Repository\DocumentCategoryRepository; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod; +use Chill\PersonBundle\Entity\AccompanyingPeriod\Resource; use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Repository\PersonRepository; use Chill\PersonBundle\Templating\Entity\PersonRenderInterface; +use Chill\ThirdPartyBundle\Entity\ThirdParty; +use Chill\ThirdPartyBundle\Templating\Entity\ThirdPartyRender; +use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository; use DateTime; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\EntityManagerInterface; @@ -40,6 +44,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; use function array_key_exists; /** + * @see AccompanyingPeriodContextTest * @template-implements DocGeneratorContextWithPublicFormInterface */ class AccompanyingPeriodContext implements @@ -62,6 +67,10 @@ class AccompanyingPeriodContext implements private TranslatorInterface $translator; + private ThirdPartyRender $thirdPartyRender; + + private ThirdPartyRepository $thirdPartyRepository; + public function __construct( DocumentCategoryRepository $documentCategoryRepository, NormalizerInterface $normalizer, @@ -70,7 +79,9 @@ class AccompanyingPeriodContext implements PersonRenderInterface $personRender, PersonRepository $personRepository, TranslatorInterface $translator, - BaseContextData $baseContextData + BaseContextData $baseContextData, + ThirdPartyRender $thirdPartyRender, + ThirdPartyRepository $thirdPartyRepository ) { $this->documentCategoryRepository = $documentCategoryRepository; $this->normalizer = $normalizer; @@ -80,6 +91,8 @@ class AccompanyingPeriodContext implements $this->personRepository = $personRepository; $this->translator = $translator; $this->baseContextData = $baseContextData; + $this->thirdPartyRender = $thirdPartyRender; + $this->thirdPartyRepository = $thirdPartyRepository; } public function adminFormReverseTransform(array $data): array @@ -103,11 +116,12 @@ class AccompanyingPeriodContext implements 'person1Label' => $data['person1Label'] ?? $this->translator->trans('docgen.person 1'), 'person2' => $data['person2'] ?? false, 'person2Label' => $data['person2Label'] ?? $this->translator->trans('docgen.person 2'), + 'thirdParty' => $data['thirdParty'] ?? false, + 'thirdPartyLabel' => $data['thirdPartyLabel'] ?? $this->translator->trans('Third party'), ]; if (array_key_exists('category', $data)) { - $r['category'] = array_key_exists('category', $data) ? - $this->documentCategoryRepository->find($data['category']) : null; + $r['category'] = $this->documentCategoryRepository->find($data['category']); } return $r; @@ -140,6 +154,14 @@ class AccompanyingPeriodContext implements 'label' => 'person 2 label', 'required' => true, ]) + ->add('thirdParty', CheckboxType::class, [ + 'required' => false, + 'label' => 'docgen.Ask for thirdParty', + ]) + ->add('thirdPartyLabel', TextType::class, [ + 'label' => 'docgen.thirdParty label', + 'required' => true, + ]) ->add('category', EntityType::class, [ 'placeholder' => 'Choose a document category', 'class' => DocumentCategory::class, @@ -190,6 +212,28 @@ class AccompanyingPeriodContext implements ]); } } + + $thirdParties = [...array_values(array_filter([$entity->getRequestorThirdParty()])), ...array_values(array_filter( + array_map( + fn (Resource $r): ?ThirdParty => $r->getThirdParty(), + $entity->getResources()->filter( + static fn (Resource $r): bool => null !== $r->getThirdParty() + )->toArray() + ) + ))]; + + if ($options['thirdParty'] ?? false) { + $builder->add('thirdParty', EntityType::class, [ + 'class' => ThirdParty::class, + 'choices' => $thirdParties, + 'choice_label' => fn (ThirdParty $p) => $this->thirdPartyRender->renderString($p, []), + 'multiple' => false, + 'required' => false, + 'expanded' => true, + 'label' => $options['thirdPartyLabel'], + 'placeholder' => $this->translator->trans('Any third party selected'), + ]); + } } public function getData(DocGeneratorTemplate $template, $entity, array $contextGenerationData = []): array @@ -215,6 +259,13 @@ class AccompanyingPeriodContext implements } } + if ($options['thirdParty']) { + $data['thirdParty'] = $this->normalizer->normalize($contextGenerationData['thirdParty'], 'docgen', [ + 'docgen:expects' => ThirdParty::class, + 'groups' => 'docgen:read' + ]); + } + return $data; } @@ -254,7 +305,7 @@ class AccompanyingPeriodContext implements { $options = $template->getOptions(); - return $options['mainPerson'] || $options['person1'] || $options['person2']; + return $options['mainPerson'] || $options['person1'] || $options['person2'] || $options ['thirdParty']; } public function contextGenerationDataNormalize(DocGeneratorTemplate $template, $entity, array $data): array @@ -264,6 +315,8 @@ class AccompanyingPeriodContext implements $normalized[$k] = null !== ($data[$k] ?? null) ? $data[$k]->getId() : null; } + $normalized['thirdParty'] = ($data['thirdParty'] ?? null)?->getId(); + return $normalized; } @@ -279,6 +332,12 @@ class AccompanyingPeriodContext implements } } + if (null !== ($id = ($data['thirdParty'] ?? null))) { + $denormalized['thirdParty'] = $this->thirdPartyRepository->find($id); + } else { + $denormalized['thirdParty'] = null; + } + return $denormalized; } diff --git a/src/Bundle/ChillPersonBundle/Service/DocGenerator/AccompanyingPeriodWorkEvaluationContext.php b/src/Bundle/ChillPersonBundle/Service/DocGenerator/AccompanyingPeriodWorkEvaluationContext.php index 34b339822..f58788120 100644 --- a/src/Bundle/ChillPersonBundle/Service/DocGenerator/AccompanyingPeriodWorkEvaluationContext.php +++ b/src/Bundle/ChillPersonBundle/Service/DocGenerator/AccompanyingPeriodWorkEvaluationContext.php @@ -18,13 +18,18 @@ use Chill\DocStoreBundle\Entity\StoredObject; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument; +use Chill\PersonBundle\Entity\AccompanyingPeriod\Resource; use Chill\PersonBundle\Entity\SocialWork\Evaluation; use Chill\PersonBundle\Repository\SocialWork\EvaluationRepository; +use Chill\ThirdPartyBundle\Entity\ThirdParty; +use Chill\ThirdPartyBundle\Templating\Entity\ThirdPartyRender; +use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * @implements DocGeneratorContextWithPublicFormInterface @@ -43,18 +48,26 @@ class AccompanyingPeriodWorkEvaluationContext implements private TranslatableStringHelperInterface $translatableStringHelper; + private ThirdPartyRender $thirdPartyRender; + + private TranslatorInterface $translator; + public function __construct( AccompanyingPeriodWorkContext $accompanyingPeriodWorkContext, EntityManagerInterface $em, EvaluationRepository $evaluationRepository, NormalizerInterface $normalizer, - TranslatableStringHelperInterface $translatableStringHelper + TranslatableStringHelperInterface $translatableStringHelper, + ThirdPartyRender $thirdPartyRender, + TranslatorInterface $translator ) { $this->accompanyingPeriodWorkContext = $accompanyingPeriodWorkContext; $this->em = $em; $this->evaluationRepository = $evaluationRepository; $this->normalizer = $normalizer; $this->translatableStringHelper = $translatableStringHelper; + $this->thirdPartyRender = $thirdPartyRender; + $this->translator = $translator; } public function adminFormReverseTransform(array $data): array @@ -102,6 +115,31 @@ class AccompanyingPeriodWorkEvaluationContext implements public function buildPublicForm(FormBuilderInterface $builder, DocGeneratorTemplate $template, $entity): void { $this->accompanyingPeriodWorkContext->buildPublicForm($builder, $template, $entity->getAccompanyingPeriodWork()); + + $thirdParties = [...array_values(array_filter($entity->getAccompanyingPeriodWork()->getThirdParties()->toArray())), ...array_values(array_filter([$entity->getAccompanyingPeriodWork()->getHandlingThierParty()])), ...array_values( + array_filter( + array_map( + fn (Resource $r): ?ThirdParty => $r->getThirdParty(), + $entity->getAccompanyingPeriodWork()->getAccompanyingPeriod()->getResources()->filter( + static fn (Resource $r): bool => null !== $r->getThirdParty() + )->toArray() + ) + ) + )]; + + $options = $template->getOptions(); + if ($options['thirdParty'] ?? false) { + $builder->add('thirdParty', EntityType::class, [ + 'class' => ThirdParty::class, + 'choices' => $thirdParties, + 'choice_label' => fn (ThirdParty $p) => $this->thirdPartyRender->renderString($p, []), + 'multiple' => false, + 'required' => false, + 'expanded' => true, + 'label' => $options['thirdPartyLabel'], + 'placeholder' => $this->translator->trans('Any third party selected'), + ]); + } } public function getData(DocGeneratorTemplate $template, $entity, array $contextGenerationData = []): array @@ -116,7 +154,6 @@ class AccompanyingPeriodWorkEvaluationContext implements AbstractNormalizer::GROUPS => ['docgen:read'], ] ); - return $data; } diff --git a/src/Bundle/ChillPersonBundle/Service/DocGenerator/PersonContext.php b/src/Bundle/ChillPersonBundle/Service/DocGenerator/PersonContext.php index 1fdfd23d9..9d7f1cdd5 100644 --- a/src/Bundle/ChillPersonBundle/Service/DocGenerator/PersonContext.php +++ b/src/Bundle/ChillPersonBundle/Service/DocGenerator/PersonContext.php @@ -26,14 +26,22 @@ use Chill\MainBundle\Security\Authorization\AuthorizationHelper; use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface; use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; +use Chill\PersonBundle\Entity\Person\PersonResource; use Chill\PersonBundle\Entity\Person; +use Chill\PersonBundle\Entity\Person\ResidentialAddress; use Chill\PersonBundle\Repository\PersonRepository; +use Chill\PersonBundle\Repository\ResidentialAddressRepository; +use Chill\ThirdPartyBundle\Entity\ThirdParty; +use Chill\ThirdPartyBundle\Templating\Entity\ThirdPartyRender; +use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository; use DateTime; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; use LogicException; +use Service\DocGenerator\PersonContextTest; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; +use Symfony\Component\Form\Extension\Core\Type\CheckboxType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Security\Core\Security; @@ -43,6 +51,9 @@ use Symfony\Contracts\Translation\TranslatorInterface; use function array_key_exists; use function count; +/** + * @see PersonContextTest + */ final class PersonContext implements PersonContextInterface { private AuthorizationHelperInterface $authorizationHelper; @@ -67,6 +78,12 @@ final class PersonContext implements PersonContextInterface private TranslatorInterface $translator; + private ThirdPartyRender $thirdPartyRender; + + private ThirdPartyRepository $thirdPartyRepository; + + private ResidentialAddressRepository $residentialAddressRepository; + public function __construct( AuthorizationHelperInterface $authorizationHelper, BaseContextData $baseContextData, @@ -78,7 +95,10 @@ final class PersonContext implements PersonContextInterface ScopeRepositoryInterface $scopeRepository, Security $security, TranslatorInterface $translator, - TranslatableStringHelperInterface $translatableStringHelper + TranslatableStringHelperInterface $translatableStringHelper, + ThirdPartyRender $thirdPartyRender, + ThirdPartyRepository $thirdPartyRepository, + ResidentialAddressRepository $residentialAddressRepository ) { $this->authorizationHelper = $authorizationHelper; $this->centerResolverManager = $centerResolverManager; @@ -91,6 +111,9 @@ final class PersonContext implements PersonContextInterface $this->showScopes = $parameterBag->get('chill_main')['acl']['form_show_scopes']; $this->translator = $translator; $this->translatableStringHelper = $translatableStringHelper; + $this->thirdPartyRender = $thirdPartyRender; + $this->thirdPartyRepository = $thirdPartyRepository; + $this->residentialAddressRepository = $residentialAddressRepository; } public function adminFormReverseTransform(array $data): array @@ -110,11 +133,12 @@ final class PersonContext implements PersonContextInterface $r = [ 'mainPerson' => $data['mainPerson'] ?? false, 'mainPersonLabel' => $data['mainPersonLabel'] ?? $this->translator->trans('docgen.Main person'), + 'thirdParty' => $data['thirdParty'] ?? false, + 'thirdPartyLabel' => $data['thirdPartyLabel'] ?? $this->translator->trans('Third party'), ]; if (array_key_exists('category', $data)) { - $r['category'] = array_key_exists('category', $data) ? - $this->documentCategoryRepository->find($data['category']) : null; + $r['category'] = $this->documentCategoryRepository->find($data['category']); } return $r; @@ -131,6 +155,14 @@ final class PersonContext implements PersonContextInterface ->setParameter('docClass', PersonDocument::class), 'choice_label' => fn ($entity = null) => $entity ? $this->translatableStringHelper->localize($entity->getName()) : '', 'required' => true, + ]) + ->add('thirdParty', CheckboxType::class, [ + 'required' => false, + 'label' => 'docgen.Ask for thirdParty', + ]) + ->add('thirdPartyLabel', TextType::class, [ + 'label' => 'docgen.thirdParty label', + 'required' => true, ]); } @@ -139,12 +171,47 @@ final class PersonContext implements PersonContextInterface */ public function buildPublicForm(FormBuilderInterface $builder, DocGeneratorTemplate $template, $entity): void { + $options = $template->getOptions(); + $builder->add('title', TextType::class, [ 'required' => true, 'label' => 'docgen.Document title', 'data' => $this->translatableStringHelper->localize($template->getName()), ]); + $thirdParties = [...array_values( + array_filter( + array_map( + fn (ResidentialAddress $r): ?ThirdParty => $r->getHostThirdParty(), + $this + ->residentialAddressRepository + ->findCurrentResidentialAddressByPerson($entity) + ) + ) + ), ...array_values( + array_filter( + array_map( + fn (PersonResource $r): ?ThirdParty => $r->getThirdParty(), + $entity->getResources()->filter( + static fn (PersonResource $r): bool => null !== $r->getThirdParty() + )->toArray() + ) + ) + )]; + + if ($options['thirdParty'] ?? false) { + $builder->add('thirdParty', EntityType::class, [ + 'class' => ThirdParty::class, + 'choices' => $thirdParties, + 'choice_label' => fn (ThirdParty $p) => $this->thirdPartyRender->renderString($p, []), + 'multiple' => false, + 'required' => false, + 'expanded' => true, + 'label' => $options['thirdPartyLabel'], + 'placeholder' => $this->translator->trans('Any third party selected'), + ]); + } + if ($this->isScopeNecessary($entity)) { $builder->add('scope', ScopePickerType::class, [ 'center' => $this->centerResolverManager->resolveCenters($entity), @@ -156,10 +223,6 @@ final class PersonContext implements PersonContextInterface public function getData(DocGeneratorTemplate $template, $entity, array $contextGenerationData = []): array { - if (!$entity instanceof Person) { - throw new UnexpectedTypeException($entity, Person::class); - } - $data = []; $data = array_merge($data, $this->baseContextData->getData($contextGenerationData['creator'] ?? null)); $data['person'] = $this->normalizer->normalize($entity, 'docgen', [ @@ -170,6 +233,13 @@ final class PersonContext implements PersonContextInterface 'docgen:person:with-budget' => true, ]); + if ($template->getOptions()['thirdParty']) { + $data['thirdParty'] = $this->normalizer->normalize($contextGenerationData['thirdParty'], 'docgen', [ + 'docgen:expects' => ThirdParty::class, + 'groups' => 'docgen:read' + ]); + } + return $data; } @@ -223,6 +293,7 @@ final class PersonContext implements PersonContextInterface return [ 'title' => $data['title'] ?? '', 'scope_id' => $scope instanceof Scope ? $scope->getId() : null, + 'thirdParty' => ($data['thirdParty'] ?? null)?->getId(), ]; } @@ -242,6 +313,7 @@ final class PersonContext implements PersonContextInterface return [ 'title' => $data['title'] ?? '', 'scope' => $scope, + 'thirdParty' => null !== ($id = ($data['thirdParty'] ?? null)) ? $this->thirdPartyRepository->find($id) : null, ]; } diff --git a/src/Bundle/ChillPersonBundle/Service/DocGenerator/PersonContextInterface.php b/src/Bundle/ChillPersonBundle/Service/DocGenerator/PersonContextInterface.php index 6de8c1c50..53e241292 100644 --- a/src/Bundle/ChillPersonBundle/Service/DocGenerator/PersonContextInterface.php +++ b/src/Bundle/ChillPersonBundle/Service/DocGenerator/PersonContextInterface.php @@ -19,7 +19,8 @@ use Chill\PersonBundle\Entity\Person; use Symfony\Component\Form\FormBuilderInterface; /** - * @template-extends DocGeneratorContextWithPublicFormInterface + * @template-extends DocGeneratorContextWithPublicFormInterface + * @template-extends DocGeneratorContextWithAdminFormInterface */ interface PersonContextInterface extends DocGeneratorContextWithAdminFormInterface, DocGeneratorContextWithPublicFormInterface { diff --git a/src/Bundle/ChillPersonBundle/Tests/Service/DocGenerator/AccompanyingPeriodContextTest.php b/src/Bundle/ChillPersonBundle/Tests/Service/DocGenerator/AccompanyingPeriodContextTest.php new file mode 100644 index 000000000..f9f888999 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Service/DocGenerator/AccompanyingPeriodContextTest.php @@ -0,0 +1,291 @@ +baseContextData = self::$container->get(BaseContextData::class); + $this->documentCategoryRepository = self::$container->get(DocumentCategoryRepository::class); + $this->em = self::$container->get(EntityManagerInterface::class); + $this->normalizer = self::$container->get(NormalizerInterface::class); + $this->personRender = self::$container->get(PersonRenderInterface::class); + $this->personRepository = self::$container->get(PersonRepository::class); + $this->translatableStringHelper = self::$container->get(TranslatableStringHelperInterface::class); + $this->translator = self::$container->get(TranslatorInterface::class); + $this->thirdPartyRender = self::$container->get(ThirdPartyRender::class); + $this->thirdPartyRepository = self::$container->get(ThirdPartyRepository::class); + } + + private function buildContext(): AccompanyingPeriodContext + { + return new AccompanyingPeriodContext( + $this->documentCategoryRepository, + $this->normalizer, + $this->translatableStringHelper, + $this->em, + $this->personRender, + $this->personRepository, + $this->translator, + $this->baseContextData, + $this->thirdPartyRender, + $this->thirdPartyRepository, + ); + } + + /** + * This test run the methods executed when a document is generated: + * + * - normalized data from the form in a way that they are stored in message queue; + * - denormalize the data from the message queue, + * - and get the data, as they will be transmitted to the GeneratorDriver + * + * @param array $options the options, as they are stored in the DocGeneratorTemplate (the admin form data) + * @param AccompanyingPeriod $entity The entity from which the data will be extracted + * @param array $data The data, from the public form + * @param array $expectedNormalized, how the normalized data are expected (allow to check that this data will be compliant with the storage in messenger queue) + * @param callable $assertionsOnData some test that will be executed on the normalized data + * @dataProvider provideNormalizedData + */ + public function testContextGenerationDataNormalizeDenormalizeGetData( + array $options, + AccompanyingPeriod $entity, + array $data, + array $expectedNormalized, + callable $assertionsOnData + ): void { + $context = $this->buildContext(); + $template = new DocGeneratorTemplate(); + $template->setName(["fr" =>"test"])->setContext(AccompanyingPeriodContext::class) + ->setDescription("description")->setActive(true) + ->setOptions($options); + + $normalized = $context->contextGenerationDataNormalize($template, $entity, $data); + + self::assertEquals($expectedNormalized, $normalized); + + $denormalized = $context->contextGenerationDataDenormalize($template, $entity, $normalized); + + $data = $context->getData($template, $entity, $denormalized); + + call_user_func($assertionsOnData, $data); + } + + public function provideNormalizedData(): iterable + { + self::bootKernel(); + $em = self::$container->get(EntityManagerInterface::class); + + $thirdParty = $em->createQuery("SELECT t FROM " . ThirdParty::class . " t") + ->setMaxResults(1) + ->getSingleResult(); + + if (null === $thirdParty) { + throw new \RuntimeException("No thirdparty in database"); + } + + $period = $em->createQuery("SELECT a FROM " . AccompanyingPeriod::class . " a WHERE a.step = 'CONFIRMED'") + ->setMaxResults(1) + ->getSingleResult(); + + if (null === $period) { + throw new \RuntimeException("No confirmed period in database"); + } + + $person = $em->createQuery("SELECT p FROM " . Person::class . " p") + ->setMaxResults(1) + ->getSingleResult(); + + if (null === $person) { + throw new \RuntimeException("No confirmed period in database"); + } + + yield [ + // test with only thirdParty + [ + 'mainPerson' => false, + 'mainPersonLabel' => 'person', + 'person1' => false, + 'person1Label' => 'person2', + 'person2' => false, + 'person2Label' => 'person2', + 'thirdParty' => true, + 'thirdPartyLabel' => '3party' + ], + $period, + [ + 'thirdParty' => $thirdParty + ], + [ + 'thirdParty' => $thirdParty->getId(), + 'mainPerson' => null, + 'person1' => null, + 'person2' => null, + ], + function (array $data) use ($thirdParty, $period) { + self::assertArrayHasKey('thirdParty', $data); + self::assertEquals($thirdParty->getId(), $data['thirdParty']['id']); + + self::assertArrayHasKey('course', $data); + self::assertEquals($period->getId(), $data['course']['id']); + }, + ]; + + yield [ + // test with only mainPerson + [ + 'mainPerson' => true, + 'mainPersonLabel' => 'person', + 'person1' => false, + 'person1Label' => 'person2', + 'person2' => false, + 'person2Label' => 'person2', + 'thirdParty' => false, + 'thirdPartyLabel' => '3party' + ], + $period, + [ + 'mainPerson' => $person, + ], + [ + 'thirdParty' => null, + 'mainPerson' => $person->getId(), + 'person1' => null, + 'person2' => null, + ], + function (array $data) use ($person, $period) { + self::assertArrayHasKey('mainPerson', $data); + self::assertEquals($person->getId(), $data['mainPerson']['id']); + + self::assertArrayHasKey('course', $data); + self::assertEquals($period->getId(), $data['course']['id']); + }, + ]; + + yield [ + // test with every options activated + [ + 'mainPerson' => true, + 'mainPersonLabel' => 'person', + 'person1' => true, + 'person1Label' => 'person2', + 'person2' => true, + 'person2Label' => 'person2', + 'thirdParty' => true, + 'thirdPartyLabel' => '3party' + ], + $period, + [ + 'mainPerson' => $person, + 'person1' => $person, + 'person2' => $person, + 'thirdParty' => $thirdParty, + ], + [ + 'thirdParty' => $thirdParty->getId(), + 'mainPerson' => $person->getId(), + 'person1' => $person->getId(), + 'person2' => $person->getId(), + ], + function (array $data) use ($person, $thirdParty, $period) { + self::assertArrayHasKey('mainPerson', $data); + self::assertEquals($person->getId(), $data['mainPerson']['id']); + + self::assertArrayHasKey('person1', $data); + self::assertEquals($person->getId(), $data['person1']['id']); + + self::assertArrayHasKey('person2', $data); + self::assertEquals($person->getId(), $data['person2']['id']); + + self::assertArrayHasKey('thirdParty', $data); + self::assertEquals($thirdParty->getId(), $data['thirdParty']['id']); + + self::assertArrayHasKey('course', $data); + self::assertEquals($period->getId(), $data['course']['id']); + }, + ]; + + yield [ + // test with any option activated + [ + 'mainPerson' => false, + 'mainPersonLabel' => 'person', + 'person1' => false, + 'person1Label' => 'person2', + 'person2' => false, + 'person2Label' => 'person2', + 'thirdParty' => false, + 'thirdPartyLabel' => '3party' + ], + $period, + [ + 'mainPerson' => null, + 'person1' => null, + 'person2' => null, + 'thirdParty' => null, + ], + [ + 'thirdParty' => null, + 'mainPerson' => null, + 'person1' => null, + 'person2' => null, + ], + function (array $data) use ($period) { + self::assertArrayHasKey('course', $data); + self::assertEquals($period->getId(), $data['course']['id']); + }, + ]; + } +} diff --git a/src/Bundle/ChillPersonBundle/Tests/Service/DocGenerator/PersonContextTest.php b/src/Bundle/ChillPersonBundle/Tests/Service/DocGenerator/PersonContextTest.php index d0138dc30..71fce8c92 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Service/DocGenerator/PersonContextTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Service/DocGenerator/PersonContextTest.php @@ -18,20 +18,30 @@ use Chill\DocStoreBundle\Entity\PersonDocument; use Chill\DocStoreBundle\Entity\StoredObject; use Chill\DocStoreBundle\Repository\DocumentCategoryRepository; use Chill\DocStoreBundle\Security\Authorization\PersonDocumentVoter; +use Chill\MainBundle\Entity\Address; use Chill\MainBundle\Entity\Center; +use Chill\MainBundle\Entity\PostalCode; use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Form\Type\ScopePickerType; +use Chill\MainBundle\Repository\ScopeRepositoryInterface; use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface; use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; +use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\Person; +use Chill\PersonBundle\Repository\ResidentialAddressRepository; +use Chill\PersonBundle\Service\DocGenerator\AccompanyingPeriodContext; use Chill\PersonBundle\Service\DocGenerator\PersonContext; +use Chill\ThirdPartyBundle\Entity\ThirdParty; +use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository; +use Chill\ThirdPartyBundle\Templating\Entity\ThirdPartyRender; use Doctrine\ORM\EntityManagerInterface; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Prophecy\Exception\Prediction\FailedPredictionException; use Prophecy\PhpUnit\ProphecyTrait; +use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\Form\Extension\Core\Type\TextType; @@ -46,10 +56,142 @@ use function count; * @internal * @coversNothing */ -final class PersonContextTest extends TestCase +final class PersonContextTest extends KernelTestCase { use ProphecyTrait; + /** + * This test run the methods executed when a document is generated: + * + * - normalized data from the form in a way that they are stored in message queue; + * - denormalize the data from the message queue, + * - and get the data, as they will be transmitted to the GeneratorDriver + * + * @param array $options the options, as they are stored in the DocGeneratorTemplate (the admin form data) + * @param Person $entity The entity from which the data will be extracted + * @param array $data The data, from the public form + * @param array $expectedNormalized, how the normalized data are expected (allow to check that this data will be compliant with the storage in messenger queue) + * @param callable $assertionsOnData some test that will be executed on the normalized data + * @dataProvider provideNormalizedData + */ + public function testContextGenerationDataNormalizeDenormalizeGetData( + array $options, + Person $entity, + array $data, + array $expectedNormalized, + callable $assertionsOnData + ): void { + // we boot kernel only for this test + self::bootKernel(); + + // we create a PersonContext with the minimal dependency injection needed (relying on + // prophecy for other dependencies) + $context = $this->buildPersonContext( + null, + self::$container->get(BaseContextData::class), + self::$container->get(CenterResolverManagerInterface::class), + self::$container->get(DocumentCategoryRepository::class), + self::$container->get(EntityManagerInterface::class), + self::$container->get(NormalizerInterface::class), + (new ParameterBag(['chill_main' => ['acl' => ['form_show_scopes' => false]]])), + null, + self::$container->get(Security::class), + null, + null, + null, + self::$container->get(ThirdPartyRepository::class) + ); + $template = new DocGeneratorTemplate(); + $template->setName(["fr" =>"test"])->setContext(AccompanyingPeriodContext::class) + ->setDescription("description")->setActive(true) + ->setOptions($options); + + $normalized = $context->contextGenerationDataNormalize($template, $entity, $data); + + self::assertEquals($expectedNormalized, $normalized); + + $denormalized = $context->contextGenerationDataDenormalize($template, $entity, $normalized); + + $data = $context->getData($template, $entity, $denormalized); + + call_user_func($assertionsOnData, $data); + } + + public function provideNormalizedData(): iterable + { + self::bootKernel(); + $em = self::$container->get(EntityManagerInterface::class); + + $thirdParty = $em->createQuery("SELECT t FROM " . ThirdParty::class . " t") + ->setMaxResults(1) + ->getSingleResult(); + + if (null === $thirdParty) { + throw new \RuntimeException("No thirdparty in database"); + } + + $person = $em->createQuery("SELECT p FROM " . Person::class . " p") + ->setMaxResults(1) + ->getSingleResult(); + + if (null === $person) { + throw new \RuntimeException("No confirmed period in database"); + } + + $category = self::$container->get(DocumentCategoryRepository::class) + ->findAll()[0]; + + if (null === $category) { + throw new \RuntimeException("no document category in database"); + } + + yield [ + [ + 'thirdParty' => true, + 'thirdPartyLabel' => '3party', + 'category' => $category, + ], + $person, + [ + 'title' => 'test', + 'thirdParty' => $thirdParty, + ], + [ + 'thirdParty' => $thirdParty->getId(), + 'title' => 'test', + 'scope_id' => null, + ], + function ($data) use ($person, $thirdParty) { + self::assertArrayHasKey('person', $data); + self::assertEquals($person->getId(), $data['person']['id']); + + self::assertArrayHasKey('thirdParty', $data); + self::assertEquals($thirdParty->getId(), $data['thirdParty']['id']); + } + ]; + + yield [ + [ + 'thirdParty' => false, + 'thirdPartyLabel' => '3party', + 'category' => $category, + ], + $person, + [ + 'title' => 'test', + ], + [ + 'title' => 'test', + 'scope_id' => null, + 'thirdParty' => null, + ], + function ($data) use ($person, $thirdParty) { + self::assertArrayHasKey('person', $data); + self::assertEquals($person->getId(), $data['person']['id']); + } + ]; + } + /** * Test that the build person context works in the case when 'form_show_scope' is false. */ @@ -208,9 +350,13 @@ final class PersonContextTest extends TestCase ?EntityManagerInterface $em = null, ?NormalizerInterface $normalizer = null, ?ParameterBagInterface $parameterBag = null, + ?ScopeRepositoryInterface $scopeRepository = null, ?Security $security = null, ?TranslatorInterface $translator = null, - ?TranslatableStringHelperInterface $translatableStringHelper = null + ?TranslatableStringHelperInterface $translatableStringHelper = null, + ?ThirdPartyRender $thirdPartyRender = null, + ?ThirdPartyRepository $thirdPartyRepository = null, + ?ResidentialAddressRepository $residentialAddressRepository = null ): PersonContext { if (null === $authorizationHelper) { $authorizationHelper = $this->prophesize(AuthorizationHelperInterface::class)->reveal(); @@ -250,6 +396,11 @@ final class PersonContextTest extends TestCase $parameterBag = new ParameterBag(['chill_main' => ['acl' => ['form_show_scopes' => true]]]); } + if (null === $scopeRepository) { + $scopeRepository = $this->prophesize(ScopeRepositoryInterface::class); + $scopeRepository = $scopeRepository->reveal(); + } + if (null === $security) { $security = $this->prophesize(Security::class); $security->getUser()->willReturn(new User()); @@ -267,6 +418,28 @@ final class PersonContextTest extends TestCase $translatableStringHelper = $translatableStringHelper->reveal(); } + if (null === $thirdPartyRender) { + $thirdPartyRender = $this->prophesize(ThirdPartyRender::class); + $thirdPartyRender = $thirdPartyRender->reveal(); + } + + if (null === $thirdPartyRepository) { + $thirdPartyRepository = $this->prophesize(ThirdPartyRepository::class); + $thirdPartyRepository = $thirdPartyRepository->reveal(); + } + + if (null === $residentialAddressRepository) { + $residentialAddressRepository = $this->prophesize(ResidentialAddressRepository::class); + $residentialAddressRepository->findCurrentResidentialAddressByPerson(Argument::type(Person::class), Argument::any()) + ->willReturn([ + (new Person\ResidentialAddress()) + ->setAddress((new Address()) + ->setStreet('test street') + ->setPostcode(new PostalCode())) + ]); + $residentialAddressRepository = $residentialAddressRepository->reveal(); + } + return new PersonContext( $authorizationHelper, $baseContextData, @@ -275,9 +448,13 @@ final class PersonContextTest extends TestCase $em, $normalizer, $parameterBag, + $scopeRepository, $security, $translator, - $translatableStringHelper + $translatableStringHelper, + $thirdPartyRender, + $thirdPartyRepository, + $residentialAddressRepository ); } } diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index 9b30e3a0b..6205fabae 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -927,10 +927,10 @@ docgen: Accompanying period work: "Action d'accompagnement" Accompanying period work context: "Evaluation des actions d'accompagnement" Main person: Usager principal - person 1: Premièr usager + person 1: Premier usager person 2: Second usager Ask for main person: Demander à l'utilisateur de préciser l'usager principal - Ask for person 1: Demander à l'utilisateur de préciser le premièr usager + Ask for person 1: Demander à l'utilisateur de préciser le premier usager Ask for person 2: Demander à l'utilisateur de préciser le second usager A basic context for accompanying period: Contexte pour les parcours A context for accompanying period work: Contexte pour les actions d'accompagnement diff --git a/src/Bundle/ChillThirdPartyBundle/Repository/ThirdPartyRepository.php b/src/Bundle/ChillThirdPartyBundle/Repository/ThirdPartyRepository.php index 76e15ef17..f9893b9d9 100644 --- a/src/Bundle/ChillThirdPartyBundle/Repository/ThirdPartyRepository.php +++ b/src/Bundle/ChillThirdPartyBundle/Repository/ThirdPartyRepository.php @@ -21,7 +21,7 @@ use DomainException; use function array_key_exists; -final class ThirdPartyRepository implements ObjectRepository +class ThirdPartyRepository implements ObjectRepository { private EntityRepository $repository; diff --git a/src/Bundle/ChillThirdPartyBundle/translations/messages.fr.yml b/src/Bundle/ChillThirdPartyBundle/translations/messages.fr.yml index 94a10177b..f62a5beff 100644 --- a/src/Bundle/ChillThirdPartyBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillThirdPartyBundle/translations/messages.fr.yml @@ -75,6 +75,7 @@ No email given: Aucune adresse courriel renseignée The party is visible in those centers: Le tiers est visible dans ces centres The party is not visible in any center: Le tiers n'est associé à aucun centre No third parties: Aucun tiers +Any third party selected: Aucun tiers sélectionné Thirdparty handling: Tiers traitant Thirdparty workers: Tiers intervenants @@ -112,6 +113,8 @@ crud: docgen: A context for person with a third party (for sending mail): Un contexte d'une personne avec un tiers (pour envoyer un courrier à ce tiers, par exemple) Person with third party: Personne avec choix d'un tiers + Ask for thirdParty: Demander à l'utilisateur de préciser un tiers + thirdParty label: Libellé du tiers # exports export: