mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-10-31 01:08:26 +00:00 
			
		
		
		
	Compare commits
	
		
			237 Commits
		
	
	
		
			58-birthda
			...
			user_filte
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 2721872da8 | |||
| ef1eb2031e | |||
| 197d69ef4a | |||
| 9423f4d055 | |||
| 99d6e9e6b8 | |||
| 8929f4b8a3 | |||
| 43b7139488 | |||
| d3251075e9 | |||
| 93a598b549 | |||
| 9b6e6ec20f | |||
| 77d4b13c1b | |||
| 2861945a52 | |||
| 5b42b85b50 | |||
| e40b1b9853 | |||
| c19232de35 | |||
| c95dc23c51 | |||
| 0361743ae0 | |||
| af4e7f1226 | |||
| ff1629cbb7 | |||
| 779eb812b0 | |||
| a990591e0c | |||
| 52d51264ba | |||
| 4e934653be | |||
| 1ee0e8e350 | |||
| 4da7040a49 | |||
| a34b5f8588 | |||
| 0d626fb345 | |||
| 25d4b6acbb | |||
| 7f9738975c | |||
| a56370d851 | |||
| 3e63b4abf3 | |||
| dd344aed52 | |||
| 1485d1ce7a | |||
| a7dbdc2b9d | |||
| b3d993165d | |||
| 9ccc57bbcb | |||
| cc0e832cc9 | |||
| c8b62d990a | |||
| b7df62d4f5 | |||
| 5a395b160f | |||
| 393e59e22b | |||
| 4a5ac170ba | |||
| c019fffbe7 | |||
| 31745bc252 | |||
| 56940d830c | |||
| 347eda05df | |||
| 90e8687799 | |||
| da50fbc1fb | |||
| 5bbc50976e | |||
| 01dee54fab | |||
| abe020f116 | |||
| 4632c18d93 | |||
| 7a1feaa8cb | |||
| 687ff63ce7 | |||
| a7c3089736 | |||
| 90be68002a | |||
| a93051d157 | |||
| f19b939bd4 | |||
| c0ae2f8ed9 | |||
| cd7a80b680 | |||
| 9f0fdb031a | |||
| 0e9597bf77 | |||
| 9978b6a6e4 | |||
| 0e5f1b4ab9 | |||
| f7c11d3567 | |||
| 51544cfc48 | |||
| 659dff3d2c | |||
| 27f797d736 | |||
| 471898e6d8 | |||
| 146103e87c | |||
| 45724100d4 | |||
| 9d2dfbe610 | |||
| 70e6aee3c5 | |||
| 6c16967cdc | |||
| 4359c2dddc | |||
| 5a102d4989 | |||
| 9073f118db | |||
| 21f11fb034 | |||
| 50de389bc7 | |||
| 960acb8c0a | |||
| c52ba06ea0 | |||
| 3fb97c3945 | |||
| 88a544fabe | |||
| bf2a4bafd8 | |||
| fe936ac0f2 | |||
| 398b633863 | |||
| 8fabfdd5c0 | |||
| 8a91be4ef3 | |||
| 3b9fae3b49 | |||
| 7349be94c8 | |||
| d815b44280 | |||
| 56957250ba | |||
| a6b451df98 | |||
| 3879e5cd9b | |||
| cb4de1f3d2 | |||
| 21f0f70350 | |||
| fadc007bfe | |||
| 1b664d0be2 | |||
| e0c21e46ae | |||
| 270e068ace | |||
| c683123eca | |||
| 5495b1cb44 | |||
| 24049b9dfc | |||
| 34a333f6a3 | |||
| c4dd46a03c | |||
| 29140d9374 | |||
| 5cbdea29e9 | |||
| 909d2dfb60 | |||
| 1f1ebb6adb | |||
| 4456fb3749 | |||
| 1d7279c022 | |||
| 727e9d0f74 | |||
| c2a734b30b | |||
| eb41293c96 | |||
| 68c850026b | |||
| 37e92ca58d | |||
| 593adadef1 | |||
| f5b71a0c41 | |||
| f42e1723ab | |||
| 2178833da7 | |||
| 23ee29ab0d | |||
| 199223293e | |||
| 520d5ab6d4 | |||
| c73beef3af | |||
| 73b95732db | |||
| 88f48d474f | |||
| 0fd36a3196 | |||
| aa6479fbf9 | |||
| 05822e7e4a | |||
| b4614974c0 | |||
| c3ac382711 | |||
| ad82685c02 | |||
| 7e8dbbe873 | |||
| 12fdfd81c4 | |||
| cf576dca7b | |||
| 7fab411b96 | |||
| 88d363fc0c | |||
| a28740c46c | |||
| 1a03718014 | |||
| 1e8fec5cbd | |||
| fb1b28407a | |||
| cc30c81fd7 | |||
| 938027cc1e | |||
| db14221729 | |||
| f10c50231f | |||
| 73bc95306e | |||
| 933e9f75b3 | |||
| 3adf3625dc | |||
| ea77adc640 | |||
| d5ee158caa | |||
| c8bab1218f | |||
| 02afcb30d4 | |||
| cb0a6bbd21 | |||
| fb0afc7e0a | |||
| d1e1b1c4ce | |||
| 2aeb72811a | |||
| 7eb4fb4e56 | |||
| 5dc1cbce48 | |||
| 59e1e02b92 | |||
| 5196d26a3e | |||
| 77f8cf0e1a | |||
| 1b9fea04ce | |||
| 78b19efe86 | |||
| 07ff425bfc | |||
| c77dd011b8 | |||
| 9c109d2efd | |||
| 80dfa092db | |||
| 9a3fcf081e | |||
| ef04a04056 | |||
| ba55fa349b | |||
| eea5cedc5f | |||
| c07e26785e | |||
| 4155af6686 | |||
| 9eb9a9a214 | |||
| 47a3e30ec5 | |||
| 20489813f0 | |||
| 4489098add | |||
| cb718a80de | |||
| ed556d9ee8 | |||
| 2b57807565 | |||
| da36c59616 | |||
| 40ddd1f1ee | |||
| e9fdabf931 | |||
| 40af1e64ac | |||
| c245ffe559 | |||
| bd074ebade | |||
| d09e5d33db | |||
| 101cca8662 | |||
| 90a5a735aa | |||
| eb107f5a15 | |||
| a3d3588b75 | |||
| 08874d734e | |||
| bd5dab2215 | |||
| ff03299f80 | |||
| 5749660760 | |||
| b679dbe26c | |||
| 6c3fa5cb98 | |||
|  | 1b0569c974 | ||
| 72f5b0b275 | |||
| 60aeb57c45 | |||
| 6bdd1f31d3 | |||
| ff3dab0934 | |||
| 2b5d007fda | |||
|  | 9593cfde36 | ||
|  | ad1b28ff11 | ||
|  | 6232dabae5 | ||
|  | ef59e6dc1c | ||
| e550817ded | |||
|  | 303666b30d | ||
|  | d0867f9aa3 | ||
|  | db33fab097 | ||
|  | 91a19b9e99 | ||
|  | c6658aa2f3 | ||
| 8dbe2d6ec2 | |||
| afcd6e0605 | |||
| 664bf743f9 | |||
| 53aa887da5 | |||
| ef6a5e0b6b | |||
| 5931b2f709 | |||
| 9d1e54d3a0 | |||
| a8945f5701 | |||
|  | 1a66a08142 | ||
|  | 71e8e2baee | ||
|  | 0a2f41c8a0 | ||
|  | 67b32341d1 | ||
|  | cb37e8c006 | ||
| ba43b6b025 | |||
|  | 3576f7f14f | ||
|  | d8d517017d | ||
|  | afb25276ee | ||
|  | e850f67b00 | ||
|  | f4a7145627 | ||
|  | 6b5423ded3 | ||
|  | eb765585b2 | ||
|  | 1a759cabe4 | ||
|  | 457d71b4f3 | ||
|  | ecb8ef0146 | 
							
								
								
									
										6
									
								
								.changes/header.tpl.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.changes/header.tpl.md
									
									
									
									
									
										Normal file
									
								
							| @@ -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). | ||||
							
								
								
									
										0
									
								
								.changes/unreleased/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								.changes/unreleased/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										5
									
								
								.changes/unreleased/DX-20230623-122408.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.changes/unreleased/DX-20230623-122408.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| kind: DX | ||||
| body: '[FilterOrderHelper] add entity choice and singleCheckbox' | ||||
| time: 2023-06-23T12:24:08.133491895+02:00 | ||||
| custom: | ||||
|   Issue: "" | ||||
							
								
								
									
										5
									
								
								.changes/unreleased/Feature-20230623-122530.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.changes/unreleased/Feature-20230623-122530.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| kind: Feature | ||||
| body: '[activity list] add filtering for activities list' | ||||
| time: 2023-06-23T12:25:30.49643551+02:00 | ||||
| custom: | ||||
|   Issue: "" | ||||
							
								
								
									
										6
									
								
								.changes/unreleased/Feature-20230623-122702.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.changes/unreleased/Feature-20230623-122702.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| kind: Feature | ||||
| body: '[activity list] in person context, show also the activities from the accompanying | ||||
|   periods where the person participates' | ||||
| time: 2023-06-23T12:27:02.159041095+02:00 | ||||
| custom: | ||||
|   Issue: "" | ||||
							
								
								
									
										5
									
								
								.changes/unreleased/Feature-20230623-124438.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.changes/unreleased/Feature-20230623-124438.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| kind: Feature | ||||
| body: '[activity list] add pagination to the list of activities' | ||||
| time: 2023-06-23T12:44:38.879098862+02:00 | ||||
| custom: | ||||
|   Issue: "" | ||||
							
								
								
									
										5
									
								
								.changes/unreleased/Feature-20230705-140336.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.changes/unreleased/Feature-20230705-140336.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| kind: Feature | ||||
| body: Allow filtering on the basis of a user within general tasks list | ||||
| time: 2023-07-05T14:03:36.664880092+02:00 | ||||
| custom: | ||||
|   Issue: "" | ||||
							
								
								
									
										677
									
								
								.changes/v2.0.0.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										677
									
								
								.changes/v2.0.0.md
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
|  | ||||
| <!-- | ||||
|  | ||||
| Coming soon... | ||||
|  | ||||
| DO NOT ADD unreleased items here. Add them under "Unreleased" title | ||||
|  | ||||
| ### Test release yyyy-mm-dd | ||||
|  | ||||
| --> | ||||
|  | ||||
| ## Stable releases | ||||
|  | ||||
| No stable releases for v2+ | ||||
|  | ||||
							
								
								
									
										17
									
								
								.changes/v2.1.0.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								.changes/v2.1.0.md
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										12
									
								
								.changes/v2.2.0.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								.changes/v2.2.0.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| ## v2.2.0 - 2023-06-18 | ||||
