mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-10-31 01:08:26 +00:00 
			
		
		
		
	Compare commits
	
		
			6 Commits
		
	
	
		
			issue706_c
			...
			fix-calend
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b8341484d4 | |||
| 9dcee26901 | |||
| 5789d7feff | |||
| fee0a5ce58 | |||
| 3ad5e592e7 | |||
| ac42fdff25 | 
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -3,9 +3,7 @@ composer | ||||
| composer.phar | ||||
| composer.lock | ||||
| docs/build/ | ||||
| node_modules/* | ||||
| .php_cs.cache | ||||
| .cache/* | ||||
|  | ||||
| ###> symfony/framework-bundle ### | ||||
| /.env.local | ||||
| @@ -26,5 +24,3 @@ node_modules/* | ||||
| /.php-cs-fixer.cache | ||||
| /.idea/ | ||||
| /.psalm/ | ||||
|  | ||||
| node_modules/* | ||||
|   | ||||
| @@ -9,22 +9,18 @@ | ||||
|     ], | ||||
|     "require": { | ||||
|         "php": "^7.4", | ||||
|         "ext-json": "*", | ||||
|         "ext-openssl": "*", | ||||
|         "ext-redis": "*", | ||||
|         "champs-libres/async-uploader-bundle": "dev-sf4#d57134aee8e504a83c902ff0cf9f8d36ac418290", | ||||
|         "champs-libres/wopi-bundle": "dev-master@dev", | ||||
|         "champs-libres/wopi-lib": "dev-master@dev", | ||||
|         "champs-libres/wopi-bundle": "dev-master#6dd8e0a14e00131eb4b889ecc30270ee4a0e5224", | ||||
|         "champs-libres/wopi-lib": "dev-master#8615f4a45a39fc2b6a98765ea835fcfd39618787", | ||||
|         "doctrine/doctrine-bundle": "^2.1", | ||||
|         "doctrine/doctrine-migrations-bundle": "^3.0", | ||||
|         "doctrine/orm": "^2.13.0", | ||||
|         "doctrine/orm": "^2.7", | ||||
|         "erusev/parsedown": "^1.7", | ||||
|         "graylog2/gelf-php": "^1.5", | ||||
|         "knplabs/knp-menu-bundle": "^3.0", | ||||
|         "knplabs/knp-time-bundle": "^1.12", | ||||
|         "knpuniversity/oauth2-client-bundle": "^2.10", | ||||
|         "league/csv": "^9.7.1", | ||||
|         "lexik/jwt-authentication-bundle": "^2.16", | ||||
|         "nyholm/psr7": "^1.4", | ||||
|         "ocramius/package-versions": "^1.10 || ^2", | ||||
|         "odolbeau/phone-number-bundle": "^3.6", | ||||
| @@ -33,12 +29,12 @@ | ||||
|         "ramsey/uuid-doctrine": "^1.7", | ||||
|         "sensio/framework-extra-bundle": "^5.5", | ||||
|         "spomky-labs/base64url": "^2.0", | ||||
|         "symfony/asset": "^4.4", | ||||
|         "symfony/browser-kit": "^4.4", | ||||
|         "symfony/css-selector": "^4.4", | ||||
|         "symfony/expression-language": "^4.4", | ||||
|         "symfony/form": "^4.4", | ||||
|         "symfony/framework-bundle": "^4.4", | ||||
|         "symfony/http-client": "^4.4 || ^5", | ||||
|         "symfony/http-foundation": "^4.4", | ||||
|         "symfony/intl": "^4.4", | ||||
|         "symfony/mailer": "^5.4", | ||||
| @@ -52,6 +48,7 @@ | ||||
|         "symfony/translation": "^4.4", | ||||
|         "symfony/twig-bundle": "^4.4", | ||||
|         "symfony/validator": "^4.4", | ||||
|         "symfony/web-link": "*", | ||||
|         "symfony/webpack-encore-bundle": "^1.11", | ||||
|         "symfony/workflow": "^4.4", | ||||
|         "symfony/yaml": "^4.4", | ||||
| @@ -75,7 +72,8 @@ | ||||
|         "symfony/maker-bundle": "^1.20", | ||||
|         "symfony/phpunit-bridge": "^4.4", | ||||
|         "symfony/stopwatch": "^4.4", | ||||
|         "symfony/var-dumper": "^4.4" | ||||
|         "symfony/var-dumper": "^4.4", | ||||
|         "symfony/web-profiler-bundle": "^4.4" | ||||
|     }, | ||||
|     "conflict": { | ||||
|         "symfony/symfony": "*" | ||||
|   | ||||
| @@ -1,93 +0,0 @@ | ||||
|  | ||||
| .. Copyright (C)  2014-2023 Champs Libres Cooperative SCRLFS | ||||
|     Permission is granted to copy, distribute and/or modify this document | ||||
|     under the terms of the GNU Free Documentation License, Version 1.3 | ||||
|     or any later version published by the Free Software Foundation; | ||||
|     with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. | ||||
|     A copy of the license is included in the section entitled "GNU | ||||
|     Free Documentation License". | ||||
|  | ||||
| .. _cronjob: | ||||
|  | ||||
| Cron jobs | ||||
| ********* | ||||
|  | ||||
| Some tasks must be executed regularly: refresh some materialized views, remove old data, ... | ||||
|  | ||||
| For this purpose, one can programmatically implements a "cron job", which will be scheduled by a specific command. | ||||
|  | ||||
| The command :code:`chill:cron-job:execute` | ||||
| ========================================== | ||||
|  | ||||
| The command :code:`chill:cron-job:execute` will schedule a task, one by one. In a classical implementation, it should | ||||
| be executed every 15 minutes (more or less), to ensure that every task can be executed. | ||||
|  | ||||
| .. warning:: | ||||
|  | ||||
|    This command should not be executed in parallel. The installer should ensure that two job are executed concurrently. | ||||
|  | ||||
| How to implements a cron job ? | ||||
| ============================== | ||||
|  | ||||
| Implements a :code:`Chill\MainBundle\Cron\CronJobInterface`. Here is an example: | ||||
|  | ||||
| .. code-block:: php | ||||
|  | ||||
|     namespace Chill\MainBundle\Service\Something; | ||||
|  | ||||
|     use Chill\MainBundle\Cron\CronJobInterface; | ||||
|     use Chill\MainBundle\Entity\CronJobExecution; | ||||
|     use DateInterval; | ||||
|     use DateTimeImmutable; | ||||
|  | ||||
|     class MyCronJob implements CronJobInterface | ||||
|     { | ||||
|         public function canRun(?CronJobExecution $cronJobExecution): bool | ||||
|         { | ||||
|             // the parameter $cronJobExecution contains data about the last execution of the cronjob | ||||
|             // if it is null, it should be executed immediatly | ||||
|             if (null === $cronJobExecution) { | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             if ($cronJobExecution->getKey() !== $this->getKey()) { | ||||
|                 throw new UnexpectedValueException(); | ||||
|             } | ||||
|  | ||||
|             // this cron job should be executed if the last execution is greater than one day, but only during the night | ||||
|  | ||||
|             $now = new DateTimeImmutable('now'); | ||||
|  | ||||
|             return $cronJobExecution->getLastStart() < $now->sub(new DateInterval('P1D')) | ||||
|                 && in_array($now->format('H'), self::ACCEPTED_HOURS, true) | ||||
|                 // introduce a random component to ensure a roll of task execution when multiple instances are hosted on same machines | ||||
|                 && mt_rand(0, 5) === 0; | ||||
|         } | ||||
|  | ||||
|         public function getKey(): string | ||||
|         { | ||||
|             return 'arbitrary-and-unique-key'; | ||||
|         } | ||||
|  | ||||
|         public function run(): void | ||||
|         { | ||||
|             // here, we execute the command | ||||
|         } | ||||
|     } | ||||
|  | ||||
| How are cron job scheduled ? | ||||
| ============================ | ||||
|  | ||||
| If the command :code:`chill:cron-job:execute` is run with one or more :code:`job` argument, those jobs are run, **without checking that the job can run** (the method :code:`canRun` is not executed). | ||||
|  | ||||
| If any :code:`job` argument is given, the :code:`CronManager` schedule job with those steps: | ||||
|  | ||||
| * the tasks are ordered, with: | ||||
|    * a priority is given for tasks that weren't never executed; | ||||
|    * then, the tasks are ordered, the last executed are the first in the list | ||||
| * then, for each tasks, and in the given order, the first task where :code:`canRun` return :code:`TRUE` will be executed. | ||||
|  | ||||
| The command :code:`chill:cron-job:execute` execute **only one** task. | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -34,7 +34,6 @@ As Chill rely on the `symfony <http://symfony.com>`_ framework, reading the fram | ||||
|     Useful snippets <useful-snippets.rst> | ||||
|     manual/index.rst | ||||
|     Assets <assets.rst> | ||||
|     Cron Jobs <cronjob.rst> | ||||
|  | ||||
| Layout and UI | ||||
| ************** | ||||
|   | ||||
| @@ -18,7 +18,6 @@ Installation & Usage | ||||
|    :maxdepth: 2 | ||||
|  | ||||
|    prod.rst | ||||
|    load-addresses.rst | ||||
|    prod-calendar-sms-sending.rst | ||||
|    msgraph-configure.rst | ||||
|  | ||||
| @@ -171,7 +170,7 @@ There are several users available: | ||||
|  | ||||
| The password is always ``password``. | ||||
|  | ||||
| Now, read `Operations` below. For running in production, read `prod_`. | ||||
| Now, read `Operations` below. | ||||
|  | ||||
|  | ||||
| Operations | ||||
|   | ||||
| @@ -1,50 +0,0 @@ | ||||
|  | ||||
| .. _addresses: | ||||
|  | ||||
| Addresses | ||||
| ********* | ||||
|  | ||||
| Chill can store a list of geolocated address references, which are used to suggest address and ensure that the data is correctly stored. | ||||
|  | ||||
| Those addresses may be load from a dedicated source. | ||||
|  | ||||
| In France | ||||
| ========= | ||||
|  | ||||
| The address are loaded from the `BANO <https://bano.openstreetmap.fr/>`_. The postal codes are loaded from `the official list of | ||||
| postal codes <https://datanova.laposte.fr/explore/dataset/laposte_hexasmal/information/>`_ | ||||
|  | ||||
| .. code-block:: bash | ||||
|  | ||||
|    # first, load postal codes | ||||
|    bin/console chill:main:postal-code:load:FR | ||||
|    # then, load all addresses, by departement (multiple departement can be loaded by repeating the departement code | ||||
|    bin/console chill:main:address-ref-from-bano 57 54 51 | ||||
|  | ||||
| In Belgium | ||||
| ========== | ||||
|  | ||||
| Addresses are prepared from the `BeST Address data <https://www.geo.be/catalog/details/ca0fd5c0-8146-11e9-9012-482ae30f98d9>`_. | ||||
|  | ||||
| Postal code are loaded from this database. There is no need to load postal codes from another source (actually, this is strongly discouraged). | ||||
|  | ||||
| The data are prepared for Chill (`See this repository <https://gitea.champs-libres.be/Chill-project/belgian-bestaddresses-transform/releases>`_). | ||||
| One can select postal code by his first number (:code:`1xxx` for postal codes from 1000 to 1999), or a limited list for development purpose. | ||||
|  | ||||
| .. code-block:: bash | ||||
|  | ||||
|    # load postal code from 1000 to 3999: | ||||
|    bin/console chill:main:address-ref-from-best-addresse 1xxx 2xxx 3xxx | ||||
|  | ||||
|    # load only an extract (for dev purposes) | ||||
|    bin/console chill:main:address-ref-from-best-addresse extract | ||||
|  | ||||
|    # load full addresses (discouraged) | ||||
|    bin/console chill:main:address-ref-from-best-addresse full | ||||
|  | ||||
| .. note:: | ||||
|  | ||||
|    There is a possibility to load the full list of addresses is discouraged: the loading is optimized with smaller extracts. | ||||
|  | ||||
|    Once you load the full list, it is not possible to load smaller extract: each extract loaded **after** will not | ||||
|    delete the addresses loaded with the full extract (and some addresses will be present twice). | ||||
| @@ -1,12 +1,10 @@ | ||||
| .. Copyright (C)  2014-2019 Champs Libres Cooperative SCRLFS | ||||
|     Permission is granted to copy, distribute and/or modify this document | ||||
|     under the terms of the GNU Free Documentation License, Version 1.3 | ||||
|     or any later version published by the Free Software Foundation; | ||||
|     with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. | ||||
|     A copy of the license is included in the section entitled "GNU | ||||
|     Free Documentation License". | ||||
|  | ||||
| .. _prod: | ||||
| Permission is granted to copy, distribute and/or modify this document | ||||
| under the terms of the GNU Free Documentation License, Version 1.3 | ||||
| or any later version published by the Free Software Foundation; | ||||
| with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. | ||||
| A copy of the license is included in the section entitled "GNU | ||||
| Free Documentation License". | ||||
|  | ||||
| Installation for production | ||||
| ########################### | ||||
| @@ -38,25 +36,12 @@ This should be adapted to your needs: | ||||
|  | ||||
| * Think about how you will backup your database. Some adminsys find easier to store database outside of docker, which might be easier to administrate or replicate. | ||||
|  | ||||
| Cron jobs | ||||
| ========= | ||||
|  | ||||
| The command :code:`chill:cron-job:execute` should be executed every 15 minutes (more or less). | ||||
|  | ||||
| This command should never be executed concurrently. It should be not have more than one process for a single instance. | ||||
|  | ||||
| Post-install tasks | ||||
| ================== | ||||
|  | ||||
| - import addresses. See :ref:`addresses`. | ||||
|  | ||||
|  | ||||
| Tweak symfony messenger | ||||
| ======================= | ||||
|  | ||||
| Calendar sync is processed using symfony messenger. | ||||
|  | ||||
| You can tweak the configuration | ||||
| You can tweak the configuration  | ||||
|  | ||||
| Going further: | ||||
|  | ||||
|   | ||||
| @@ -5,70 +5,69 @@ Add condition with distinct alias on each export join clauses (Indicators + Filt | ||||
|  | ||||
| These are alias conventions : | ||||
|  | ||||
| | Entity                                  | Join                                    | Attribute                                  | Alias                                  | | ||||
| |:----------------------------------------|:----------------------------------------|:-------------------------------------------|:---------------------------------------| | ||||
| | AccompanyingPeriod::class               |                                         |                                            | acp                                    | | ||||
| |                                         | AccompanyingPeriodWork::class           | acp.works                                  | acpw                                   | | ||||
| |                                         | AccompanyingPeriodParticipation::class  | acp.participations                         | acppart                                | | ||||
| |                                         | Location::class                         | acp.administrativeLocation                 | acploc                                 | | ||||
| |                                         | ClosingMotive::class                    | acp.closingMotive                          | acpmotive                              | | ||||
| |                                         | UserJob::class                          | acp.job                                    | acpjob                                 | | ||||
| |                                         | Origin::class                           | acp.origin                                 | acporigin                              | | ||||
| |                                         | Scope::class                            | acp.scopes                                 | acpscope                               | | ||||
| |                                         | SocialIssue::class                      | acp.socialIssues                           | acpsocialissue                         | | ||||
| |                                         | User::class                             | acp.user                                   | acpuser                                | | ||||
| |                                         | AccompanyingPeriopStepHistory::class    | acp.stepHistories                          | acpstephistories                       | | ||||
| | AccompanyingPeriodWork::class           |                                         |                                            | acpw                                   | | ||||
| |                                         | AccompanyingPeriodWorkEvaluation::class | acpw.accompanyingPeriodWorkEvaluations     | workeval                               | | ||||
| |                                         | User::class                             | acpw.referrers                             | acpwuser                               | | ||||
| |                                         | SocialAction::class                     | acpw.socialAction                          | acpwsocialaction                       | | ||||
| |                                         | Goal::class                             | acpw.goals                                 | goal                                   | | ||||
| |                                         | Result::class                           | acpw.results                               | result                                 | | ||||
| | AccompanyingPeriodParticipation::class  |                                         |                                            | acppart                                | | ||||
| |                                         | Person::class                           | acppart.person                             | partperson                             | | ||||
| | AccompanyingPeriodWorkEvaluation::class |                                         |                                            | workeval                               | | ||||
| |                                         | Evaluation::class                       | workeval.evaluation                        | eval                                   | | ||||
| | Goal::class                             |                                         |                                            | goal                                   | | ||||
| |                                         | Result::class                           | goal.results                               | goalresult                             | | ||||
| | Person::class                           |                                         |                                            | person                                 | | ||||
| |                                         | Center::class                           | person.center                              | center                                 | | ||||
| |                                         | HouseholdMember::class                  | partperson.householdParticipations         | householdmember                        | | ||||
| |                                         | MaritalStatus::class                    | person.maritalStatus                       | personmarital                          | | ||||
| |                                         | VendeePerson::class                     |                                            | vp                                     | | ||||
| |                                         | VendeePersonMineur::class               |                                            | vpm                                    | | ||||
| |                                         | CurrentPersonAddress::class             | person.currentPersonAddress                | currentPersonAddress (on a given date) | | ||||
| | ResidentialAddress::class               |                                         |                                            | resaddr                                | | ||||
| |                                         | ThirdParty::class                       | resaddr.hostThirdParty                     | tparty                                 | | ||||
| | ThirdParty::class                       |                                         |                                            | tparty                                 | | ||||
| |                                         | ThirdPartyCategory::class               | tparty.categories                          | tpartycat                              | | ||||
| | HouseholdMember::class                  |                                         |                                            | householdmember                        | | ||||
| |                                         | Household::class                        | householdmember.household                  | household                              | | ||||
| |                                         | Person::class                           | householdmember.person                     | memberperson                           | | ||||
| |                                         |                                         | memberperson.center                        | membercenter                           | | ||||
| | Household::class                        |                                         |                                            | household                              | | ||||
| |                                         | HouseholdComposition::class             | household.compositions                     | composition                            | | ||||
| | Activity::class                         |                                         |                                            | activity                               | | ||||
| |                                         | Person::class                           | activity.person                            | actperson                              | | ||||
| |                                         | AccompanyingPeriod::class               | activity.accompanyingPeriod                | acp                                    | | ||||
| |                                         | Person::class                           | activity\_person\_having\_activity.person  | person\_person\_having\_activity       | | ||||
| |                                         | ActivityReason::class                   | activity\_person\_having\_activity.reasons | reasons\_person\_having\_activity      | | ||||
| |                                         | ActivityType::class                     | activity.activityType                      | acttype                                | | ||||
| |                                         | Location::class                         | activity.location                          | actloc                                 | | ||||
| |                                         | SocialAction::class                     | activity.socialActions                     | actsocialaction                        | | ||||
| |                                         | SocialIssue::class                      | activity.socialIssues                      | actsocialssue                          | | ||||
| |                                         | ThirdParty::class                       | activity.thirdParties                      | acttparty                              | | ||||
| |                                         | User::class                             | activity.user                              | actuser                                | | ||||
| |                                         | User::class                             | activity.users                             | actusers                               | | ||||
| |                                         | ActivityReason::class                   | activity.reasons                           | actreasons                             | | ||||
| |                                         | Center::class                           | actperson.center                           | actcenter                              | | ||||
| |                                         | Person::class                           | activity.createdBy                         | actcreator                             | | ||||
| | ActivityReason::class                   |                                         |                                            | actreasons                             | | ||||
| |                                         | ActivityReasonCategory::class           | actreason.category                         | actreasoncat                           | | ||||
| | Calendar::class                         |                                         |                                            | cal                                    | | ||||
| |                                         | CancelReason::class                     | cal.cancelReason                           | calcancel                              | | ||||
| |                                         | Location::class                         | cal.location                               | calloc                                 | | ||||
| |                                         | User::class                             | cal.user                                   | caluser                                | | ||||
| | VendeePerson::class                     |                                         |                                            | vp                                     | | ||||
| |                                         | SituationProfessionelle::class          | vp.situationProfessionelle                 | vpprof                                 | | ||||
| |                                         | StatutLogement::class                   | vp.statutLogement                          | vplog                                  | | ||||
| |                                         | TempsDeTravail::class                   | vp.tempsDeTravail                          | vptt                                   | | ||||
| | Entity                                  | Join                                    | Attribute                                  | Alias                             | | ||||
| |:----------------------------------------|:----------------------------------------|:-------------------------------------------|:----------------------------------| | ||||
| | AccompanyingPeriod::class               |                                         |                                            | acp                               | | ||||
| |                                         | AccompanyingPeriodWork::class           | acp.works                                  | acpw                              | | ||||
| |                                         | AccompanyingPeriodParticipation::class  | acp.participations                         | acppart                           | | ||||
| |                                         | Location::class                         | acp.administrativeLocation                 | acploc                            | | ||||
| |                                         | ClosingMotive::class                    | acp.closingMotive                          | acpmotive                         | | ||||
| |                                         | UserJob::class                          | acp.job                                    | acpjob                            | | ||||
| |                                         | Origin::class                           | acp.origin                                 | acporigin                         | | ||||
| |                                         | Scope::class                            | acp.scopes                                 | acpscope                          | | ||||
| |                                         | SocialIssue::class                      | acp.socialIssues                           | acpsocialissue                    | | ||||
| |                                         | User::class                             | acp.user                                   | acpuser                           | | ||||
| |                                         | AccompanyingPeriopStepHistory::class    | acp.stepHistories                          | acpstephistories                  | | ||||
| | AccompanyingPeriodWork::class           |                                         |                                            | acpw                              | | ||||
| |                                         | AccompanyingPeriodWorkEvaluation::class | acpw.accompanyingPeriodWorkEvaluations     | workeval                          | | ||||
| |                                         | User::class                             | acpw.referrers                             | acpwuser                          | | ||||
| |                                         | SocialAction::class                     | acpw.socialAction                          | acpwsocialaction                  | | ||||
| |                                         | Goal::class                             | acpw.goals                                 | goal                              | | ||||
| |                                         | Result::class                           | acpw.results                               | result                            | | ||||
| | AccompanyingPeriodParticipation::class  |                                         |                                            | acppart                           | | ||||
| |                                         | Person::class                           | acppart.person                             | partperson                        | | ||||
| | AccompanyingPeriodWorkEvaluation::class |                                         |                                            | workeval                          | | ||||
| |                                         | Evaluation::class                       | workeval.evaluation                        | eval                              | | ||||
| | Goal::class                             |                                         |                                            | goal                              | | ||||
| |                                         | Result::class                           | goal.results                               | goalresult                        | | ||||
| | Person::class                           |                                         |                                            | person                            | | ||||
| |                                         | Center::class                           | person.center                              | center                            | | ||||
| |                                         | HouseholdMember::class                  | partperson.householdParticipations         | householdmember                   | | ||||
| |                                         | MaritalStatus::class                    | person.maritalStatus                       | personmarital                     | | ||||
| |                                         | VendeePerson::class                     |                                            | vp                                | | ||||
| |                                         | VendeePersonMineur::class               |                                            | vpm                               | | ||||
| | ResidentialAddress::class               |                                         |                                            | resaddr                           | | ||||
| |                                         | ThirdParty::class                       | resaddr.hostThirdParty                     | tparty                            | | ||||
| | ThirdParty::class                       |                                         |                                            | tparty                            | | ||||
| |                                         | ThirdPartyCategory::class               | tparty.categories                          | tpartycat                         | | ||||
| | HouseholdMember::class                  |                                         |                                            | householdmember                   | | ||||
| |                                         | Household::class                        | householdmember.household                  | household                         | | ||||
| |                                         | Person::class                           | householdmember.person                     | memberperson                      | | ||||
| |                                         |                                         | memberperson.center                        | membercenter                      | | ||||
| | Household::class                        |                                         |                                            | household                         | | ||||
| |                                         | HouseholdComposition::class             | household.compositions                     | composition                       | | ||||
| | Activity::class                         |                                         |                                            | activity                          | | ||||
| |                                         | Person::class                           | activity.person                            | actperson                         | | ||||
| |                                         | AccompanyingPeriod::class               | activity.accompanyingPeriod                | acp                               | | ||||
| |                                         | Person::class                           | activity\_person\_having\_activity.person  | person\_person\_having\_activity  | | ||||
| |                                         | ActivityReason::class                   | activity\_person\_having\_activity.reasons | reasons\_person\_having\_activity | | ||||
| |                                         | ActivityType::class                     | activity.activityType                      | acttype                           | | ||||
| |                                         | Location::class                         | activity.location                          | actloc                            | | ||||
| |                                         | SocialAction::class                     | activity.socialActions                     | actsocialaction                   | | ||||
| |                                         | SocialIssue::class                      | activity.socialIssues                      | actsocialssue                     | | ||||
| |                                         | ThirdParty::class                       | activity.thirdParties                      | acttparty                         | | ||||
| |                                         | User::class                             | activity.user                              | actuser                           | | ||||
| |                                         | User::class                             | activity.users                             | actusers                          | | ||||
| |                                         | ActivityReason::class                   | activity.reasons                           | actreasons                        | | ||||
| |                                         | Center::class                           | actperson.center                           | actcenter                         | | ||||
| |                                         | Person::class                           | activity.createdBy                         | actcreator                        | | ||||
| | ActivityReason::class                   |                                         |                                            | actreasons                        | | ||||
| |                                         | ActivityReasonCategory::class           | actreason.category                         | actreasoncat                      | | ||||
| | Calendar::class                         |                                         |                                            | cal                               | | ||||
| |                                         | CancelReason::class                     | cal.cancelReason                           | calcancel                         | | ||||
| |                                         | Location::class                         | cal.location                               | calloc                            | | ||||
| |                                         | User::class                             | cal.user                                   | caluser                           | | ||||
| | VendeePerson::class                     |                                         |                                            | vp                                | | ||||
| |                                         | SituationProfessionelle::class          | vp.situationProfessionelle                 | vpprof                            | | ||||
| |                                         | StatutLogement::class                   | vp.statutLogement                          | vplog                             | | ||||
| |                                         | TempsDeTravail::class                   | vp.tempsDeTravail                          | vptt                              | | ||||
|   | ||||
							
								
								
									
										67
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								package.json
									
									
									
									
									
								
							| @@ -1,67 +0,0 @@ | ||||
| { | ||||
|     "name": "chill", | ||||
|     "version": "2.0.0", | ||||
|     "devDependencies": { | ||||
|     "@alexlafroscia/yaml-merge": "^4.0.0", | ||||
|     "@apidevtools/swagger-cli": "^4.0.4", | ||||
|     "@babel/core": "^7.20.5", | ||||
|     "@babel/preset-env": "^7.20.2", | ||||
|     "@ckeditor/ckeditor5-build-classic": "^35.3.2", | ||||
|     "@ckeditor/ckeditor5-dev-utils": "^31.1.13", | ||||
|     "@ckeditor/ckeditor5-dev-webpack-plugin": "^31.1.13", | ||||
|     "@ckeditor/ckeditor5-markdown-gfm": "^35.3.2", | ||||
|     "@ckeditor/ckeditor5-theme-lark": "^35.3.2", | ||||
|     "@ckeditor/ckeditor5-vue": "^4.0.1", | ||||
|     "@symfony/webpack-encore": "^4.1.0", | ||||
|     "@tsconfig/node14": "^1.0.1", | ||||
|     "bindings": "^1.5.0", | ||||
|     "bootstrap": "^5.0.1", | ||||
|     "chokidar": "^3.5.1", | ||||
|     "fork-awesome": "^1.1.7", | ||||
|     "jquery": "^3.6.0", | ||||
|     "node-sass": "^8.0.0", | ||||
|     "popper.js": "^1.16.1", | ||||
|     "postcss-loader": "^7.0.2", | ||||
|     "raw-loader": "^4.0.2", | ||||
|     "sass-loader": "^13.0.0", | ||||
|     "select2": "^4.0.13", | ||||
|     "select2-bootstrap-theme": "0.1.0-beta.10", | ||||
|     "style-loader": "^3.3.1", | ||||
|     "ts-loader": "^9.3.1", | ||||
|     "typescript": "^4.7.2", | ||||
|     "vue-loader": "^17.0.0", | ||||
|     "webpack": "^5.75.0", | ||||
|     "webpack-cli": "^5.0.1" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "@fullcalendar/core": "^5.11.0", | ||||
|     "@fullcalendar/daygrid": "^5.11.0", | ||||
|     "@fullcalendar/interaction": "^5.11.0", | ||||
|     "@fullcalendar/list": "^5.11.0", | ||||
|     "@fullcalendar/timegrid": "^5.11.0", | ||||
|     "@fullcalendar/vue3": "^5.11.1", | ||||
|     "@popperjs/core": "^2.9.2", | ||||
|     "dropzone": "^5.7.6", | ||||
|     "es6-promise": "^4.2.8", | ||||
|     "leaflet": "^1.7.1", | ||||
|     "masonry-layout": "^4.2.2", | ||||
|     "mime": "^3.0.0", | ||||
|     "swagger-ui": "^4.15.5", | ||||
|     "vis-network": "^9.1.0", | ||||
|     "vue": "^3.2.37", | ||||
|     "vue-i18n": "^9.1.6", | ||||
|     "vue-multiselect": "3.0.0-alpha.2", | ||||
|     "vue-toast-notification": "^2.0", | ||||
|     "vuex": "^4.0.0" | ||||
|   }, | ||||
|   "browserslist": [ | ||||
|     "Firefox ESR" | ||||
|   ], | ||||
|   "scripts": { | ||||
|     "dev-server": "encore dev-server", | ||||
|     "dev": "encore dev", | ||||
|     "watch": "encore dev --watch", | ||||
|     "build": "encore production --progress" | ||||
|   }, | ||||
|   "private": true | ||||
| } | ||||
| @@ -5,6 +5,11 @@ parameters: | ||||
|             count: 1 | ||||
|             path: src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php | ||||
|  | ||||
|         - | ||||
|             message: "#^Access to an undefined property Chill\\\\PersonBundle\\\\Entity\\\\Household\\\\PersonHouseholdAddress\\:\\:\\$relation\\.$#" | ||||
|             count: 1 | ||||
|             path: src/Bundle/ChillPersonBundle/Entity/Household/PersonHouseholdAddress.php | ||||
|  | ||||
|         - | ||||
|             message: "#^Access to an undefined property Chill\\\\PersonBundle\\\\Entity\\\\AccompanyingPeriod\\:\\:\\$work\\.$#" | ||||
|             count: 1 | ||||
| @@ -25,6 +30,11 @@ parameters: | ||||
|             count: 1 | ||||
|             path: src/Bundle/ChillPersonBundle/Serializer/Normalizer/MembersEditorNormalizer.php | ||||
|  | ||||
|         - | ||||
|             message: "#^Undefined variable\\: \\$choiceSlug$#" | ||||
|             count: 1 | ||||
|             path: src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php | ||||
|  | ||||
|         - | ||||
|             message: "#^Undefined variable\\: \\$choiceSlug$#" | ||||
|             count: 1 | ||||
|   | ||||
| @@ -10,6 +10,16 @@ parameters: | ||||
| 			count: 1 | ||||
| 			path: src/Bundle/ChillActivityBundle/Entity/ActivityReasonCategory.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method Chill\\\\ActivityBundle\\\\Export\\\\Export\\\\StatActivityDuration\\:\\:getDescription\\(\\) should return string but return statement is missing\\.$#" | ||||
| 			count: 1 | ||||
| 			path: src/Bundle/ChillActivityBundle/Export/Export/StatActivityDuration.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method Chill\\\\ActivityBundle\\\\Export\\\\Export\\\\StatActivityDuration\\:\\:getTitle\\(\\) should return string but return statement is missing\\.$#" | ||||
| 			count: 1 | ||||
| 			path: src/Bundle/ChillActivityBundle/Export/Export/StatActivityDuration.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#" | ||||
| 			count: 1 | ||||
| @@ -320,6 +330,21 @@ parameters: | ||||
| 			count: 6 | ||||
| 			path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#" | ||||
| 			count: 1 | ||||
| 			path: src/Bundle/ChillPersonBundle/Export/Aggregator/CountryOfBirthAggregator.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#" | ||||
| 			count: 1 | ||||
| 			path: src/Bundle/ChillPersonBundle/Export/Aggregator/NationalityAggregator.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#" | ||||
| 			count: 2 | ||||
| 			path: src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#" | ||||
| 			count: 1 | ||||
| @@ -340,6 +365,11 @@ parameters: | ||||
| 			count: 1 | ||||
| 			path: src/Bundle/ChillPersonBundle/Form/Type/PersonPhoneType.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#" | ||||
| 			count: 3 | ||||
| 			path: src/Bundle/ChillPersonBundle/Search/PersonSearch.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method Chill\\\\PersonBundle\\\\Search\\\\PersonSearch\\:\\:renderResult\\(\\) should return string but return statement is missing\\.$#" | ||||
| 			count: 1 | ||||
|   | ||||
| @@ -43,7 +43,6 @@ use Symfony\Component\HttpFoundation\Request; | ||||
| use Symfony\Component\HttpFoundation\Response; | ||||
| use Symfony\Component\Security\Core\Role\Role; | ||||
| use Symfony\Component\Serializer\SerializerInterface; | ||||
| use Symfony\Contracts\Translation\TranslatorInterface; | ||||
| use function array_key_exists; | ||||
|  | ||||
| final class ActivityController extends AbstractController | ||||
| @@ -74,8 +73,6 @@ final class ActivityController extends AbstractController | ||||
|  | ||||
|     private ThirdPartyRepository $thirdPartyRepository; | ||||
|  | ||||
|     private TranslatorInterface $translator; | ||||
|  | ||||
|     private UserRepositoryInterface $userRepository; | ||||
|  | ||||
|     public function __construct( | ||||
| @@ -92,8 +89,7 @@ final class ActivityController extends AbstractController | ||||
|         LoggerInterface $logger, | ||||
|         SerializerInterface $serializer, | ||||
|         UserRepositoryInterface $userRepository, | ||||
|         CenterResolverManagerInterface $centerResolver, | ||||
|         TranslatorInterface $translator | ||||
|         CenterResolverManagerInterface $centerResolver | ||||
|     ) { | ||||
|         $this->activityACLAwareRepository = $activityACLAwareRepository; | ||||
|         $this->activityTypeRepository = $activityTypeRepository; | ||||
| @@ -109,7 +105,6 @@ final class ActivityController extends AbstractController | ||||
|         $this->serializer = $serializer; | ||||
|         $this->userRepository = $userRepository; | ||||
|         $this->centerResolver = $centerResolver; | ||||
|         $this->translator = $translator; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -165,7 +160,7 @@ final class ActivityController extends AbstractController | ||||
|                 $this->entityManager->remove($activity); | ||||
|                 $this->entityManager->flush(); | ||||
|  | ||||
|                 $this->addFlash('success', $this->translator | ||||
|                 $this->addFlash('success', $this->get('translator') | ||||
|                     ->trans('The activity has been successfully removed.')); | ||||
|  | ||||
|                 $params = $this->buildParamsToUrl($person, $accompanyingPeriod); | ||||
| @@ -250,7 +245,7 @@ final class ActivityController extends AbstractController | ||||
|                 ); | ||||
|             } | ||||
|  | ||||
|             $this->addFlash('success', $this->translator->trans('Success : activity updated!')); | ||||
|             $this->addFlash('success', $this->get('translator')->trans('Success : activity updated!')); | ||||
|  | ||||
|             return $this->redirectToRoute('chill_activity_activity_show', $params); | ||||
|         } | ||||
| @@ -368,7 +363,6 @@ final class ActivityController extends AbstractController | ||||
|  | ||||
|         if ($person instanceof Person) { | ||||
|             $entity->setPerson($person); | ||||
|             $entity->getPersons()->add($person); | ||||
|         } | ||||
|  | ||||
|         if ($accompanyingPeriod instanceof AccompanyingPeriod) { | ||||
| @@ -478,7 +472,7 @@ final class ActivityController extends AbstractController | ||||
|                 ); | ||||
|             } | ||||
|  | ||||
|             $this->addFlash('success', $this->translator->trans('Success : activity created!')); | ||||
|             $this->addFlash('success', $this->get('translator')->trans('Success : activity created!')); | ||||
|  | ||||
|             $params = $this->buildParamsToUrl($person, $accompanyingPeriod); | ||||
|  | ||||
|   | ||||
| @@ -13,24 +13,15 @@ namespace Chill\ActivityBundle\Controller; | ||||
|  | ||||
| use Chill\ActivityBundle\Entity\ActivityReason; | ||||
| use Chill\ActivityBundle\Form\ActivityReasonType; | ||||
| use Chill\ActivityBundle\Repository\ActivityReasonRepository; | ||||
| use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; | ||||
| use Symfony\Component\Form\Extension\Core\Type\SubmitType; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
| use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; | ||||
|  | ||||
| /** | ||||
|  * ActivityReason controller. | ||||
|  */ | ||||
| class ActivityReasonController extends AbstractController | ||||
| { | ||||
|     private ActivityReasonRepository $activityReasonRepository; | ||||
|  | ||||
|     public function __construct(ActivityReasonRepository $activityReasonRepository) | ||||
|     { | ||||
|         $this->activityReasonRepository = $activityReasonRepository; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates a new ActivityReason entity. | ||||
|      */ | ||||
| @@ -65,8 +56,8 @@ class ActivityReasonController extends AbstractController | ||||
|  | ||||
|         $entity = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityReason::class)->find($id); | ||||
|  | ||||
|         if (null === $entity) { | ||||
|             throw new NotFoundHttpException('Unable to find ActivityReason entity.'); | ||||
|         if (!$entity) { | ||||
|             throw $this->createNotFoundException('Unable to find ActivityReason entity.'); | ||||
|         } | ||||
|  | ||||
|         $editForm = $this->createEditForm($entity); | ||||
| @@ -84,7 +75,7 @@ class ActivityReasonController extends AbstractController | ||||
|     { | ||||
|         $em = $this->getDoctrine()->getManager(); | ||||
|  | ||||
|         $entities = $this->activityReasonRepository->findAll(); | ||||
|         $entities = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityReason::class)->findAll(); | ||||
|  | ||||
|         return $this->render('ChillActivityBundle:ActivityReason:index.html.twig', [ | ||||
|             'entities' => $entities, | ||||
|   | ||||
| @@ -63,8 +63,10 @@ class ActivityReason | ||||
|  | ||||
|     /** | ||||
|      * Get category. | ||||
|      * | ||||
|      * @return ActivityReasonCategory | ||||
|      */ | ||||
|     public function getCategory(): ?ActivityReasonCategory | ||||
|     public function getCategory() | ||||
|     { | ||||
|         return $this->category; | ||||
|     } | ||||
| @@ -105,11 +107,6 @@ class ActivityReason | ||||
|         return $this->name; | ||||
|     } | ||||
|  | ||||
|     public function isActiveAndParentActive(): bool | ||||
|     { | ||||
|         return $this->active && null !== $this->getCategory() && $this->getCategory()->getActive(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set active. | ||||
|      * | ||||
|   | ||||
| @@ -1,68 +0,0 @@ | ||||
| <?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\Export\Aggregator\ACPAggregators; | ||||
|  | ||||
| use Chill\ActivityBundle\Entity\Activity; | ||||
| use Chill\MainBundle\Export\AggregatorInterface; | ||||
| use Chill\PersonBundle\Export\Declarations; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
|  | ||||
| class ByActivityNumberAggregator implements AggregatorInterface | ||||
| { | ||||
|     public function addRole(): ?string | ||||
|     { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public function alterQuery(QueryBuilder $qb, $data): void | ||||
|     { | ||||
|         $qb | ||||
|             ->addSelect('(SELECT COUNT(activity.id) FROM ' . Activity::class . ' activity WHERE activity.accompanyingPeriod = acp) AS activity_by_number_aggregator') | ||||
|             ->addGroupBy('activity_by_number_aggregator'); | ||||
|     } | ||||
|  | ||||
|     public function applyOn(): string | ||||
|     { | ||||
|         return Declarations::ACP_TYPE; | ||||
|     } | ||||
|  | ||||
|     public function buildForm(FormBuilderInterface $builder): void | ||||
|     { | ||||
|         // No form needed | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|         return static function ($value) { | ||||
|             if ('_header' === $value) { | ||||
|                 return ''; | ||||
|             } | ||||
|  | ||||
|             if (null === $value) { | ||||
|                 return ''; | ||||
|             } | ||||
|  | ||||
|             return $value; | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     public function getQueryKeys($data): array | ||||
|     { | ||||
|         return ['activity_by_number_aggregator']; | ||||
|     } | ||||
|  | ||||
|     public function getTitle(): string | ||||
|     { | ||||
|         return 'Group acp by activity number'; | ||||
|     } | ||||
| } | ||||
| @@ -60,7 +60,7 @@ class ByCreatorAggregator implements AggregatorInterface | ||||
|                 return 'Created by'; | ||||
|             } | ||||
|  | ||||
|             if (null === $value || '' === $value) { | ||||
|             if (null === $value) { | ||||
|                 return ''; | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -65,7 +65,7 @@ class BySocialActionAggregator implements AggregatorInterface | ||||
|                 return 'Social action'; | ||||
|             } | ||||
|  | ||||
|             if (null === $value || '' === $value) { | ||||
|             if (null === $value) { | ||||
|                 return ''; | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -65,7 +65,7 @@ class BySocialIssueAggregator implements AggregatorInterface | ||||
|                 return 'Social issues'; | ||||
|             } | ||||
|  | ||||
|             if (null === $value || '' === $value) { | ||||
|             if (null === $value) { | ||||
|                 return ''; | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -65,7 +65,7 @@ class ByThirdpartyAggregator implements AggregatorInterface | ||||
|                 return 'Accepted thirdparty'; | ||||
|             } | ||||
|  | ||||
|             if (null === $value || '' === $value) { | ||||
|             if (null === $value) { | ||||
|                 return ''; | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -65,7 +65,7 @@ class CreatorScopeAggregator implements AggregatorInterface | ||||
|                 return 'Scope'; | ||||
|             } | ||||
|  | ||||
|             if (null === $value || '' === $value) { | ||||
|             if (null === $value) { | ||||
|                 return ''; | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -65,13 +65,11 @@ class LocationTypeAggregator implements AggregatorInterface | ||||
|                 return 'Accepted locationtype'; | ||||
|             } | ||||
|  | ||||
|             if (null === $value || '' === $value) { | ||||
|             if (null === $value) { | ||||
|                 return ''; | ||||
|             } | ||||
|  | ||||
|             if (null === $lt = $this->locationTypeRepository->find($value)) { | ||||
|                 return ''; | ||||
|             } | ||||
|             $lt = $this->locationTypeRepository->find($value); | ||||
|  | ||||
|             return $this->translatableStringHelper->localize( | ||||
|                 $lt->getTitle() | ||||
|   | ||||
| @@ -44,7 +44,7 @@ class ActivityTypeAggregator implements AggregatorInterface | ||||
|     public function alterQuery(QueryBuilder $qb, $data) | ||||
|     { | ||||
|         if (!in_array('acttype', $qb->getAllAliases(), true)) { | ||||
|             $qb->leftJoin('activity.activityType', 'acttype'); | ||||
|             $qb->join('activity.activityType', 'acttype'); | ||||
|         } | ||||
|  | ||||
|         $qb->addSelect(sprintf('IDENTITY(activity.activityType) AS %s', self::KEY)); | ||||
| @@ -71,7 +71,7 @@ class ActivityTypeAggregator implements AggregatorInterface | ||||
|                 return 'Activity type'; | ||||
|             } | ||||
|  | ||||
|             if (null === $value || '' === $value) { | ||||
|             if (null === $value) { | ||||
|                 return ''; | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -66,7 +66,7 @@ class ActivityUserAggregator implements AggregatorInterface | ||||
|                 return 'Activity user'; | ||||
|             } | ||||
|  | ||||
|             if (null === $value || '' === $value) { | ||||
|             if (null === $value) { | ||||
|                 return ''; | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -64,7 +64,7 @@ class ActivityUsersAggregator implements AggregatorInterface | ||||
|                 return 'Activity users'; | ||||
|             } | ||||
|  | ||||
|             if (null === $value || '' === $value) { | ||||
|             if (null === $value) { | ||||
|                 return ''; | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -63,7 +63,7 @@ class ActivityUsersJobAggregator implements \Chill\MainBundle\Export\AggregatorI | ||||
|                 return 'Users \'s job'; | ||||
|             } | ||||
|  | ||||
|             if (null === $value || '' === $value) { | ||||
|             if (null === $value) { | ||||
|                 return ''; | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -63,7 +63,7 @@ class ActivityUsersScopeAggregator implements \Chill\MainBundle\Export\Aggregato | ||||
|                 return 'Users \'s scope'; | ||||
|             } | ||||
|  | ||||
|             if (null === $value || '' === $value) { | ||||
|             if (null === $value) { | ||||
|                 return ''; | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -134,10 +134,6 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali | ||||
|                 return 'reasons' === $data['level'] ? 'Group by reasons' : 'Group by categories of reason'; | ||||
|             } | ||||
|  | ||||
|             if (null === $value || '' === $value) { | ||||
|                 return ''; | ||||
|             } | ||||
|  | ||||
|             switch ($data['level']) { | ||||
|                 case 'reasons': | ||||
|                     $r = $this->activityReasonRepository->find($value); | ||||
|   | ||||
| @@ -1,84 +0,0 @@ | ||||
| <?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\Export\Aggregator; | ||||
|  | ||||
| use Chill\ActivityBundle\Export\Declarations; | ||||
| use Chill\MainBundle\Export\AggregatorInterface; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use LogicException; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
| use Symfony\Contracts\Translation\TranslatorInterface; | ||||
|  | ||||
| class SentReceivedAggregator implements AggregatorInterface | ||||
| { | ||||
|     private TranslatorInterface $translator; | ||||
|  | ||||
|     public function __construct(TranslatorInterface $translator) | ||||
|     { | ||||
|         $this->translator = $translator; | ||||
|     } | ||||
|  | ||||
|     public function addRole(): ?string | ||||
|     { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public function alterQuery(QueryBuilder $qb, $data): void | ||||
|     { | ||||
|         $qb->addSelect('activity.sentReceived AS activity_sentreceived_aggregator') | ||||
|             ->addGroupBy('activity_sentreceived_aggregator'); | ||||
|     } | ||||
|  | ||||
|     public function applyOn(): string | ||||
|     { | ||||
|         return Declarations::ACTIVITY; | ||||
|     } | ||||
|  | ||||
|     public function buildForm(FormBuilderInterface $builder): void | ||||
|     { | ||||
|         // No form needed | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data): callable | ||||
|     { | ||||
|         return function (?string $value): string { | ||||
|             if ('_header' === $value) { | ||||
|                 return 'export.aggregator.activity.by_sent_received.Sent or received'; | ||||
|             } | ||||
|  | ||||
|             switch ($value) { | ||||
|                 case null: | ||||
|                 case '': | ||||
|                     return ''; | ||||
|  | ||||
|                 case 'sent': | ||||
|                     return $this->translator->trans('export.aggregator.activity.by_sent_received.is sent'); | ||||
|  | ||||
|                 case 'received': | ||||
|                     return $this->translator->trans('export.aggregator.activity.by_sent_received.is received'); | ||||
|  | ||||
|                 default: | ||||
|                     throw new LogicException(sprintf('The value %s is not valid', $value)); | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     public function getQueryKeys($data): array | ||||
|     { | ||||
|         return ['activity_sentreceived_aggregator']; | ||||
|     } | ||||
|  | ||||
|     public function getTitle(): string | ||||
|     { | ||||
|         return 'export.aggregator.activity.by_sent_received.Group activity by sentreceived'; | ||||
|     } | ||||
| } | ||||
| @@ -1,165 +0,0 @@ | ||||
| <?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\Export\Export\LinkedToACP; | ||||
|  | ||||
| use Chill\ActivityBundle\Entity\Activity; | ||||
| use Chill\ActivityBundle\Export\Export\ListActivityHelper; | ||||
| use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter; | ||||
| use Chill\MainBundle\Entity\Scope; | ||||
| use Chill\MainBundle\Export\GroupedExportInterface; | ||||
| use Chill\MainBundle\Export\Helper\TranslatableStringExportLabelHelper; | ||||
| use Chill\MainBundle\Export\ListInterface; | ||||
| use Chill\PersonBundle\Entity\Person\PersonCenterHistory; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
|  | ||||
| class ListActivity implements ListInterface, GroupedExportInterface | ||||
| { | ||||
|     private EntityManagerInterface $entityManager; | ||||
|  | ||||
|     private ListActivityHelper $helper; | ||||
|  | ||||
|     private TranslatableStringExportLabelHelper $translatableStringExportLabelHelper; | ||||
|  | ||||
|     public function __construct( | ||||
|         ListActivityHelper $helper, | ||||
|         EntityManagerInterface $entityManager, | ||||
|         TranslatableStringExportLabelHelper $translatableStringExportLabelHelper | ||||
|     ) { | ||||
|         $this->helper = $helper; | ||||
|         $this->entityManager = $entityManager; | ||||
|         $this->translatableStringExportLabelHelper = $translatableStringExportLabelHelper; | ||||
|     } | ||||
|  | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|         $this->helper->buildForm($builder); | ||||
|     } | ||||
|  | ||||
|     public function getAllowedFormattersTypes() | ||||
|     { | ||||
|         return $this->helper->getAllowedFormattersTypes(); | ||||
|     } | ||||
|  | ||||
|     public function getDescription() | ||||
|     { | ||||
|         return ListActivityHelper::MSG_KEY . 'List activities linked to an accompanying course'; | ||||
|     } | ||||
|  | ||||
|     public function getGroup(): string | ||||
|     { | ||||
|         return 'Exports of activities linked to an accompanying period'; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|         switch ($key) { | ||||
|             case 'acpId': | ||||
|                 return static function ($value) { | ||||
|                     if ('_header' === $value) { | ||||
|                         return ListActivityHelper::MSG_KEY . 'accompanying course id'; | ||||
|                     } | ||||
|  | ||||
|                     return $value ?? ''; | ||||
|                 }; | ||||
|  | ||||
|             case 'scopesNames': | ||||
|                return $this->translatableStringExportLabelHelper->getLabelMulti($key, $values, ListActivityHelper::MSG_KEY . 'course circles'); | ||||
|  | ||||
|             default: | ||||
|                 return $this->helper->getLabels($key, $values, $data); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public function getQueryKeys($data) | ||||
|     { | ||||
|         return | ||||
|             array_merge( | ||||
|                 $this->helper->getQueryKeys($data), | ||||
|                 [ | ||||
|                     'acpId', | ||||
|                     'scopesNames', | ||||
|                 ] | ||||
|             ); | ||||
|     } | ||||
|  | ||||
|     public function getResult($query, $data) | ||||
|     { | ||||
|         return $this->helper->getResult($query, $data); | ||||
|     } | ||||
|  | ||||
|     public function getTitle() | ||||
|     { | ||||
|         return ListActivityHelper::MSG_KEY . 'List activity linked to a course'; | ||||
|     } | ||||
|  | ||||
|     public function getType() | ||||
|     { | ||||
|         return $this->helper->getType(); | ||||
|     } | ||||
|  | ||||
|     public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) | ||||
|     { | ||||
|         $centers = array_map(static function ($el) { | ||||
|             return $el['center']; | ||||
|         }, $acl); | ||||
|  | ||||
|         $qb = $this->entityManager->createQueryBuilder(); | ||||
|  | ||||
|         $qb | ||||
|             ->distinct() | ||||
|             ->from(Activity::class, 'activity') | ||||
|             ->join('activity.accompanyingPeriod', 'acp') | ||||
|             ->leftJoin('acp.participations', 'acppart') | ||||
|             ->leftJoin('acppart.person', 'person') | ||||
|             ->andWhere('acppart.startDate != acppart.endDate OR acppart.endDate IS NULL') | ||||
|             ->andWhere( | ||||
|                 $qb->expr()->exists( | ||||
|                     'SELECT 1 | ||||
|                     FROM ' . PersonCenterHistory::class . ' acl_count_person_history | ||||
|                     WHERE acl_count_person_history.person = person | ||||
|                     AND acl_count_person_history.center IN (:authorized_centers) | ||||
|                     ' | ||||
|                 ) | ||||
|             ) | ||||
|             // some grouping are necessary | ||||
|             ->addGroupBy('acp.id') | ||||
|             ->addOrderBy('activity.date') | ||||
|             ->addOrderBy('activity.id') | ||||
|             ->setParameter('authorized_centers', $centers); | ||||
|  | ||||
|         $this->helper->addSelect($qb); | ||||
|  | ||||
|         // add select for this step | ||||
|         $qb | ||||
|             ->addSelect('acp.id AS acpId') | ||||
|             ->addSelect('(SELECT AGGREGATE(acpScope.name) FROM ' . Scope::class . ' acpScope WHERE acpScope MEMBER OF acp.scopes) AS scopesNames') | ||||
|             ->addGroupBy('scopesNames'); | ||||
|  | ||||
|         return $qb; | ||||
|     } | ||||
|  | ||||
|     public function requiredRole(): string | ||||
|     { | ||||
|         return ActivityStatsVoter::LISTS; | ||||
|     } | ||||
|  | ||||
|     public function supportsModifiers() | ||||
|     { | ||||
|         return array_merge( | ||||
|             $this->helper->supportsModifiers(), | ||||
|             [ | ||||
|                 \Chill\PersonBundle\Export\Declarations::ACP_TYPE, | ||||
|             ] | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| @@ -124,7 +124,7 @@ class ListActivity implements ListInterface, GroupedExportInterface | ||||
|                         return 'attendee'; | ||||
|                     } | ||||
|  | ||||
|                     return $value ? 'X' : ''; | ||||
|                     return $value ? 1 : 0; | ||||
|                 }; | ||||
|  | ||||
|             case 'list_reasons': | ||||
| @@ -210,20 +210,10 @@ class ListActivity implements ListInterface, GroupedExportInterface | ||||
|  | ||||
|         $qb | ||||
|             ->from('ChillActivityBundle:Activity', 'activity') | ||||
|             ->join('activity.person', 'actperson') | ||||
|             ->join('actperson.centerHistory', 'centerHistory'); | ||||
|  | ||||
|         $qb->where( | ||||
|             $qb->expr()->andX( | ||||
|                 $qb->expr()->lte('centerHistory.startDate', 'activity.date'), | ||||
|                 $qb->expr()->orX( | ||||
|                     $qb->expr()->isNull('centerHistory.endDate'), | ||||
|                     $qb->expr()->gt('centerHistory.endDate', 'activity.date') | ||||
|                 ) | ||||
|             ) | ||||
|         ) | ||||
|             ->andWhere($qb->expr()->in('centerHistory.center', ':centers')) | ||||
|             ->setParameter('centers', $centers); | ||||
|             ->join('activity.person', 'person') | ||||
|             ->join('actperson.center', 'actcenter') | ||||
|             ->andWhere('actcenter IN (:authorized_centers)') | ||||
|             ->setParameter('authorized_centers', $centers); | ||||
|  | ||||
|         foreach ($this->fields as $f) { | ||||
|             if (in_array($f, $data['fields'], true)) { | ||||
| @@ -234,17 +224,17 @@ class ListActivity implements ListInterface, GroupedExportInterface | ||||
|                         break; | ||||
|  | ||||
|                     case 'person_firstname': | ||||
|                         $qb->addSelect('actperson.firstName AS person_firstname'); | ||||
|                         $qb->addSelect('person.firstName AS person_firstname'); | ||||
|  | ||||
|                         break; | ||||
|  | ||||
|                     case 'person_lastname': | ||||
|                         $qb->addSelect('actperson.lastName AS person_lastname'); | ||||
|                         $qb->addSelect('person.lastName AS person_lastname'); | ||||
|  | ||||
|                         break; | ||||
|  | ||||
|                     case 'person_id': | ||||
|                         $qb->addSelect('actperson.id AS person_id'); | ||||
|                         $qb->addSelect('person.id AS person_id'); | ||||
|  | ||||
|                         break; | ||||
|  | ||||
| @@ -261,7 +251,7 @@ class ListActivity implements ListInterface, GroupedExportInterface | ||||
|                         break; | ||||
|  | ||||
|                     case 'type_name': | ||||
|                         $qb->join('activity.activityType', 'type'); | ||||
|                         $qb->join('activity.type', 'type'); | ||||
|                         $qb->addSelect('type.name AS type_name'); | ||||
|  | ||||
|                         break; | ||||
| @@ -273,11 +263,6 @@ class ListActivity implements ListInterface, GroupedExportInterface | ||||
|  | ||||
|                         break; | ||||
|  | ||||
|                     case 'attendee': | ||||
|                         $qb->addSelect('IDENTITY(activity.attendee) AS attendee'); | ||||
|  | ||||
|                         break; | ||||
|  | ||||
|                     default: | ||||
|                         $qb->addSelect(sprintf('activity.%s as %s', $f, $f)); | ||||
|  | ||||
|   | ||||
| @@ -1,269 +0,0 @@ | ||||
| <?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\Export\Export; | ||||
|  | ||||
| use Chill\ActivityBundle\Export\Declarations; | ||||
| use Chill\ActivityBundle\Repository\ActivityPresenceRepositoryInterface; | ||||
| use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface; | ||||
| use Chill\MainBundle\Export\FormatterInterface; | ||||
| use Chill\MainBundle\Export\Helper\DateTimeHelper; | ||||
| use Chill\MainBundle\Export\Helper\TranslatableStringExportLabelHelper; | ||||
| use Chill\MainBundle\Export\Helper\UserHelper; | ||||
| use Chill\MainBundle\Templating\TranslatableStringHelperInterface; | ||||
| use Chill\PersonBundle\Export\Helper\LabelPersonHelper; | ||||
| use Chill\ThirdPartyBundle\Export\Helper\LabelThirdPartyHelper; | ||||
| use Doctrine\ORM\AbstractQuery; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use LogicException; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
| use Symfony\Contracts\Translation\TranslatorInterface; | ||||
| use const SORT_NUMERIC; | ||||
|  | ||||
| class ListActivityHelper | ||||
| { | ||||
|     public const MSG_KEY = 'export.list.activity.'; | ||||
|  | ||||
|     private ActivityPresenceRepositoryInterface $activityPresenceRepository; | ||||
|  | ||||
|     private ActivityTypeRepositoryInterface $activityTypeRepository; | ||||
|  | ||||
|     private DateTimeHelper $dateTimeHelper; | ||||
|  | ||||
|     private LabelPersonHelper $labelPersonHelper; | ||||
|  | ||||
|     private LabelThirdPartyHelper $labelThirdPartyHelper; | ||||
|  | ||||
|     private TranslatableStringHelperInterface $translatableStringHelper; | ||||
|  | ||||
|     private TranslatableStringExportLabelHelper $translatableStringLabelHelper; | ||||
|  | ||||
|     private TranslatorInterface $translator; | ||||
|  | ||||
|     private UserHelper $userHelper; | ||||
|  | ||||
|     public function __construct( | ||||
|         ActivityPresenceRepositoryInterface $activityPresenceRepository, | ||||
|         ActivityTypeRepositoryInterface $activityTypeRepository, | ||||
|         DateTimeHelper $dateTimeHelper, | ||||
|         LabelPersonHelper $labelPersonHelper, | ||||
|         LabelThirdPartyHelper $labelThirdPartyHelper, | ||||
|         TranslatorInterface $translator, | ||||
|         TranslatableStringHelperInterface $translatableStringHelper, | ||||
|         TranslatableStringExportLabelHelper $translatableStringLabelHelper, | ||||
|         UserHelper $userHelper | ||||
|     ) { | ||||
|         $this->activityPresenceRepository = $activityPresenceRepository; | ||||
|         $this->activityTypeRepository = $activityTypeRepository; | ||||
|         $this->dateTimeHelper = $dateTimeHelper; | ||||
|         $this->labelPersonHelper = $labelPersonHelper; | ||||
|         $this->labelThirdPartyHelper = $labelThirdPartyHelper; | ||||
|         $this->translator = $translator; | ||||
|         $this->translatableStringHelper = $translatableStringHelper; | ||||
|         $this->translatableStringLabelHelper = $translatableStringLabelHelper; | ||||
|         $this->userHelper = $userHelper; | ||||
|     } | ||||
|  | ||||
|     public function addSelect(QueryBuilder $qb): void | ||||
|     { | ||||
|         $qb | ||||
|             ->addSelect('activity.id AS id') | ||||
|             ->addSelect('activity.date') | ||||
|             ->addSelect('IDENTITY(activity.activityType) AS typeName') | ||||
|             ->leftJoin('activity.reasons', 'reasons') | ||||
|             ->addSelect('AGGREGATE(reasons.name) AS listReasons') | ||||
|             ->leftJoin('activity.persons', 'actPerson') | ||||
|             ->addSelect('AGGREGATE(actPerson.id) AS personsIds') | ||||
|             ->addSelect('AGGREGATE(actPerson.id) AS personsNames') | ||||
|             ->leftJoin('activity.users', 'users_u') | ||||
|             ->addSelect('AGGREGATE(users_u.id) AS usersIds') | ||||
|             ->addSelect('AGGREGATE(users_u.id) AS usersNames') | ||||
|             ->leftJoin('activity.thirdParties', 'thirdparty') | ||||
|             ->addSelect('AGGREGATE(thirdparty.id) AS thirdPartiesIds') | ||||
|             ->addSelect('AGGREGATE(thirdparty.id) AS thirdPartiesNames') | ||||
|             ->addSelect('IDENTITY(activity.attendee) AS attendeeName') | ||||
|             ->addSelect('activity.durationTime') | ||||
|             ->addSelect('activity.travelTime') | ||||
|             ->addSelect('activity.emergency') | ||||
|             ->leftJoin('activity.location', 'location') | ||||
|             ->addSelect('location.name AS locationName') | ||||
|             ->addSelect('activity.sentReceived') | ||||
|             ->addSelect('IDENTITY(activity.createdBy) AS createdBy') | ||||
|             ->addSelect('activity.createdAt') | ||||
|             ->addSelect('IDENTITY(activity.updatedBy) AS updatedBy') | ||||
|             ->addSelect('activity.updatedAt') | ||||
|             ->addGroupBy('activity.id') | ||||
|             ->addGroupBy('location.id'); | ||||
|     } | ||||
|  | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     public function getAllowedFormattersTypes() | ||||
|     { | ||||
|         return [FormatterInterface::TYPE_LIST]; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|         switch ($key) { | ||||
|             case 'createdAt': | ||||
|             case 'updatedAt': | ||||
|                 return $this->dateTimeHelper->getLabel($key); | ||||
|  | ||||
|             case 'createdBy': | ||||
|             case 'updatedBy': | ||||
|                 return $this->userHelper->getLabel($key, $values, $key); | ||||
|  | ||||
|             case 'date': | ||||
|                 return $this->dateTimeHelper->getLabel(self::MSG_KEY . $key); | ||||
|  | ||||
|             case 'attendeeName': | ||||
|                 return function ($value) { | ||||
|                     if ('_header' === $value) { | ||||
|                         return 'Attendee'; | ||||
|                     } | ||||
|  | ||||
|                     if (null === $value || null === $presence = $this->activityPresenceRepository->find($value)) { | ||||
|                         return ''; | ||||
|                     } | ||||
|  | ||||
|                     return $this->translatableStringHelper->localize($presence->getName()); | ||||
|                 }; | ||||
|  | ||||
|             case 'listReasons': | ||||
|                 return $this->translatableStringLabelHelper->getLabelMulti($key, $values, 'Activity Reasons'); | ||||
|  | ||||
|             case 'typeName': | ||||
|                 return function ($value) { | ||||
|                     if ('_header' === $value) { | ||||
|                         return 'Activity type'; | ||||
|                     } | ||||
|  | ||||
|                     if (null === $value || null === $type = $this->activityTypeRepository->find($value)) { | ||||
|                         return ''; | ||||
|                     } | ||||
|  | ||||
|                     return $this->translatableStringHelper->localize($type->getName()); | ||||
|                 }; | ||||
|  | ||||
|             case 'usersNames': | ||||
|                 return $this->userHelper->getLabelMulti($key, $values, self::MSG_KEY . 'users name'); | ||||
|  | ||||
|             case 'usersIds': | ||||
|             case 'thirdPartiesIds': | ||||
|             case 'personsIds': | ||||
|                 return static function ($value) use ($key) { | ||||
|                     if ('_header' === $value) { | ||||
|                         switch ($key) { | ||||
|                             case 'usersIds': | ||||
|                                 return self::MSG_KEY . 'users ids'; | ||||
|  | ||||
|                             case 'thirdPartiesIds': | ||||
|                                 return self::MSG_KEY . 'third parties ids'; | ||||
|  | ||||
|                             case 'personsIds': | ||||
|                                 return self::MSG_KEY . 'persons ids'; | ||||
|  | ||||
|                             default: | ||||
|                                 throw new LogicException('key not supported'); | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     $decoded = json_decode($value); | ||||
|  | ||||
|                     return implode( | ||||
|                         '|', | ||||
|                         array_unique( | ||||
|                             array_filter($decoded, static fn (?int $id) => null !== $id), | ||||
|                             SORT_NUMERIC | ||||
|                         ) | ||||
|                     ); | ||||
|                 }; | ||||
|  | ||||
|             case 'personsNames': | ||||
|                 return $this->labelPersonHelper->getLabelMulti($key, $values, self::MSG_KEY . 'persons name'); | ||||
|  | ||||
|             case 'thirdPartiesNames': | ||||
|                 return $this->labelThirdPartyHelper->getLabelMulti($key, $values, self::MSG_KEY . 'thirds parties'); | ||||
|  | ||||
|             case 'sentReceived': | ||||
|                 return function ($value) { | ||||
|                     if ('_header' === $value) { | ||||
|                         return self::MSG_KEY . 'sent received'; | ||||
|                     } | ||||
|  | ||||
|                     if (null === $value) { | ||||
|                         return ''; | ||||
|                     } | ||||
|  | ||||
|                     return $this->translator->trans($value); | ||||
|                 }; | ||||
|  | ||||
|             default: | ||||
|                 return function ($value) use ($key) { | ||||
|                     if ('_header' === $value) { | ||||
|                         return self::MSG_KEY . $key; | ||||
|                     } | ||||
|  | ||||
|                     if (null === $value) { | ||||
|                         return ''; | ||||
|                     } | ||||
|  | ||||
|                     return $this->translator->trans($value); | ||||
|                 }; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public function getQueryKeys($data) | ||||
|     { | ||||
|         return [ | ||||
|             'id', | ||||
|             'date', | ||||
|             'typeName', | ||||
|             'listReasons', | ||||
|             'attendeeName', | ||||
|             'durationTime', | ||||
|             'travelTime', | ||||
|             'emergency', | ||||
|             'locationName', | ||||
|             'sentReceived', | ||||
|             'personsIds', | ||||
|             'personsNames', | ||||
|             'usersIds', | ||||
|             'usersNames', | ||||
|             'thirdPartiesIds', | ||||
|             'thirdPartiesNames', | ||||
|             'createdBy', | ||||
|             'createdAt', | ||||
|             'updatedBy', | ||||
|             'updatedAt', | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     public function getResult($query, $data) | ||||
|     { | ||||
|         return $query->getQuery()->getResult(AbstractQuery::HYDRATE_SCALAR); | ||||
|     } | ||||
|  | ||||
|     public function getType(): string | ||||
|     { | ||||
|         return Declarations::ACTIVITY; | ||||
|     } | ||||
|  | ||||
|     public function supportsModifiers() | ||||
|     { | ||||
|         return [ | ||||
|             Declarations::ACTIVITY, | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @@ -17,9 +17,11 @@ use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface; | ||||
| use Chill\MainBundle\Export\FilterInterface; | ||||
| use Chill\MainBundle\Templating\TranslatableStringHelperInterface; | ||||
| use Chill\PersonBundle\Export\Declarations; | ||||
| use Doctrine\ORM\Query\Expr; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use Symfony\Bridge\Doctrine\Form\Type\EntityType; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
| use function in_array; | ||||
|  | ||||
| class ActivityTypeFilter implements FilterInterface | ||||
| { | ||||
| @@ -42,13 +44,14 @@ class ActivityTypeFilter implements FilterInterface | ||||
|  | ||||
|     public function alterQuery(QueryBuilder $qb, $data) | ||||
|     { | ||||
|         $qb->andWhere( | ||||
|             $qb->expr()->exists( | ||||
|                 'SELECT 1 FROM ' . Activity::class . ' act_type_filter_activity | ||||
|                 WHERE act_type_filter_activity.activityType IN (:act_type_filter_activity_types) AND act_type_filter_activity.accompanyingPeriod = acp' | ||||
|             ) | ||||
|         ); | ||||
|         $qb->setParameter('act_type_filter_activity_types', $data['accepted_activitytypes']); | ||||
|         if (!in_array('activity', $qb->getAllAliases(), true)) { | ||||
|             $qb->join(Activity::class, 'activity', Expr\Join::WITH, 'activity.accompanyingPeriod = acp'); | ||||
|         } | ||||
|  | ||||
|         $clause = $qb->expr()->in('activity.activityType', ':selected_activity_types'); | ||||
|  | ||||
|         $qb->andWhere($clause); | ||||
|         $qb->setParameter('selected_activity_types', $data['types']); | ||||
|     } | ||||
|  | ||||
|     public function applyOn() | ||||
|   | ||||
| @@ -1,57 +0,0 @@ | ||||
| <?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\Export\Filter\ACPFilters; | ||||
|  | ||||
| use Chill\ActivityBundle\Entity\Activity; | ||||
| use Chill\MainBundle\Export\FilterInterface; | ||||
| use Chill\PersonBundle\Export\Declarations; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
|  | ||||
| class HasNoActivityFilter implements FilterInterface | ||||
| { | ||||
|     public function addRole(): ?string | ||||
|     { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public function alterQuery(QueryBuilder $qb, $data) | ||||
|     { | ||||
|         $qb | ||||
|             ->andWhere(' | ||||
|                 NOT EXISTS ( | ||||
|                     SELECT 1 FROM ' . Activity::class . ' activity | ||||
|                     WHERE activity.accompanyingPeriod = acp | ||||
|                 ) | ||||
|             '); | ||||
|     } | ||||
|  | ||||
|     public function applyOn(): string | ||||
|     { | ||||
|         return Declarations::ACP_TYPE; | ||||
|     } | ||||
|  | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|         //no form needed | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string'): array | ||||
|     { | ||||
|         return ['Filtered acp which has no activities', []]; | ||||
|     } | ||||
|  | ||||
|     public function getTitle(): string | ||||
|     { | ||||
|         return 'Filter acp which has no activity'; | ||||
|     } | ||||
| } | ||||
| @@ -1,74 +0,0 @@ | ||||
| <?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\Export\Filter\ACPFilters; | ||||
|  | ||||
| use Chill\ActivityBundle\Export\Declarations; | ||||
| use Chill\MainBundle\Export\FilterInterface; | ||||
| use Chill\MainBundle\Form\Type\PickUserLocationType; | ||||
| use Chill\MainBundle\Templating\TranslatableStringHelper; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
|  | ||||
| class LocationFilter implements FilterInterface | ||||
| { | ||||
|     private TranslatableStringHelper $translatableStringHelper; | ||||
|  | ||||
|     public function __construct(TranslatableStringHelper $translatableStringHelper) | ||||
|     { | ||||
|         $this->translatableStringHelper = $translatableStringHelper; | ||||
|     } | ||||
|  | ||||
|     public function addRole(): ?string | ||||
|     { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public function alterQuery(QueryBuilder $qb, $data) | ||||
|     { | ||||
|         $qb->andWhere( | ||||
|             $qb->expr()->in('activity.location', ':location') | ||||
|         ); | ||||
|  | ||||
|         $qb->setParameter('location', $data['accepted_location']); | ||||
|     } | ||||
|  | ||||
|     public function applyOn(): string | ||||
|     { | ||||
|         return Declarations::ACTIVITY_ACP; | ||||
|     } | ||||
|  | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|         $builder->add('accepted_location', PickUserLocationType::class, [ | ||||
|             'multiple' => true, | ||||
|             'label' => 'pick location', | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string'): array | ||||
|     { | ||||
|         $locations = []; | ||||
|  | ||||
|         foreach ($data['accepted_location'] as $location) { | ||||
|             $locations[] = $location->getName(); | ||||
|         } | ||||
|  | ||||
|         return ['Filtered activity by location: only %locations%', [ | ||||
|             '%locations%' => implode(', ', $locations), | ||||
|         ]]; | ||||
|     } | ||||
|  | ||||
|     public function getTitle(): string | ||||
|     { | ||||
|         return 'Filter activity by location'; | ||||
|     } | ||||
| } | ||||
| @@ -13,10 +13,9 @@ namespace Chill\ActivityBundle\Export\Filter; | ||||
|  | ||||
| use Chill\ActivityBundle\Export\Declarations; | ||||
| use Chill\MainBundle\Export\FilterInterface; | ||||
| use Chill\MainBundle\Form\Type\ChillDateType; | ||||
| use Chill\MainBundle\Form\Type\Export\FilterType; | ||||
| use Chill\MainBundle\Form\Type\PickRollingDateType; | ||||
| use Chill\MainBundle\Service\RollingDate\RollingDate; | ||||
| use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface; | ||||
| use DateTime; | ||||
| use Doctrine\ORM\Query\Expr; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
| @@ -29,14 +28,9 @@ class ActivityDateFilter implements FilterInterface | ||||
| { | ||||
|     protected TranslatorInterface $translator; | ||||
|  | ||||
|     private RollingDateConverterInterface $rollingDateConverter; | ||||
|  | ||||
|     public function __construct( | ||||
|         TranslatorInterface $translator, | ||||
|         RollingDateConverterInterface $rollingDateConverter | ||||
|     ) { | ||||
|     public function __construct(TranslatorInterface $translator) | ||||
|     { | ||||
|         $this->translator = $translator; | ||||
|         $this->rollingDateConverter = $rollingDateConverter; | ||||
|     } | ||||
|  | ||||
|     public function addRole(): ?string | ||||
| @@ -60,14 +54,8 @@ class ActivityDateFilter implements FilterInterface | ||||
|         } | ||||
|  | ||||
|         $qb->add('where', $where); | ||||
|         $qb->setParameter( | ||||
|             'date_from', | ||||
|             $this->rollingDateConverter->convert($data['date_from']) | ||||
|         ); | ||||
|         $qb->setParameter( | ||||
|             'date_to', | ||||
|             $this->rollingDateConverter->convert($data['date_to']) | ||||
|         ); | ||||
|         $qb->setParameter('date_from', $data['date_from']); | ||||
|         $qb->setParameter('date_to', $data['date_to']); | ||||
|     } | ||||
|  | ||||
|     public function applyOn(): string | ||||
| @@ -78,13 +66,13 @@ class ActivityDateFilter implements FilterInterface | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|         $builder | ||||
|             ->add('date_from', PickRollingDateType::class, [ | ||||
|             ->add('date_from', ChillDateType::class, [ | ||||
|                 'label' => 'Activities after this date', | ||||
|                 'data' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START), | ||||
|                 'data' => new DateTime(), | ||||
|             ]) | ||||
|             ->add('date_to', PickRollingDateType::class, [ | ||||
|             ->add('date_to', ChillDateType::class, [ | ||||
|                 'label' => 'Activities before this date', | ||||
|                 'data' => new RollingDate(RollingDate::T_TODAY), | ||||
|                 'data' => new DateTime(), | ||||
|             ]); | ||||
|  | ||||
|         $builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) { | ||||
| @@ -133,8 +121,8 @@ class ActivityDateFilter implements FilterInterface | ||||
|         return [ | ||||
|             'Filtered by date of activity: only between %date_from% and %date_to%', | ||||
|             [ | ||||
|                 '%date_from%' => $this->rollingDateConverter->convert($data['date_from'])->format('d-m-Y'), | ||||
|                 '%date_to%' => $this->rollingDateConverter->convert($data['date_to'])->format('d-m-Y'), | ||||
|                 '%date_from%' => $data['date_from']->format('d-m-Y'), | ||||
|                 '%date_to%' => $data['date_to']->format('d-m-Y'), | ||||
|             ], | ||||
|         ]; | ||||
|     } | ||||
|   | ||||
| @@ -50,7 +50,7 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt | ||||
|     { | ||||
|         $where = $qb->getDQLPart('where'); | ||||
|         $join = $qb->getDQLPart('join'); | ||||
|         $clause = $qb->expr()->in('actreasons', ':selected_activity_reasons'); | ||||
|         $clause = $qb->expr()->in('reasons', ':selected_activity_reasons'); | ||||
|  | ||||
|         if (!in_array('actreasons', $qb->getAllAliases(), true)) { | ||||
|             $qb->join('activity.reasons', 'actreasons'); | ||||
| @@ -77,7 +77,6 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt | ||||
|             'class' => ActivityReason::class, | ||||
|             'choice_label' => fn (ActivityReason $reason) => $this->translatableStringHelper->localize($reason->getName()), | ||||
|             'group_by' => fn (ActivityReason $reason) => $this->translatableStringHelper->localize($reason->getCategory()->getName()), | ||||
|             'attr' => ['class' => 'select2 '], | ||||
|             'multiple' => true, | ||||
|             'expanded' => false, | ||||
|         ]); | ||||
|   | ||||
| @@ -39,9 +39,9 @@ class UsersJobFilter implements FilterInterface | ||||
|         $qb | ||||
|             ->andWhere( | ||||
|                 $qb->expr()->exists( | ||||
|                     'SELECT 1 FROM ' . Activity::class . ' activity_users_job_filter_act | ||||
|                 'SELECT 1 FROM ' . Activity::class . ' activity_users_job_filter_act | ||||
|                 JOIN activity_users_job_filter_act.users users WHERE users.userJob IN (:activity_users_job_filter_jobs) AND  activity_users_job_filter_act = activity ' | ||||
|                 ) | ||||
|             ) | ||||
|             ) | ||||
|             ->setParameter('activity_users_job_filter_jobs', $data['jobs']); | ||||
|     } | ||||
|   | ||||
| @@ -11,8 +11,7 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace Chill\ActivityBundle\Form; | ||||
|  | ||||
| use Chill\ActivityBundle\Entity\ActivityReason; | ||||
| use Chill\ActivityBundle\Form\Type\TranslatableActivityReasonCategoryType; | ||||
| use Chill\ActivityBundle\Form\Type\TranslatableActivityReasonCategory; | ||||
| use Chill\MainBundle\Form\Type\TranslatableStringFormType; | ||||
| use Symfony\Component\Form\AbstractType; | ||||
| use Symfony\Component\Form\Extension\Core\Type\CheckboxType; | ||||
| @@ -26,13 +25,13 @@ class ActivityReasonType extends AbstractType | ||||
|         $builder | ||||
|             ->add('name', TranslatableStringFormType::class) | ||||
|             ->add('active', CheckboxType::class, ['required' => false]) | ||||
|             ->add('category', TranslatableActivityReasonCategoryType::class); | ||||
|             ->add('category', TranslatableActivityReasonCategory::class); | ||||
|     } | ||||
|  | ||||
|     public function configureOptions(OptionsResolver $resolver) | ||||
|     { | ||||
|         $resolver->setDefaults([ | ||||
|             'data_class' => ActivityReason::class, | ||||
|             'data_class' => 'Chill\ActivityBundle\Entity\ActivityReason', | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -13,7 +13,7 @@ namespace Chill\ActivityBundle\Form; | ||||
|  | ||||
| use Chill\ActivityBundle\Entity\Activity; | ||||
| use Chill\ActivityBundle\Entity\ActivityPresence; | ||||
| use Chill\ActivityBundle\Form\Type\PickActivityReasonType; | ||||
| use Chill\ActivityBundle\Entity\ActivityReason; | ||||
| use Chill\ActivityBundle\Security\Authorization\ActivityVoter; | ||||
| use Chill\DocStoreBundle\Form\StoredObjectType; | ||||
| use Chill\MainBundle\Entity\Center; | ||||
| @@ -229,10 +229,19 @@ class ActivityType extends AbstractType | ||||
|         } | ||||
|  | ||||
|         if ($activityType->isVisible('reasons')) { | ||||
|             $builder->add('reasons', PickActivityReasonType::class, [ | ||||
|             $builder->add('reasons', EntityType::class, [ | ||||
|                 'label' => $activityType->getLabel('reasons'), | ||||
|                 'required' => $activityType->isRequired('reasons'), | ||||
|                 'class' => ActivityReason::class, | ||||
|                 'multiple' => true, | ||||
|                 'choice_label' => function (ActivityReason $activityReason) { | ||||
|                     return $this->translatableStringHelper->localize($activityReason->getName()); | ||||
|                 }, | ||||
|                 'attr' => ['class' => 'select2 '], | ||||
|                 'query_builder' => static function (EntityRepository $er) { | ||||
|                     return $er->createQueryBuilder('a') | ||||
|                         ->where('a.active = true'); | ||||
|                 }, | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -12,9 +12,9 @@ declare(strict_types=1); | ||||
| namespace Chill\ActivityBundle\Form\Type; | ||||
| 
 | ||||
| use Chill\ActivityBundle\Entity\ActivityReason; | ||||
| use Chill\ActivityBundle\Repository\ActivityReasonRepository; | ||||
| use Chill\ActivityBundle\Templating\Entity\ActivityReasonRender; | ||||
| use Chill\MainBundle\Templating\TranslatableStringHelperInterface; | ||||
| use Chill\MainBundle\Templating\TranslatableStringHelper; | ||||
| use Doctrine\ORM\EntityRepository; | ||||
| use Symfony\Bridge\Doctrine\Form\Type\EntityType; | ||||
| use Symfony\Component\Form\AbstractType; | ||||
| use Symfony\Component\OptionsResolver\OptionsResolver; | ||||
| @@ -22,29 +22,31 @@ use Symfony\Component\OptionsResolver\OptionsResolver; | ||||
| /** | ||||
|  * FormType to choose amongst activity reasons. | ||||
|  */ | ||||
| class PickActivityReasonType extends AbstractType | ||||
| class TranslatableActivityReason extends AbstractType | ||||
| { | ||||
|     private ActivityReasonRepository $activityReasonRepository; | ||||
|     /** | ||||
|      * @var ActivityReasonRender | ||||
|      */ | ||||
|     protected $reasonRender; | ||||
| 
 | ||||
|     private ActivityReasonRender $reasonRender; | ||||
| 
 | ||||
|     private TranslatableStringHelperInterface $translatableStringHelper; | ||||
|     /** | ||||
|      * @var TranslatableStringHelper | ||||
|      */ | ||||
|     protected $translatableStringHelper; | ||||
| 
 | ||||
|     public function __construct( | ||||
|         ActivityReasonRepository $activityReasonRepository, | ||||
|         ActivityReasonRender $reasonRender, | ||||
|         TranslatableStringHelperInterface $translatableStringHelper | ||||
|         TranslatableStringHelper $translatableStringHelper, | ||||
|         ActivityReasonRender $reasonRender | ||||
|     ) { | ||||
|         $this->activityReasonRepository = $activityReasonRepository; | ||||
|         $this->reasonRender = $reasonRender; | ||||
|         $this->translatableStringHelper = $translatableStringHelper; | ||||
|         $this->reasonRender = $reasonRender; | ||||
|     } | ||||
| 
 | ||||
|     public function configureOptions(OptionsResolver $resolver) | ||||
|     { | ||||
|         $resolver->setDefaults( | ||||
|             [ | ||||
|                 'class' => ActivityReason::class, | ||||
|                 'class' => 'ChillActivityBundle:ActivityReason', | ||||
|                 'choice_label' => function (ActivityReason $choice) { | ||||
|                     return $this->reasonRender->renderString($choice, []); | ||||
|                 }, | ||||
| @@ -55,7 +57,10 @@ class PickActivityReasonType extends AbstractType | ||||
| 
 | ||||
|                     return null; | ||||
|                 }, | ||||
|                 'choices' => $this->activityReasonRepository->findAll(), | ||||
|                 'query_builder' => static function (EntityRepository $er) { | ||||
|                     return $er->createQueryBuilder('r') | ||||
|                         ->where('r.active = true'); | ||||
|                 }, | ||||
|                 'attr' => ['class' => ' select2 '], | ||||
|             ] | ||||
|         ); | ||||
| @@ -0,0 +1,59 @@ | ||||
| <?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\Form\Type; | ||||
|  | ||||
| use Doctrine\ORM\EntityRepository; | ||||
| use Symfony\Bridge\Doctrine\Form\Type\EntityType; | ||||
| use Symfony\Component\Form\AbstractType; | ||||
| use Symfony\Component\HttpFoundation\RequestStack; | ||||
| use Symfony\Component\OptionsResolver\OptionsResolver; | ||||
|  | ||||
| /** | ||||
|  * Description of TranslatableActivityReasonCategory. | ||||
|  */ | ||||
| class TranslatableActivityReasonCategory extends AbstractType | ||||
| { | ||||
|     /** | ||||
|      * @var RequestStack | ||||
|      */ | ||||
|     private $requestStack; | ||||
|  | ||||
|     public function __construct(RequestStack $requestStack) | ||||
|     { | ||||
|         $this->requestStack = $requestStack; | ||||
|     } | ||||
|  | ||||
|     public function configureOptions(OptionsResolver $resolver) | ||||
|     { | ||||
|         $locale = $this->requestStack->getCurrentRequest()->getLocale(); | ||||
|         $resolver->setDefaults( | ||||
|             [ | ||||
|                 'class' => 'ChillActivityBundle:ActivityReasonCategory', | ||||
|                 'choice_label' => 'name[' . $locale . ']', | ||||
|                 'query_builder' => static function (EntityRepository $er) { | ||||
|                     return $er->createQueryBuilder('c') | ||||
|                         ->where('c.active = true'); | ||||
|                 }, | ||||
|             ] | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function getBlockPrefix() | ||||
|     { | ||||
|         return 'translatable_activity_reason_category'; | ||||
|     } | ||||
|  | ||||
|     public function getParent() | ||||
|     { | ||||
|         return EntityType::class; | ||||
|     } | ||||
| } | ||||
| @@ -1,58 +0,0 @@ | ||||
| <?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\Form\Type; | ||||
|  | ||||
| use Chill\ActivityBundle\Entity\ActivityReasonCategory; | ||||
| use Chill\MainBundle\Templating\TranslatableStringHelperInterface; | ||||
| use Symfony\Bridge\Doctrine\Form\Type\EntityType; | ||||
| use Symfony\Component\Form\AbstractType; | ||||
| use Symfony\Component\OptionsResolver\OptionsResolver; | ||||
| use Symfony\Contracts\Translation\TranslatorInterface; | ||||
|  | ||||
| /** | ||||
|  * Description of TranslatableActivityReasonCategory. | ||||
|  */ | ||||
| class TranslatableActivityReasonCategoryType extends AbstractType | ||||
| { | ||||
|     private TranslatableStringHelperInterface $translatableStringHelper; | ||||
|  | ||||
|     private TranslatorInterface $translator; | ||||
|  | ||||
|     public function __construct(TranslatableStringHelperInterface $translatableStringHelper, TranslatorInterface $translator) | ||||
|     { | ||||
|         $this->translatableStringHelper = $translatableStringHelper; | ||||
|         $this->translator = $translator; | ||||
|     } | ||||
|  | ||||
|     public function configureOptions(OptionsResolver $resolver) | ||||
|     { | ||||
|         $resolver->setDefaults( | ||||
|             [ | ||||
|                 'class' => ActivityReasonCategory::class, | ||||
|                 'choice_label' => function (ActivityReasonCategory $category) { | ||||
|                     return $this->translatableStringHelper->localize($category->getName()) | ||||
|                         . (!$category->getActive() ? ' (' . $this->translator->trans('inactive') . ')' : ''); | ||||
|                 }, | ||||
|             ] | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function getBlockPrefix() | ||||
|     { | ||||
|         return 'translatable_activity_reason_category'; | ||||
|     } | ||||
|  | ||||
|     public function getParent() | ||||
|     { | ||||
|         return EntityType::class; | ||||
|     } | ||||
| } | ||||
| @@ -36,6 +36,7 @@ final class AdminMenuBuilder implements LocalMenuBuilderInterface | ||||
|             ->setAttribute('class', 'list-group-item-header') | ||||
|             ->setExtras([ | ||||
|                 'order' => 5000, | ||||
|                 'icons' => ['exchange'], | ||||
|             ]); | ||||
|  | ||||
|         $menu->addChild('Activity Reasons', [ | ||||
|   | ||||
| @@ -1,51 +0,0 @@ | ||||
| <?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\ActivityPresence; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use Doctrine\ORM\EntityRepository; | ||||
|  | ||||
| class ActivityPresenceRepository implements ActivityPresenceRepositoryInterface | ||||
| { | ||||
|     private EntityRepository $repository; | ||||
|  | ||||
|     public function __construct(EntityManagerInterface $entityManager) | ||||
|     { | ||||
|         $this->repository = $entityManager->getRepository($this->getClassName()); | ||||
|     } | ||||
|  | ||||
|     public function find($id): ?ActivityPresence | ||||
|     { | ||||
|         return $this->repository->find($id); | ||||
|     } | ||||
|  | ||||
|     public function findAll(): array | ||||
|     { | ||||
|         return $this->repository->findAll(); | ||||
|     } | ||||
|  | ||||
|     public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array | ||||
|     { | ||||
|         return $this->findBy($criteria, $orderBy, $limit, $offset); | ||||
|     } | ||||
|  | ||||
|     public function findOneBy(array $criteria): ?ActivityPresence | ||||
|     { | ||||
|         return $this->findOneBy($criteria); | ||||
|     } | ||||
|  | ||||
|     public function getClassName(): string | ||||
|     { | ||||
|         return ActivityPresence::class; | ||||
|     } | ||||
| } | ||||
| @@ -1,33 +0,0 @@ | ||||
| <?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\ActivityPresence; | ||||
|  | ||||
| interface ActivityPresenceRepositoryInterface | ||||
| { | ||||
|     public function find($id): ?ActivityPresence; | ||||
|  | ||||
|     /** | ||||
|      * @return array|ActivityPresence[] | ||||
|      */ | ||||
|     public function findAll(): array; | ||||
|  | ||||
|     /** | ||||
|      * @return array|ActivityPresence[] | ||||
|      */ | ||||
|     public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array; | ||||
|  | ||||
|     public function findOneBy(array $criteria): ?ActivityPresence; | ||||
|  | ||||
|     public function getClassName(): string; | ||||
| } | ||||
| @@ -14,38 +14,17 @@ namespace Chill\ActivityBundle\Repository; | ||||
| use Chill\ActivityBundle\Entity\ActivityReason; | ||||
| use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; | ||||
| use Doctrine\Persistence\ManagerRegistry; | ||||
| use Symfony\Component\HttpFoundation\RequestStack; | ||||
|  | ||||
| /** | ||||
|  * @method ActivityReason|null find($id, $lockMode = null, $lockVersion = null) | ||||
|  * @method ActivityReason|null findOneBy(array $criteria, array $orderBy = null) | ||||
|  * @method ActivityReason[]    findAll() | ||||
|  * @method ActivityReason[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) | ||||
|  */ | ||||
| class ActivityReasonRepository extends ServiceEntityRepository | ||||
| { | ||||
|     private RequestStack $requestStack; | ||||
|  | ||||
|     public function __construct( | ||||
|         ManagerRegistry $registry, | ||||
|         RequestStack $requestStack | ||||
|     ) { | ||||
|         parent::__construct($registry, ActivityReason::class); | ||||
|  | ||||
|         $this->requestStack = $requestStack; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return ActivityReason[] | ||||
|      */ | ||||
|     public function findAll(): array | ||||
|     public function __construct(ManagerRegistry $registry) | ||||
|     { | ||||
|         $qb = $this->createQueryBuilder('ar'); | ||||
|         $qb->select(['ar']) | ||||
|             ->leftJoin('ar.category', 'category') | ||||
|             ->addOrderBy('JSON_EXTRACT(category.name, :lang)') | ||||
|             ->addOrderBy('JSON_EXTRACT(ar.name, :lang)') | ||||
|             ->setParameter('lang', $this->requestStack->getCurrentRequest()->getLocale() ?? 'fr'); | ||||
|  | ||||
|         return $qb->getQuery()->getResult(); | ||||
|         parent::__construct($registry, ActivityReason::class); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -88,11 +88,3 @@ div.flex-bloc.concerned-groups { | ||||
|       font-size: 120%; | ||||
|    } | ||||
| } | ||||
|  | ||||
| /// DOCUMENT LIST IN ACTIVITY ITEM | ||||
| li.document-list-item { | ||||
|     display: flex; | ||||
|     width: 100%; | ||||
|     justify-content: space-between; | ||||
|     margin-bottom: 0.3rem; | ||||
| } | ||||
|   | ||||
| @@ -117,8 +117,7 @@ export default { | ||||
|                     target: { //name, id | ||||
|                         }, | ||||
|                     edit: false, | ||||
|                     addressId: null, | ||||
|                     defaults: window.addaddress | ||||
|                     addressId: null | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -30,7 +30,7 @@ const store = createStore({ | ||||
|     }, | ||||
|     getters: { | ||||
|         suggestedEntities(state) { | ||||
|             if (typeof state.activity.accompanyingPeriod === "undefined" || state.activity.accompanyingPeriod === null) { | ||||
|             if (typeof state.activity.accompanyingPeriod === "undefined") { | ||||
|                 return []; | ||||
|             } | ||||
|             const allEntities = [ | ||||
|   | ||||
| @@ -39,9 +39,6 @@ const makeConcernedThirdPartiesLocation = (locationType, store) => { | ||||
|     return locations; | ||||
| }; | ||||
| const makeAccompanyingPeriodLocation = (locationType, store) => { | ||||
|     if (store.state.activity.accompanyingPeriod === null) { | ||||
|         return {}; | ||||
|     } | ||||
|     const accPeriodLocation = store.state.activity.accompanyingPeriod.location; | ||||
|     return { | ||||
|         type: 'location', | ||||
|   | ||||
| @@ -68,7 +68,7 @@ | ||||
|                     <div class="wl-col title"><h3>{{ 'Referrer'|trans }}</h3></div> | ||||
|                     <div class="wl-col list"> | ||||
|                         <p class="wl-item"> | ||||
|                             <span class="badge-user">{{ activity.user|chill_entity_render_box }}</span> | ||||
|                             {{ activity.user|chill_entity_render_box }} | ||||
|                         </p> | ||||
|                     </div> | ||||
|                 </div> | ||||
| @@ -137,42 +137,19 @@ | ||||
|                         {{ activity.comment|chill_entity_render_box({ | ||||
|                             'disable_markdown': false, | ||||
|                             'limit_lines': 3, | ||||
|                             'metadata': false, | ||||
|                             'metadata': false | ||||
|                         }) }} | ||||
|                     </div> | ||||
|                 </div> | ||||
|             {% endif %} | ||||
|  | ||||
|             {% if is_granted('CHILL_ACTIVITY_SEE_DETAILS', activity) and activity.privateComment.hasCommentForUser(app.user) %} | ||||
|                 <div class="wl-row"> | ||||
|                     <div class="wl-col title"> | ||||
|                         <h3>{{ 'Private comment'|trans }}</h3> | ||||
|                     </div> | ||||
|                     <div class="wl-col list"> | ||||
|                         <section class="chill-entity entity-comment-embeddable"> | ||||
|                             <blockquote class="chill-user-quote private-quote"> | ||||
|                                 {{ activity.privateComment.comments[app.user.id]|chill_markdown_to_html }} | ||||
|                             </blockquote> | ||||
|                         </section> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             {% endif %} | ||||
|  | ||||
|             {% if is_granted('CHILL_ACTIVITY_SEE_DETAILS', activity) and activity.documents|length > 0 %} | ||||
|                 <div class="wl-row"> | ||||
|                     <div class="wl-col title"> | ||||
|                         <h3>{{ 'Documents'|trans }}</h3> | ||||
|                     </div> | ||||
|                     <div class="wl-col list"> | ||||
|                         <ul> | ||||
|                             {% for d in activity.documents %} | ||||
|                                 <li class="document-list-item">{{ d.title|chill_print_or_message('document.Any title') }} {{ d|chill_document_button_group(d.title, is_granted('CHILL_ACTIVITY_UPDATE', activity), {small: true}) }}</li> | ||||
|                             {% endfor %} | ||||
|                         </ul> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             {% endif %} | ||||
|  | ||||
|             {#  Only if ACL SEE_DETAILS AND/OR only on template SHOW ?? | ||||
|                 durationTime | ||||
|                 travelTime | ||||
|                 comment | ||||
|                 documents | ||||
|                 attendee | ||||
|             #} | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|   | ||||
| @@ -8,13 +8,11 @@ | ||||
| {% block js %} | ||||
|     {{ parent() }} | ||||
|     {{ encore_entry_script_tags('mod_notification_toggle_read_status') }} | ||||
|     {{ encore_entry_script_tags('mod_document_action_buttons_group') }} | ||||
| {% endblock %} | ||||
|  | ||||
| {% block css %} | ||||
|     {{ parent() }} | ||||
|     {{ encore_entry_link_tags('mod_notification_toggle_read_status') }} | ||||
|     {{ encore_entry_link_tags('mod_document_action_buttons_group') }} | ||||
| {% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
|   | ||||
| @@ -23,13 +23,11 @@ | ||||
| {% block js %} | ||||
|     {{ parent() }} | ||||
|     {{ encore_entry_script_tags('mod_notification_toggle_read_status') }} | ||||
|     {{ encore_entry_script_tags('mod_document_action_buttons_group') }} | ||||
| {% endblock %} | ||||
|  | ||||
| {% block css %} | ||||
|     {{ parent() }} | ||||
|     {{ encore_entry_link_tags('mod_notification_toggle_read_status') }} | ||||
|     {{ encore_entry_link_tags('mod_document_action_buttons_group') }} | ||||
| {% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
|   | ||||
| @@ -41,7 +41,7 @@ | ||||
|                         {% if activity.user and t.userVisible %} | ||||
|                             <li> | ||||
|                                 <span class="item-key">{{ 'Referrer'|trans ~ ': ' }}</span> | ||||
|                                 <span class="badge-user">{{ activity.user|chill_entity_render_box }}</span> | ||||
|                                 <b>{{ activity.user|chill_entity_render_box}}</b> | ||||
|                             </li> | ||||
|                         {% endif %} | ||||
|  | ||||
|   | ||||
| @@ -35,9 +35,7 @@ | ||||
|         <div class="item-row separator"> | ||||
|             <dl class="chill_view_data"> | ||||
|                 <dt class="inline">{{ 'Referrer'|trans|capitalize }}</dt> | ||||
|                 <dd> | ||||
|                     <span class="badge-user">{{ entity.user|chill_entity_render_box }}</span> | ||||
|                 </dd> | ||||
|                 <dd>{{ entity.user|chill_entity_render_box }}</dd> | ||||
|  | ||||
|                 {%- if entity.scope -%} | ||||
|                     <dt class="inline">{{ 'Scope'|trans }}</dt> | ||||
| @@ -158,7 +156,7 @@ | ||||
|                 <dd> | ||||
|                     <section class="chill-entity entity-comment-embeddable"> | ||||
|                         <blockquote class="chill-user-quote private-quote"> | ||||
|                             {{ entity.privateComment.comments[userId]|chill_markdown_to_html }} | ||||
|                             {{ entity.privateComment.comments[userId] }} | ||||
|                         </blockquote> | ||||
|                     </section> | ||||
|                 </dd> | ||||
| @@ -170,11 +168,11 @@ | ||||
|                     {% if entity.documents|length > 0 %} | ||||
|                         <ul> | ||||
|                             {% for d in entity.documents %} | ||||
|                                 <li class="document-list-item">{{ d.title|chill_print_or_message('document.Any title') }} {{ d|chill_document_button_group(d.title, is_granted('CHILL_ACTIVITY_UPDATE', entity), {small: true}) }}</li> | ||||
|                                 <li>{{ d.title }}{{ m.download_button(d) }}</li> | ||||
|                             {% endfor %} | ||||
|                         </ul> | ||||
|                     {% else %} | ||||
|                         <span class="chill-no-data-statement">{{ 'No document found'|trans }}</span> | ||||
|                         <span class="chill-no-data-statement">{{ 'Any document found'|trans }}</span> | ||||
|                     {% endif %} | ||||
|                 </dd> | ||||
|             {% endif %} | ||||
|   | ||||
| @@ -8,14 +8,12 @@ | ||||
|     {{ parent() }} | ||||
|     {{ encore_entry_script_tags('mod_notification_toggle_read_status') }} | ||||
|     {{ encore_entry_script_tags('mod_async_upload') }} | ||||
|     {{ encore_entry_script_tags('mod_document_action_buttons_group') }} | ||||
| {% endblock %} | ||||
|  | ||||
| {% block css %} | ||||
|     {{ parent() }} | ||||
|     {{ encore_entry_link_tags('mod_notification_toggle_read_status') }} | ||||
|     {{ encore_entry_link_tags('mod_async_upload') }} | ||||
|     {{ encore_entry_link_tags('mod_document_action_buttons_group') }} | ||||
| {% endblock %} | ||||
|  | ||||
| {% import 'ChillActivityBundle:ActivityReason:macro.html.twig' as m %} | ||||
|   | ||||
| @@ -7,13 +7,13 @@ | ||||
| {% block js %} | ||||
|     {{ parent() }} | ||||
|     {{ encore_entry_script_tags('mod_notification_toggle_read_status') }} | ||||
|     {{ encore_entry_script_tags('mod_document_action_buttons_group') }} | ||||
|     {{ encore_entry_link_tags('mod_async_upload') }} | ||||
| {% endblock %} | ||||
|  | ||||
| {% block css %} | ||||
|     {{ parent() }} | ||||
|     {{ encore_entry_link_tags('mod_notification_toggle_read_status') }} | ||||
|     {{ encore_entry_link_tags('mod_document_action_buttons_group') }} | ||||
|     {{ encore_entry_link_tags('mod_async_upload') }} | ||||
| {% endblock %} | ||||
|  | ||||
| {% import 'ChillActivityBundle:ActivityReason:macro.html.twig' as m %} | ||||
|   | ||||
| @@ -7,34 +7,22 @@ | ||||
|         <thead> | ||||
|             <tr> | ||||
|                 <th>{{ 'Name'|trans }}</th> | ||||
|                 <th>{{ 'Active'|trans }}</th> | ||||
|                 <th>{{ 'Actions'|trans }}</th> | ||||
|             </tr> | ||||
|         </thead> | ||||
|         <tbody> | ||||
|         {% for entity in entities %} | ||||
|             <tr class="{% if entity.active %}active{% else %}inactive{% endif %}"> | ||||
|                 <td><a href="{{ path('chill_activity_activityreason_show', { 'id': entity.id }) }}">{{ entity.name|localize_translatable_string }}</a></td> | ||||
|                 <td> | ||||
|                     {% if entity.category is not null -%} | ||||
|                     {{  entity.category.name|localize_translatable_string }} > | ||||
|                     {% endif -%} | ||||
|                     {{ entity.name|localize_translatable_string }} | ||||
|                 </td> | ||||
|                 <td> | ||||
|                     <i class="fa {% if entity.active %}fa-check-square-o{% else %}fa-square-o{% endif %}"></i> | ||||
|                     {% if entity.active and not entity.isActiveAndParentActive %} | ||||
|                     <span class="badge text-bg-danger text-white">{{ 'Associated activity reason category is inactive'|trans }}</span> | ||||
|                     {% endif %} | ||||
|                 </td> | ||||
|                 <td> | ||||
|                     <ul class="record_actions"> | ||||
|                         <li> | ||||
|                             <a href="{{ path('chill_activity_activityreason_show', { 'id': entity.id }) }}" class="btn btn-show" title="{{ 'show'|trans }}"></a> | ||||
|                         </li> | ||||
|                         <li> | ||||
|                             <a href="{{ path('chill_activity_activityreason_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a> | ||||
|                         </li> | ||||
|                     </ul> | ||||
|                 <ul class="record_actions"> | ||||
|                     <li> | ||||
|                         <a href="{{ path('chill_activity_activityreason_show', { 'id': entity.id }) }}" class="btn btn-show" title="{{ 'show'|trans }}"></a> | ||||
|                     </li> | ||||
|                     <li> | ||||
|                         <a href="{{ path('chill_activity_activityreason_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a> | ||||
|                     </li> | ||||
|                 </ul> | ||||
|                 </td> | ||||
|             </tr> | ||||
|         {% endfor %} | ||||
|   | ||||
| @@ -7,7 +7,6 @@ | ||||
|         <thead> | ||||
|             <tr> | ||||
|                 <th>{{ 'Name'|trans }}</th> | ||||
|                 <th>{{ 'Active'|trans }}</th> | ||||
|                 <th>{{ 'Actions'|trans }}</th> | ||||
|             </tr> | ||||
|         </thead> | ||||
| @@ -15,11 +14,7 @@ | ||||
|         {% for entity in entities %} | ||||
|             <tr> | ||||
|                 <td> | ||||
|                     {{ entity.name|localize_translatable_string }} | ||||
|                 </td> | ||||
|                 <td> | ||||
|                     <i class="fa {% if entity.active %}fa-check-square-o{% else %}fa-square-o{% endif %}"></i> | ||||
|                 </td> | ||||
|                     <a href="{{ path('chill_activity_activityreasoncategory_show', { 'id': entity.id }) }}">{{ entity.name|localize_translatable_string }}</a></td> | ||||
|                 <td> | ||||
|                     <ul class="record_actions"> | ||||
|                     <li> | ||||
|   | ||||
| @@ -22,7 +22,6 @@ use Chill\DocStoreBundle\Repository\DocumentCategoryRepository; | ||||
| use Chill\MainBundle\Templating\TranslatableStringHelperInterface; | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod; | ||||
| use Chill\PersonBundle\Entity\Person; | ||||
| use Chill\PersonBundle\Repository\PersonRepository; | ||||
| use Chill\PersonBundle\Templating\Entity\PersonRenderInterface; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use Symfony\Bridge\Doctrine\Form\Type\EntityType; | ||||
| @@ -46,8 +45,6 @@ class ActivityContext implements | ||||
|  | ||||
|     private PersonRenderInterface $personRender; | ||||
|  | ||||
|     private PersonRepository $personRepository; | ||||
|  | ||||
|     private TranslatableStringHelperInterface $translatableStringHelper; | ||||
|  | ||||
|     private TranslatorInterface $translator; | ||||
| @@ -58,7 +55,6 @@ class ActivityContext implements | ||||
|         TranslatableStringHelperInterface $translatableStringHelper, | ||||
|         EntityManagerInterface $em, | ||||
|         PersonRenderInterface $personRender, | ||||
|         PersonRepository $personRepository, | ||||
|         TranslatorInterface $translator, | ||||
|         BaseContextData $baseContextData | ||||
|     ) { | ||||
| @@ -67,7 +63,6 @@ class ActivityContext implements | ||||
|         $this->translatableStringHelper = $translatableStringHelper; | ||||
|         $this->em = $em; | ||||
|         $this->personRender = $personRender; | ||||
|         $this->personRepository = $personRepository; | ||||
|         $this->translator = $translator; | ||||
|         $this->baseContextData = $baseContextData; | ||||
|     } | ||||
| @@ -152,7 +147,7 @@ class ActivityContext implements | ||||
|         $options = $template->getOptions(); | ||||
|  | ||||
|         $data = []; | ||||
|         $data = array_merge($data, $this->baseContextData->getData($contextGenerationData['creator'] ?? null)); | ||||
|         $data = array_merge($data, $this->baseContextData->getData()); | ||||
|         $data['activity'] = $this->normalizer->normalize($entity, 'docgen', ['docgen:expects' => Activity::class, 'groups' => 'docgen:read']); | ||||
|  | ||||
|         $data['course'] = $this->normalizer->normalize($entity->getAccompanyingPeriod(), 'docgen', ['docgen:expects' => AccompanyingPeriod::class, 'groups' => 'docgen:read']); | ||||
| @@ -211,32 +206,6 @@ class ActivityContext implements | ||||
|         return $options['mainPerson'] || $options['person1'] || $options['person2']; | ||||
|     } | ||||
|  | ||||
|     public function contextGenerationDataNormalize(DocGeneratorTemplate $template, $entity, array $data): array | ||||
|     { | ||||
|         $normalized = []; | ||||
|  | ||||
|         foreach (['mainPerson', 'person1', 'person2'] as $k) { | ||||
|             $normalized[$k] = null === $data[$k] ? null : $data[$k]->getId(); | ||||
|         } | ||||
|  | ||||
|         return $normalized; | ||||
|     } | ||||
|  | ||||
|     public function contextGenerationDataDenormalize(DocGeneratorTemplate $template, $entity, array $data): array | ||||
|     { | ||||
|         $denormalized = []; | ||||
|  | ||||
|         foreach (['mainPerson', 'person1', 'person2'] as $k) { | ||||
|             if (null !== ($id = ($data[$k] ?? null))) { | ||||
|                 $denormalized[$k] = $this->personRepository->find($id); | ||||
|             } else { | ||||
|                 $denormalized[$k] = null; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $denormalized; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Activity $entity | ||||
|      */ | ||||
|   | ||||
| @@ -146,16 +146,6 @@ class ListActivitiesByAccompanyingPeriodContext implements | ||||
|         return $this->accompanyingPeriodContext->hasPublicForm($template, $entity); | ||||
|     } | ||||
|  | ||||
|     public function contextGenerationDataNormalize(DocGeneratorTemplate $template, $entity, array $data): array | ||||
|     { | ||||
|         return $this->accompanyingPeriodContext->contextGenerationDataNormalize($template, $entity, $data); | ||||
|     } | ||||
|  | ||||
|     public function contextGenerationDataDenormalize(DocGeneratorTemplate $template, $entity, array $data): array | ||||
|     { | ||||
|         return $this->accompanyingPeriodContext->contextGenerationDataDenormalize($template, $entity, $data); | ||||
|     } | ||||
|  | ||||
|     public function storeGenerated(DocGeneratorTemplate $template, StoredObject $storedObject, object $entity, array $contextGenerationData): void | ||||
|     { | ||||
|         $this->accompanyingPeriodContext->storeGenerated($template, $storedObject, $entity, $contextGenerationData); | ||||
|   | ||||
| @@ -369,12 +369,8 @@ final class ActivityControllerTest extends WebTestCase | ||||
|                 $center | ||||
|             ); | ||||
|         $reachableScopesId = array_intersect( | ||||
|             array_map(static function ($s) { | ||||
|                 return $s->getId(); | ||||
|             }, $reachableScopesDelete), | ||||
|             array_map(static function ($s) { | ||||
|                 return $s->getId(); | ||||
|             }, $reachableScopesUpdate) | ||||
|             array_map(static function ($s) { return $s->getId(); }, $reachableScopesDelete), | ||||
|             array_map(static function ($s) { return $s->getId(); }, $reachableScopesUpdate) | ||||
|         ); | ||||
|  | ||||
|         if (count($reachableScopesId) === 0) { | ||||
|   | ||||
| @@ -188,9 +188,7 @@ final class ActivityTypeTest extends KernelTestCase | ||||
|  | ||||
|         // map all the values in an array | ||||
|         $values = array_map( | ||||
|             static function ($choice) { | ||||
|                 return $choice->value; | ||||
|             }, | ||||
|             static function ($choice) { return $choice->value; }, | ||||
|             $view['activity']['durationTime']->vars['choices'] | ||||
|         ); | ||||
|  | ||||
|   | ||||
| @@ -11,7 +11,7 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace Chill\ActivityBundle\Tests\Form\Type; | ||||
|  | ||||
| use Chill\ActivityBundle\Form\Type\PickActivityReasonType; | ||||
| use Chill\ActivityBundle\Form\Type\TranslatableActivityReason; | ||||
| use Chill\MainBundle\Templating\TranslatableStringHelper; | ||||
| use Symfony\Component\Form\PreloadedExtension; | ||||
| use Symfony\Component\Form\Test\TypeTestCase; | ||||
| @@ -36,7 +36,7 @@ final class TranslatableActivityReasonTest extends TypeTestCase | ||||
|  | ||||
|     public function testSimple() | ||||
|     { | ||||
|         $translatableActivityReasonType = new PickActivityReasonType( | ||||
|         $translatableActivityReasonType = new TranslatableActivityReason( | ||||
|             $this->getTranslatableStringHelper() | ||||
|         ); | ||||
|  | ||||
|   | ||||
| @@ -1,11 +1,4 @@ | ||||
| services: | ||||
|     _defaults: | ||||
|         autowire: true | ||||
|         autoconfigure: true | ||||
|  | ||||
|     Chill\ActivityBundle\Controller\: | ||||
|         resource: '../../Controller/' | ||||
|         tags: ['controller.service_arguments'] | ||||
|  | ||||
|     Chill\ActivityBundle\Controller\ActivityController: | ||||
|         autowire: true | ||||
|         tags: ['controller.service_arguments'] | ||||
|   | ||||
| @@ -41,12 +41,6 @@ services: | ||||
|         tags: | ||||
|             - { name: chill.export, alias: 'avg_activity_visit_duration_linked_to_acp' } | ||||
|  | ||||
|     Chill\ActivityBundle\Export\Export\LinkedToACP\ListActivity: | ||||
|         tags: | ||||
|             - { name: chill.export, alias: 'list_activity_acp'} | ||||
|  | ||||
|     Chill\ActivityBundle\Export\Export\ListActivityHelper: ~ | ||||
|  | ||||
|     ## Filters | ||||
|     chill.activity.export.type_filter: | ||||
|         class: Chill\ActivityBundle\Export\Filter\ActivityTypeFilter | ||||
| @@ -79,11 +73,6 @@ services: | ||||
|         tags: | ||||
|             - { name: chill.export_filter, alias: 'accompanyingcourse_activitytype_filter' } | ||||
|  | ||||
|     chill.activity.export.location_filter: | ||||
|         class: Chill\ActivityBundle\Export\Filter\ACPFilters\LocationFilter | ||||
|         tags: | ||||
|             - { name: chill.export_filter, alias: 'activity_location_filter' } | ||||
|  | ||||
|     chill.activity.export.locationtype_filter: | ||||
|         class: Chill\ActivityBundle\Export\Filter\ACPFilters\LocationTypeFilter | ||||
|         tags: | ||||
| @@ -131,18 +120,15 @@ services: | ||||
|         tags: | ||||
|             - { name: chill.export_filter, alias: 'activity_usersscope_filter' } | ||||
|  | ||||
|     Chill\ActivityBundle\Export\Filter\ACPFilters\HasNoActivityFilter: | ||||
|         tags: | ||||
|             - { name: chill.export_filter, alias: 'accompanyingcourse_has_no_activity_filter' } | ||||
|  | ||||
|     ## Aggregators | ||||
|     Chill\ActivityBundle\Export\Aggregator\PersonAggregators\ActivityReasonAggregator: | ||||
|         tags: | ||||
|             - { name: chill.export_aggregator, alias: activity_reason_aggregator } | ||||
|  | ||||
|     Chill\ActivityBundle\Export\Aggregator\ActivityTypeAggregator: | ||||
|     chill.activity.export.type_aggregator: | ||||
|         class: Chill\ActivityBundle\Export\Aggregator\ActivityTypeAggregator | ||||
|         tags: | ||||
|             - { name: chill.export_aggregator, alias: activity_common_type_aggregator } | ||||
|             - { name: chill.export_aggregator, alias: activity_type_aggregator } | ||||
|  | ||||
|     chill.activity.export.user_aggregator: | ||||
|         class: Chill\ActivityBundle\Export\Aggregator\ActivityUserAggregator | ||||
| @@ -193,11 +179,3 @@ services: | ||||
|     Chill\ActivityBundle\Export\Aggregator\ActivityUsersJobAggregator: | ||||
|         tags: | ||||
|             - { name: chill.export_aggregator, alias: activity_users_job_aggregator } | ||||
|  | ||||
|     Chill\ActivityBundle\Export\Aggregator\ACPAggregators\ByActivityNumberAggregator: | ||||
|         tags: | ||||
|             - { name: chill.export_aggregator, alias: accompanyingcourse_by_activity_number_aggregator } | ||||
|  | ||||
|     Chill\ActivityBundle\Export\Aggregator\SentReceivedAggregator: | ||||
|         tags: | ||||
|             - { name: chill.export_aggregator, alias: activity_sentreceived_aggregator } | ||||
|   | ||||
| @@ -1,12 +1,19 @@ | ||||
| --- | ||||
| services: | ||||
|     Chill\ActivityBundle\Form\Type\TranslatableActivityReasonCategoryType: | ||||
|         autowire: true | ||||
|         autoconfigure: true | ||||
|     chill.activity.form.type.translatableactivityreasoncategory: | ||||
|         class: Chill\ActivityBundle\Form\Type\TranslatableActivityReasonCategory | ||||
|         arguments: | ||||
|             - "@request_stack" | ||||
|         tags: | ||||
|             - { name: form.type, alias: translatable_activity_reason_category } | ||||
|  | ||||
|     Chill\ActivityBundle\Form\Type\PickActivityReasonType: | ||||
|         autowire: true | ||||
|         autoconfigure: true | ||||
|     chill.activity.form.type.translatableactivityreason: | ||||
|         class: Chill\ActivityBundle\Form\Type\TranslatableActivityReason | ||||
|         arguments: | ||||
|             $translatableStringHelper: "@chill.main.helper.translatable_string" | ||||
|             $reasonRender: '@Chill\ActivityBundle\Templating\Entity\ActivityReasonRender' | ||||
|         tags: | ||||
|             - { name: form.type, alias: translatable_activity_reason } | ||||
|  | ||||
|     chill.activity.form.type.translatableactivitytype: | ||||
|         class: Chill\ActivityBundle\Form\Type\TranslatableActivityType | ||||
|   | ||||
| @@ -1,8 +1,5 @@ | ||||
| --- | ||||
| services: | ||||
|     Chill\ActivityBundle\Repository\ActivityReasonRepository: | ||||
|         autowire: true | ||||
|  | ||||
|     chill_activity.repository.activity_type: '@Chill\ActivityBundle\Repository\ActivityTypeRepository' | ||||
|     chill_activity.repository.reason: '@Chill\ActivityBundle\Repository\ActivityReasonRepository' | ||||
|     chill_activity.repository.reason_category: '@Chill\ActivityBundle\Repository\ActivityReasonCategoryRepository' | ||||
|   | ||||
| @@ -45,8 +45,6 @@ by: 'Par ' | ||||
| location: Lieu | ||||
| Reasons: Sujets | ||||
| Private comment: Commentaire privé | ||||
| sent: Envoyé | ||||
| received: Reçu | ||||
|  | ||||
|  | ||||
| #forms | ||||
| @@ -77,7 +75,7 @@ Choose a type: Choisir un type | ||||
| 4 hours: 4 heures | ||||
| 4 hours 30: 4 heures 30 | ||||
| 5 hours: 5 heures | ||||
| Concerned groups: Parties concernées par l'échange | ||||
| Concerned groups: Parties concernées | ||||
| Persons in accompanying course: Usagers du parcours | ||||
| Third persons: Tiers non-pro. | ||||
| Others persons: Usagers | ||||
| @@ -117,7 +115,6 @@ Activity Reasons: Sujets d'une activité | ||||
| Activity Reasons Category: Catégories de sujet d'activités | ||||
| Activity Types Categories: Catégories des types d'activité | ||||
| Activity Presences: Presences aux activités | ||||
| Associated activity reason category is inactive: La catégorie de sujet attachée est inactive | ||||
|  | ||||
|  | ||||
| # Crud | ||||
| @@ -252,8 +249,6 @@ Activity reasons for those activities: Sujets de ces activités | ||||
|  | ||||
| Filter by activity type: Filtrer les activités par type | ||||
|  | ||||
| Filter activity by location: Filtrer les activités par localisation | ||||
| 'Filtered activity by location: only %locations%': "Filtré par localisation: uniquement %locations%" | ||||
| Filter activity by locationtype: Filtrer les activités par type de localisation | ||||
| 'Filtered activity by locationtype: only %types%': "Filtré par type de localisation: uniquement %types%" | ||||
| Accepted locationtype: Types de localisation | ||||
| @@ -265,6 +260,8 @@ activity is not emergency: l'activité n'est pas urgente | ||||
| Filter activity by sentreceived: Filtrer les activités par envoyé/reçu | ||||
| 'Filtered activity by sentreceived: only %sentreceived%': "Filtré par envoyé/reçu: uniquement %sentreceived%" | ||||
| Accepted sentreceived: '' | ||||
| is sent: envoyé | ||||
| is received: reçu | ||||
| Filter activity by linked socialaction: Filtrer les activités par action liée | ||||
| 'Filtered activity by linked socialaction: only %actions%': "Filtré par action liée: uniquement %actions%" | ||||
| Filter activity by linked socialissue: Filtrer les activités par problématique liée | ||||
| @@ -280,10 +277,6 @@ Filter activity by userscope: Filtrer les activités par service du créateur | ||||
| 'Filtered activity by userscope: only %scopes%': "Filtré par service du créateur: uniquement %scopes%" | ||||
| Accepted userscope: Services | ||||
|  | ||||
| Filter acp which has no activity: Filtrer les parcours qui n’ont pas d’activité | ||||
| Filtered acp which has no activities: Filtrer les parcours sans activité associée | ||||
| Group acp by activity number: Grouper les parcours par nombre d’activité | ||||
|  | ||||
| #aggregators | ||||
| Activity type: Type d'activité | ||||
| Activity user: Utilisateur lié à l'activité | ||||
| @@ -326,32 +319,11 @@ This is the minimal activity data: Activité n° | ||||
|  | ||||
| docgen: | ||||
|     Activity basic: Echange | ||||
|     A basic context for activity: Contexte pour les activités | ||||
|     Accompanying period with a list of activities: Parcours d'accompagnement avec liste des activités | ||||
|     Accompanying period with a list of activities description: Ce contexte reprend les informations du parcours, et tous les activités pour un parcours. Les activités ne sont pas filtrés. | ||||
|     A basic context for activity: Contexte pour les échanges | ||||
|     Accompanying period with a list of activities: Parcours d'accompagnement avec liste des échanges | ||||
|     Accompanying period with a list of activities description: Ce contexte reprend les informations du parcours, et tous les échanges pour un parcours. Les échanges ne sont pas filtrés. | ||||
|  | ||||
| export: | ||||
|     list: | ||||
|         activity: | ||||
|             users name: Nom des utilisateurs | ||||
|             users ids: Identifiant des utilisateurs | ||||
|             third parties ids: Identifiant des tiers | ||||
|             persons ids: Identifiant des personnes | ||||
|             persons name: Nom des personnes | ||||
|             thirds parties: Tiers | ||||
|             date: Date de l'activité | ||||
|             locationName: Localisation | ||||
|             sent received: Envoyé ou reçu | ||||
|             emergency: Urgence | ||||
|             accompanying course id: Identifiant du parcours | ||||
|             course circles: Cercles du parcours | ||||
|             travelTime: Durée de déplacement | ||||
|             durationTime: Durée | ||||
|             id: Identifiant | ||||
|             List activities linked to an accompanying course: Liste les activités liées à un parcours en fonction de différents filtres. | ||||
|             List activity linked to a course: Liste des activités liées à un parcours | ||||
|  | ||||
|  | ||||
|     filter: | ||||
|         activity: | ||||
|             by_usersjob: | ||||
| @@ -360,10 +332,3 @@ export: | ||||
|             by_usersscope: | ||||
|                 Filter by users scope: Filtrer les activités par services d'au moins un utilisateur participant | ||||
|                 'Filtered activity by users scope: only %scopes%': 'Filtré par service d''au moins un utilisateur participant: seulement %scopes%' | ||||
|     aggregator: | ||||
|         activity: | ||||
|             by_sent_received: | ||||
|                 Sent or received: Envoyé ou reçu | ||||
|                 is sent: envoyé | ||||
|                 is received: reçu | ||||
|                 Group activity by sentreceived: Grouper les activités par envoyé / reçu | ||||
|   | ||||
| @@ -231,4 +231,4 @@ This is the minimal activity data: Activité n° | ||||
|  | ||||
| docgen: | ||||
|     Activity basic: Echange | ||||
|     A basic context for activity: Contexte pour les activités | ||||
|     A basic context for activity: Contexte pour les échanges | ||||
|   | ||||
| @@ -16,8 +16,8 @@ For this type of activity, document is required: Pour ce type d'activité, un do | ||||
| For this type of activity, emergency is required: Pour ce type d'activité, le champ "Urgent" est requis | ||||
| For this type of activity, accompanying period is required: Pour ce type d'activité, le parcours d'accompagnement est requis | ||||
| For this type of activity, you must add at least one social issue: Pour ce type d'activité, vous devez ajouter au moins une problématique sociale | ||||
| For this type of activity, you must add at least one social action: Pour ce type d'activité, vous devez indiquer au moins une action sociale | ||||
| For this type of activity, you must add at least one social action: Pour ce type d'activité, vous devez indiquez au moins une action sociale | ||||
|  | ||||
| # admin | ||||
| This parameter must be equal to social issue parameter: Ce paramètre doit être égal au paramètre "Visibilité du champs Problématiques sociales" | ||||
| The socialActionsVisible value is not compatible with the socialIssuesVisible value: Cette valeur du paramètre "Visibilité du champs Actions sociales" n'est pas compatible avec la valeur du paramètre "Visibilité du champs Problématiques sociales" | ||||
| The socialActionsVisible value is not compatible with the socialIssuesVisible value: Cette valeur du paramètre "Visibilité du champs Actions sociales" n'est pas compatible avec la valeur du paramètre "Visibilité du champs Problématiques sociales" | ||||
| @@ -30,8 +30,6 @@ final class ChillAsideActivityExtension extends Extension implements PrependExte | ||||
|         $loader->load('services.yaml'); | ||||
|         $loader->load('services/form.yaml'); | ||||
|         $loader->load('services/menu.yaml'); | ||||
|         $loader->load('services/security.yaml'); | ||||
|         $loader->load('services/export.yaml'); | ||||
|     } | ||||
|  | ||||
|     public function prepend(ContainerBuilder $container) | ||||
|   | ||||
| @@ -1,78 +0,0 @@ | ||||
| <?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\AsideActivityBundle\Export\Aggregator; | ||||
|  | ||||
| use Chill\AsideActivityBundle\Export\Declarations; | ||||
| use Chill\AsideActivityBundle\Repository\AsideActivityCategoryRepository; | ||||
| use Chill\MainBundle\Export\AggregatorInterface; | ||||
| use Chill\MainBundle\Templating\TranslatableStringHelper; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
|  | ||||
| class ByActivityTypeAggregator implements AggregatorInterface | ||||
| { | ||||
|     private AsideActivityCategoryRepository $asideActivityCategoryRepository; | ||||
|  | ||||
|     private TranslatableStringHelper $translatableStringHelper; | ||||
|  | ||||
|     public function __construct(AsideActivityCategoryRepository $asideActivityCategoryRepository, TranslatableStringHelper $translatableStringHelper) | ||||
|     { | ||||
|         $this->asideActivityCategoryRepository = $asideActivityCategoryRepository; | ||||
|         $this->translatableStringHelper = $translatableStringHelper; | ||||
|     } | ||||
|  | ||||
|     public function addRole(): ?string | ||||
|     { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public function alterQuery(QueryBuilder $qb, $data) | ||||
|     { | ||||
|         $qb->addSelect('IDENTITY(aside.type) AS by_aside_activity_type_aggregator') | ||||
|             ->addGroupBy('by_aside_activity_type_aggregator'); | ||||
|     } | ||||
|  | ||||
|     public function applyOn(): string | ||||
|     { | ||||
|         return Declarations::ASIDE_ACTIVITY_TYPE; | ||||
|     } | ||||
|  | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|         // No form needed | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|         return function ($value): string { | ||||
|             if ('_header' === $value) { | ||||
|                 return 'export.aggregator.Aside activity type'; | ||||
|             } | ||||
|  | ||||
|             if (null === $value || null === $t = $this->asideActivityCategoryRepository->find($value)) { | ||||
|                 return ''; | ||||
|             } | ||||
|  | ||||
|             return $this->translatableStringHelper->localize($t->getTitle()); | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     public function getQueryKeys($data): array | ||||
|     { | ||||
|         return ['by_aside_activity_type_aggregator']; | ||||
|     } | ||||
|  | ||||
|     public function getTitle(): string | ||||
|     { | ||||
|         return 'export.aggregator.Group by aside activity type'; | ||||
|     } | ||||
| } | ||||
| @@ -1,89 +0,0 @@ | ||||
| <?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\AsideActivityBundle\Export\Aggregator; | ||||
|  | ||||
| use Chill\AsideActivityBundle\Export\Declarations; | ||||
| use Chill\MainBundle\Export\AggregatorInterface; | ||||
| use Chill\MainBundle\Repository\UserJobRepositoryInterface; | ||||
| use Chill\MainBundle\Templating\TranslatableStringHelperInterface; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
|  | ||||
| use function in_array; | ||||
|  | ||||
| class ByUserJobAggregator implements AggregatorInterface | ||||
| { | ||||
|     private TranslatableStringHelperInterface $translatableStringHelper; | ||||
|  | ||||
|     private UserJobRepositoryInterface $userJobRepository; | ||||
|  | ||||
|     public function __construct(UserJobRepositoryInterface $userJobRepository, TranslatableStringHelperInterface $translatableStringHelper) | ||||
|     { | ||||
|         $this->userJobRepository = $userJobRepository; | ||||
|         $this->translatableStringHelper = $translatableStringHelper; | ||||
|     } | ||||
|  | ||||
|     public function addRole(): ?string | ||||
|     { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public function alterQuery(QueryBuilder $qb, $data) | ||||
|     { | ||||
|         if (!in_array('aside_user', $qb->getAllAliases(), true)) { | ||||
|             $qb->leftJoin('aside.agent', 'aside_user'); | ||||
|         } | ||||
|  | ||||
|         $qb | ||||
|             ->addSelect('IDENTITY(aside_user.userJob) AS aside_activity_user_job_aggregator') | ||||
|             ->addGroupBy('aside_activity_user_job_aggregator'); | ||||
|     } | ||||
|  | ||||
|     public function applyOn() | ||||
|     { | ||||
|         return Declarations::ASIDE_ACTIVITY_TYPE; | ||||
|     } | ||||
|  | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|         // nothing to add in the form | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|         return function ($value): string { | ||||
|             if ('_header' === $value) { | ||||
|                 return 'Users \'s job'; | ||||
|             } | ||||
|  | ||||
|             if (null === $value || '' === $value) { | ||||
|                 return ''; | ||||
|             } | ||||
|  | ||||
|             $j = $this->userJobRepository->find($value); | ||||
|  | ||||
|             return $this->translatableStringHelper->localize( | ||||
|                 $j->getLabel() | ||||
|             ); | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     public function getQueryKeys($data): array | ||||
|     { | ||||
|         return ['aside_activity_user_job_aggregator']; | ||||
|     } | ||||
|  | ||||
|     public function getTitle() | ||||
|     { | ||||
|         return 'export.aggregator.Aggregate by user job'; | ||||
|     } | ||||
| } | ||||
| @@ -1,89 +0,0 @@ | ||||
| <?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\AsideActivityBundle\Export\Aggregator; | ||||
|  | ||||
| use Chill\AsideActivityBundle\Export\Declarations; | ||||
| use Chill\MainBundle\Export\AggregatorInterface; | ||||
| use Chill\MainBundle\Repository\ScopeRepositoryInterface; | ||||
| use Chill\MainBundle\Templating\TranslatableStringHelperInterface; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
|  | ||||
| use function in_array; | ||||
|  | ||||
| class ByUserScopeAggregator implements AggregatorInterface | ||||
| { | ||||
|     private ScopeRepositoryInterface $scopeRepository; | ||||
|  | ||||
|     private TranslatableStringHelperInterface $translatableStringHelper; | ||||
|  | ||||
|     public function __construct(ScopeRepositoryInterface $scopeRepository, TranslatableStringHelperInterface $translatableStringHelper) | ||||
|     { | ||||
|         $this->scopeRepository = $scopeRepository; | ||||
|         $this->translatableStringHelper = $translatableStringHelper; | ||||
|     } | ||||
|  | ||||
|     public function addRole(): ?string | ||||
|     { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public function alterQuery(QueryBuilder $qb, $data) | ||||
|     { | ||||
|         if (!in_array('aside_user', $qb->getAllAliases(), true)) { | ||||
|             $qb->leftJoin('aside.agent', 'aside_user'); | ||||
|         } | ||||
|  | ||||
|         $qb | ||||
|             ->addSelect('IDENTITY(aside_user.mainScope) AS aside_activity_user_scope_aggregator') | ||||
|             ->addGroupBy('aside_activity_user_scope_aggregator'); | ||||
|     } | ||||
|  | ||||
|     public function applyOn() | ||||
|     { | ||||
|         return Declarations::ASIDE_ACTIVITY_TYPE; | ||||
|     } | ||||
|  | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|         // nothing to add in the form | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|         return function ($value): string { | ||||
|             if ('_header' === $value) { | ||||
|                 return 'Users \'s scope'; | ||||
|             } | ||||
|  | ||||
|             if (null === $value || '' === $value) { | ||||
|                 return ''; | ||||
|             } | ||||
|  | ||||
|             $s = $this->scopeRepository->find($value); | ||||
|  | ||||
|             return $this->translatableStringHelper->localize( | ||||
|                 $s->getName() | ||||
|             ); | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     public function getQueryKeys($data): array | ||||
|     { | ||||
|         return ['aside_activity_user_scope_aggregator']; | ||||
|     } | ||||
|  | ||||
|     public function getTitle() | ||||
|     { | ||||
|         return 'export.aggregator.Aggregate by user scope'; | ||||
|     } | ||||
| } | ||||
| @@ -1,20 +0,0 @@ | ||||
| <?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\AsideActivityBundle\Export; | ||||
|  | ||||
| /** | ||||
|  * This class declare constants used for the export framework. | ||||
|  */ | ||||
| abstract class Declarations | ||||
| { | ||||
|     public const ASIDE_ACTIVITY_TYPE = 'aside_activity'; | ||||
| } | ||||
| @@ -1,102 +0,0 @@ | ||||
| <?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\AsideActivityBundle\Export\Export; | ||||
|  | ||||
| use Chill\AsideActivityBundle\Export\Declarations; | ||||
| use Chill\AsideActivityBundle\Repository\AsideActivityRepository; | ||||
| use Chill\AsideActivityBundle\Security\AsideActivityVoter; | ||||
| use Chill\MainBundle\Export\ExportInterface; | ||||
| use Chill\MainBundle\Export\FormatterInterface; | ||||
| use Chill\MainBundle\Export\GroupedExportInterface; | ||||
| use Doctrine\ORM\Query; | ||||
| use LogicException; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
|  | ||||
| class AvgAsideActivityDuration implements ExportInterface, GroupedExportInterface | ||||
| { | ||||
|     private AsideActivityRepository $repository; | ||||
|  | ||||
|     public function __construct( | ||||
|         AsideActivityRepository $repository | ||||
|     ) { | ||||
|         $this->repository = $repository; | ||||
|     } | ||||
|  | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     public function getAllowedFormattersTypes(): array | ||||
|     { | ||||
|         return [FormatterInterface::TYPE_TABULAR]; | ||||
|     } | ||||
|  | ||||
|     public function getDescription(): string | ||||
|     { | ||||
|         return 'export.Average aside activities duration'; | ||||
|     } | ||||
|  | ||||
|     public function getGroup(): string | ||||
|     { | ||||
|         return 'export.Exports of aside activities'; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|         if ('export_avg_aside_activity_duration' !== $key) { | ||||
|             throw new LogicException("the key {$key} is not used by this export"); | ||||
|         } | ||||
|  | ||||
|         return static fn ($value) => '_header' === $value ? 'Average duration aside activities' : $value; | ||||
|     } | ||||
|  | ||||
|     public function getQueryKeys($data): array | ||||
|     { | ||||
|         return ['export_avg_aside_activity_duration']; | ||||
|     } | ||||
|  | ||||
|     public function getResult($query, $data) | ||||
|     { | ||||
|         return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); | ||||
|     } | ||||
|  | ||||
|     public function getTitle(): string | ||||
|     { | ||||
|         return 'export.Average aside activities duration'; | ||||
|     } | ||||
|  | ||||
|     public function getType(): string | ||||
|     { | ||||
|         return Declarations::ASIDE_ACTIVITY_TYPE; | ||||
|     } | ||||
|  | ||||
|     public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) | ||||
|     { | ||||
|         $qb = $this->repository->createQueryBuilder('aside'); | ||||
|  | ||||
|         $qb | ||||
|             ->select('AVG(aside.duration) as export_avg_aside_activity_duration') | ||||
|             ->andWhere($qb->expr()->isNotNull('aside.duration')); | ||||
|  | ||||
|         return $qb; | ||||
|     } | ||||
|  | ||||
|     public function requiredRole(): string | ||||
|     { | ||||
|         return AsideActivityVoter::STATS; | ||||
|     } | ||||
|  | ||||
|     public function supportsModifiers(): array | ||||
|     { | ||||
|         return [Declarations::ASIDE_ACTIVITY_TYPE]; | ||||
|     } | ||||
| } | ||||
| @@ -1,107 +0,0 @@ | ||||
| <?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\AsideActivityBundle\Export\Export; | ||||
|  | ||||
| use Chill\AsideActivityBundle\Export\Declarations; | ||||
| use Chill\AsideActivityBundle\Repository\AsideActivityRepository; | ||||
| use Chill\AsideActivityBundle\Security\AsideActivityVoter; | ||||
| use Chill\MainBundle\Export\ExportInterface; | ||||
| use Chill\MainBundle\Export\FormatterInterface; | ||||
| use Chill\MainBundle\Export\GroupedExportInterface; | ||||
| use Doctrine\ORM\Query; | ||||
| use LogicException; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
|  | ||||
| class CountAsideActivity implements ExportInterface, GroupedExportInterface | ||||
| { | ||||
|     private AsideActivityRepository $repository; | ||||
|  | ||||
|     public function __construct( | ||||
|         AsideActivityRepository $repository | ||||
|     ) { | ||||
|         $this->repository = $repository; | ||||
|     } | ||||
|  | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     public function getAllowedFormattersTypes(): array | ||||
|     { | ||||
|         return [FormatterInterface::TYPE_TABULAR]; | ||||
|     } | ||||
|  | ||||
|     public function getDescription(): string | ||||
|     { | ||||
|         return 'export.Count aside activities by various parameters.'; | ||||
|     } | ||||
|  | ||||
|     public function getGroup(): string | ||||
|     { | ||||
|         return 'export.Exports of aside activities'; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|         if ('export_result' !== $key) { | ||||
|             throw new LogicException("the key {$key} is not used by this export"); | ||||
|         } | ||||
|  | ||||
|         $labels = array_combine($values, $values); | ||||
|         $labels['_header'] = $this->getTitle(); | ||||
|  | ||||
|         return static function ($value) use ($labels) { | ||||
|             return $labels[$value]; | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     public function getQueryKeys($data): array | ||||
|     { | ||||
|         return ['export_result']; | ||||
|     } | ||||
|  | ||||
|     public function getResult($query, $data) | ||||
|     { | ||||
|         return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); | ||||
|     } | ||||
|  | ||||
|     public function getTitle(): string | ||||
|     { | ||||
|         return 'export.Count aside activities'; | ||||
|     } | ||||
|  | ||||
|     public function getType(): string | ||||
|     { | ||||
|         return Declarations::ASIDE_ACTIVITY_TYPE; | ||||
|     } | ||||
|  | ||||
|     public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) | ||||
|     { | ||||
|         $qb = $this->repository->createQueryBuilder('aside'); | ||||
|  | ||||
|         $qb->select('COUNT(DISTINCT aside.id) AS export_result'); | ||||
|  | ||||
|         return $qb; | ||||
|     } | ||||
|  | ||||
|     public function requiredRole(): string | ||||
|     { | ||||
|         return AsideActivityVoter::STATS; | ||||
|     } | ||||
|  | ||||
|     public function supportsModifiers(): array | ||||
|     { | ||||
|         return [ | ||||
|             Declarations::ASIDE_ACTIVITY_TYPE, | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @@ -1,243 +0,0 @@ | ||||
| <?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\AsideActivityBundle\Export\Export; | ||||
|  | ||||
| use Chill\AsideActivityBundle\Entity\AsideActivity; | ||||
| use Chill\AsideActivityBundle\Export\Declarations; | ||||
| use Chill\AsideActivityBundle\Repository\AsideActivityCategoryRepository; | ||||
| use Chill\AsideActivityBundle\Security\AsideActivityVoter; | ||||
| use Chill\AsideActivityBundle\Templating\Entity\CategoryRender; | ||||
| use Chill\MainBundle\Entity\Center; | ||||
| use Chill\MainBundle\Export\FormatterInterface; | ||||
| use Chill\MainBundle\Export\GroupedExportInterface; | ||||
| use Chill\MainBundle\Export\Helper\DateTimeHelper; | ||||
| use Chill\MainBundle\Export\Helper\UserHelper; | ||||
| use Chill\MainBundle\Export\ListInterface; | ||||
| use Chill\MainBundle\Repository\CenterRepositoryInterface; | ||||
| use Chill\MainBundle\Repository\ScopeRepositoryInterface; | ||||
| use Chill\MainBundle\Templating\TranslatableStringHelperInterface; | ||||
| use DateTimeInterface; | ||||
| use Doctrine\ORM\AbstractQuery; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use LogicException; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
|  | ||||
| final class ListAsideActivity implements ListInterface, GroupedExportInterface | ||||
| { | ||||
|     private AsideActivityCategoryRepository $asideActivityCategoryRepository; | ||||
|  | ||||
|     private CategoryRender $categoryRender; | ||||
|  | ||||
|     private CenterRepositoryInterface $centerRepository; | ||||
|  | ||||
|     private DateTimeHelper $dateTimeHelper; | ||||
|  | ||||
|     private EntityManagerInterface $em; | ||||
|  | ||||
|     private ScopeRepositoryInterface $scopeRepository; | ||||
|  | ||||
|     private TranslatableStringHelperInterface $translatableStringHelper; | ||||
|  | ||||
|     private UserHelper $userHelper; | ||||
|  | ||||
|     public function __construct( | ||||
|         EntityManagerInterface $em, | ||||
|         DateTimeHelper $dateTimeHelper, | ||||
|         UserHelper $userHelper, | ||||
|         ScopeRepositoryInterface $scopeRepository, | ||||
|         CenterRepositoryInterface $centerRepository, | ||||
|         AsideActivityCategoryRepository $asideActivityCategoryRepository, | ||||
|         CategoryRender $categoryRender, | ||||
|         TranslatableStringHelperInterface $translatableStringHelper | ||||
|     ) { | ||||
|         $this->em = $em; | ||||
|         $this->dateTimeHelper = $dateTimeHelper; | ||||
|         $this->userHelper = $userHelper; | ||||
|         $this->scopeRepository = $scopeRepository; | ||||
|         $this->centerRepository = $centerRepository; | ||||
|         $this->asideActivityCategoryRepository = $asideActivityCategoryRepository; | ||||
|         $this->categoryRender = $categoryRender; | ||||
|         $this->translatableStringHelper = $translatableStringHelper; | ||||
|     } | ||||
|  | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     public function getAllowedFormattersTypes() | ||||
|     { | ||||
|         return [FormatterInterface::TYPE_LIST]; | ||||
|     } | ||||
|  | ||||
|     public function getDescription() | ||||
|     { | ||||
|         return 'export.aside_activity.List of aside activities'; | ||||
|     } | ||||
|  | ||||
|     public function getGroup(): string | ||||
|     { | ||||
|         return 'export.Exports of aside activities'; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|         switch ($key) { | ||||
|             case 'id': | ||||
|             case 'note': | ||||
|                 return static function ($value) use ($key) { | ||||
|                     if ('_header' === $value) { | ||||
|                         return 'export.aside_activity.' . $key; | ||||
|                     } | ||||
|  | ||||
|                     return $value ?? ''; | ||||
|                 }; | ||||
|  | ||||
|             case 'duration': | ||||
|                 return static function ($value) use ($key) { | ||||
|                     if ('_header' === $value) { | ||||
|                         return 'export.aside_activity.' . $key; | ||||
|                     } | ||||
|  | ||||
|                     if (null === $value) { | ||||
|                         return ''; | ||||
|                     } | ||||
|  | ||||
|                     if ($value instanceof DateTimeInterface) { | ||||
|                         return $value->format('H:i:s'); | ||||
|                     } | ||||
|  | ||||
|                     return $value; | ||||
|                 }; | ||||
|  | ||||
|             case 'createdAt': | ||||
|             case 'updatedAt': | ||||
|             case 'date': | ||||
|                 return $this->dateTimeHelper->getLabel('export.aside_activity.' . $key); | ||||
|  | ||||
|             case 'agent_id': | ||||
|             case 'creator_id': | ||||
|                 return $this->userHelper->getLabel($key, $values, 'export.aside_activity.' . $key); | ||||
|  | ||||
|             case 'aside_activity_type': | ||||
|                 return function ($value) { | ||||
|                     if ('_header' === $value) { | ||||
|                         return 'export.aside_activity.aside_activity_type'; | ||||
|                     } | ||||
|  | ||||
|                     if (null === $value || '' === $value || null === $c = $this->asideActivityCategoryRepository->find($value)) { | ||||
|                         return ''; | ||||
|                     } | ||||
|  | ||||
|                     return $this->categoryRender->renderString($c, []); | ||||
|                 }; | ||||
|  | ||||
|             case 'main_scope': | ||||
|                 return function ($value) { | ||||
|                     if ('_header' === $value) { | ||||
|                         return 'export.aside_activity.main_scope'; | ||||
|                     } | ||||
|  | ||||
|                     if (null === $value || '' === $value || null === $c = $this->scopeRepository->find($value)) { | ||||
|                         return ''; | ||||
|                     } | ||||
|  | ||||
|                     return $this->translatableStringHelper->localize($c->getName()); | ||||
|                 }; | ||||
|  | ||||
|             case 'main_center': | ||||
|                 return function ($value) { | ||||
|                     if ('_header' === $value) { | ||||
|                         return 'export.aside_activity.main_center'; | ||||
|                     } | ||||
|  | ||||
|                     /** @var Center $c */ | ||||
|                     if (null === $value || '' === $value || null === $c = $this->centerRepository->find($value)) { | ||||
|                         return ''; | ||||
|                     } | ||||
|  | ||||
|                     return $c->getName(); | ||||
|                 }; | ||||
|  | ||||
|             default: | ||||
|                 throw new LogicException('this key is not supported : ' . $key); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public function getQueryKeys($data) | ||||
|     { | ||||
|         return [ | ||||
|             'id', | ||||
|             'createdAt', | ||||
|             'updatedAt', | ||||
|             'agent_id', | ||||
|             'creator_id', | ||||
|             'main_scope', | ||||
|             'main_center', | ||||
|             'aside_activity_type', | ||||
|             'date', | ||||
|             'duration', | ||||
|             'note', | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param QueryBuilder $query | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function getResult($query, $data): array | ||||
|     { | ||||
|         return $query->getQuery()->getResult(AbstractQuery::HYDRATE_ARRAY); | ||||
|     } | ||||
|  | ||||
|     public function getTitle() | ||||
|     { | ||||
|         return 'export.aside_activity.List of aside activities'; | ||||
|     } | ||||
|  | ||||
|     public function getType(): string | ||||
|     { | ||||
|         return Declarations::ASIDE_ACTIVITY_TYPE; | ||||
|     } | ||||
|  | ||||
|     public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) | ||||
|     { | ||||
|         $qb = $this->em->createQueryBuilder() | ||||
|             ->from(AsideActivity::class, 'aside') | ||||
|             ->leftJoin('aside.agent', 'agent'); | ||||
|  | ||||
|         $qb | ||||
|             ->addSelect('aside.id AS id') | ||||
|             ->addSelect('aside.createdAt AS createdAt') | ||||
|             ->addSelect('aside.updatedAt AS updatedAt') | ||||
|             ->addSelect('IDENTITY(aside.agent) AS agent_id') | ||||
|             ->addSelect('IDENTITY(aside.createdBy) AS creator_id') | ||||
|             ->addSelect('IDENTITY(agent.mainScope) AS main_scope') | ||||
|             ->addSelect('IDENTITY(agent.mainCenter) AS main_center') | ||||
|             ->addSelect('IDENTITY(aside.type) AS aside_activity_type') | ||||
|             ->addSelect('aside.date') | ||||
|             ->addSelect('aside.duration') | ||||
|             ->addSelect('aside.note'); | ||||
|  | ||||
|         return $qb; | ||||
|     } | ||||
|  | ||||
|     public function requiredRole(): string | ||||
|     { | ||||
|         return AsideActivityVoter::STATS; | ||||
|     } | ||||
|  | ||||
|     public function supportsModifiers() | ||||
|     { | ||||
|         return [Declarations::ASIDE_ACTIVITY_TYPE]; | ||||
|     } | ||||
| } | ||||
| @@ -1,102 +0,0 @@ | ||||
| <?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\AsideActivityBundle\Export\Export; | ||||
|  | ||||
| use Chill\AsideActivityBundle\Export\Declarations; | ||||
| use Chill\AsideActivityBundle\Repository\AsideActivityRepository; | ||||
| use Chill\AsideActivityBundle\Security\AsideActivityVoter; | ||||
| use Chill\MainBundle\Export\ExportInterface; | ||||
| use Chill\MainBundle\Export\FormatterInterface; | ||||
| use Chill\MainBundle\Export\GroupedExportInterface; | ||||
| use Doctrine\ORM\Query; | ||||
| use LogicException; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
|  | ||||
| class SumAsideActivityDuration implements ExportInterface, GroupedExportInterface | ||||
| { | ||||
|     private AsideActivityRepository $repository; | ||||
|  | ||||
|     public function __construct( | ||||
|         AsideActivityRepository $repository | ||||
|     ) { | ||||
|         $this->repository = $repository; | ||||
|     } | ||||
|  | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     public function getAllowedFormattersTypes(): array | ||||
|     { | ||||
|         return [FormatterInterface::TYPE_TABULAR]; | ||||
|     } | ||||
|  | ||||
|     public function getDescription(): string | ||||
|     { | ||||
|         return 'export.Sum aside activities duration'; | ||||
|     } | ||||
|  | ||||
|     public function getGroup(): string | ||||
|     { | ||||
|         return 'export.Exports of aside activities'; | ||||
|     } | ||||
|  | ||||
|     public function getLabels($key, array $values, $data) | ||||
|     { | ||||
|         if ('export_sum_aside_activity_duration' !== $key) { | ||||
|             throw new LogicException("the key {$key} is not used by this export"); | ||||
|         } | ||||
|  | ||||
|         return static fn ($value) => '_header' === $value ? 'Sum duration aside activities' : $value; | ||||
|     } | ||||
|  | ||||
|     public function getQueryKeys($data): array | ||||
|     { | ||||
|         return ['export_sum_aside_activity_duration']; | ||||
|     } | ||||
|  | ||||
|     public function getResult($query, $data) | ||||
|     { | ||||
|         return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); | ||||
|     } | ||||
|  | ||||
|     public function getTitle(): string | ||||
|     { | ||||
|         return 'export.Sum aside activities duration'; | ||||
|     } | ||||
|  | ||||
|     public function getType(): string | ||||
|     { | ||||
|         return Declarations::ASIDE_ACTIVITY_TYPE; | ||||
|     } | ||||
|  | ||||
|     public function initiateQuery(array $requiredModifiers, array $acl, array $data = []) | ||||
|     { | ||||
|         $qb = $this->repository | ||||
|             ->createQueryBuilder('aside'); | ||||
|  | ||||
|         $qb->select('SUM(aside.duration) as export_sum_aside_activity_duration') | ||||
|             ->andWhere($qb->expr()->isNotNull('aside.duration')); | ||||
|  | ||||
|         return $qb; | ||||
|     } | ||||
|  | ||||
|     public function requiredRole(): string | ||||
|     { | ||||
|         return AsideActivityVoter::STATS; | ||||
|     } | ||||
|  | ||||
|     public function supportsModifiers(): array | ||||
|     { | ||||
|         return [Declarations::ASIDE_ACTIVITY_TYPE]; | ||||
|     } | ||||
| } | ||||
| @@ -1,96 +0,0 @@ | ||||
| <?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\AsideActivityBundle\Export\Filter; | ||||
|  | ||||
| use Chill\AsideActivityBundle\Entity\AsideActivityCategory; | ||||
| use Chill\AsideActivityBundle\Export\Declarations; | ||||
| use Chill\AsideActivityBundle\Repository\AsideActivityCategoryRepository; | ||||
| use Chill\AsideActivityBundle\Templating\Entity\CategoryRender; | ||||
| use Chill\MainBundle\Export\FilterInterface; | ||||
| use Chill\MainBundle\Templating\TranslatableStringHelperInterface; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use Symfony\Bridge\Doctrine\Form\Type\EntityType; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
|  | ||||
| class ByActivityTypeFilter implements FilterInterface | ||||
| { | ||||
|     private AsideActivityCategoryRepository $asideActivityTypeRepository; | ||||
|  | ||||
|     private CategoryRender $categoryRender; | ||||
|  | ||||
|     private TranslatableStringHelperInterface $translatableStringHelper; | ||||
|  | ||||
|     public function __construct( | ||||
|         CategoryRender $categoryRender, | ||||
|         TranslatableStringHelperInterface $translatableStringHelper, | ||||
|         AsideActivityCategoryRepository $asideActivityTypeRepository | ||||
|     ) { | ||||
|         $this->categoryRender = $categoryRender; | ||||
|         $this->asideActivityTypeRepository = $asideActivityTypeRepository; | ||||
|         $this->translatableStringHelper = $translatableStringHelper; | ||||
|     } | ||||
|  | ||||
|     public function addRole(): ?string | ||||
|     { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public function alterQuery(QueryBuilder $qb, $data) | ||||
|     { | ||||
|         $clause = $qb->expr()->in('aside.type', ':types'); | ||||
|  | ||||
|         $qb->andWhere($clause); | ||||
|         $qb->setParameter('types', $data['types']); | ||||
|     } | ||||
|  | ||||
|     public function applyOn(): string | ||||
|     { | ||||
|         return Declarations::ASIDE_ACTIVITY_TYPE; | ||||
|     } | ||||
|  | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|         $builder | ||||
|             ->add('types', EntityType::class, [ | ||||
|                 'class' => AsideActivityCategory::class, | ||||
|                 'choices' => $this->asideActivityTypeRepository->findAllActive(), | ||||
|                 'required' => false, | ||||
|                 'multiple' => true, | ||||
|                 'expanded' => false, | ||||
|                 'attr' => [ | ||||
|                     'class' => 'select2', | ||||
|                 ], | ||||
|                 'choice_label' => function (AsideActivityCategory $category) { | ||||
|                     $options = []; | ||||
|  | ||||
|                     return $this->categoryRender->renderString($category, $options); | ||||
|                 }, | ||||
|             ]); | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string'): array | ||||
|     { | ||||
|         $types = array_map( | ||||
|             fn (AsideActivityCategory $t): string => $this->translatableStringHelper->localize($t->getTitle()), | ||||
|             $data['types']->toArray() | ||||
|         ); | ||||
|  | ||||
|         return ['export.filter.Filtered by aside activity type: only %type%', [ | ||||
|             '%type%' => implode(', ', $types), | ||||
|         ]]; | ||||
|     } | ||||
|  | ||||
|     public function getTitle(): string | ||||
|     { | ||||
|         return 'export.filter.Filter by aside activity type'; | ||||
|     } | ||||
| } | ||||
| @@ -1,135 +0,0 @@ | ||||
| <?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\AsideActivityBundle\Export\Filter; | ||||
|  | ||||
| use Chill\AsideActivityBundle\Export\Declarations; | ||||
| use Chill\MainBundle\Export\FilterInterface; | ||||
| use Chill\MainBundle\Form\Type\Export\FilterType; | ||||
| use Chill\MainBundle\Form\Type\PickRollingDateType; | ||||
| use Chill\MainBundle\Service\RollingDate\RollingDate; | ||||
| use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
| use Symfony\Component\Form\FormError; | ||||
| use Symfony\Component\Form\FormEvent; | ||||
| use Symfony\Component\Form\FormEvents; | ||||
| use Symfony\Contracts\Translation\TranslatorInterface; | ||||
|  | ||||
| class ByDateFilter implements FilterInterface | ||||
| { | ||||
|     protected TranslatorInterface $translator; | ||||
|  | ||||
|     private RollingDateConverterInterface $rollingDateConverter; | ||||
|  | ||||
|     public function __construct( | ||||
|         RollingDateConverterInterface $rollingDateConverter, | ||||
|         TranslatorInterface $translator | ||||
|     ) { | ||||
|         $this->translator = $translator; | ||||
|         $this->rollingDateConverter = $rollingDateConverter; | ||||
|     } | ||||
|  | ||||
|     public function addRole(): ?string | ||||
|     { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public function alterQuery(QueryBuilder $qb, $data) | ||||
|     { | ||||
|         $clause = $qb->expr()->between( | ||||
|             'aside.date', | ||||
|             ':date_from', | ||||
|             ':date_to' | ||||
|         ); | ||||
|  | ||||
|         $qb->andWhere($clause); | ||||
|  | ||||
|         $qb->setParameter( | ||||
|             'date_from', | ||||
|             $this->rollingDateConverter->convert($data['date_from']) | ||||
|         )->setParameter( | ||||
|             'date_to', | ||||
|             $this->rollingDateConverter->convert($data['date_to']) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function applyOn(): string | ||||
|     { | ||||
|         return Declarations::ASIDE_ACTIVITY_TYPE; | ||||
|     } | ||||
|  | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|         $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) { | ||||
|             /** @var \Symfony\Component\Form\FormInterface $filterForm */ | ||||
|             $filterForm = $event->getForm()->getParent(); | ||||
|             $enabled = $filterForm->get(FilterType::ENABLED_FIELD)->getData(); | ||||
|  | ||||
|             if (true === $enabled) { | ||||
|                 // if the filter is enabled, add some validation | ||||
|                 $form = $event->getForm(); | ||||
|                 $date_from = $form->get('date_from')->getData(); | ||||
|                 $date_to = $form->get('date_to')->getData(); | ||||
|  | ||||
|                 // check that fields are not empty | ||||
|                 if (null === $date_from) { | ||||
|                     $form->get('date_from')->addError(new FormError( | ||||
|                         $this->translator->trans('This field ' | ||||
|                             . 'should not be empty') | ||||
|                     )); | ||||
|                 } | ||||
|  | ||||
|                 if (null === $date_to) { | ||||
|                     $form->get('date_to')->addError(new FormError( | ||||
|                         $this->translator->trans('This field ' | ||||
|                             . 'should not be empty') | ||||
|                     )); | ||||
|                 } | ||||
|  | ||||
|                 // check that date_from is before date_to | ||||
|                 if ( | ||||
|                     (null !== $date_from && null !== $date_to) | ||||
|                     && $date_from >= $date_to | ||||
|                 ) { | ||||
|                     $form->get('date_to')->addError(new FormError( | ||||
|                         $this->translator->trans('export.filter.This date should be after ' | ||||
|                             . 'the date given in "Implied in an aside activity after ' | ||||
|                             . 'this date" field') | ||||
|                     )); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string'): array | ||||
|     { | ||||
|         return ['export.filter.Filtered by aside activities between %dateFrom% and %dateTo%', [ | ||||
|             '%dateFrom%' => $this->rollingDateConverter->convert($data['date_from'])->format('d-m-Y'), | ||||
|             '%dateTo%' => $this->rollingDateConverter->convert($data['date_to'])->format('d-m-Y'), | ||||
|         ]]; | ||||
|     } | ||||
|  | ||||
|     public function getTitle(): string | ||||
|     { | ||||
|         return 'export.filter.Filter by aside activity date'; | ||||
|     } | ||||
| } | ||||
| @@ -1,74 +0,0 @@ | ||||
| <?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\AsideActivityBundle\Export\Filter; | ||||
|  | ||||
| use Chill\AsideActivityBundle\Export\Declarations; | ||||
| use Chill\MainBundle\Export\FilterInterface; | ||||
| use Chill\MainBundle\Form\Type\PickUserDynamicType; | ||||
| use Chill\MainBundle\Templating\Entity\UserRender; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
|  | ||||
| class ByUserFilter implements FilterInterface | ||||
| { | ||||
|     private UserRender $userRender; | ||||
|  | ||||
|     public function __construct(UserRender $userRender) | ||||
|     { | ||||
|         $this->userRender = $userRender; | ||||
|     } | ||||
|  | ||||
|     public function addRole(): ?string | ||||
|     { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public function alterQuery(QueryBuilder $qb, $data) | ||||
|     { | ||||
|         $clause = $qb->expr()->in('aside.agent', ':users'); | ||||
|  | ||||
|         $qb | ||||
|             ->andWhere($clause) | ||||
|             ->setParameter('users', $data['accepted_users']); | ||||
|     } | ||||
|  | ||||
|     public function applyOn(): string | ||||
|     { | ||||
|         return Declarations::ASIDE_ACTIVITY_TYPE; | ||||
|     } | ||||
|  | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|         $builder->add('accepted_users', PickUserDynamicType::class, [ | ||||
|             'multiple' => true, | ||||
|             'label' => 'Creators', | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string'): array | ||||
|     { | ||||
|         $users = []; | ||||
|  | ||||
|         foreach ($data['accepted_users'] as $u) { | ||||
|             $users[] = $this->userRender->renderString($u, []); | ||||
|         } | ||||
|  | ||||
|         return ['export.filter.Filtered aside activity by user: only %users%', [ | ||||
|             '%users%' => implode(', ', $users), | ||||
|         ]]; | ||||
|     } | ||||
|  | ||||
|     public function getTitle(): string | ||||
|     { | ||||
|         return 'export.filter.Filter aside activity by user'; | ||||
|     } | ||||
| } | ||||
| @@ -1,81 +0,0 @@ | ||||
| <?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\AsideActivityBundle\Export\Filter; | ||||
|  | ||||
| use Chill\AsideActivityBundle\Entity\AsideActivity; | ||||
| use Chill\AsideActivityBundle\Export\Declarations; | ||||
| use Chill\MainBundle\Entity\UserJob; | ||||
| use Chill\MainBundle\Export\FilterInterface; | ||||
| use Chill\MainBundle\Templating\TranslatableStringHelperInterface; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use Symfony\Bridge\Doctrine\Form\Type\EntityType; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
|  | ||||
| class ByUserJobFilter implements FilterInterface | ||||
| { | ||||
|     private TranslatableStringHelperInterface $translatableStringHelper; | ||||
|  | ||||
|     public function __construct(TranslatableStringHelperInterface $translatableStringHelper) | ||||
|     { | ||||
|         $this->translatableStringHelper = $translatableStringHelper; | ||||
|     } | ||||
|  | ||||
|     public function addRole(): ?string | ||||
|     { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public function alterQuery(QueryBuilder $qb, $data) | ||||
|     { | ||||
|         $qb | ||||
|             ->andWhere( | ||||
|                 $qb->expr()->exists( | ||||
|                     'SELECT 1 FROM ' . AsideActivity::class . ' aside_activity_user_job_filter_act | ||||
|                 JOIN aside_activity_user_job_filter_act.agent aside_activity_user_job_filter_user WHERE aside_activity_user_job_filter_user.userJob IN (:aside_activity_user_job_filter_jobs) AND aside_activity_user_job_filter_act = aside' | ||||
|                 ) | ||||
|             ) | ||||
|             ->setParameter('aside_activity_user_job_filter_jobs', $data['jobs']); | ||||
|     } | ||||
|  | ||||
|     public function applyOn() | ||||
|     { | ||||
|         return Declarations::ASIDE_ACTIVITY_TYPE; | ||||
|     } | ||||
|  | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|         $builder->add('jobs', EntityType::class, [ | ||||
|             'class' => UserJob::class, | ||||
|             'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize($j->getLabel()), | ||||
|             'multiple' => true, | ||||
|             'expanded' => true, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string') | ||||
|     { | ||||
|         return ['export.filter.Filtered aside activities by user jobs: only %jobs%', [ | ||||
|             '%jobs%' => implode( | ||||
|                 ', ', | ||||
|                 array_map( | ||||
|                     fn (UserJob $job) => $this->translatableStringHelper->localize($job->getLabel()), | ||||
|                     $data['jobs']->toArray() | ||||
|                 ) | ||||
|             ), | ||||
|         ]]; | ||||
|     } | ||||
|  | ||||
|     public function getTitle() | ||||
|     { | ||||
|         return 'export.filter.Filter by user jobs'; | ||||
|     } | ||||
| } | ||||
| @@ -1,88 +0,0 @@ | ||||
| <?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\AsideActivityBundle\Export\Filter; | ||||
|  | ||||
| use Chill\AsideActivityBundle\Entity\AsideActivity; | ||||
| use Chill\AsideActivityBundle\Export\Declarations; | ||||
| use Chill\MainBundle\Entity\Scope; | ||||
| use Chill\MainBundle\Export\FilterInterface; | ||||
| use Chill\MainBundle\Repository\ScopeRepositoryInterface; | ||||
| use Chill\MainBundle\Templating\TranslatableStringHelperInterface; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use Symfony\Bridge\Doctrine\Form\Type\EntityType; | ||||
| use Symfony\Component\Form\FormBuilderInterface; | ||||
|  | ||||
| class ByUserScopeFilter implements FilterInterface | ||||
| { | ||||
|     private ScopeRepositoryInterface $scopeRepository; | ||||
|  | ||||
|     private TranslatableStringHelperInterface $translatableStringHelper; | ||||
|  | ||||
|     public function __construct( | ||||
|         ScopeRepositoryInterface $scopeRepository, | ||||
|         TranslatableStringHelperInterface $translatableStringHelper | ||||
|     ) { | ||||
|         $this->scopeRepository = $scopeRepository; | ||||
|         $this->translatableStringHelper = $translatableStringHelper; | ||||
|     } | ||||
|  | ||||
|     public function addRole(): ?string | ||||
|     { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public function alterQuery(QueryBuilder $qb, $data) | ||||
|     { | ||||
|         $qb | ||||
|             ->andWhere( | ||||
|                 $qb->expr()->exists( | ||||
|                     'SELECT 1 FROM ' . AsideActivity::class . ' aside_activity_user_scope_filter_act | ||||
|                 JOIN aside_activity_user_scope_filter_act.agent aside_activity_user_scope_filter_user WHERE aside_activity_user_scope_filter_user.mainScope IN (:aside_activity_user_scope_filter_scopes) AND  aside_activity_user_scope_filter_act = aside ' | ||||
|                 ) | ||||
|             ) | ||||
|             ->setParameter('aside_activity_user_scope_filter_scopes', $data['scopes']); | ||||
|     } | ||||
|  | ||||
|     public function applyOn() | ||||
|     { | ||||
|         return Declarations::ASIDE_ACTIVITY_TYPE; | ||||
|     } | ||||
|  | ||||
|     public function buildForm(FormBuilderInterface $builder) | ||||
|     { | ||||
|         $builder->add('scopes', EntityType::class, [ | ||||
|             'class' => Scope::class, | ||||
|             'choices' => $this->scopeRepository->findAllActive(), | ||||
|             'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()), | ||||
|             'multiple' => true, | ||||
|             'expanded' => true, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function describeAction($data, $format = 'string') | ||||
|     { | ||||
|         return ['export.filter.Filtered aside activities by user scope: only %scopes%', [ | ||||
|             '%scopes%' => implode( | ||||
|                 ', ', | ||||
|                 array_map( | ||||
|                     fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()), | ||||
|                     $data['scopes']->toArray() | ||||
|                 ) | ||||
|             ), | ||||
|         ]]; | ||||
|     } | ||||
|  | ||||
|     public function getTitle() | ||||
|     { | ||||
|         return 'export.filter.Filter by user scope'; | ||||
|     } | ||||
| } | ||||
| @@ -12,7 +12,8 @@ declare(strict_types=1); | ||||
| namespace Chill\AsideActivityBundle\Form; | ||||
|  | ||||
| use Chill\AsideActivityBundle\Entity\AsideActivity; | ||||
| use Chill\AsideActivityBundle\Form\Type\PickAsideActivityCategoryType; | ||||
| use Chill\AsideActivityBundle\Entity\AsideActivityCategory; | ||||
| use Chill\AsideActivityBundle\Templating\Entity\CategoryRender; | ||||
| use Chill\MainBundle\Form\Type\ChillDateType; | ||||
| use Chill\MainBundle\Form\Type\ChillTextareaType; | ||||
| use Chill\MainBundle\Form\Type\PickUserDynamicType; | ||||
| @@ -20,6 +21,8 @@ use DateInterval; | ||||
| use DateTime; | ||||
| use DateTimeImmutable; | ||||
| use DateTimeZone; | ||||
| use Doctrine\ORM\EntityRepository; | ||||
| use Symfony\Bridge\Doctrine\Form\Type\EntityType; | ||||
| use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; | ||||
| use Symfony\Component\Form\AbstractType; | ||||
| use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; | ||||
| @@ -34,16 +37,20 @@ use function in_array; | ||||
|  | ||||
| final class AsideActivityFormType extends AbstractType | ||||
| { | ||||
|     private CategoryRender $categoryRender; | ||||
|  | ||||
|     private TokenStorageInterface $storage; | ||||
|  | ||||
|     private array $timeChoices; | ||||
|  | ||||
|     public function __construct( | ||||
|         ParameterBagInterface $parameterBag, | ||||
|         TokenStorageInterface $storage | ||||
|         TokenStorageInterface $storage, | ||||
|         CategoryRender $categoryRender | ||||
|     ) { | ||||
|         $this->timeChoices = $parameterBag->get('chill_aside_activity.form.time_duration'); | ||||
|         $this->storage = $storage; | ||||
|         $this->categoryRender = $categoryRender; | ||||
|     } | ||||
|  | ||||
|     public function buildForm(FormBuilderInterface $builder, array $options) | ||||
| @@ -74,10 +81,28 @@ final class AsideActivityFormType extends AbstractType | ||||
|                     'required' => true, | ||||
|                 ] | ||||
|             ) | ||||
|             ->add('type', PickAsideActivityCategoryType::class, [ | ||||
|                 'label' => 'Type', | ||||
|                 'required' => true, | ||||
|             ]) | ||||
|             ->add( | ||||
|                 'type', | ||||
|                 EntityType::class, | ||||
|                 [ | ||||
|                     'label' => 'Type', | ||||
|                     'required' => true, | ||||
|                     'class' => AsideActivityCategory::class, | ||||
|                     'placeholder' => 'Choose the activity category', | ||||
|                     'query_builder' => static function (EntityRepository $er) { | ||||
|                         $qb = $er->createQueryBuilder('ac'); | ||||
|                         $qb->where($qb->expr()->eq('ac.isActive', 'TRUE')) | ||||
|                             ->addOrderBy('ac.ordering', 'ASC'); | ||||
|  | ||||
|                         return $qb; | ||||
|                     }, | ||||
|                     'choice_label' => function (AsideActivityCategory $asideActivityCategory) { | ||||
|                         $options = []; | ||||
|  | ||||
|                         return $this->categoryRender->renderString($asideActivityCategory, $options); | ||||
|                     }, | ||||
|                 ] | ||||
|             ) | ||||
|             ->add('duration', ChoiceType::class, $durationTimeOptions) | ||||
|             ->add('note', ChillTextareaType::class, [ | ||||
|                 'label' => 'Note', | ||||
|   | ||||
| @@ -1,57 +0,0 @@ | ||||
| <?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\AsideActivityBundle\Form\Type; | ||||
|  | ||||
| use Chill\AsideActivityBundle\Entity\AsideActivityCategory; | ||||
| use Chill\AsideActivityBundle\Templating\Entity\CategoryRender; | ||||
| use Doctrine\ORM\EntityRepository; | ||||
| use Symfony\Bridge\Doctrine\Form\Type\EntityType; | ||||
| use Symfony\Component\Form\AbstractType; | ||||
| use Symfony\Component\OptionsResolver\OptionsResolver; | ||||
|  | ||||
| final class PickAsideActivityCategoryType extends AbstractType | ||||
| { | ||||
|     private CategoryRender $categoryRender; | ||||
|  | ||||
|     public function __construct( | ||||
|         CategoryRender $categoryRender | ||||
|     ) { | ||||
|         $this->categoryRender = $categoryRender; | ||||
|     } | ||||
|  | ||||
|     public function configureOptions(OptionsResolver $resolver) | ||||
|     { | ||||
|         $resolver | ||||
|             ->setDefaults([ | ||||
|                 'class' => AsideActivityCategory::class, | ||||
|                 'placeholder' => 'Choose the activity category', | ||||
|                 'query_builder' => static function (EntityRepository $er) { | ||||
|                     $qb = $er->createQueryBuilder('ac'); | ||||
|                     $qb->where($qb->expr()->eq('ac.isActive', 'TRUE')) | ||||
|                         ->addOrderBy('ac.ordering', 'ASC'); | ||||
|  | ||||
|                     return $qb; | ||||
|                 }, | ||||
|                 'choice_label' => function (AsideActivityCategory $asideActivityCategory) { | ||||
|                     $options = []; | ||||
|  | ||||
|                     return $this->categoryRender->renderString($asideActivityCategory, $options); | ||||
|                 }, | ||||
|                 'attr' => ['class' => 'select2'], | ||||
|             ]); | ||||
|     } | ||||
|  | ||||
|     public function getParent(): string | ||||
|     { | ||||
|         return EntityType::class; | ||||
|     } | ||||
| } | ||||
| @@ -38,11 +38,6 @@ class AsideActivityCategoryRepository implements ObjectRepository | ||||
|         return $this->repository->findAll(); | ||||
|     } | ||||
|  | ||||
|     public function findAllActive(): array | ||||
|     { | ||||
|         return $this->repository->findBy(['isActive' => true]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param mixed|null $limit | ||||
|      * @param mixed|null $offset | ||||
|   | ||||
| @@ -12,20 +12,46 @@ declare(strict_types=1); | ||||
| namespace Chill\AsideActivityBundle\Repository; | ||||
|  | ||||
| use Chill\AsideActivityBundle\Entity\AsideActivity; | ||||
| use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; | ||||
| use Doctrine\Persistence\ManagerRegistry; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use Doctrine\ORM\EntityRepository; | ||||
| use Doctrine\Persistence\ObjectRepository; | ||||
|  | ||||
| /** | ||||
|  * @method AsideActivity|null find($id, $lockMode = null, $lockVersion = null) | ||||
|  * @method AsideActivity|null findOneBy(array $criteria, array $orderBy = null) | ||||
|  * @method AsideActivity[]    findAll() | ||||
|  * @method AsideActivity[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) | ||||
|  */ | ||||
| final class AsideActivityRepository extends ServiceEntityRepository | ||||
| final class AsideActivityRepository implements ObjectRepository | ||||
| { | ||||
|     public function __construct(ManagerRegistry $registry) | ||||
|     private EntityRepository $repository; | ||||
|  | ||||
|     public function __construct(EntityManagerInterface $entityManager) | ||||
|     { | ||||
|         parent::__construct($registry, AsideActivity::class); | ||||
|         $this->repository = $entityManager->getRepository(AsideActivity::class); | ||||
|     } | ||||
|  | ||||
|     public function find($id): ?AsideActivity | ||||
|     { | ||||
|         return $this->repository->find($id); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return AsideActivity[] | ||||
|      */ | ||||
|     public function findAll(): array | ||||
|     { | ||||
|         return $this->repository->findAll(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param mixed|null $limit | ||||
|      * @param mixed|null $offset | ||||
|      * | ||||
|      * @return AsideActivity[] | ||||
|      */ | ||||
|     public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array | ||||
|     { | ||||
|         return $this->repository->findBy($criteria, $orderBy, $limit, $offset); | ||||
|     } | ||||
|  | ||||
|     public function findOneBy(array $criteria): ?AsideActivity | ||||
|     { | ||||
|         return $this->repository->findOneBy($criteria); | ||||
|     } | ||||
|  | ||||
|     public function getClassName(): string | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
|  | ||||
| <div class="{% block crud_content_main_div_class %}col-10 centered{% endblock %}"> | ||||
| 	{% block crud_content_header %} | ||||
| 		<h1>{{ ('crud.'~crud_name~'.title_delete')|trans({ '%as_string%': 'Aside Activity' }) }}</h1> | ||||
| 	{% endblock crud_content_header %} | ||||
| @@ -27,4 +27,4 @@ | ||||
| 	</ul> | ||||
|  | ||||
| 	{{ form_end(form) }} | ||||
|  | ||||
| </div> | ||||
|   | ||||
| @@ -87,5 +87,5 @@ | ||||
| 				</li> | ||||
| 			</ul> | ||||
| 		{% endif %} | ||||
|     </div> | ||||
|  | ||||
| 	{% endblock %} | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| {% extends '@ChillMain/layout.html.twig' %} | ||||
| {% extends '@ChillMain/Admin/layout.html.twig' %} | ||||
|  | ||||
| {% block js %} | ||||
|     {{ parent() }} | ||||
| @@ -14,7 +14,7 @@ | ||||
| {% include('@ChillMain/CRUD/_new_title.html.twig') %} | ||||
| {% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
| {% block admin_content %} | ||||
| {% embed '@ChillMain/CRUD/_new_content.html.twig' %} | ||||
|     {% block content_form_actions_save_and_show %}{% endblock %} | ||||
| {% endembed %} | ||||
|   | ||||
| @@ -1,79 +0,0 @@ | ||||
| <?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\AsideActivityBundle\Security; | ||||
|  | ||||
| use Chill\MainBundle\Entity\Center; | ||||
| use Chill\MainBundle\Entity\User; | ||||
| use Chill\MainBundle\Security\Authorization\AbstractChillVoter; | ||||
| use Chill\MainBundle\Security\Authorization\VoterHelperFactoryInterface; | ||||
| use Chill\MainBundle\Security\Authorization\VoterHelperInterface; | ||||
| use Chill\MainBundle\Security\ProvideRoleHierarchyInterface; | ||||
| use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; | ||||
|  | ||||
| class AsideActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface | ||||
| { | ||||
|     public const STATS = 'CHILL_ASIDE_ACTIVITY_STATS'; | ||||
|  | ||||
|     private VoterHelperInterface $voterHelper; | ||||
|  | ||||
|     public function __construct( | ||||
|         VoterHelperFactoryInterface $voterHelperFactory | ||||
|     ) { | ||||
|         $this->voterHelper = $voterHelperFactory | ||||
|             ->generate(self::class) | ||||
|             ->addCheckFor(Center::class, [self::STATS]) | ||||
|             ->build(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public function getRoles(): array | ||||
|     { | ||||
|         return $this->getAttributes(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string[][] | ||||
|      */ | ||||
|     public function getRolesWithHierarchy(): array | ||||
|     { | ||||
|         return ['Aside activity' => $this->getRoles()]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public function getRolesWithoutScope(): array | ||||
|     { | ||||
|         return $this->getAttributes(); | ||||
|     } | ||||
|  | ||||
|     protected function supports($attribute, $subject) | ||||
|     { | ||||
|         return $this->voterHelper->supports($attribute, $subject); | ||||
|     } | ||||
|  | ||||
|     protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool | ||||
|     { | ||||
|         if (!$token->getUser() instanceof User) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         return $this->voterHelper->voteOnAttribute($attribute, $subject, $token); | ||||
|     } | ||||
|  | ||||
|     private function getAttributes(): array | ||||
|     { | ||||
|         return [self::STATS]; | ||||
|     } | ||||
| } | ||||
| @@ -1,64 +0,0 @@ | ||||
| services: | ||||
|   _defaults: | ||||
|     autowire: true | ||||
|     autoconfigure: true | ||||
|  | ||||
|   Chill\AsideActivityBundle\Export\Export\ListAsideActivity: | ||||
|       tags: | ||||
|           - { name: chill.export, alias: 'list_aside_activity' } | ||||
|  | ||||
|   ## Indicators | ||||
|   Chill\AsideActivityBundle\Export\Export\CountAsideActivity: | ||||
|     tags: | ||||
|       - { name: chill.export, alias: 'count_aside_activity' } | ||||
|  | ||||
|   Chill\AsideActivityBundle\Export\Export\SumAsideActivityDuration: | ||||
|       tags: | ||||
|           - { name: chill.export, alias: 'sum_aside_activity_duration' } | ||||
|  | ||||
|   Chill\AsideActivityBundle\Export\Export\AvgAsideActivityDuration: | ||||
|       tags: | ||||
|           - { name: chill.export, alias: 'avg_aside_activity_duration' } | ||||
|  | ||||
|   ## Filters | ||||
|   chill.aside_activity.export.date_filter: | ||||
|     class: Chill\AsideActivityBundle\Export\Filter\ByDateFilter | ||||
|     tags: | ||||
|       - { name: chill.export_filter, alias: 'aside_activity_date_filter' } | ||||
|  | ||||
|   chill.aside_activity.export.type_filter: | ||||
|     class: Chill\AsideActivityBundle\Export\Filter\ByActivityTypeFilter | ||||
|     tags: | ||||
|       - { name: chill.export_filter, alias: 'aside_activity_type_filter' } | ||||
|  | ||||
|   chill.aside_activity.export.user_job_filter: | ||||
|       class: Chill\AsideActivityBundle\Export\Filter\ByUserJobFilter | ||||
|       tags: | ||||
|           - { name: chill.export_filter, alias: 'aside_activity_user_job_filter' } | ||||
|  | ||||
|   chill.aside_activity.export.user_scope_filter: | ||||
|       class: Chill\AsideActivityBundle\Export\Filter\ByUserScopeFilter | ||||
|       tags: | ||||
|           - { name: chill.export_filter, alias: 'aside_activity_user_scope_filter' } | ||||
|  | ||||
|   chill.aside_activity.export.user_filter: | ||||
|       class: Chill\AsideActivityBundle\Export\Filter\ByUserFilter | ||||
|       tags: | ||||
|           - { name: chill.export_filter, alias: 'aside_activity_user_filter' } | ||||
|  | ||||
|   ## Aggregators | ||||
|  | ||||
|   chill.aside_activity.export.type_aggregator: | ||||
|     class: Chill\AsideActivityBundle\Export\Aggregator\ByActivityTypeAggregator | ||||
|     tags: | ||||
|       - { name: chill.export_aggregator, alias: activity_type_aggregator } | ||||
|  | ||||
|   chill.aside_activity.export.user_job_aggregator: | ||||
|       class: Chill\AsideActivityBundle\Export\Aggregator\ByUserJobAggregator | ||||
|       tags: | ||||
|           - { name: chill.export_aggregator, alias: aside_activity_user_job_aggregator } | ||||
|  | ||||
|   chill.aside_activity.export.user_scope_aggregator: | ||||
|       class: Chill\AsideActivityBundle\Export\Aggregator\ByUserScopeAggregator | ||||
|       tags: | ||||
|           - { name: chill.export_aggregator, alias: aside_activity_user_scope_aggregator } | ||||
| @@ -1,7 +0,0 @@ | ||||
| services: | ||||
|   Chill\AsideActivityBundle\Security\AsideActivityVoter: | ||||
|     autowire: true | ||||
|     autoconfigure: true | ||||
|     tags: | ||||
|       - { name: security.voter } | ||||
|       - { name: chill.role } | ||||
| @@ -29,16 +29,16 @@ location: Lieu | ||||
|  | ||||
| # Crud | ||||
| crud: | ||||
|     aside_activity: | ||||
|         title_view: Détail de l'activité annexe | ||||
|         title_new: Nouvelle activité annexe | ||||
|         title_edit: Édition d'une activité annexe | ||||
|         title_delete: Supprimer une activité annexe | ||||
|         button_delete: Supprimer | ||||
|         confirm_message_delete: Êtes-vous sûr de vouloir supprimer cette activité annexe? | ||||
|     aside_activity_category: | ||||
|         title_new: Nouvelle catégorie d'activité annexe | ||||
|         title_edit: Édition d'une catégorie de type d'activité | ||||
|   aside_activity: | ||||
|     title_view: Détail de l'activité annexe | ||||
|     title_new: Nouvelle activité annexe | ||||
|     title_edit: Édition d'une activité annexe | ||||
|     title_delete: Supprimer une activité annexe | ||||
|     button_delete: Supprimer | ||||
|     confirm_message_delete: Êtes-vous sûr de vouloir supprimer cette activité annexe? | ||||
|   aside_activity_category: | ||||
|     title_new: Nouvelle catégorie d'activité annexe | ||||
|     title_edit: Édition d'une catégorie de type d'activité | ||||
|  | ||||
| #forms | ||||
| Create a new aside activity type: Nouvelle categorie d'activité annexe | ||||
| @@ -166,46 +166,3 @@ Aside activities: Activités annexes | ||||
| Aside activity types: Types d'activités annexes | ||||
| Aside activity type configuration: Configuration des categories d'activités annexes | ||||
| Aside activity configuration: Configuration des activités annexes | ||||
|  | ||||
| # exports | ||||
| export: | ||||
|     aside_activity: | ||||
|         List of aside activities: Liste des activités annexes | ||||
|         createdAt: Création | ||||
|         updatedAt: Dernière mise à jour | ||||
|         agent_id: Utilisateur | ||||
|         creator_id: Créateur | ||||
|         main_scope: Service principal de l'utilisateur | ||||
|         main_center: Centre principal de l'utilisteur | ||||
|         aside_activity_type: Catégorie d'activité annexe | ||||
|         date: Date | ||||
|         duration: Durée | ||||
|         note: Note | ||||
|  | ||||
|     Exports of aside activities: Exports des activités annexes | ||||
|     Count aside activities: Nombre d'activités annexes | ||||
|     Count aside activities by various parameters.: Compte le nombre d'activités annexes selon divers critères | ||||
|     Average aside activities duration: Durée moyenne des activités annexes | ||||
|     Sum aside activities duration: Durée des activités annexes | ||||
|     filter: | ||||
|         Filter by aside activity date: Filtrer les activités annexes par date | ||||
|         Filter by aside activity type: Filtrer les activités annexes par type d'activité | ||||
|         'Filtered by aside activity type: only %type%': "Filtré par type d'activité annexe: uniquement %type%" | ||||
|         Filtered by aside activities between %dateFrom% and %dateTo%: Filtré par date d'activité annexe, entre %dateFrom% et %dateTo% | ||||
|         This date should be after the date given in "Implied in an aside activity after this date" field: Cette date devrait être postérieure à la date donnée dans le champ "activités annexes après cette date" | ||||
|         Aside activities after this date: Actvitités annexes après cette date | ||||
|         Aside activities before this date: Actvitités annexes avant cette date | ||||
|         'Filtered aside activity by user: only %users%': "Filtré par utilisateur: uniquement %users%" | ||||
|         Filter aside activity by user: Filtrer par utilisateur | ||||
|         'Filtered aside activities by user jobs: only %jobs%': "Filtré par métier des utilisateurs: uniquement %jobs%" | ||||
|         Filter by user jobs: Filtrer les activités annexes par métier des utilisateurs | ||||
|         'Filtered aside activities by user scope: only %scopes%': "Filtré par service des utilisateur: uniquement %scopes%" | ||||
|         Filter by user scope: Filtrer les activités annexes par service d'utilisateur | ||||
|     aggregator: | ||||
|         Group by aside activity type: Grouper les activités annexes par type d'activité | ||||
|         Aside activity type: Type d'activité annexe | ||||
|         Aggregate by user job: Grouper les activités annexes par métier des utilisateurs | ||||
|         Aggregate by user scope: Grouper les activités annexes par service des utilisateurs | ||||
|  | ||||
| # ROLES | ||||
| CHILL_ASIDE_ACTIVITY_STATS: Statistiques pour les activités annexes | ||||
|   | ||||
| @@ -29,10 +29,10 @@ class CalculatorManager | ||||
|  | ||||
|     public function addCalculator(CalculatorInterface $calculator, bool $default) | ||||
|     { | ||||
|         $this->calculators[$calculator->getAlias()] = $calculator; | ||||
|         $this->calculators[$calculator::getAlias()] = $calculator; | ||||
|  | ||||
|         if ($default) { | ||||
|             $this->defaultCalculator[] = $calculator->getAlias(); | ||||
|             $this->defaultCalculator[] = $calculator::getAlias(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -50,7 +50,7 @@ class CalculatorManager | ||||
|             $result = $calculator->calculate($elements); | ||||
|  | ||||
|             if (null !== $result) { | ||||
|                 $results[$calculator->getAlias()] = $result; | ||||
|                 $results[$calculator::getAlias()] = $result; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
							
								
								
									
										94
									
								
								src/Bundle/ChillBudgetBundle/Config/ConfigRepository.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								src/Bundle/ChillBudgetBundle/Config/ConfigRepository.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| <?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\BudgetBundle\Config; | ||||
|  | ||||
| class ConfigRepository | ||||
| { | ||||
|     /** | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $charges; | ||||
|  | ||||
|     /** | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $resources; | ||||
|  | ||||
|     public function __construct($resources, $charges) | ||||
|     { | ||||
|         $this->resources = $resources; | ||||
|         $this->charges = $charges; | ||||
|     } | ||||
|  | ||||
|     public function getChargesKeys(bool $onlyActive = false): array | ||||
|     { | ||||
|         return array_map(static function ($element) { return $element['key']; }, $this->getCharges($onlyActive)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array where keys are the resource'key and label the ressource label | ||||
|      */ | ||||
|     public function getChargesLabels(bool $onlyActive = false) | ||||
|     { | ||||
|         $charges = []; | ||||
|  | ||||
|         foreach ($this->getCharges($onlyActive) as $definition) { | ||||
|             $charges[$definition['key']] = $this->normalizeLabel($definition['labels']); | ||||
|         } | ||||
|  | ||||
|         return $charges; | ||||
|     } | ||||
|  | ||||
|     public function getResourcesKeys(bool $onlyActive = false): array | ||||
|     { | ||||
|         return array_map(static function ($element) { return $element['key']; }, $this->getResources($onlyActive)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array where keys are the resource'key and label the ressource label | ||||
|      */ | ||||
|     public function getResourcesLabels(bool $onlyActive = false) | ||||
|     { | ||||
|         $resources = []; | ||||
|  | ||||
|         foreach ($this->getResources($onlyActive) as $definition) { | ||||
|             $resources[$definition['key']] = $this->normalizeLabel($definition['labels']); | ||||
|         } | ||||
|  | ||||
|         return $resources; | ||||
|     } | ||||
|  | ||||
|     private function getCharges(bool $onlyActive = false): array | ||||
|     { | ||||
|         return $onlyActive ? | ||||
|             array_filter($this->charges, static function ($el) { return $el['active']; }) | ||||
|             : $this->charges; | ||||
|     } | ||||
|  | ||||
|     private function getResources(bool $onlyActive = false): array | ||||
|     { | ||||
|         return $onlyActive ? | ||||
|             array_filter($this->resources, static function ($el) { return $el['active']; }) | ||||
|             : $this->resources; | ||||
|     } | ||||
|  | ||||
|     private function normalizeLabel($labels) | ||||
|     { | ||||
|         $normalizedLabels = []; | ||||
|  | ||||
|         foreach ($labels as $labelDefinition) { | ||||
|             $normalizedLabels[$labelDefinition['lang']] = $labelDefinition['label']; | ||||
|         } | ||||
|  | ||||
|         return $normalizedLabels; | ||||
|     } | ||||
| } | ||||
| @@ -1,26 +0,0 @@ | ||||
| <?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\BudgetBundle\Controller\Admin; | ||||
|  | ||||
| use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; | ||||
| use Symfony\Component\Routing\Annotation\Route; | ||||
|  | ||||
| class AdminController extends AbstractController | ||||
| { | ||||
|     /** | ||||
|      * @Route("/{_locale}/admin/budget", name="chill_admin_budget") | ||||
|      */ | ||||
|     public function indexAdminAction() | ||||
|     { | ||||
|         return $this->render('@ChillBudget/Admin/index.html.twig'); | ||||
|     } | ||||
| } | ||||
| @@ -1,28 +0,0 @@ | ||||
| <?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\BudgetBundle\Controller\Admin; | ||||
|  | ||||
| use Chill\MainBundle\CRUD\Controller\CRUDController; | ||||
| use Chill\MainBundle\Pagination\PaginatorInterface; | ||||
| use Doctrine\ORM\QueryBuilder; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
|  | ||||
| class ChargeKindController extends CRUDController | ||||
| { | ||||
|     protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator) | ||||
|     { | ||||
|         /** @var QueryBuilder $query */ | ||||
|         $query->addOrderBy('e.ordering', 'ASC'); | ||||
|  | ||||
|         return $query; | ||||
|     } | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user