| ### Feature | ||||
| * When navigating from a workflow regarding to an evaluation's document to an accompanying course, scroll directly to the document, and blink to highlight this document | ||||
| * Add notification to accompanying period work and work's evaluation's documents | ||||
| * ([#113](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/113))[Export] Filter accompanying period by step at date: allow to pick multiple steps | ||||
| * ([#113](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/113))[export] add a filter on accompanying period: filter by step between two dates | ||||
| ### Fixed | ||||
| * use the correct annotation for the association between PersonCurrentCenter and Person | ||||
| * ([#58](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/58))Fix birthdate timezone in PersonRenderBox | ||||
| * ([#55](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/55))Fix the notification counter | ||||
| ### DX | ||||
| * DQL function OVERLAPSI: simplify expression in postgresql | ||||
							
								
								
									
										3
									
								
								.changes/v2.2.1.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.changes/v2.2.1.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| ## v2.2.1 - 2023-06-19 | ||||
| ### Fixed | ||||
| * ([#114](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/114)) [notification on document evaluation] fix entityId and return path when adding a notification on a document in an evaluation | ||||
							
								
								
									
										5
									
								
								.changes/v2.2.2.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.changes/v2.2.2.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| ## v2.2.2 - 2023-06-26 | ||||
| ### Fixed | ||||
| * [Accompanying period comments]: order comments from the most recent to the oldest, in the list | ||||
| * Api: filter social action to keep only the currently activated | ||||
| * ([#82](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/82)) Fix deletion and re-creation of filiation relationship | ||||
							
								
								
									
										42
									
								
								.changes/v2.3.0.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								.changes/v2.3.0.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| ## v2.3.0 - 2023-06-27 | ||||
| ### Feature | ||||
| * ([#110](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/110)) Edit saved exports options: the saved exports options (forms, filters, aggregators) are now editable. | ||||
| * ([#103](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/103)) Get an unified list of document in person and accompanying period context | ||||
| * [export] Set the default date of calculation of the accompanying period's list as "today" | ||||
| * Force accompanying period user history to be unique for the same period and stardate/enddate [:warning: may encounter migration issue] | ||||
|  | ||||
|   If some issue is encountered during migration, use this SQL to find the line which are in conflict, examine the problem and delete some of the concerning line | ||||
| * | ||||
|   ```sql | ||||
|   -- to see the line which are in conflict with another one | ||||
|   SELECT o.* | ||||
|   FROM chill_person_accompanying_period_user_history o | ||||
|   JOIN chill_person_accompanying_period_user_history c ON o.id < c.id AND o.accompanyingperiod_id = c.accompanyingperiod_id | ||||
|   WHERE tsrange(o.startdate, o.enddate, '[)') && tsrange(c.startdate, c.enddate, '[)') | ||||
|   ORDER BY accompanyingperiod_id; | ||||
|   -- to examine line in conflict for a given accompanyingperiod_id (given by the previous query) | ||||
|   SELECT * FROM chill_person_accompanying_period_user_history WHERE accompanyingperiod_id = IIIIDDDD order by startdate, enddate; | ||||
|   ``` | ||||
| * Rename label of filter in French: "parcours actif" => "parcours ouvert", and "filtrer les parcours ouverts" => "Filtrer les parcours dont la date d'ouverture" | ||||
|  | ||||
| ### Traduction francophone des principaux changements | ||||
|  | ||||
| * Les exports enregistrés sont éditables par l'utilisateur; | ||||
| * L'onglet "Document" dans les parcours et les dossiers d'usager affiche désormais les documents ajoutés à différents endroits. | ||||
|  | ||||
|   Pour les parcours, il s'agit de: | ||||
|  | ||||
|   - documents ajoutés directement dans le parcours; | ||||
|   - documents des échanges; | ||||
|   - documents des rendez-vous; | ||||
|   - documents des évaluations; | ||||
|   - documents directement ajoutés dans le dossier des usagers concernés par le parcours; | ||||
|  | ||||
|   Pour les usagers, il s'agit de: | ||||
|  | ||||
|   - documents des échanges; | ||||
|   - documents des parcours; | ||||
|   - documents des rendez-vous; | ||||
|   - documents des actions, des échanges, des rendez-vous, des évaluations ajoutés dans les parcours. | ||||
| * Dans la liste des parcours, la date de calcul des éléments associés est "aujourd'hui" par défaut. | ||||
| * Dans les exports, renommage des libellés des filtres: "parcours actif" => "parcours ouvert", et "filtrer les parcours ouverts" => "Filtrer les parcours dont la date d'ouverture" | ||||
							
								
								
									
										36
									
								
								.changes/v2.4.0.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								.changes/v2.4.0.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| ## v2.4.0 - 2023-07-07 | ||||
|  | ||||
| ### Feature | ||||
| * ([#113](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/113)) [export] on "filter by user working" on accompanying period, add two dates to filters intervention within a period | ||||
| * ([#113](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/113)) [export] Add an aggregator by user's job working on a course | ||||
| * ([#113](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/113)) [export] add an aggregator by user's scope working on a course | ||||
| * [export] on aggregator "user working on a course" | ||||
| * ([#113](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/113)) [export] add a center aggregator for Person | ||||
| * ([#113](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/113)) [export] add a filter on "job working on a course" | ||||
| * ([#113](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/113)) [export] Add a filter on "scope working on a course" | ||||
| * ([#121](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/121)) Create a role "See Confidential Periods", separated from the "Reassign courses" role | ||||
| * ([#124](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/124)) Sync user absence / presence through microsoft outlook / graph api. | ||||
|  | ||||
| ### Fixed | ||||
| * ([#116](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/116)) On the accompanying course page, open the action on view mode if the user does not have right to update them (i.e. if the accompanying period is closed) | ||||
| * [export] Rename label for CurrentActionFilter (on accompanying period work) to make precision between "ouvert" and "sans date de fin" | ||||
| * Force the db to have either a person_location or a address_location, and avoid to have both also internally in the entity | ||||
| * [export] set rolling date on person age aggregator | ||||
| * [export] fix list when a person locating a course is without address | ||||
| * [export] remove unused condition on course about duration participation | ||||
| * Command to subscribe on MS Graph users calendars: improve the loop to be more efficient | ||||
|  | ||||
| ### DX | ||||
| * Rolling Date: can receive a null parameter | ||||
|  | ||||
| ### Traduction francophone des principaux changements | ||||
|  | ||||
| - sur le "filtre par intervenant", ajoute deux dates pour limiter la période d'intervention; | ||||
| - ajout d'un regroupement par métier des intervenants sur un parcours; | ||||
| - ajout d'un regroupement par service des intervenants sur un parcours; | ||||
| - ajout d'un regroupement par utilisateur intervenant sur un parcours | ||||
| - ajout d'un regroupement "par centre de l'usager"; | ||||
| - ajout d'un filtre "par métier intervenant sur un parcours"; | ||||
| - ajout d'un filtre "par service intervenant sur un parcours"; | ||||
| - création d'un rôle spécifique pour voir les parcours confidentiels (et séparer de celui de la liste qui permet de ré-assigner les parcours en lot); | ||||
| - synchronisation de l'absence des utilisateurs par microsoft graph api | ||||
							
								
								
									
										37
									
								
								.changie.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								.changie.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| changesDir: .changes | ||||
| unreleasedDir: unreleased | ||||
| headerPath: header.tpl.md | ||||
| changelogPath: CHANGELOG.md | ||||
| versionExt: md | ||||
| versionFormat: '## {{.Version}} - {{.Time.Format "2006-01-02"}}' | ||||
| kindFormat: '### {{.Kind}}' | ||||
| # Note: it is possible to add a `.custom.Long` text manually into the yaml file produced by `changie new`. This will add a long description. | ||||
| changeFormat: >- | ||||
|     * {{ if not (eq .Custom.Issue "") }}([#{{ .Custom.Issue }}](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/{{ .Custom.Issue }})) {{ end }}{{.Body}} {{ if not (eq .Custom.Long "") }} | ||||
|  | ||||
|       {{ .Custom.Long }}{{ end }} | ||||
| 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_ | ||||
| @@ -34,6 +34,7 @@ variables: | ||||
| stages: | ||||
|     - Composer install | ||||
|     - Tests | ||||
|     - Deploy | ||||
|  | ||||
| build: | ||||
|     stage: Composer install | ||||
| @@ -121,3 +122,14 @@ unit_tests: | ||||
|         paths: | ||||
|             - bin | ||||
|             - tests/app/vendor/ | ||||
|  | ||||
| release: | ||||
|     stage: Deploy | ||||
|     image: registry.gitlab.com/gitlab-org/release-cli:latest | ||||
|     rules: | ||||
|         - if: $CI_COMMIT_TAG | ||||
|     script: | ||||
|         - echo "running release_job" | ||||
|     release: | ||||
|         tag_name: '$CI_COMMIT_TAG' | ||||
|         description: "./.changes/v$CI_COMMIT_TAG.md" | ||||
|   | ||||
| @@ -13,6 +13,7 @@ $finder = PhpCsFixer\Finder::create(); | ||||
|  | ||||
| $finder | ||||
|     ->in(__DIR__.'/src') | ||||
|     ->in(__DIR__.'/utils') | ||||
|     ->append([__FILE__]) | ||||
|     ->exclude(['docs/', 'tests/app']) | ||||
|     ->notPath('tests/app') | ||||
|   | ||||
							
								
								
									
										139
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										139
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -1,16 +1,140 @@ | ||||
| # 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.4.0 - 2023-07-07 | ||||
|  | ||||
| ### Feature | ||||
| * ([#113](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/113)) [export] on "filter by user working" on accompanying period, add two dates to filters intervention within a period | ||||
| * ([#113](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/113)) [export] Add an aggregator by user's job working on a course | ||||
| * ([#113](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/113)) [export] add an aggregator by user's scope working on a course | ||||
| * [export] on aggregator "user working on a course" | ||||
| * ([#113](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/113)) [export] add a center aggregator for Person | ||||
| * ([#113](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/113)) [export] add a filter on "job working on a course" | ||||
| * ([#113](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/113)) [export] Add a filter on "scope working on a course" | ||||
| * ([#121](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/121)) Create a role "See Confidential Periods", separated from the "Reassign courses" role | ||||
| * ([#124](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/124)) Sync user absence / presence through microsoft outlook / graph api. | ||||
|  | ||||
| ### Fixed | ||||
| * ([#116](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/116)) On the accompanying course page, open the action on view mode if the user does not have right to update them (i.e. if the accompanying period is closed) | ||||
| * [export] Rename label for CurrentActionFilter (on accompanying period work) to make precision between "ouvert" and "sans date de fin" | ||||
| * Force the db to have either a person_location or a address_location, and avoid to have both also internally in the entity | ||||
| * [export] set rolling date on person age aggregator | ||||
| * [export] fix list when a person locating a course is without address | ||||
| * [export] remove unused condition on course about duration participation | ||||
| * Command to subscribe on MS Graph users calendars: improve the loop to be more efficient | ||||
|  | ||||
| ### DX | ||||
| * Rolling Date: can receive a null parameter | ||||
|  | ||||
| ### Traduction francophone des principaux changements | ||||
|  | ||||
| - sur le "filtre par intervenant", ajoute deux dates pour limiter la période d'intervention; | ||||
| - ajout d'un regroupement par métier des intervenants sur un parcours; | ||||
| - ajout d'un regroupement par service des intervenants sur un parcours; | ||||
| - ajout d'un regroupement par utilisateur intervenant sur un parcours | ||||
| - ajout d'un regroupement "par centre de l'usager"; | ||||
| - ajout d'un filtre "par métier intervenant sur un parcours"; | ||||
| - ajout d'un filtre "par service intervenant sur un parcours"; | ||||
| - création d'un rôle spécifique pour voir les parcours confidentiels (et séparer de celui de la liste qui permet de ré-assigner les parcours en lot); | ||||
| - synchronisation de l'absence des utilisateurs par microsoft graph api | ||||
|  | ||||
| ## v2.3.0 - 2023-06-27 | ||||
| ### Feature | ||||
| * ([#110](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/110)) Edit saved exports options: the saved exports options (forms, filters, aggregators) are now editable. | ||||
| * ([#103](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/103)) Get an unified list of document in person and accompanying period context | ||||
| * [export] Set the default date of calculation of the accompanying period's list as "today" | ||||
| * Force accompanying period user history to be unique for the same period and stardate/enddate [:warning: may encounter migration issue] | ||||
|  | ||||
|   If some issue is encountered during migration, use this SQL to find the line which are in conflict, examine the problem and delete some of the concerning line | ||||
| * | ||||
|   ```sql | ||||
|   -- to see the line which are in conflict with another one | ||||
|   SELECT o.* | ||||
|   FROM chill_person_accompanying_period_user_history o | ||||
|   JOIN chill_person_accompanying_period_user_history c ON o.id < c.id AND o.accompanyingperiod_id = c.accompanyingperiod_id | ||||
|   WHERE tsrange(o.startdate, o.enddate, '[)') && tsrange(c.startdate, c.enddate, '[)') | ||||
|   ORDER BY accompanyingperiod_id; | ||||
|   -- to examine line in conflict for a given accompanyingperiod_id (given by the previous query) | ||||
|   SELECT * FROM chill_person_accompanying_period_user_history WHERE accompanyingperiod_id = IIIIDDDD order by startdate, enddate; | ||||
|   ``` | ||||
| * Rename label of filter in French: "parcours actif" => "parcours ouvert", and "filtrer les parcours ouverts" => "Filtrer les parcours dont la date d'ouverture" | ||||
|  | ||||
| ### Traduction francophone des principaux changements | ||||
|  | ||||
| * Les exports enregistrés sont éditables par l'utilisateur; | ||||
| * L'onglet "Document" dans les parcours et les dossiers d'usager affiche désormais les documents ajoutés à différents endroits. | ||||
|  | ||||
|   Pour les parcours, il s'agit de: | ||||
|  | ||||
|   - documents ajoutés directement dans le parcours; | ||||
|   - documents des échanges; | ||||
|   - documents des rendez-vous; | ||||
|   - documents des évaluations; | ||||
|   - documents directement ajoutés dans le dossier des usagers concernés par le parcours; | ||||
|  | ||||
|   Pour les usagers, il s'agit de: | ||||
|  | ||||
|   - documents des échanges; | ||||
|   - documents des parcours; | ||||
|   - documents des rendez-vous; | ||||
|   - documents des actions, des échanges, des rendez-vous, des évaluations ajoutés dans les parcours. | ||||
| * Dans la liste des parcours, la date de calcul des éléments associés est "aujourd'hui" par défaut. | ||||
| * Dans les exports, renommage des libellés des filtres: "parcours actif" => "parcours ouvert", et "filtrer les parcours ouverts" => "Filtrer les parcours dont la date d'ouverture" | ||||
|  | ||||
| ## v2.2.2 - 2023-06-26 | ||||
| ### Fixed | ||||
| * [Accompanying period comments]: order comments from the most recent to the oldest, in the list | ||||
| * Api: filter social action to keep only the currently activated | ||||
| * ([#82](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/82)) Fix deletion and re-creation of filiation relationship | ||||
|  | ||||
| ## v2.2.1 - 2023-06-19 | ||||
| ### Fixed | ||||
| * ([#114](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/114)) [notification on document evaluation] fix entityId and return path when adding a notification on a document in an evaluation | ||||
|  | ||||
| ## v2.2.0 - 2023-06-18 | ||||
| ### Feature | ||||
| * When navigating from a workflow regarding to an evaluation's document to an accompanying course, scroll directly to the document, and blink to highlight this document | ||||
| * Add notification to accompanying period work and work's evaluation's documents | ||||
| * ([#113](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/113))[Export] Filter accompanying period by step at date: allow to pick multiple steps | ||||
| * ([#113](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/113))[export] add a filter on accompanying period: filter by step between two dates | ||||
| ### Fixed | ||||
| * use the correct annotation for the association between PersonCurrentCenter and Person | ||||
| * ([#58](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/58))Fix birthdate timezone in PersonRenderBox | ||||
| * ([#55](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/55))Fix the notification counter | ||||
| ### DX | ||||
| * DQL function OVERLAPSI: simplify expression in postgresql | ||||
|  | ||||
| ## 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 | ||||
|  | ||||
| <!-- write down unreleased development here --> | ||||
| * [person][export] Fixed: rename the alias for `accompanying_period` to `acp` in filter associated with person | ||||
| * [activity][export] Feature: improve label for aliases in "Filter by activity type" | ||||
| * [activity][export] DX/Feature: use of an `ActivityTypeRepositoryInterface` instead of the old-style EntityRepository | ||||
| @@ -18,9 +142,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. | ||||
|   | ||||
| @@ -67,6 +67,7 @@ | ||||
|         "fakerphp/faker": "^1.13", | ||||
|         "jangregor/phpstan-prophecy": "^1.0", | ||||
|         "nelmio/alice": "^3.8", | ||||
|         "nikic/php-parser": "^4.15", | ||||
|         "phpspec/prophecy-phpunit": "^2.0", | ||||
|         "phpstan/extension-installer": "^1.2", | ||||
|         "phpstan/phpstan": "^1.9", | ||||
| @@ -103,14 +104,16 @@ | ||||
|             "Chill\\ReportBundle\\": "src/Bundle/ChillReportBundle", | ||||
|             "Chill\\TaskBundle\\": "src/Bundle/ChillTaskBundle", | ||||
|             "Chill\\ThirdPartyBundle\\": "src/Bundle/ChillThirdPartyBundle", | ||||
|             "Chill\\WopiBundle\\": "src/Bundle/ChillWopiBundle/src" | ||||
|             "Chill\\WopiBundle\\": "src/Bundle/ChillWopiBundle/src", | ||||
|             "Chill\\Utils\\Rector\\": "utils/rector/src" | ||||
|         } | ||||
|     }, | ||||
|     "autoload-dev": { | ||||
|         "psr-4": { | ||||
|             "App\\": "tests/app/src/", | ||||
|             "Chill\\DocGeneratorBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests", | ||||
|             "Chill\\WopiBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests" | ||||
|             "Chill\\WopiBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests", | ||||
|             "Chill\\Utils\\Rector\\Tests\\": "utils/rector/tests" | ||||
|         } | ||||
|     }, | ||||
|     "config": { | ||||
|   | ||||
| @@ -62,7 +62,6 @@ class BirthdateFilter implements ExportElementValidatedInterface, FilterInterfac | ||||
|     { | ||||
|         $builder->add('date_from', DateType::class, [ | ||||
|             'label' => 'Born after this date', | ||||
|             'data' => new DateTime(), | ||||
|             'attr' => ['class' => 'datepicker'], | ||||
|             'widget' => 'single_text', | ||||
|             'format' => 'dd-MM-yyyy', | ||||
| @@ -70,12 +69,15 @@ class BirthdateFilter implements ExportElementValidatedInterface, FilterInterfac | ||||
|  | ||||
|         $builder->add('date_to', DateType::class, [ | ||||
|             'label' => 'Born before this date', | ||||
|             'data' => new DateTime(), | ||||
|             'attr' => ['class' => 'datepicker'], | ||||
|             'widget' => 'single_text', | ||||
|             'format' => 'dd-MM-yyyy', | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return ['date_from' => new DateTime(), 'date_to' => new DateTime()]; | ||||
|     } | ||||
|  | ||||
|     // here, we create a simple string which will describe the action of | ||||
|     // the filter in the Response | ||||
|   | ||||
| @@ -36,6 +36,10 @@ class CountPerson implements ExportInterface | ||||
|     { | ||||
|         // this export does not add any form | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getAllowedFormattersTypes() | ||||
|     { | ||||
|   | ||||
| @@ -18,6 +18,7 @@ These are alias conventions : | ||||
| |                                         | SocialIssue::class                      | acp.socialIssues                           | acpsocialissue                         | | ||||
| |                                         | User::class                             | acp.user                                   | acpuser                                | | ||||
| |                                         | AccompanyingPeriopStepHistory::class    | acp.stepHistories                          | acpstephistories                       | | ||||
| |                                         | AccompanyingPeriodInfo::class           | not existing (using custom WITH clause)    | acpinfo                                | | ||||
| | AccompanyingPeriodWork::class           |                                         |                                            | acpw                                   | | ||||
| |                                         | AccompanyingPeriodWorkEvaluation::class | acpw.accompanyingPeriodWorkEvaluations     | workeval                               | | ||||
| |                                         | User::class                             | acpw.referrers                             | acpwuser                               | | ||||
| @@ -28,6 +29,8 @@ These are alias conventions : | ||||
| |                                         | Person::class                           | acppart.person                             | partperson                             | | ||||
| | AccompanyingPeriodWorkEvaluation::class |                                         |                                            | workeval                               | | ||||
| |                                         | Evaluation::class                       | workeval.evaluation                        | eval                                   | | ||||
| | AccompanyingPeriodInfo::class           |                                         |                                            | acpinfo                                | | ||||
| |                                         | User::class                             | acpinfo.user                               | acpinfo_user                           | | ||||
| | Goal::class                             |                                         |                                            | goal                                   | | ||||
| |                                         | Result::class                           | goal.results                               | goalresult                             | | ||||
| | Person::class                           |                                         |                                            | person                                 | | ||||
|   | ||||
| @@ -2,6 +2,7 @@ parameters: | ||||
|     level: 5 | ||||
|     paths: | ||||
|         - src/ | ||||
|         - utils/ | ||||
|     tmpDir: .cache/ | ||||
|     reportUnmatchedIgnoredErrors: false | ||||
|     excludePaths: | ||||
|   | ||||
							
								
								
									
										29
									
								
								phpunit.rector.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								phpunit.rector.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||
|          xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.6/phpunit.xsd" | ||||
|          bootstrap="tests/app/vendor/autoload.php" | ||||
|          cacheResultFile=".cache/phpunit/test-results-rector" | ||||
|          executionOrder="depends,defects" | ||||
|          forceCoversAnnotation="true" | ||||
|          beStrictAboutCoversAnnotation="true" | ||||
|          beStrictAboutOutputDuringTests="true" | ||||
|          beStrictAboutTodoAnnotatedTests="true" | ||||
|          convertDeprecationsToExceptions="true" | ||||
|          failOnRisky="true" | ||||
|          failOnWarning="true" | ||||
|          verbose="true" | ||||
|          colors="true" | ||||
| > | ||||
|     <testsuites> | ||||
|         <testsuite name="default"> | ||||
|             <directory>utils/rector/tests</directory> | ||||
|         </testsuite> | ||||
|     </testsuites> | ||||
|  | ||||
|     <coverage cacheDirectory=".cache/phpunit/code-coverage-rector" | ||||
|               processUncoveredFiles="true"> | ||||
|         <include> | ||||
|             <directory suffix=".php">utils/rector/src</directory> | ||||
|         </include> | ||||
|     </coverage> | ||||
| </phpunit> | ||||
| @@ -24,6 +24,9 @@ return static function (RectorConfig $rectorConfig): void { | ||||
|         LevelSetList::UP_TO_PHP_74 | ||||
|     ]); | ||||
|  | ||||
|     // chill rules | ||||
|     $rectorConfig->rule(\Chill\Utils\Rector\Rector\ChillBundleAddFormDefaultDataOnExportFilterAggregatorRector::class); | ||||
|  | ||||
|     // skip some path... | ||||
|     $rectorConfig->skip([ | ||||
|         // make rector stuck for some files | ||||
|   | ||||
| @@ -18,11 +18,17 @@ use Chill\ActivityBundle\Repository\ActivityACLAwareRepositoryInterface; | ||||
| use Chill\ActivityBundle\Repository\ActivityRepository; | ||||
| use Chill\ActivityBundle\Repository\ActivityTypeCategoryRepository; | ||||
| use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface; | ||||
| use Chill\ActivityBundle\Repository\ActivityUserJobRepository; | ||||
| use Chill\ActivityBundle\Security\Authorization\ActivityVoter; | ||||
| use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable; | ||||
| use Chill\MainBundle\Entity\UserJob; | ||||
| use Chill\MainBundle\Pagination\PaginatorFactory; | ||||
| use Chill\MainBundle\Repository\LocationRepository; | ||||
| use Chill\MainBundle\Repository\UserRepositoryInterface; | ||||
| use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface; | ||||
| use Chill\MainBundle\Templating\Listing\FilterOrderHelper; | ||||
| use Chill\MainBundle\Templating\Listing\FilterOrderHelperFactoryInterface; | ||||
| use Chill\MainBundle\Templating\TranslatableStringHelperInterface; | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod; | ||||
| use Chill\PersonBundle\Entity\Person; | ||||
| use Chill\PersonBundle\Privacy\PrivacyEvent; | ||||
| @@ -47,68 +53,26 @@ use function array_key_exists; | ||||
|  | ||||
| final class ActivityController extends AbstractController | ||||
| { | ||||
|     private AccompanyingPeriodRepository $accompanyingPeriodRepository; | ||||
|  | ||||
|     private ActivityACLAwareRepositoryInterface $activityACLAwareRepository; | ||||
|  | ||||
|     private ActivityRepository $activityRepository; | ||||
|  | ||||
|     private ActivityTypeCategoryRepository $activityTypeCategoryRepository; | ||||
|  | ||||
|     private ActivityTypeRepositoryInterface $activityTypeRepository; | ||||
|  | ||||
|     private CenterResolverManagerInterface $centerResolver; | ||||
|  | ||||
|     private EntityManagerInterface $entityManager; | ||||
|  | ||||
|     private EventDispatcherInterface $eventDispatcher; | ||||
|  | ||||
|     private LocationRepository $locationRepository; | ||||
|  | ||||
|     private LoggerInterface $logger; | ||||
|  | ||||
|     private PersonRepository $personRepository; | ||||
|  | ||||
|     private SerializerInterface $serializer; | ||||
|  | ||||
|     private ThirdPartyRepository $thirdPartyRepository; | ||||
|  | ||||
|     private TranslatorInterface $translator; | ||||
|  | ||||
|     private UserRepositoryInterface $userRepository; | ||||
|  | ||||
|     public function __construct( | ||||
|         ActivityACLAwareRepositoryInterface $activityACLAwareRepository, | ||||
|         ActivityTypeRepositoryInterface $activityTypeRepository, | ||||
|         ActivityTypeCategoryRepository $activityTypeCategoryRepository, | ||||
|         PersonRepository $personRepository, | ||||
|         ThirdPartyRepository $thirdPartyRepository, | ||||
|         LocationRepository $locationRepository, | ||||
|         ActivityRepository $activityRepository, | ||||
|         AccompanyingPeriodRepository $accompanyingPeriodRepository, | ||||
|         EntityManagerInterface $entityManager, | ||||
|         EventDispatcherInterface $eventDispatcher, | ||||
|         LoggerInterface $logger, | ||||
|         SerializerInterface $serializer, | ||||
|         UserRepositoryInterface $userRepository, | ||||
|         CenterResolverManagerInterface $centerResolver, | ||||
|         TranslatorInterface $translator | ||||
|         private readonly ActivityACLAwareRepositoryInterface $activityACLAwareRepository, | ||||
|         private readonly ActivityTypeRepositoryInterface $activityTypeRepository, | ||||
|         private readonly ActivityTypeCategoryRepository $activityTypeCategoryRepository, | ||||
|         private readonly PersonRepository $personRepository, | ||||
|         private readonly ThirdPartyRepository $thirdPartyRepository, | ||||
|         private readonly LocationRepository $locationRepository, | ||||
|         private readonly ActivityRepository $activityRepository, | ||||
|         private readonly AccompanyingPeriodRepository $accompanyingPeriodRepository, | ||||
|         private readonly EntityManagerInterface $entityManager, | ||||
|         private readonly EventDispatcherInterface $eventDispatcher, | ||||
|         private readonly LoggerInterface $logger, | ||||
|         private readonly SerializerInterface $serializer, | ||||
|         private readonly UserRepositoryInterface $userRepository, | ||||
|         private readonly CenterResolverManagerInterface $centerResolver, | ||||
|         private readonly TranslatorInterface $translator, | ||||
|         private readonly FilterOrderHelperFactoryInterface $filterOrderHelperFactory, | ||||
|         private readonly TranslatableStringHelperInterface $translatableStringHelper, | ||||
|         private readonly PaginatorFactory $paginatorFactory, | ||||
|     ) { | ||||
|         $this->activityACLAwareRepository = $activityACLAwareRepository; | ||||
|         $this->activityTypeRepository = $activityTypeRepository; | ||||
|         $this->activityTypeCategoryRepository = $activityTypeCategoryRepository; | ||||
|         $this->personRepository = $personRepository; | ||||
|         $this->thirdPartyRepository = $thirdPartyRepository; | ||||
|         $this->locationRepository = $locationRepository; | ||||
|         $this->activityRepository = $activityRepository; | ||||
|         $this->accompanyingPeriodRepository = $accompanyingPeriodRepository; | ||||
|         $this->entityManager = $entityManager; | ||||
|         $this->eventDispatcher = $eventDispatcher; | ||||
|         $this->logger = $logger; | ||||
|         $this->serializer = $serializer; | ||||
|         $this->userRepository = $userRepository; | ||||
|         $this->centerResolver = $centerResolver; | ||||
|         $this->translator = $translator; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -289,14 +253,31 @@ final class ActivityController extends AbstractController | ||||
|     { | ||||
|         $view = null; | ||||
|         $activities = []; | ||||
|         // TODO: add pagination | ||||
|  | ||||
|         [$person, $accompanyingPeriod] = $this->getEntity($request); | ||||
|         $filter = $this->buildFilterOrder($person ?? $accompanyingPeriod); | ||||
|  | ||||
|         $filterArgs = [ | ||||
|             'my_activities' => $filter->getSingleCheckboxData('my_activities'), | ||||
|             'types' => $filter->getEntityChoiceData('activity_types'), | ||||
|             'jobs' => $filter->getEntityChoiceData('jobs'), | ||||
|             'before' => $filter->getDateRangeData('activity_date')['to'], | ||||
|             'after' => $filter->getDateRangeData('activity_date')['from'], | ||||
|         ]; | ||||
|  | ||||
|         if ($person instanceof Person) { | ||||
|             $this->denyAccessUnlessGranted(ActivityVoter::SEE, $person); | ||||
|             $count = $this->activityACLAwareRepository->countByPerson($person, ActivityVoter::SEE, $filterArgs); | ||||
|             $paginator = $this->paginatorFactory->create($count); | ||||
|             $activities = $this->activityACLAwareRepository | ||||
|                 ->findByPerson($person, ActivityVoter::SEE, 0, null, ['date' => 'DESC', 'id' => 'DESC']); | ||||
|                 ->findByPerson( | ||||
|                     $person, | ||||
|                     ActivityVoter::SEE, | ||||
|                     $paginator->getCurrentPageFirstItemNumber(), | ||||
|                     $paginator->getItemsPerPage(), | ||||
|                     ['date' => 'DESC', 'id' => 'DESC'], | ||||
|                     $filterArgs | ||||
|                 ); | ||||
|  | ||||
|             $event = new PrivacyEvent($person, [ | ||||
|                 'element_class' => Activity::class, | ||||
| @@ -308,10 +289,21 @@ final class ActivityController extends AbstractController | ||||
|         } elseif ($accompanyingPeriod instanceof AccompanyingPeriod) { | ||||
|             $this->denyAccessUnlessGranted(ActivityVoter::SEE, $accompanyingPeriod); | ||||
|  | ||||
|             $count = $this->activityACLAwareRepository->countByAccompanyingPeriod($accompanyingPeriod, ActivityVoter::SEE, $filterArgs); | ||||
|             $paginator = $this->paginatorFactory->create($count); | ||||
|             $activities = $this->activityACLAwareRepository | ||||
|                 ->findByAccompanyingPeriod($accompanyingPeriod, ActivityVoter::SEE, 0, null, ['date' => 'DESC', 'id' => 'DESC']); | ||||
|                 ->findByAccompanyingPeriod( | ||||
|                     $accompanyingPeriod, | ||||
|                     ActivityVoter::SEE, | ||||
|                     $paginator->getCurrentPageFirstItemNumber(), | ||||
|                     $paginator->getItemsPerPage(), | ||||
|                     ['date' => 'DESC', 'id' => 'DESC'], | ||||
|                     $filterArgs | ||||
|                 ); | ||||
|  | ||||
|             $view = 'ChillActivityBundle:Activity:listAccompanyingCourse.html.twig'; | ||||
|         } else { | ||||
|             throw new \LogicException("Unsupported"); | ||||
|         } | ||||
|  | ||||
|         return $this->render( | ||||
| @@ -320,10 +312,40 @@ final class ActivityController extends AbstractController | ||||
|                 'activities' => $activities, | ||||
|                 'person' => $person, | ||||
|                 'accompanyingCourse' => $accompanyingPeriod, | ||||
|                 'filter' => $filter, | ||||
|                 'paginator' => $paginator, | ||||
|             ] | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     private function buildFilterOrder(AccompanyingPeriod|Person $associated): FilterOrderHelper | ||||
|     { | ||||
|  | ||||
|         $filterBuilder = $this->filterOrderHelperFactory->create(self::class); | ||||
|         $types = $this->activityACLAwareRepository->findActivityTypeByAssociated($associated); | ||||
|         $jobs = $this->activityACLAwareRepository->findUserJobByAssociated($associated); | ||||
|  | ||||
|         $filterBuilder | ||||
|             ->addDateRange('activity_date', 'activity.date') | ||||
|             ->addSingleCheckbox('my_activities', 'activity_filter.My activities') | ||||
|             ->addEntityChoice('activity_types', 'activity_filter.Types', \Chill\ActivityBundle\Entity\ActivityType::class, $types, [ | ||||
|                 'choice_label' => function (\Chill\ActivityBundle\Entity\ActivityType $activityType) { | ||||
|                     $text = match ($activityType->hasCategory()) { | ||||
|                         true => $this->translatableStringHelper->localize($activityType->getCategory()->getName()) . ' > ', | ||||
|                         false => '', | ||||
|                     }; | ||||
|  | ||||
|                     return $text . $this->translatableStringHelper->localize($activityType->getName()); | ||||
|                 } | ||||
|             ]) | ||||
|             ->addEntityChoice('jobs', 'activity_filter.Jobs', UserJob::class, $jobs, [ | ||||
|                 'choice_label' => fn (UserJob $u) => $this->translatableStringHelper->localize($u->getLabel()) | ||||
|             ]) | ||||
|         ; | ||||
|  | ||||
|         return $filterBuilder->build(); | ||||
|     } | ||||
|  | ||||
|     public function newAction(Request $request): Response | ||||
|     { | ||||
|         $view = null; | ||||
|   | ||||
| @@ -40,6 +40,10 @@ class ByActivityNumberAggregator implements AggregatorInterface | ||||
|     { | ||||
|         // No form needed | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|   | ||||
| @@ -52,6 +52,10 @@ class ByCreatorAggregator implements AggregatorInterface | ||||
|     { | ||||
|         // no form | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|   | ||||
| @@ -57,6 +57,10 @@ class BySocialActionAggregator implements AggregatorInterface | ||||
|     { | ||||
|         // no form | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|   | ||||
| @@ -57,6 +57,10 @@ class BySocialIssueAggregator implements AggregatorInterface | ||||
|     { | ||||
|         // no form | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|   | ||||
| @@ -57,6 +57,10 @@ class ByThirdpartyAggregator implements AggregatorInterface | ||||
|     { | ||||
|         // no form | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|   | ||||
| @@ -57,6 +57,10 @@ class CreatorScopeAggregator implements AggregatorInterface | ||||
|     { | ||||
|         // no form | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|   | ||||
| @@ -29,14 +29,6 @@ class DateAggregator implements AggregatorInterface | ||||
|  | ||||
|     private const DEFAULT_CHOICE = 'year'; | ||||
|  | ||||
|     private TranslatorInterface $translator; | ||||
|  | ||||
|     public function __construct( | ||||
|         TranslatorInterface $translator | ||||
|     ) { | ||||
|         $this->translator = $translator; | ||||
|     } | ||||
|  | ||||
|     public function addRole(): ?string | ||||
|     { | ||||
|         return null; | ||||
| @@ -84,9 +76,12 @@ class DateAggregator implements AggregatorInterface | ||||
|             'multiple' => false, | ||||
|             'expanded' => true, | ||||
|             'empty_data' => self::DEFAULT_CHOICE, | ||||
|             'data' => self::DEFAULT_CHOICE, | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return ['frequency' => self::DEFAULT_CHOICE]; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|   | ||||
| @@ -57,6 +57,10 @@ class LocationTypeAggregator implements AggregatorInterface | ||||
|     { | ||||
|         // no form | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|   | ||||
| @@ -60,6 +60,10 @@ class ActivityTypeAggregator implements AggregatorInterface | ||||
|     { | ||||
|         // no form required for this aggregator | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data): Closure | ||||
|     { | ||||
|   | ||||
| @@ -58,6 +58,10 @@ class ActivityUserAggregator implements AggregatorInterface | ||||
|     { | ||||
|         // nothing to add | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, $values, $data): Closure | ||||
|     { | ||||
|   | ||||
| @@ -56,6 +56,10 @@ class ActivityUsersAggregator implements AggregatorInterface | ||||
|     { | ||||
|         // nothing to add on the form | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|   | ||||
| @@ -55,6 +55,10 @@ class ActivityUsersJobAggregator implements \Chill\MainBundle\Export\AggregatorI | ||||
|     { | ||||
|         // nothing to add in the form | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|   | ||||
| @@ -55,6 +55,10 @@ class ActivityUsersScopeAggregator implements \Chill\MainBundle\Export\Aggregato | ||||
|     { | ||||
|         // nothing to add in the form | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|   | ||||
| @@ -110,6 +110,10 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali | ||||
|             ] | ||||
|         ); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|   | ||||
| @@ -47,6 +47,10 @@ class SentReceivedAggregator implements AggregatorInterface | ||||
|     { | ||||
|         // No form needed | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data): callable | ||||
|     { | ||||
|   | ||||
| @@ -39,6 +39,10 @@ class AvgActivityDuration implements ExportInterface, GroupedExportInterface | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getAllowedFormattersTypes(): array | ||||
|     { | ||||
|   | ||||
| @@ -40,6 +40,10 @@ class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterfac | ||||
|     { | ||||
|         // TODO: Implement buildForm() method. | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getAllowedFormattersTypes(): array | ||||
|     { | ||||
|   | ||||
| @@ -39,6 +39,10 @@ class CountActivity implements ExportInterface, GroupedExportInterface | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getAllowedFormattersTypes(): array | ||||
|     { | ||||
|   | ||||
| @@ -44,6 +44,10 @@ class ListActivity implements ListInterface, GroupedExportInterface | ||||
|     { | ||||
|         $this->helper->buildForm($builder); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getAllowedFormattersTypes() | ||||
|     { | ||||
|   | ||||
| @@ -40,6 +40,10 @@ class SumActivityDuration implements ExportInterface, GroupedExportInterface | ||||
|     { | ||||
|         // TODO: Implement buildForm() method. | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getAllowedFormattersTypes(): array | ||||
|     { | ||||
|   | ||||
| @@ -40,6 +40,10 @@ class SumActivityVisitDuration implements ExportInterface, GroupedExportInterfac | ||||
|     { | ||||
|         // TODO: Implement buildForm() method. | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getAllowedFormattersTypes(): array | ||||
|     { | ||||
|   | ||||
| @@ -35,6 +35,10 @@ class CountActivity implements ExportInterface, GroupedExportInterface | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getAllowedFormattersTypes() | ||||
|     { | ||||
|   | ||||
| @@ -88,6 +88,10 @@ class ListActivity implements ListInterface, GroupedExportInterface | ||||
|             ])], | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getAllowedFormattersTypes() | ||||
|     { | ||||
|   | ||||
| @@ -53,6 +53,10 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getAllowedFormattersTypes() | ||||
|     { | ||||
|   | ||||
| @@ -68,6 +68,10 @@ class ActivityTypeFilter implements FilterInterface | ||||
|             'expanded' => true, | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string'): array | ||||
|     { | ||||
|   | ||||
| @@ -52,6 +52,10 @@ class ByCreatorFilter implements FilterInterface | ||||
|             'multiple' => true, | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string'): array | ||||
|     { | ||||
|   | ||||
| @@ -60,6 +60,10 @@ class BySocialActionFilter implements FilterInterface | ||||
|             'multiple' => true, | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string'): array | ||||
|     { | ||||
|   | ||||
| @@ -60,6 +60,10 @@ class BySocialIssueFilter implements FilterInterface | ||||
|             'multiple' => true, | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string'): array | ||||
|     { | ||||
|   | ||||
| @@ -68,9 +68,12 @@ class EmergencyFilter implements FilterInterface | ||||
|             'multiple' => false, | ||||
|             'expanded' => true, | ||||
|             'empty_data' => self::DEFAULT_CHOICE, | ||||
|             'data' => self::DEFAULT_CHOICE, | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return ['accepted_emergency' => self::DEFAULT_CHOICE]; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string'): array | ||||
|     { | ||||
|   | ||||
| @@ -44,6 +44,10 @@ class HasNoActivityFilter implements FilterInterface | ||||
|     { | ||||
|         //no form needed | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string'): array | ||||
|     { | ||||
|   | ||||
| @@ -46,6 +46,10 @@ class LocationFilter implements FilterInterface | ||||
|             'label' => 'pick location', | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string'): array | ||||
|     { | ||||
|   | ||||
| @@ -65,6 +65,10 @@ class LocationTypeFilter implements FilterInterface | ||||
|             //'label' => false, | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string'): array | ||||
|     { | ||||
|   | ||||
| @@ -69,9 +69,12 @@ class SentReceivedFilter implements FilterInterface | ||||
|             'multiple' => false, | ||||
|             'expanded' => true, | ||||
|             'empty_data' => self::DEFAULT_CHOICE, | ||||
|             'data' => self::DEFAULT_CHOICE, | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return ['accepted_sentreceived' => self::DEFAULT_CHOICE]; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string'): array | ||||
|     { | ||||
|   | ||||
| @@ -61,6 +61,10 @@ class UserFilter implements FilterInterface | ||||
|             'label' => 'Creators', | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string'): array | ||||
|     { | ||||
|   | ||||
| @@ -71,6 +71,10 @@ class UserScopeFilter implements FilterInterface | ||||
|             'expanded' => true, | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string'): array | ||||
|     { | ||||
|   | ||||
| @@ -80,11 +80,9 @@ class ActivityDateFilter implements FilterInterface | ||||
|         $builder | ||||
|             ->add('date_from', PickRollingDateType::class, [ | ||||
|                 'label' => 'Activities after this date', | ||||
|                 'data' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START), | ||||
|             ]) | ||||
|             ->add('date_to', PickRollingDateType::class, [ | ||||
|                 'label' => 'Activities before this date', | ||||
|                 'data' => new RollingDate(RollingDate::T_TODAY), | ||||
|             ]); | ||||
|  | ||||
|         $builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) { | ||||
| @@ -127,6 +125,10 @@ class ActivityDateFilter implements FilterInterface | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return ['date_from' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START), 'date_to' => new RollingDate(RollingDate::T_TODAY)]; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string') | ||||
|     { | ||||
|   | ||||
| @@ -78,6 +78,10 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter | ||||
|             ], | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string') | ||||
|     { | ||||
|   | ||||
| @@ -56,6 +56,10 @@ class ActivityUsersFilter implements FilterInterface | ||||
|             'label' => 'Users', | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string') | ||||
|     { | ||||
|   | ||||
| @@ -82,6 +82,10 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt | ||||
|             'expanded' => false, | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string') | ||||
|     { | ||||
|   | ||||
| @@ -112,7 +112,6 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt | ||||
|     { | ||||
|         $builder->add('date_from', DateType::class, [ | ||||
|             'label' => 'Implied in an activity after this date', | ||||
|             'data' => new DateTime(), | ||||
|             'attr' => ['class' => 'datepicker'], | ||||
|             'widget' => 'single_text', | ||||
|             'format' => 'dd-MM-yyyy', | ||||
| @@ -120,7 +119,6 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt | ||||
|  | ||||
|         $builder->add('date_to', DateType::class, [ | ||||
|             'label' => 'Implied in an activity before this date', | ||||
|             'data' => new DateTime(), | ||||
|             'attr' => ['class' => 'datepicker'], | ||||
|             'widget' => 'single_text', | ||||
|             'format' => 'dd-MM-yyyy', | ||||
| @@ -130,7 +128,6 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt | ||||
|             'class' => ActivityReason::class, | ||||
|             'choice_label' => fn (ActivityReason $reason): ?string => $this->translatableStringHelper->localize($reason->getName()), | ||||
|             'group_by' => fn (ActivityReason $reason): ?string => $this->translatableStringHelper->localize($reason->getCategory()->getName()), | ||||
|             'data' => $this->activityReasonRepository->findAll(), | ||||
|             'multiple' => true, | ||||
|             'expanded' => false, | ||||
|             'label' => 'Activity reasons for those activities', | ||||
| @@ -176,6 +173,10 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return ['date_from' => new DateTime(), 'date_to' => new DateTime(), 'reasons' => $this->activityReasonRepository->findAll()]; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string') | ||||
|     { | ||||
|   | ||||
| @@ -60,6 +60,10 @@ class UsersJobFilter implements FilterInterface | ||||
|             'expanded' => true, | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string') | ||||
|     { | ||||
|   | ||||
| @@ -67,6 +67,10 @@ class UsersScopeFilter implements FilterInterface | ||||
|             'expanded' => true, | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string') | ||||
|     { | ||||
|   | ||||
| @@ -18,67 +18,193 @@ use Chill\ActivityBundle\Security\Authorization\ActivityVoter; | ||||
| use Chill\MainBundle\Entity\Location; | ||||
| use Chill\MainBundle\Entity\LocationType; | ||||
| use Chill\MainBundle\Entity\Scope; | ||||
| use Chill\MainBundle\Security\Authorization\AuthorizationHelper; | ||||
| use Chill\MainBundle\Security\Resolver\CenterResolverDispatcherInterface; | ||||
| use Chill\MainBundle\Entity\User; | ||||
| use Chill\MainBundle\Entity\UserJob; | ||||
| use Chill\MainBundle\Security\Authorization\AuthorizationHelperForCurrentUserInterface; | ||||
| use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface; | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod; | ||||
| use Chill\PersonBundle\Entity\Person; | ||||
| use Doctrine\DBAL\Types\Types; | ||||
| use Doctrine\ORM\AbstractQuery; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use Doctrine\ORM\NonUniqueResultException; | ||||
| use Doctrine\ORM\NoResultException; | ||||
| use Doctrine\ORM\Query\Expr\Join; | ||||
| use Doctrine\ORM\Query\ResultSetMappingBuilder; | ||||
| use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; | ||||
| use Symfony\Component\Security\Core\Role\Role; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use Symfony\Component\HttpFoundation\RequestStack; | ||||
| use Symfony\Component\Security\Core\Security; | ||||
|  | ||||
| use function count; | ||||
| use function in_array; | ||||
|  | ||||
| final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInterface | ||||
| final readonly class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInterface | ||||
| { | ||||
|     private AuthorizationHelper $authorizationHelper; | ||||
|  | ||||
|     private CenterResolverDispatcherInterface $centerResolverDispatcher; | ||||
|  | ||||
|     private EntityManagerInterface $em; | ||||
|  | ||||
|     private ActivityRepository $repository; | ||||
|  | ||||
|     private Security $security; | ||||
|  | ||||
|     private TokenStorageInterface $tokenStorage; | ||||
|  | ||||
|     public function __construct( | ||||
|         AuthorizationHelper $authorizationHelper, | ||||
|         CenterResolverDispatcherInterface $centerResolverDispatcher, | ||||
|         TokenStorageInterface $tokenStorage, | ||||
|         ActivityRepository $repository, | ||||
|         EntityManagerInterface $em, | ||||
|         Security $security | ||||
|         private AuthorizationHelperForCurrentUserInterface $authorizationHelper, | ||||
|         private CenterResolverManagerInterface $centerResolverManager, | ||||
|         private ActivityRepository $repository, | ||||
|         private EntityManagerInterface $em, | ||||
|         private Security $security, | ||||
|         private RequestStack $requestStack, | ||||
|     ) { | ||||
|         $this->authorizationHelper = $authorizationHelper; | ||||
|         $this->centerResolverDispatcher = $centerResolverDispatcher; | ||||
|         $this->tokenStorage = $tokenStorage; | ||||
|         $this->repository = $repository; | ||||
|         $this->em = $em; | ||||
|         $this->security = $security; | ||||
|     } | ||||
|  | ||||
|     public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array | ||||
|     /** | ||||
|      * @throws NonUniqueResultException | ||||
|      * @throws NoResultException | ||||
|      */ | ||||
|     public function countByAccompanyingPeriod(AccompanyingPeriod $period, string $role, array $filters = []): int | ||||
|     { | ||||
|         $user = $this->security->getUser(); | ||||
|         $center = $this->centerResolverDispatcher->resolveCenter($period); | ||||
|         $qb = $this->buildBaseQuery($filters); | ||||
|  | ||||
|         if (0 === count($orderBy)) { | ||||
|             $orderBy = ['date' => 'DESC']; | ||||
|         $qb | ||||
|             ->select('COUNT(a)') | ||||
|             ->andWhere('a.accompanyingPeriod = :period')->setParameter('period', $period); | ||||
|  | ||||
|         return $qb->getQuery()->getSingleScalarResult(); | ||||
|     } | ||||
|  | ||||
|     public function countByPerson(Person $person, string $role, array $filters = []): int | ||||
|     { | ||||
|         $qb = $this->buildBaseQuery($filters); | ||||
|  | ||||
|         $qb = $this->filterBaseQueryByPerson($qb, $person, $role); | ||||
|  | ||||
|         $qb->select('COUNT(a)'); | ||||
|  | ||||
|         return $qb->getQuery()->getSingleScalarResult(); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, array $orderBy = ['date' => 'DESC'], array $filters = []): array | ||||
|     { | ||||
|         $qb = $this->buildBaseQuery($filters); | ||||
|  | ||||
|         $qb->andWhere('a.accompanyingPeriod = :period')->setParameter('period', $period); | ||||
|  | ||||
|         foreach ($orderBy as $field => $order) { | ||||
|             $qb->addOrderBy('a.' . $field, $order); | ||||
|         } | ||||
|  | ||||
|         $scopes = $this->authorizationHelper | ||||
|             ->getReachableCircles($user, $role, $center); | ||||
|         if (null !== $start) { | ||||
|             $qb->setFirstResult($start); | ||||
|         } | ||||
|         if (null !== $limit) { | ||||
|             $qb->setMaxResults($limit); | ||||
|         } | ||||
|  | ||||
|         return $this->em->getRepository(Activity::class) | ||||
|             ->findByAccompanyingPeriod($period, $scopes, true, $limit, $start, $orderBy); | ||||
|         return $qb->getQuery()->getResult(); | ||||
|     } | ||||
|  | ||||
|     public function buildBaseQuery(array $filters): QueryBuilder | ||||
|     { | ||||
|         $qb = $this->repository | ||||
|             ->createQueryBuilder('a') | ||||
|         ; | ||||
|  | ||||
|         if (($filters['my_activities'] ?? false) and ($user = $this->security->getUser()) instanceof User) { | ||||
|             $qb->andWhere( | ||||
|                 $qb->expr()->orX( | ||||
|                     'a.createdBy = :user', | ||||
|                     'a.user = :user', | ||||
|                     ':user MEMBER OF a.users' | ||||
|                 ) | ||||
|             )->setParameter('user', $user); | ||||
|         } | ||||
|  | ||||
|         if ([] !== ($types = $filters['types'] ?? [])) { | ||||
|             $qb->andWhere('a.activityType IN (:types)')->setParameter('types', $types); | ||||
|         } | ||||
|  | ||||
|         if ([] !== ($jobs = $filters['jobs'] ?? [])) { | ||||
|             $qb | ||||
|                 ->leftJoin('a.createdBy', 'creator') | ||||
|                 ->leftJoin('a.user', 'activity_u') | ||||
|                 ->andWhere( | ||||
|                     $qb->expr()->orX( | ||||
|                         'creator.userJob IN (:jobs)', | ||||
|                         'activity_u.userJob IN (:jobs)', | ||||
|                         'EXISTS (SELECT 1 FROM ' . User::class . ' activity_user WHERE activity_user MEMBER OF a.users AND activity_user.userJob IN (:jobs))' | ||||
|                     ) | ||||
|                 ) | ||||
|                 ->setParameter('jobs', $jobs); | ||||
|         } | ||||
|  | ||||
|         if (null !== ($after = $filters['after'] ?? null)) { | ||||
|             $qb->andWhere('a.date >= :after')->setParameter('after', $after); | ||||
|         } | ||||
|  | ||||
|         if (null !== ($before = $filters['before'] ?? null)) { | ||||
|             $qb->andWhere('a.date <= :before')->setParameter('before', $before); | ||||
|         } | ||||
|  | ||||
|         return $qb; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccompanyingPeriod|Person $associated | ||||
|      * @return array<ActivityType> | ||||
|      */ | ||||
|     public function findActivityTypeByAssociated(AccompanyingPeriod|Person $associated): array | ||||
|     { | ||||
|         $in = $this->em->createQueryBuilder(); | ||||
|         $in | ||||
|             ->select('1') | ||||
|             ->from(Activity::class, 'a'); | ||||
|  | ||||
|         if ($associated instanceof Person) { | ||||
|             $in = $this->filterBaseQueryByPerson($in, $associated, ActivityVoter::SEE); | ||||
|         } else { | ||||
|             $in->andWhere('a.accompanyingPeriod = :period')->setParameter('period', $associated); | ||||
|         } | ||||
|  | ||||
|         // join between the embedded exist query and the main query | ||||
|         $in->andWhere('a.activityType = t'); | ||||
|  | ||||
|         $qb = $this->em->createQueryBuilder()->setParameters($in->getParameters()); | ||||
|         $qb | ||||
|             ->select('t') | ||||
|             ->from(ActivityType::class, 't') | ||||
|             ->where( | ||||
|                 $qb->expr()->exists($in->getDQL()) | ||||
|             ); | ||||
|  | ||||
|         return $qb->getQuery()->getResult(); | ||||
|     } | ||||
|  | ||||
|     public function findUserJobByAssociated(Person|AccompanyingPeriod $associated): array | ||||
|     { | ||||
|         $in = $this->em->createQueryBuilder(); | ||||
|         $in->select('IDENTITY(u.userJob)') | ||||
|             ->from(User::class, 'u') | ||||
|             ->join( | ||||
|                 Activity::class, | ||||
|                 'a', | ||||
|                 Join::WITH, | ||||
|                 'a.createdBy = u OR a.user = u OR u MEMBER OF a.users' | ||||
|             ); | ||||
|  | ||||
|         if ($associated instanceof Person) { | ||||
|             $in = $this->filterBaseQueryByPerson($in, $associated, ActivityVoter::SEE); | ||||
|         } else { | ||||
|             $in->andWhere('a.accompanyingPeriod = :associated'); | ||||
|             $in->setParameter('associated', $associated); | ||||
|         } | ||||
|  | ||||
|         $qb = $this->em->createQueryBuilder()->setParameters($in->getParameters()); | ||||
|  | ||||
|         $qb->select('ub', 'JSON_EXTRACT(ub.label, :lang) AS HIDDEN lang') | ||||
|             ->from(UserJob::class, 'ub') | ||||
|             ->where($qb->expr()->in('ub.id', $in->getDQL())) | ||||
|             ->setParameter('lang', $this->requestStack->getCurrentRequest()->getLocale()) | ||||
|             ->orderBy('lang') | ||||
|         ; | ||||
|  | ||||
|         return $qb->getQuery()->getResult(); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public function findByAccompanyingPeriodSimplified(AccompanyingPeriod $period, ?int $limit = 1000): array | ||||
|     { | ||||
|         $rsm = new ResultSetMappingBuilder($this->em); | ||||
| @@ -159,25 +285,73 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte | ||||
|         return $nq->getResult(AbstractQuery::HYDRATE_ARRAY); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $orderBy | ||||
|      * | ||||
|      * @return Activity[]|array | ||||
|      */ | ||||
|     public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array | ||||
|     public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = [], array $filters = []): array | ||||
|     { | ||||
|         $user = $this->security->getUser(); | ||||
|         $center = $this->centerResolverDispatcher->resolveCenter($person); | ||||
|         $qb = $this->buildBaseQuery($filters); | ||||
|  | ||||
|         if (0 === count($orderBy)) { | ||||
|             $orderBy = ['date' => 'DESC']; | ||||
|         $qb = $this->filterBaseQueryByPerson($qb, $person, $role); | ||||
|  | ||||
|         foreach ($orderBy as $field => $direction) { | ||||
|             $qb->addOrderBy('a.' . $field, $direction); | ||||
|         } | ||||
|  | ||||
|         $reachableScopes = $this->authorizationHelper | ||||
|             ->getReachableCircles($user, $role, $center); | ||||
|         if (null !== $start) { | ||||
|             $qb->setFirstResult($start); | ||||
|         } | ||||
|         if (null !== $limit) { | ||||
|             $qb->setMaxResults($limit); | ||||
|         } | ||||
|  | ||||
|         return $this->em->getRepository(Activity::class) | ||||
|             ->findByPersonImplied($person, $reachableScopes, $orderBy, $limit, $start); | ||||
|         return $qb->getQuery()->getResult(); | ||||
|     } | ||||
|  | ||||
|     private function filterBaseQueryByPerson(QueryBuilder $qb, Person $person, string $role): QueryBuilder | ||||
|     { | ||||
|         $orX = $qb->expr()->orX(); | ||||
|         $counter = 0; | ||||
|         foreach ($this->centerResolverManager->resolveCenters($person) as $center) { | ||||
|             $scopes = $this->authorizationHelper->getReachableScopes($role, $center); | ||||
|  | ||||
|             if ([] === $scopes) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             $orX->add(sprintf('a.person = :person AND a.scope IN (:scopes_%d)', $counter)); | ||||
|             $qb->setParameter(sprintf('scopes_%d', $counter), $scopes); | ||||
|             $qb->setParameter('person', $person); | ||||
|             $counter++; | ||||
|         } | ||||
|  | ||||
|         foreach  ($person->getAccompanyingPeriodParticipations() as $participation) { | ||||
|             if (!$this->security->isGranted(ActivityVoter::SEE, $participation->getAccompanyingPeriod())) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             $and = $qb->expr()->andX( | ||||
|                 sprintf('a.accompanyingPeriod = :period_%d', $counter), | ||||
|                 sprintf('a.date >= :participation_start_%d', $counter) | ||||
|             ); | ||||
|  | ||||
|             $qb | ||||
|                 ->setParameter(sprintf('period_%d', $counter), $participation->getAccompanyingPeriod()) | ||||
|                 ->setParameter(sprintf('participation_start_%d', $counter), $participation->getStartDate()); | ||||
|  | ||||
|             if (null !== $participation->getEndDate()) { | ||||
|                 $and->add(sprintf('a.date < :participation_end_%d', $counter)); | ||||
|                 $qb | ||||
|                     ->setParameter(sprintf('participation_end_%d', $counter), $participation->getEndDate()); | ||||
|             } | ||||
|             $orX->add($and); | ||||
|             $counter++; | ||||
|         } | ||||
|  | ||||
|         if (0 === $orX->count()) { | ||||
|             $qb->andWhere('FALSE = TRUE'); | ||||
|         } else { | ||||
|             $qb->andWhere($orX); | ||||
|         } | ||||
|  | ||||
|         return $qb; | ||||
|     } | ||||
|  | ||||
|     public function queryTimelineIndexer(string $context, array $args = []): array | ||||
| @@ -226,7 +400,6 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte | ||||
|  | ||||
|         // acls: | ||||
|         $reachableCenters = $this->authorizationHelper->getReachableCenters( | ||||
|             $this->tokenStorage->getToken()->getUser(), | ||||
|             ActivityVoter::SEE | ||||
|         ); | ||||
|  | ||||
| @@ -251,7 +424,7 @@ final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInte | ||||
|                 continue; | ||||
|             } | ||||
|             // we get all the reachable scopes for this center | ||||
|             $reachableScopes = $this->authorizationHelper->getReachableScopes($this->tokenStorage->getToken()->getUser(), ActivityVoter::SEE, $center); | ||||
|             $reachableScopes = $this->authorizationHelper->getReachableScopes(ActivityVoter::SEE, $center); | ||||
|             // we get the ids for those scopes | ||||
|             $reachablesScopesId = array_map( | ||||
|                 static fn (Scope $scope) => $scope->getId(), | ||||
|   | ||||
| @@ -11,15 +11,32 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace Chill\ActivityBundle\Repository; | ||||
|  | ||||
| use Chill\ActivityBundle\Entity\Activity; | ||||
| use Chill\ActivityBundle\Entity\ActivityType; | ||||
| use Chill\MainBundle\Entity\UserJob; | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod; | ||||
| use Chill\PersonBundle\Entity\Person; | ||||
|  | ||||
| interface ActivityACLAwareRepositoryInterface | ||||
| { | ||||
|     /** | ||||
|      * @return Activity[]|array | ||||
|      * Return all the activities associated to an accompanying period and that the user is allowed to apply the given role. | ||||
|      * | ||||
|      * | ||||
|      * @param array{my_activities?: bool, types?: array<ActivityType>, jobs?: array<UserJob>, after?: \DateTimeImmutable|null, before?: \DateTimeImmutable|null} $filters | ||||
|      * @return array<Activity> | ||||
|      */ | ||||
|     public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array; | ||||
|     public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, array $orderBy = ['date' => 'DESC'], array $filters = []): array; | ||||
|  | ||||
|     /** | ||||
|      * @param array{my_activities?: bool, types?: array<ActivityType>, jobs?: array<UserJob>, after?: \DateTimeImmutable|null, before?: \DateTimeImmutable|null} $filters | ||||
|      */ | ||||
|     public function countByAccompanyingPeriod(AccompanyingPeriod $period, string $role, array $filters = []): int; | ||||
|  | ||||
|     /** | ||||
|      * @param array{my_activities?: bool, types?: array<ActivityType>, jobs?: array<UserJob>, after?: \DateTimeImmutable|null, before?: \DateTimeImmutable|null} $filters | ||||
|      */ | ||||
|     public function countByPerson(Person $person, string $role, array $filters = []): int; | ||||
|  | ||||
|     /** | ||||
|      * Return a list of activities, simplified as array (not object). | ||||
| @@ -31,7 +48,28 @@ interface ActivityACLAwareRepositoryInterface | ||||
|     public function findByAccompanyingPeriodSimplified(AccompanyingPeriod $period, ?int $limit = 1000): array; | ||||
|  | ||||
|     /** | ||||
|      * @return Activity[]|array | ||||
|      * @param array{my_activities?: bool, types?: array<ActivityType>, jobs?: array<UserJob>, after?: \DateTimeImmutable|null, before?: \DateTimeImmutable|null} $filters | ||||
|      * @return array<Activity> | ||||
|      */ | ||||
|     public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array; | ||||
|     public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, array $orderBy = ['date' => 'DESC'], array $filters = []): array; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Return a list of the type for the activities associated to person or accompanying period | ||||
|      * | ||||
|      * @return array<ActivityType> | ||||
|      */ | ||||
|     public function findActivityTypeByAssociated(AccompanyingPeriod|Person $associated): array; | ||||
|  | ||||
|     /** | ||||
|      * Return a list of the user job for the activities associated to person or accompanying period | ||||
|      * | ||||
|      * Associated mean the job: | ||||
|      * - of the creator; | ||||
|      * - of the user (activity.user) | ||||
|      * - of all the users | ||||
|      * | ||||
|      * @return array<UserJob> | ||||
|      */ | ||||
|     public function findUserJobByAssociated(AccompanyingPeriod|Person $associated): array; | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,198 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| /* | ||||
|  * Chill is a software for social workers | ||||
|  * | ||||
|  * For the full copyright and license information, please view | ||||
|  * the LICENSE file that was distributed with this source code. | ||||
|  */ | ||||
|  | ||||
| namespace Chill\ActivityBundle\Repository; | ||||
|  | ||||
| use Chill\ActivityBundle\Entity\Activity; | ||||
| use Chill\ActivityBundle\Security\Authorization\ActivityVoter; | ||||
| use Chill\ActivityBundle\Service\GenericDoc\Providers\AccompanyingPeriodActivityGenericDocProvider; | ||||
| use Chill\ActivityBundle\Service\GenericDoc\Providers\PersonActivityGenericDocProvider; | ||||
| use Chill\DocStoreBundle\Entity\PersonDocument; | ||||
| use Chill\DocStoreBundle\Entity\StoredObject; | ||||
| use Chill\DocStoreBundle\GenericDoc\FetchQuery; | ||||
| use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface; | ||||
| use Chill\DocStoreBundle\GenericDoc\Providers\PersonDocumentGenericDocProvider; | ||||
| use Chill\DocStoreBundle\Repository\PersonDocumentACLAwareRepositoryInterface; | ||||
| use Chill\DocStoreBundle\Security\Authorization\PersonDocumentVoter; | ||||
| use Chill\MainBundle\Entity\Scope; | ||||
| use Chill\MainBundle\Security\Authorization\AuthorizationHelperForCurrentUserInterface; | ||||
| use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface; | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod; | ||||
| use Chill\PersonBundle\Entity\Person; | ||||
| use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkVoter; | ||||
| use DateTimeImmutable; | ||||
| use Doctrine\DBAL\Types\Types; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use Doctrine\ORM\Mapping\MappingException; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use Symfony\Component\HttpKernel\HttpCache\Store; | ||||
| use Symfony\Component\Security\Core\Security; | ||||
|  | ||||
| final readonly class ActivityDocumentACLAwareRepository implements ActivityDocumentACLAwareRepositoryInterface | ||||
| { | ||||
|     public function __construct( | ||||
|         private EntityManagerInterface $em, | ||||
|         private CenterResolverManagerInterface $centerResolverManager, | ||||
|         private AuthorizationHelperForCurrentUserInterface $authorizationHelperForCurrentUser, | ||||
|         private Security $security | ||||
|     ) { | ||||
|     } | ||||
|  | ||||
|     public function buildFetchQueryActivityDocumentLinkedToPersonFromPersonContext(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQueryInterface | ||||
|     { | ||||
|         $query = $this->buildBaseFetchQueryActivityDocumentLinkedToPersonFromPersonContext($person, $startDate, $endDate, $content); | ||||
|  | ||||
|         return $this->addFetchQueryByPersonACL($query, $person); | ||||
|     } | ||||
|  | ||||
|     public function buildBaseFetchQueryActivityDocumentLinkedToPersonFromPersonContext(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery | ||||
|     { | ||||
|         $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class); | ||||
|         $activityMetadata = $this->em->getClassMetadata(Activity::class); | ||||
|  | ||||
|         $query = new FetchQuery( | ||||
|             PersonActivityGenericDocProvider::KEY, | ||||
|             sprintf('jsonb_build_object(\'id\', stored_obj.%s, \'activity_id\', activity.%s)', $storedObjectMetadata->getSingleIdentifierColumnName(), $activityMetadata->getSingleIdentifierColumnName()), | ||||
|             sprintf('stored_obj.%s', $storedObjectMetadata->getColumnName('createdAt')), | ||||
|             sprintf('%s AS stored_obj', $storedObjectMetadata->getSchemaName().'.'.$storedObjectMetadata->getTableName()) | ||||
|         ); | ||||
|  | ||||
|         $query->addJoinClause( | ||||
|             'JOIN public.activity_storedobject activity_doc ON activity_doc.storedobject_id = stored_obj.id' | ||||
|         ); | ||||
|  | ||||
|         $query->addJoinClause( | ||||
|             'JOIN public.activity activity ON activity.id = activity_doc.activity_id' | ||||
|         ); | ||||
|  | ||||
|         $query->addWhereClause( | ||||
|             sprintf('activity.%s = ?', $activityMetadata->getSingleAssociationJoinColumnName('person')), | ||||
|             [$person->getId()], | ||||
|             [Types::INTEGER] | ||||
|         ); | ||||
|  | ||||
|         return $this->addWhereClauses($query, $startDate, $endDate, $content); | ||||
|     } | ||||
|  | ||||
|     public function buildFetchQueryActivityDocumentLinkedToAccompanyingPeriodFromPersonContext(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery | ||||
|     { | ||||
|         $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class); | ||||
|         $activityMetadata = $this->em->getClassMetadata(Activity::class); | ||||
|  | ||||
|         $query = new FetchQuery( | ||||
|             AccompanyingPeriodActivityGenericDocProvider::KEY, | ||||
|             sprintf('jsonb_build_object(\'id\', stored_obj.%s, \'activity_id\', activity.%s)', $storedObjectMetadata->getSingleIdentifierColumnName(), $activityMetadata->getSingleIdentifierColumnName()), | ||||
|             sprintf('stored_obj.%s', $storedObjectMetadata->getColumnName('createdAt')), | ||||
|             sprintf('%s AS stored_obj', $storedObjectMetadata->getSchemaName().'.'.$storedObjectMetadata->getTableName()) | ||||
|         ); | ||||
|  | ||||
|         $query->addJoinClause( | ||||
|             'JOIN public.activity_storedobject activity_doc ON activity_doc.storedobject_id = stored_obj.id' | ||||
|         ); | ||||
|  | ||||
|         $query->addJoinClause( | ||||
|             'JOIN public.activity activity ON activity.id = activity_doc.activity_id' | ||||
|         ); | ||||
|  | ||||
|         // add documents of activities from parcours context | ||||
|         $or = []; | ||||
|         $orParams = []; | ||||
|         $orTypes = []; | ||||
|         foreach ($person->getAccompanyingPeriodParticipations() as $participation) { | ||||
|             if (!$this->security->isGranted(ActivityVoter::SEE, $participation->getAccompanyingPeriod())) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             $or[] = sprintf( | ||||
|                 '(activity.%s = ? AND stored_obj.%s BETWEEN ?::date AND COALESCE(?::date, \'infinity\'::date))', | ||||
|                 $activityMetadata->getSingleAssociationJoinColumnName('accompanyingPeriod'), | ||||
|                 $storedObjectMetadata->getColumnName('createdAt') | ||||
|             ); | ||||
|             $orParams = [...$orParams, $participation->getAccompanyingPeriod()->getId(), | ||||
|                 DateTimeImmutable::createFromInterface($participation->getStartDate()), | ||||
|                 null === $participation->getEndDate() ? null : DateTimeImmutable::createFromInterface($participation->getEndDate())]; | ||||
|             $orTypes = [...$orTypes, Types::INTEGER, Types::DATE_IMMUTABLE, Types::DATE_IMMUTABLE]; | ||||
|         } | ||||
|  | ||||
|         if ([] === $or) { | ||||
|             $query->addWhereClause('TRUE = FALSE'); | ||||
|  | ||||
|             return $query; | ||||
|         } | ||||
|  | ||||
|         $query->addWhereClause(sprintf('(%s)', implode(' OR ', $or)), $orParams, $orTypes); | ||||
|  | ||||
|         return $this->addWhereClauses($query, $startDate, $endDate, $content); | ||||
|     } | ||||
|  | ||||
|     private function addWhereClauses(FetchQuery $query, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery | ||||
|     { | ||||
|         $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class); | ||||
|  | ||||
|         if (null !== $startDate) { | ||||
|             $query->addWhereClause( | ||||
|                 sprintf('stored_obj.%s >= ?', $storedObjectMetadata->getColumnName('createdAt')), | ||||
|                 [$startDate], | ||||
|                 [Types::DATE_IMMUTABLE] | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         if (null !== $endDate) { | ||||
|             $query->addWhereClause( | ||||
|                 sprintf('stored_obj.%s < ?', $storedObjectMetadata->getColumnName('createdAt')), | ||||
|                 [$endDate], | ||||
|                 [Types::DATE_IMMUTABLE] | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         if (null !== $content and '' !== $content) { | ||||
|             $query->addWhereClause( | ||||
|                 'stored_obj.title ilike ?', | ||||
|                 ['%' . $content . '%'], | ||||
|                 [Types::STRING] | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         return $query; | ||||
|     } | ||||
|  | ||||
|     private function addFetchQueryByPersonACL(FetchQuery $fetchQuery, Person $person): FetchQuery | ||||
|     { | ||||
|         $activityMetadata = $this->em->getClassMetadata(Activity::class); | ||||
|  | ||||
|         $reachableScopes = []; | ||||
|  | ||||
|         foreach ($this->centerResolverManager->resolveCenters($person) as $center) { | ||||
|             $reachableScopes = [ | ||||
|                 ...$reachableScopes, | ||||
|                 ...$this->authorizationHelperForCurrentUser->getReachableScopes(ActivityVoter::SEE, $center) | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         if ([] === $reachableScopes) { | ||||
|             $fetchQuery->addWhereClause('FALSE = TRUE'); | ||||
|  | ||||
|             return $fetchQuery; | ||||
|         } | ||||
|  | ||||
|         $fetchQuery->addWhereClause( | ||||
|             sprintf( | ||||
|                 'activity.%s IN (%s)', | ||||
|                 $activityMetadata->getSingleAssociationJoinColumnName('scope'), | ||||
|                 implode(', ', array_fill(0, count($reachableScopes), '?')) | ||||
|             ), | ||||
|             array_map(static fn (Scope $s) => $s->getId(), $reachableScopes), | ||||
|             array_fill(0, count($reachableScopes), Types::INTEGER) | ||||
|         ); | ||||
|  | ||||
|         return $fetchQuery; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,37 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| /* | ||||
|  * Chill is a software for social workers | ||||
|  * | ||||
|  * For the full copyright and license information, please view | ||||
|  * the LICENSE file that was distributed with this source code. | ||||
|  */ | ||||
|  | ||||
| namespace Chill\ActivityBundle\Repository; | ||||
|  | ||||
| use Chill\DocStoreBundle\GenericDoc\FetchQuery; | ||||
| use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface; | ||||
| use Chill\PersonBundle\Entity\Person; | ||||
| use DateTimeImmutable; | ||||
|  | ||||
| /** | ||||
|  * Gives queries usable for fetching documents, with ACL aware | ||||
|  */ | ||||
| interface ActivityDocumentACLAwareRepositoryInterface | ||||
| { | ||||
|     /** | ||||
|      * Return a fetch query for querying document's activities for a person | ||||
|      * | ||||
|      * This method must check the rights to see a document: the user must be allowed to see the given activities | ||||
|      */ | ||||
|     public function buildFetchQueryActivityDocumentLinkedToPersonFromPersonContext(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQueryInterface; | ||||
|  | ||||
|     /** | ||||
|      * Return a fetch query for querying document's activities for an activity in accompanying periods, but for a given person | ||||
|      * | ||||
|      * This method must check the rights to see a document: the user must be allowed to see the given accompanying periods | ||||
|      */ | ||||
|     public function buildFetchQueryActivityDocumentLinkedToAccompanyingPeriodFromPersonContext(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery; | ||||
| } | ||||
| @@ -11,9 +11,13 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace Chill\ActivityBundle\Repository; | ||||
|  | ||||
| use Chill\ActivityBundle\Entity\Activity; | ||||
| use Chill\ActivityBundle\Entity\ActivityType; | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod; | ||||
| use Chill\PersonBundle\Entity\Person; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use Doctrine\ORM\EntityRepository; | ||||
| use Doctrine\ORM\Query\Expr\Join; | ||||
|  | ||||
| final class ActivityTypeRepository implements ActivityTypeRepositoryInterface | ||||
| { | ||||
|   | ||||
| @@ -12,12 +12,14 @@ declare(strict_types=1); | ||||
| namespace Chill\ActivityBundle\Repository; | ||||
|  | ||||
| use Chill\ActivityBundle\Entity\ActivityType; | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod; | ||||
| use Chill\PersonBundle\Entity\Person; | ||||
| use Doctrine\Persistence\ObjectRepository; | ||||
|  | ||||
| interface ActivityTypeRepositoryInterface extends ObjectRepository | ||||
| { | ||||
|     /** | ||||
|      * @return array|ActivityType[] | ||||
|      * @return array<ActivityType> | ||||
|      */ | ||||
|     public function findAllActive(): array; | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,7 @@ | ||||
| // Access to Bootstrap variables and mixins | ||||
| @import '~ChillMainAssets/module/bootstrap/shared'; | ||||
| @import '~ChillPersonAssets/chill/scss/mixins.scss'; | ||||
| @import 'bootstrap/scss/_badge.scss'; | ||||
|  | ||||
| //// ACTIVITY CREATION | ||||
| // first step: select type page | ||||
| @@ -96,3 +98,25 @@ li.document-list-item { | ||||
|     justify-content: space-between; | ||||
|     margin-bottom: 0.3rem; | ||||
| } | ||||
|  | ||||
| .badge-activity-type { | ||||
|     display: inline-block; | ||||
|     background-color: #f3f3f3; | ||||
|  | ||||
|     .title_label { | ||||
|         @include chill_badge(#9acd32); | ||||
|     } | ||||
|  | ||||
|     .title_action { | ||||
|         padding: var(--bs-badge-padding-y) var(--bs-badge-padding-x); | ||||
|         margin-right: 1rem; | ||||
|  | ||||
|         font-size: var(--bs-badge-font-size); | ||||
|         font-weight: var(--bs-badge-font-weight); | ||||
|         line-height: 1; | ||||
|         color: var(--bs-badge-color); | ||||
|         text-align: center; | ||||
|         white-space: nowrap; | ||||
|         vertical-align: baseline; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -80,12 +80,15 @@ | ||||
|  | ||||
| <div class="context-{{ context }}"> | ||||
|  | ||||
|     {{ filter|chill_render_filter_order_helper }} | ||||
|  | ||||
|     {% if activities|length == 0 %} | ||||
|         <p class="chill-no-data-statement"> | ||||
|             {{ "There isn't any activities."|trans }} | ||||
|         </p> | ||||
|  | ||||
|     {% else %} | ||||
|  | ||||
|         <div class="flex-table activity-list"> | ||||
|             {% for activity in activities %} | ||||
|                 {% include 'ChillActivityBundle:Activity:_list_item.html.twig' with { | ||||
| @@ -96,4 +99,6 @@ | ||||
|         </div> | ||||
|     {% endif %} | ||||
|  | ||||
|     {{ chill_pagination(paginator) }} | ||||
|  | ||||
| </div> | ||||
|   | ||||
| @@ -0,0 +1,83 @@ | ||||
| {% import "@ChillDocStore/Macro/macro.html.twig" as m %} | ||||
| {% import "@ChillDocStore/Macro/macro_mimeicon.html.twig" as mm %} | ||||
| {% import '@ChillPerson/Macro/updatedBy.html.twig' as mmm %} | ||||
|  | ||||
| {% set person_id = null %} | ||||
| {% if activity.person %} | ||||
|     {% set person_id = activity.person.id %} | ||||
| {% endif %} | ||||
|  | ||||
| {% set accompanying_course_id = null %} | ||||
| {% if activity.accompanyingPeriod %} | ||||
|     {% set accompanying_course_id = activity.accompanyingPeriod.id %} | ||||
| {% endif %} | ||||
|  | ||||
| <div class="item-bloc activity-item{% if itemBlocClass is defined %} {{ itemBlocClass }}{% endif %}"> | ||||
|     <div class="item-row"> | ||||
|         <div class="item-col" style="width: unset"> | ||||
|             {% if document.isPending %} | ||||
|                 <div class="badge text-bg-info" data-docgen-is-pending="{{ document.id }}">{{ 'docgen.Doc generation is pending'|trans }}</div> | ||||
|             {% elseif document.isFailure %} | ||||
|                 <div class="badge text-bg-warning">{{ 'docgen.Doc generation failed'|trans }}</div> | ||||
|             {% endif %} | ||||
|  | ||||
|             <div> | ||||
|                 {% if activity.accompanyingPeriod is not null and context == 'person' %} | ||||
|                     <span class="badge bg-primary"> | ||||
|                         <i class="fa fa-random"></i> {{ activity.accompanyingPeriod.id }} | ||||
|                     </span>  | ||||
|                 {% endif %} | ||||
|                 <div class="badge-activity-type"> | ||||
|                     <span class="title_label"></span> | ||||
|                     <span class="title_action"> | ||||
|                     {{ activity.type.name | localize_translatable_string }} | ||||
|                         {% if activity.emergency %} | ||||
|                             <span class="badge bg-danger rounded-pill fs-6 float-end">{{ 'Emergency'|trans|upper }}</span> | ||||
|                         {% endif %} | ||||
|                     </span> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="denomination h2"> | ||||
|                 {{ document.title|chill_print_or_message("No title") }} | ||||
|             </div> | ||||
|             {% if document.hasTemplate %} | ||||
|                 <div> | ||||
|                     <p>{{ document.template.name|localize_translatable_string }}</p> | ||||
|                 </div> | ||||
|             {% endif %} | ||||
|         </div> | ||||
|  | ||||
|         <div class="item-col"> | ||||
|             <div class="container"> | ||||
|                 <div class="dates row text-end"> | ||||
|                     <span>{{ document.createdAt|format_date('short') }}</span> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|  | ||||
|     <div class="item-row separator"> | ||||
|         <div class="item-col item-meta"> | ||||
|             {{ mmm.createdBy(document) }} | ||||
|         </div> | ||||
|         <ul class="item-col record_actions flex-shrink-1"> | ||||
|             {% if is_granted('CHILL_ACTIVITY_SEE_DETAILS', activity) %} | ||||
|                 <li> | ||||
|                     {{ document|chill_document_button_group(document.title, is_granted('CHILL_ACTIVITY_UPDATE', activity), {small: false})  }} | ||||
|                 </li> | ||||
|             {% endif %} | ||||
|             {% if is_granted('CHILL_ACTIVITY_SEE', activity)%} | ||||
|                 <li> | ||||
|                     <a href="{{ chill_path_add_return_path('chill_activity_activity_show', {'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id}) }}" class="btn btn-show"></a> | ||||
|                 </li> | ||||
|             {% endif %} | ||||
|             {% if is_granted('CHILL_ACTIVITY_UPDATE', activity) %} | ||||
|                 <li> | ||||
|                     <a href="{{ chill_path_add_return_path('chill_activity_activity_edit', {'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}" class="btn btn-edit"></a> | ||||
|                 </li> | ||||
|             {% endif %} | ||||
|         </ul> | ||||
|  | ||||
|     </div> | ||||
| </div> | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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); | ||||
|                 } | ||||
|             ) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,114 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| /* | ||||
|  * Chill is a software for social workers | ||||
|  * | ||||
|  * For the full copyright and license information, please view | ||||
|  * the LICENSE file that was distributed with this source code. | ||||
|  */ | ||||
|  | ||||
| namespace Chill\ActivityBundle\Service\GenericDoc\Providers; | ||||
|  | ||||
| use Chill\ActivityBundle\Entity\Activity; | ||||
| use Chill\ActivityBundle\Repository\ActivityDocumentACLAwareRepositoryInterface; | ||||
| use Chill\ActivityBundle\Security\Authorization\ActivityVoter; | ||||
| use Chill\DocStoreBundle\Entity\StoredObject; | ||||
| use Chill\DocStoreBundle\GenericDoc\FetchQuery; | ||||
| use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface; | ||||
| use Chill\DocStoreBundle\GenericDoc\GenericDocForAccompanyingPeriodProviderInterface; | ||||
| use Chill\DocStoreBundle\GenericDoc\GenericDocForPersonProviderInterface; | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod; | ||||
| use Chill\PersonBundle\Entity\Person; | ||||
| use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter; | ||||
| use DateTimeImmutable; | ||||
| use Doctrine\DBAL\Types\Types; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use Doctrine\ORM\Mapping\MappingException; | ||||
| use Symfony\Component\Security\Core\Security; | ||||
|  | ||||
| final class AccompanyingPeriodActivityGenericDocProvider implements GenericDocForAccompanyingPeriodProviderInterface, GenericDocForPersonProviderInterface | ||||
| { | ||||
|     public const KEY = 'accompanying_period_activity_document'; | ||||
|  | ||||
|     public function __construct( | ||||
|         private EntityManagerInterface $em, | ||||
|         private Security $security, | ||||
|         private ActivityDocumentACLAwareRepositoryInterface $activityDocumentACLAwareRepository, | ||||
|     ) { | ||||
|     } | ||||
|  | ||||
|     public function buildFetchQueryForAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null, ?string $origin = null): FetchQueryInterface | ||||
|     { | ||||
|         $storedObjectMetadata = $this->em->getClassMetadata(StoredObject::class); | ||||
|         $activityMetadata = $this->em->getClassMetadata(Activity::class); | ||||
|  | ||||
|         $query = new FetchQuery( | ||||
|             self::KEY, | ||||
|             sprintf("jsonb_build_object('id', doc_obj.%s, 'activity_id', activity.%s)", $storedObjectMetadata->getSingleIdentifierColumnName(), $activityMetadata->getSingleIdentifierColumnName()), | ||||
|             'doc_obj.'.$storedObjectMetadata->getColumnName('createdAt'), | ||||
|             $storedObjectMetadata->getSchemaName().'.'.$storedObjectMetadata->getTableName().' AS doc_obj' | ||||
|         ); | ||||
|  | ||||
|         $query->addJoinClause( | ||||
|             'JOIN public.activity_storedobject activity_doc ON activity_doc.storedobject_id = doc_obj.id' | ||||
|         ); | ||||
|  | ||||
|         $query->addJoinClause( | ||||
|             'JOIN public.activity activity ON activity.id = activity_doc.activity_id' | ||||
|         ); | ||||
|  | ||||
|         $query->addWhereClause( | ||||
|             'activity.accompanyingperiod_id = ?', | ||||
|             [$accompanyingPeriod->getId()], | ||||
|             [Types::INTEGER] | ||||
|         ); | ||||
|  | ||||
|         if (null !== $startDate) { | ||||
|             $query->addWhereClause( | ||||
|                 sprintf('doc_obj.%s >= ?', $storedObjectMetadata->getColumnName('createdAt')), | ||||
|                 [$startDate], | ||||
|                 [Types::DATE_IMMUTABLE] | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         if (null !== $endDate) { | ||||
|             $query->addWhereClause( | ||||
|                 sprintf('doc_obj.%s < ?', $storedObjectMetadata->getColumnName('createdAt')), | ||||
|                 [$endDate], | ||||
|                 [Types::DATE_IMMUTABLE] | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         if (null !== $content) { | ||||
|             $query->addWhereClause( | ||||
|                 'doc_obj.title ilike ?', | ||||
|                 ['%' . $content . '%'], | ||||
|                 [Types::STRING] | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         return $query; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccompanyingPeriod $accompanyingPeriod | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function isAllowedForAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): bool | ||||
|     { | ||||
|         return $this->security->isGranted(ActivityVoter::SEE, $accompanyingPeriod); | ||||
|     } | ||||
|  | ||||
|     public function isAllowedForPerson(Person $person): bool | ||||
|     { | ||||
|         return $this->security->isGranted(AccompanyingPeriodVoter::SEE, $person); | ||||
|     } | ||||
|  | ||||
|     public function buildFetchQueryForPerson(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null, ?string $origin = null): FetchQueryInterface | ||||
|     { | ||||
|         return $this->activityDocumentACLAwareRepository | ||||
|             ->buildFetchQueryActivityDocumentLinkedToAccompanyingPeriodFromPersonContext($person, $startDate, $endDate, $content); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,53 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| /* | ||||
|  * Chill is a software for social workers | ||||
|  * | ||||
|  * For the full copyright and license information, please view | ||||
|  * the LICENSE file that was distributed with this source code. | ||||
|  */ | ||||
|  | ||||
| namespace Chill\ActivityBundle\Service\GenericDoc\Providers; | ||||
|  | ||||
| use Chill\ActivityBundle\Repository\ActivityDocumentACLAwareRepository; | ||||
| use Chill\ActivityBundle\Repository\ActivityDocumentACLAwareRepositoryInterface; | ||||
| use Chill\ActivityBundle\Security\Authorization\ActivityVoter; | ||||
| use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface; | ||||
| use Chill\DocStoreBundle\GenericDoc\GenericDocForPersonProviderInterface; | ||||
| use Chill\DocStoreBundle\Repository\PersonDocumentACLAwareRepositoryInterface; | ||||
| use Chill\PersonBundle\Entity\Person; | ||||
| use DateTimeImmutable; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use Symfony\Component\Security\Core\Security; | ||||
|  | ||||
| final readonly class PersonActivityGenericDocProvider implements GenericDocForPersonProviderInterface | ||||
| { | ||||
|     public const KEY = 'person_activity_document'; | ||||
|  | ||||
|     public function __construct( | ||||
|         private Security                                    $security, | ||||
|         private ActivityDocumentACLAwareRepositoryInterface $personActivityDocumentACLAwareRepository, | ||||
|     ) { | ||||
|     } | ||||
|  | ||||
|     public function buildFetchQueryForPerson(Person $person, ?DateTimeImmutable $startDate = null, ?DateTimeImmutable $endDate = null, ?string $content = null, ?string $origin = null): FetchQueryInterface | ||||
|     { | ||||
|         return $this->personActivityDocumentACLAwareRepository->buildFetchQueryActivityDocumentLinkedToPersonFromPersonContext( | ||||
|             $person, | ||||
|             $startDate, | ||||
|             $endDate, | ||||
|             $content | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Person $person | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function isAllowedForPerson(Person $person): bool | ||||
|     { | ||||
|         return $this->security->isGranted(ActivityVoter::SEE, $person); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,52 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| /* | ||||
|  * Chill is a software for social workers | ||||
|  * | ||||
|  * For the full copyright and license information, please view | ||||
|  * the LICENSE file that was distributed with this source code. | ||||
|  */ | ||||
|  | ||||
| namespace Chill\ActivityBundle\Service\GenericDoc\Renderers; | ||||
|  | ||||
| use Chill\ActivityBundle\Repository\ActivityRepository; | ||||
| use Chill\ActivityBundle\Service\GenericDoc\Providers\AccompanyingPeriodActivityGenericDocProvider; | ||||
| use Chill\ActivityBundle\Service\GenericDoc\Providers\PersonActivityGenericDocProvider; | ||||
| use Chill\DocStoreBundle\GenericDoc\GenericDocDTO; | ||||
| use Chill\DocStoreBundle\GenericDoc\Twig\GenericDocRendererInterface; | ||||
| use Chill\DocStoreBundle\Repository\StoredObjectRepository; | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod; | ||||
|  | ||||
| final class AccompanyingPeriodActivityGenericDocRenderer implements GenericDocRendererInterface | ||||
| { | ||||
|     private StoredObjectRepository $objectRepository; | ||||
|  | ||||
|     private ActivityRepository $activityRepository; | ||||
|  | ||||
|     public function __construct(StoredObjectRepository $storedObjectRepository, ActivityRepository $activityRepository) | ||||
|     { | ||||
|         $this->objectRepository = $storedObjectRepository; | ||||
|         $this->activityRepository = $activityRepository; | ||||
|     } | ||||
|  | ||||
|     public function supports(GenericDocDTO $genericDocDTO, $options = []): bool | ||||
|     { | ||||
|         return $genericDocDTO->key === AccompanyingPeriodActivityGenericDocProvider::KEY || $genericDocDTO->key === PersonActivityGenericDocProvider::KEY; | ||||
|     } | ||||
|  | ||||
|     public function getTemplate(GenericDocDTO $genericDocDTO, $options = []): string | ||||
|     { | ||||
|         return '@ChillActivity/GenericDoc/activity_document.html.twig'; | ||||
|     } | ||||
|  | ||||
|     public function getTemplateData(GenericDocDTO $genericDocDTO, $options = []): array | ||||
|     { | ||||
|         return [ | ||||
|             'activity' => $this->activityRepository->find($genericDocDTO->identifiers['activity_id']), | ||||
|             'document' => $this->objectRepository->find($genericDocDTO->identifiers['id']), | ||||
|             'context' => $genericDocDTO->getContext(), | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,325 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| /* | ||||
|  * Chill is a software for social workers | ||||
|  * | ||||
|  * For the full copyright and license information, please view | ||||
|  * the LICENSE file that was distributed with this source code. | ||||
|  */ | ||||
|  | ||||
| namespace Chill\ActivityBundle\Tests\Repository; | ||||
|  | ||||
| use Chill\ActivityBundle\Entity\ActivityType; | ||||
| use Chill\ActivityBundle\Repository\ActivityACLAwareRepository; | ||||
| use Chill\ActivityBundle\Repository\ActivityRepository; | ||||
| use Chill\ActivityBundle\Security\Authorization\ActivityVoter; | ||||
| use Chill\MainBundle\Entity\Center; | ||||
| use Chill\MainBundle\Entity\Scope; | ||||
| use Chill\MainBundle\Entity\User; | ||||
| use Chill\MainBundle\Entity\UserJob; | ||||
| use Chill\MainBundle\Security\Authorization\AuthorizationHelperForCurrentUserInterface; | ||||
| use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface; | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod; | ||||
| use Chill\PersonBundle\Entity\Person; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use Prophecy\Argument; | ||||
| use Prophecy\PhpUnit\ProphecyTrait; | ||||
| use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
| use Symfony\Component\HttpFoundation\RequestStack; | ||||
| use Symfony\Component\Security\Core\Security; | ||||
|  | ||||
| /** | ||||
|  * @internal | ||||
|  * @coversNothing | ||||
|  */ | ||||
| class ActivityACLAwareRepositoryTest extends KernelTestCase | ||||
| { | ||||
|     use ProphecyTrait; | ||||
|     private AuthorizationHelperForCurrentUserInterface $authorizationHelperForCurrentUser; | ||||
|  | ||||
|     private CenterResolverManagerInterface $centerResolverManager; | ||||
|  | ||||
|     private ActivityRepository $activityRepository; | ||||
|  | ||||
|     private EntityManagerInterface $entityManager; | ||||
|  | ||||
|     private Security $security; | ||||
|  | ||||
|     private RequestStack $requestStack; | ||||
|  | ||||
|     protected function setUp(): void | ||||
|     { | ||||
|         self::bootKernel(); | ||||
|  | ||||
|         $this->authorizationHelperForCurrentUser = self::$container->get(AuthorizationHelperForCurrentUserInterface::class); | ||||
|         $this->centerResolverManager = self::$container->get(CenterResolverManagerInterface::class); | ||||
|         $this->activityRepository = self::$container->get(ActivityRepository::class); | ||||
|         $this->entityManager = self::$container->get(EntityManagerInterface::class); | ||||
|         $this->security = self::$container->get(Security::class); | ||||
|  | ||||
|         $this->requestStack = $requestStack = new RequestStack(); | ||||
|         $request = $this->prophesize(Request::class); | ||||
|         $request->getLocale()->willReturn('fr'); | ||||
|         $request->getDefaultLocale()->willReturn('fr'); | ||||
|         $requestStack->push($request->reveal()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @dataProvider provideDataFindByAccompanyingPeriod | ||||
|      */ | ||||
|     public function testFindByAccompanyingPeriod(AccompanyingPeriod $period, User $user, string $role, ?int $start = 0, ?int $limit = 1000, array $orderBy = ['date' => 'DESC'], array $filters = []): void | ||||
|     { | ||||
|         $security = $this->prophesize(Security::class); | ||||
|         $security->isGranted($role, $period)->willReturn(true); | ||||
|         $security->getUser()->willReturn($user); | ||||
|  | ||||
|         $repository = new ActivityACLAwareRepository( | ||||
|             $this->authorizationHelperForCurrentUser, | ||||
|             $this->centerResolverManager, | ||||
|             $this->activityRepository, | ||||
|             $this->entityManager, | ||||
|             $security->reveal(), | ||||
|             $this->requestStack | ||||
|         ); | ||||
|  | ||||
|         $actual = $repository->findByAccompanyingPeriod($period, $role, $start, $limit, $orderBy, $filters); | ||||
|  | ||||
|         self::assertIsArray($actual); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @dataProvider provideDataFindByAccompanyingPeriod | ||||
|      */ | ||||
|     public function testFindActivityTypeByAccompanyingPeriod(AccompanyingPeriod $period, User $user, string $role, ?int $start = 0, ?int $limit = 1000, array $orderBy = ['date' => 'DESC'], array $filters = []): void | ||||
|     { | ||||
|         $security = $this->prophesize(Security::class); | ||||
|         $security->isGranted($role, $period)->willReturn(true); | ||||
|         $security->getUser()->willReturn($user); | ||||
|  | ||||
|         $repository = new ActivityACLAwareRepository( | ||||
|             $this->authorizationHelperForCurrentUser, | ||||
|             $this->centerResolverManager, | ||||
|             $this->activityRepository, | ||||
|             $this->entityManager, | ||||
|             $security->reveal(), | ||||
|             $this->requestStack | ||||
|         ); | ||||
|  | ||||
|         $actual = $repository->findActivityTypeByAssociated($period); | ||||
|  | ||||
|         self::assertIsArray($actual); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @dataProvider provideDataFindByPerson | ||||
|      */ | ||||
|     public function testFindActivityTypeByPerson(Person $person, User $user, array $centers, array $scopes, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = [], array $filters = []): void | ||||
|     { | ||||
|         $role = ActivityVoter::SEE; | ||||
|         $centerResolver = $this->prophesize(CenterResolverManagerInterface::class); | ||||
|         $centerResolver->resolveCenters($person)->willReturn($centers); | ||||
|  | ||||
|         $authorizationHelper = $this->prophesize(AuthorizationHelperForCurrentUserInterface::class); | ||||
|         $authorizationHelper->getReachableScopes($role, Argument::type(Center::class)) | ||||
|             ->willReturn($scopes); | ||||
|  | ||||
|         $security = $this->prophesize(Security::class); | ||||
|         $security->isGranted($role, Argument::type(AccompanyingPeriod::class))->willReturn(true); | ||||
|         $security->getUser()->willReturn($user); | ||||
|  | ||||
|         $repository = new ActivityACLAwareRepository( | ||||
|             $authorizationHelper->reveal(), | ||||
|             $centerResolver->reveal(), | ||||
|             $this->activityRepository, | ||||
|             $this->entityManager, | ||||
|             $security->reveal(), | ||||
|             $this->requestStack | ||||
|         ); | ||||
|  | ||||
|         $actual = $repository->findByPerson($person, $role, $start, $limit, $orderBy, $filters); | ||||
|  | ||||
|         self::assertIsArray($actual); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @dataProvider provideDataFindByPerson | ||||
|      */ | ||||
|     public function testFindByPerson(Person $person, User $user, array $centers, array $scopes, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = [], array $filters = []): void | ||||
|     { | ||||
|         $centerResolver = $this->prophesize(CenterResolverManagerInterface::class); | ||||
|         $centerResolver->resolveCenters($person)->willReturn($centers); | ||||
|  | ||||
|         $authorizationHelper = $this->prophesize(AuthorizationHelperForCurrentUserInterface::class); | ||||
|         $authorizationHelper->getReachableScopes($role, Argument::type(Center::class)) | ||||
|             ->willReturn($scopes); | ||||
|  | ||||
|         $security = $this->prophesize(Security::class); | ||||
|         $security->isGranted($role, Argument::type(AccompanyingPeriod::class))->willReturn(true); | ||||
|         $security->getUser()->willReturn($user); | ||||
|  | ||||
|         $repository = new ActivityACLAwareRepository( | ||||
|             $authorizationHelper->reveal(), | ||||
|             $centerResolver->reveal(), | ||||
|             $this->activityRepository, | ||||
|             $this->entityManager, | ||||
|             $security->reveal(), | ||||
|             $this->requestStack | ||||
|         ); | ||||
|  | ||||
|         $actual = $repository->findByPerson($person, $role, $start, $limit, $orderBy, $filters); | ||||
|  | ||||
|         self::assertIsArray($actual); | ||||
|     } | ||||
|  | ||||
|     public function provideDataFindByPerson(): iterable | ||||
|     { | ||||
|         $this->setUp(); | ||||
|  | ||||
|         /** @var Person $person */ | ||||
|         if (null === $person = $this->entityManager->createQueryBuilder() | ||||
|             ->select('p')->from(Person::class, 'p')->setMaxResults(1) | ||||
|             ->getQuery()->getSingleResult()) { | ||||
|             throw new \RuntimeException("person not found"); | ||||
|         } | ||||
|  | ||||
|         /** @var AccompanyingPeriod $period1 */ | ||||
|         if (null === $period1 = $this->entityManager | ||||
|             ->createQueryBuilder() | ||||
|             ->select('a') | ||||
|             ->from(AccompanyingPeriod::class, 'a') | ||||
|             ->setMaxResults(1) | ||||
|             ->getQuery() | ||||
|             ->getSingleResult()) { | ||||
|             throw new \RuntimeException("no period found"); | ||||
|         } | ||||
|  | ||||
|         /** @var AccompanyingPeriod $period2 */ | ||||
|         if (null === $period2 = $this->entityManager | ||||
|             ->createQueryBuilder() | ||||
|             ->select('a') | ||||
|             ->from(AccompanyingPeriod::class, 'a') | ||||
|             ->where('a.id > :pid') | ||||
|             ->setParameter('pid', $period1->getId()) | ||||
|             ->setMaxResults(1) | ||||
|             ->getQuery() | ||||
|             ->getSingleResult()) { | ||||
|             throw new \RuntimeException("no second period found"); | ||||
|         } | ||||
|         // add a period | ||||
|         $period1->addPerson($person); | ||||
|         $period2->addPerson($person); | ||||
|         $period1->getParticipationsContainsPerson($person)->first()->setEndDate( | ||||
|             (new \DateTime('now'))->add(new \DateInterval('P1M')) | ||||
|         ); | ||||
|  | ||||
|         if ([] === $types = $this->entityManager | ||||
|             ->createQueryBuilder() | ||||
|             ->select('t') | ||||
|             ->from(ActivityType::class, 't') | ||||
|             ->setMaxResults(2) | ||||
|             ->getQuery() | ||||
|             ->getResult()) { | ||||
|             throw new \RuntimeException("no types"); | ||||
|         } | ||||
|  | ||||
|         if ([] === $jobs = $this->entityManager | ||||
|             ->createQueryBuilder() | ||||
|             ->select('j') | ||||
|             ->from(UserJob::class, 'j') | ||||
|             ->setMaxResults(2) | ||||
|             ->getQuery() | ||||
|             ->getResult() | ||||
|         ) { | ||||
|             throw new \RuntimeException("no jobs found"); | ||||
|         } | ||||
|  | ||||
|         if (null === $user = $this->entityManager | ||||
|             ->createQueryBuilder() | ||||
|             ->select('u') | ||||
|             ->from(User::class, 'u') | ||||
|             ->setMaxResults(1) | ||||
|             ->getQuery() | ||||
|             ->getSingleResult() | ||||
|         ) { | ||||
|             throw new \RuntimeException("no user found"); | ||||
|         } | ||||
|  | ||||
|         if ([] === $centers = $this->entityManager->createQueryBuilder() | ||||
|             ->select('c')->from(Center::class, 'c')->setMaxResults(2)->getQuery() | ||||
|             ->getResult()) { | ||||
|             throw new \RuntimeException("no centers found"); | ||||
|         } | ||||
|  | ||||
|         if ([] === $scopes = $this->entityManager->createQueryBuilder() | ||||
|             ->select('s')->from(Scope::class, 's')->setMaxResults(2)->getQuery() | ||||
|             ->getResult()) { | ||||
|             throw new \RuntimeException("no scopes found"); | ||||
|         } | ||||
|  | ||||
|         yield [$person, $user, $centers, $scopes, ActivityVoter::SEE, 0, 5, ['date' => 'DESC'], []]; | ||||
|         yield [$person, $user, $centers, $scopes, ActivityVoter::SEE, 0, 5, ['date' => 'DESC'], ['my_activities' => true]]; | ||||
|         yield [$person, $user, $centers, $scopes, ActivityVoter::SEE, 0, 5, ['date' => 'DESC'], ['types' => $types]]; | ||||
|         yield [$person, $user, $centers, $scopes, ActivityVoter::SEE, 0, 5, ['date' => 'DESC'], ['jobs' => $jobs]]; | ||||
|         yield [$person, $user, $centers, $scopes, ActivityVoter::SEE, 0, 5, ['date' => 'DESC'], ['after' => new \DateTimeImmutable('1 year ago')]]; | ||||
|         yield [$person, $user, $centers, $scopes, ActivityVoter::SEE, 0, 5, ['date' => 'DESC'], ['before' => new \DateTimeImmutable('1 year ago')]]; | ||||
|         yield [$person, $user, $centers, $scopes, ActivityVoter::SEE, 0, 5, ['date' => 'DESC'], ['after' => new \DateTimeImmutable('1 year ago'), 'before' => new \DateTimeImmutable('1 month ago')]]; | ||||
|     } | ||||
|  | ||||
|     public function provideDataFindByAccompanyingPeriod(): iterable | ||||
|     { | ||||
|         $this->setUp(); | ||||
|  | ||||
|         if (null === $period = $this->entityManager | ||||
|             ->createQueryBuilder() | ||||
|             ->select('a') | ||||
|             ->from(AccompanyingPeriod::class, 'a') | ||||
|             ->setMaxResults(1) | ||||
|             ->getQuery() | ||||
|             ->getSingleResult()) { | ||||
|             throw new \RuntimeException("no period found"); | ||||
|         } | ||||
|  | ||||
|         if ([] === $types = $this->entityManager | ||||
|             ->createQueryBuilder() | ||||
|             ->select('t') | ||||
|             ->from(ActivityType::class, 't') | ||||
|             ->setMaxResults(2) | ||||
|             ->getQuery() | ||||
|             ->getResult()) { | ||||
|             throw new \RuntimeException("no types"); | ||||
|         } | ||||
|  | ||||
|         if ([] === $jobs = $this->entityManager | ||||
|             ->createQueryBuilder() | ||||
|             ->select('j') | ||||
|             ->from(UserJob::class, 'j') | ||||
|             ->setMaxResults(2) | ||||
|             ->getQuery() | ||||
|             ->getResult() | ||||
|         ) { | ||||
|             throw new \RuntimeException("no jobs found"); | ||||
|         } | ||||
|  | ||||
|         if (null === $user = $this->entityManager | ||||
|             ->createQueryBuilder() | ||||
|             ->select('u') | ||||
|             ->from(User::class, 'u') | ||||
|             ->setMaxResults(1) | ||||
|             ->getQuery() | ||||
|             ->getSingleResult() | ||||
|         ) { | ||||
|             throw new \RuntimeException("no user found"); | ||||
|         } | ||||
|  | ||||
|         yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], []]; | ||||
|         yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], ['my_activities' => true]]; | ||||
|         yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], ['types' => $types]]; | ||||
|         yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], ['jobs' => $jobs]]; | ||||
|         yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], ['after' => new \DateTimeImmutable('1 year ago')]]; | ||||
|         yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], ['before' => new \DateTimeImmutable('1 year ago')]]; | ||||
|         yield [$period, $user, ActivityVoter::SEE, 0, 10, ['date' => 'DESC'], ['after' => new \DateTimeImmutable('1 year ago'), 'before' => new \DateTimeImmutable('1 month ago')]]; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,126 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| /* | ||||
|  * Chill is a software for social workers | ||||
|  * | ||||
|  * For the full copyright and license information, please view | ||||
|  * the LICENSE file that was distributed with this source code. | ||||
|  */ | ||||
|  | ||||
| namespace Chill\ActivityBundle\Tests\Repository; | ||||
|  | ||||
| use Chill\ActivityBundle\Repository\ActivityDocumentACLAwareRepository; | ||||
| use Chill\ActivityBundle\Security\Authorization\ActivityVoter; | ||||
| use Chill\DocStoreBundle\GenericDoc\FetchQueryToSqlBuilder; | ||||
| use Chill\MainBundle\Entity\Scope; | ||||
| use Chill\MainBundle\Security\Authorization\AuthorizationHelperForCurrentUserInterface; | ||||
| use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface; | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod; | ||||
| use Chill\PersonBundle\Entity\Person; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use phpseclib3\Math\BinaryField; | ||||
| use Prophecy\Argument; | ||||
| use Prophecy\PhpUnit\ProphecyTrait; | ||||
| use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; | ||||
| use Symfony\Component\Security\Core\Security; | ||||
|  | ||||
| /** | ||||
|  * @internal | ||||
|  * @coversNothing | ||||
|  */ | ||||
| class ActivityDocumentACLAwareRepositoryTest extends KernelTestCase | ||||
| { | ||||
|     use ProphecyTrait; | ||||
|  | ||||
|     private EntityManagerInterface $entityManager; | ||||
|  | ||||
|     private CenterResolverManagerInterface $centerResolverManager; | ||||
|  | ||||
|     private AuthorizationHelperForCurrentUserInterface $authorizationHelperForCurrentUser; | ||||
|  | ||||
|     private Security $security; | ||||
|  | ||||
|     protected function setUp(): void | ||||
|     { | ||||
|         self::bootKernel(); | ||||
|         $this->entityManager = self::$container->get(EntityManagerInterface::class); | ||||
|         $this->centerResolverManager = self::$container->get(CenterResolverManagerInterface::class); | ||||
|         $this->authorizationHelperForCurrentUser = self::$container->get(AuthorizationHelperForCurrentUserInterface::class); | ||||
|         $this->security = self::$container->get(Security::class); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @dataProvider provideDataForPerson | ||||
|      */ | ||||
|     public function testBuildFetchQueryActivityDocumentLinkedToPersonFromPersonContext(Person $person, array $reachableScopes, bool $_unused, ?\DateTimeImmutable $startDate, ?\DateTimeImmutable $endDate, ?string $content): void | ||||
|     { | ||||
|         $authorizationHelper = $this->prophesize(AuthorizationHelperForCurrentUserInterface::class); | ||||
|         $authorizationHelper->getReachableScopes(ActivityVoter::SEE, Argument::any()) | ||||
|             ->willReturn($reachableScopes); | ||||
|  | ||||
|         $repository = new ActivityDocumentACLAwareRepository( | ||||
|             $this->entityManager, | ||||
|             $this->centerResolverManager, | ||||
|             $authorizationHelper->reveal(), | ||||
|             $this->security | ||||
|         ); | ||||
|  | ||||
|         $query = $repository->buildFetchQueryActivityDocumentLinkedToPersonFromPersonContext($person, $startDate, $endDate, $content); | ||||
|         ['sql' => $sql, 'params' => $params, 'types' => $types] = (new FetchQueryToSqlBuilder())->toSql($query); | ||||
|  | ||||
|         $nb = $this->entityManager->getConnection()->fetchOne("SELECT COUNT(*) FROM ({$sql}) sq", $params, $types); | ||||
|  | ||||
|         self::assertIsInt($nb); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @dataProvider provideDataForPerson | ||||
|      */ | ||||
|     public function testBuildFetchQueryActivityDocumentLinkedToAccompanyingPeriodFromPersonContext(Person $person, array $_unused, bool $canSeePeriod, ?\DateTimeImmutable $startDate, ?\DateTimeImmutable $endDate, ?string $content): void | ||||
|     { | ||||
|         $security = $this->prophesize(Security::class); | ||||
|         $security->isGranted(ActivityVoter::SEE, Argument::type(AccompanyingPeriod::class)) | ||||
|             ->willReturn($canSeePeriod); | ||||
|  | ||||
|         $repository = new ActivityDocumentACLAwareRepository( | ||||
|             $this->entityManager, | ||||
|             $this->centerResolverManager, | ||||
|             $this->authorizationHelperForCurrentUser, | ||||
|             $security->reveal() | ||||
|         ); | ||||
|  | ||||
|         $query = $repository->buildFetchQueryActivityDocumentLinkedToAccompanyingPeriodFromPersonContext($person, $startDate, $endDate, $content); | ||||
|  | ||||
|         ['sql' => $sql, 'params' => $params, 'types' => $types] = (new FetchQueryToSqlBuilder())->toSql($query); | ||||
|  | ||||
|         $nb = $this->entityManager->getConnection()->fetchOne("SELECT COUNT(*) FROM ({$sql}) sq", $params, $types); | ||||
|  | ||||
|         self::assertIsInt($nb); | ||||
|     } | ||||
|  | ||||
|     public function provideDataForPerson(): iterable | ||||
|     { | ||||
|         $this->setUp(); | ||||
|  | ||||
|         if (null === $person = $this->entityManager->createQuery("SELECT p FROM " . Person::class . " p WHERE SIZE(p.accompanyingPeriodParticipations) > 0 ") | ||||
|             ->setMaxResults(1) | ||||
|             ->getSingleResult()) { | ||||
|             throw new \RuntimeException("no person in dtabase"); | ||||
|         } | ||||
|  | ||||
|         if ([] === $scopes = $this->entityManager->createQuery("SELECT s FROM " . Scope::class . " s ")->setMaxResults(5)->getResult()) { | ||||
|             throw new \RuntimeException("no scopes in database"); | ||||
|         } | ||||
|  | ||||
|         yield [$person, [], true, null, null, null]; | ||||
|         yield [$person, $scopes, true, null, null, null]; | ||||
|         yield [$person, $scopes, true, new \DateTimeImmutable("1 month ago"), null, null]; | ||||
|         yield [$person, $scopes, true, new \DateTimeImmutable("1 month ago"), new \DateTimeImmutable("1 week ago"), null]; | ||||
|         yield [$person, $scopes, true, new \DateTimeImmutable("1 month ago"), new \DateTimeImmutable("1 week ago"), "content"]; | ||||
|         yield [$person, $scopes, true, null, new \DateTimeImmutable("1 week ago"), "content"]; | ||||
|         yield [$person, [], true, new \DateTimeImmutable("1 month ago"), new \DateTimeImmutable("1 week ago"), "content"]; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -161,6 +161,7 @@ class TimelineActivityProvider implements TimelineProviderInterface | ||||
|  | ||||
|         // loop on reachable scopes | ||||
|         foreach ($reachableScopes as $scope) { | ||||
|             /** @phpstan-ignore-next-line  */ | ||||
|             if (in_array($scope->getId(), $scopes_ids, true)) { | ||||
|                 continue; | ||||
|             } | ||||
|   | ||||
| @@ -38,3 +38,6 @@ services: | ||||
|  | ||||
|     Chill\ActivityBundle\Service\EntityInfo\: | ||||
|         resource: '../Service/EntityInfo/' | ||||
|  | ||||
|     Chill\ActivityBundle\Service\GenericDoc\: | ||||
|         resource: '../Service/GenericDoc/' | ||||
|   | ||||
| @@ -83,12 +83,23 @@ Third persons: Tiers non-pro. | ||||
| Others persons: Usagers | ||||
| Third parties: Tiers professionnels | ||||
| Users concerned: T(M)S | ||||
|  | ||||
| activity: | ||||
|     date: Date de l'échange | ||||
|     Insert a document: Insérer un document | ||||
|     Remove a document: Supprimer le document | ||||
|     comment: Commentaire | ||||
| No documents: Aucun document | ||||
|  | ||||
| # activity filter in list page | ||||
| activity_filter: | ||||
|     My activities: Mes échanges (où j'interviens) | ||||
|     Types: Par type d'échange | ||||
|     Jobs: Par métier impliqué | ||||
|     By: Filtrer par | ||||
|     Search: Chercher dans la liste | ||||
|     By date: Filtrer par date | ||||
|  | ||||
| #timeline | ||||
| '%user% has done an %activity_type%': '%user% a effectué un échange de type "%activity_type%"' | ||||
|  | ||||
| @@ -372,3 +383,8 @@ export: | ||||
|                 is sent: envoyé | ||||
|                 is received: reçu | ||||
|                 Group activity by sentreceived: Grouper les échanges par envoyé / reçu | ||||
|  | ||||
| generic_doc: | ||||
|     filter: | ||||
|         keys: | ||||
|             accompanying_period_activity_document: Document des échanges des parcours | ||||
|   | ||||
| @@ -50,6 +50,10 @@ class ByActivityTypeAggregator implements AggregatorInterface | ||||
|     { | ||||
|         // No form needed | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|   | ||||
| @@ -57,6 +57,10 @@ class ByUserJobAggregator implements AggregatorInterface | ||||
|     { | ||||
|         // nothing to add in the form | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|   | ||||
| @@ -57,6 +57,10 @@ class ByUserScopeAggregator implements AggregatorInterface | ||||
|     { | ||||
|         // nothing to add in the form | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|   | ||||
| @@ -34,6 +34,10 @@ class AvgAsideActivityDuration implements ExportInterface, GroupedExportInterfac | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getAllowedFormattersTypes(): array | ||||
|     { | ||||
|   | ||||
| @@ -34,6 +34,10 @@ class CountAsideActivity implements ExportInterface, GroupedExportInterface | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getAllowedFormattersTypes(): array | ||||
|     { | ||||
|   | ||||
| @@ -73,6 +73,10 @@ final class ListAsideActivity implements ListInterface, GroupedExportInterface | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getAllowedFormattersTypes() | ||||
|     { | ||||
|   | ||||
| @@ -34,6 +34,10 @@ class SumAsideActivityDuration implements ExportInterface, GroupedExportInterfac | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function getAllowedFormattersTypes(): array | ||||
|     { | ||||
|   | ||||
| @@ -76,6 +76,10 @@ class ByActivityTypeFilter implements FilterInterface | ||||
|                 }, | ||||
|             ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string'): array | ||||
|     { | ||||
|   | ||||
| @@ -72,11 +72,9 @@ class ByDateFilter implements FilterInterface | ||||
|         $builder | ||||
|             ->add('date_from', PickRollingDateType::class, [ | ||||
|                 'label' => 'export.filter.Aside activities after this date', | ||||
|                 'data' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START), | ||||
|             ]) | ||||
|             ->add('date_to', PickRollingDateType::class, [ | ||||
|                 'label' => 'export.filter.Aside activities before this date', | ||||
|                 'data' => new RollingDate(RollingDate::T_TODAY), | ||||
|             ]); | ||||
|  | ||||
|         $builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) { | ||||
| @@ -119,6 +117,10 @@ class ByDateFilter implements FilterInterface | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return ['date_from' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START), 'date_to' => new RollingDate(RollingDate::T_TODAY)]; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string'): array | ||||
|     { | ||||
|   | ||||
| @@ -53,6 +53,10 @@ class ByUserFilter implements FilterInterface | ||||
|             'label' => 'Creators', | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string'): array | ||||
|     { | ||||
|   | ||||
| @@ -60,6 +60,10 @@ class ByUserJobFilter implements FilterInterface | ||||
|             'expanded' => true, | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string') | ||||
|     { | ||||
|   | ||||
| @@ -67,6 +67,10 @@ class ByUserScopeFilter implements FilterInterface | ||||
|             'expanded' => true, | ||||
|         ]); | ||||
|     } | ||||
|     public function getFormDefaultData(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string') | ||||
|     { | ||||
|   | ||||
| @@ -176,11 +176,12 @@ export: | ||||
|         agent_id: Utilisateur | ||||
|         creator_id: Créateur | ||||
|         main_scope: Service principal de l'utilisateur | ||||
|         main_center: Centre principal de l'utilisteur | ||||
|         main_center: Centre principal de l'utilisateur | ||||
|         aside_activity_type: Catégorie d'activité annexe | ||||
|         date: Date | ||||
|         duration: Durée | ||||
|         note: Note | ||||
|         id: Identifiant | ||||
|  | ||||
|     Exports of aside activities: Exports des activités annexes | ||||
|     Count aside activities: Nombre d'activités annexes | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user