mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-10 00:34:58 +00:00
Compare commits
325 Commits
2.7.0
...
183-fix-ty
Author | SHA1 | Date | |
---|---|---|---|
6280453523
|
|||
68f56671a4
|
|||
dc860d0c46
|
|||
6fd80f9f2e
|
|||
b2aa465b03 | |||
0fa8944c29 | |||
7494dbfc7c | |||
642958bde2 | |||
57bd6d1be4 | |||
bbcbbf078f | |||
ba778b1cf8 | |||
728fd642fa | |||
4150eb56b4 | |||
2927561c02 | |||
5188891108 | |||
c6deb21606 | |||
cdfb084fe4 | |||
5ce21aadce | |||
b9000a38d3 | |||
89a185a34f | |||
bc6c3a1089
|
|||
2c50f484f0
|
|||
4bc1de01d6
|
|||
e21fe70b75
|
|||
461995b56b | |||
e635b73256
|
|||
54ae17a8d2
|
|||
617d09ab8a | |||
f8ee2903b2 | |||
36b0844e79
|
|||
7bff5ce39e
|
|||
2a151d13ed | |||
4375ecf49a
|
|||
a6e930958b
|
|||
5f805626f7
|
|||
4c9ea740c8
|
|||
981dc6a959
|
|||
11fb9bcd0b
|
|||
a4edb34668
|
|||
f799fe0649
|
|||
c7bd60a106
|
|||
9ec5a633ad
|
|||
d54d34be7c
|
|||
01292ba9ae
|
|||
794daa5c3e
|
|||
37265c09f7
|
|||
98cd0f3c00 | |||
bc2041cbdd
|
|||
0b0cbed9db
|
|||
c9cfe4c7e9
|
|||
75e15c1389
|
|||
48e0a0af7d
|
|||
adf1110340
|
|||
a6fcdb5256
|
|||
6b8d6b76ba
|
|||
bbf9c58fbf | |||
0c8ecfe493 | |||
8523f14214
|
|||
b32fa42afa
|
|||
be8975ee04
|
|||
05865521b5 | |||
dd47ddc268
|
|||
0df93fb703
|
|||
c62495a280
|
|||
93b189b091
|
|||
304bf4258b
|
|||
efcb903d10
|
|||
b65f76262a
|
|||
51a4ffca2e
|
|||
68d28f3e28
|
|||
63e9d1a96f
|
|||
21524f052e
|
|||
978db5a5c5
|
|||
363785b779
|
|||
4e13b2ae3a
|
|||
f0b3e3af14
|
|||
dbc19ca692
|
|||
239372270e
|
|||
ada28265ee | |||
0b6b25fd95 | |||
c526973475 | |||
9bbddd8405 | |||
935210aa1d | |||
58e189ee07
|
|||
9f476dddaf | |||
dac48ea4e0 | |||
af4bee4d50 | |||
b4e5618e00 | |||
15e23087ed | |||
e3559774fd
|
|||
d6a1044585 | |||
c6a06ebaf9 | |||
c00c26c3e5 | |||
fa3fc2c781 | |||
6e48d036d7 | |||
31fc7fffe9 | |||
84ba626fb5 | |||
eddcfc3921 | |||
f025b0d184 | |||
8c44e92079 | |||
1973a4b849 | |||
bea21d45fc | |||
3aa10927d7 | |||
4460db1dc4 | |||
e4cf07c7b3 | |||
2100d45671 | |||
aeb0d5eab8 | |||
bc69f83c37 | |||
9b272e9b9e | |||
f225a83a3e | |||
e738bf0f5e | |||
0953faedc4 | |||
7c25ca8dd4 | |||
8b7600e09f | |||
9db0011b2e | |||
3f4a42adb2 | |||
f18ee2383c | |||
28583f4193 | |||
c5b153e6ed | |||
2d4d1eda50 | |||
baeccf0970 | |||
6665a443b9 | |||
fc919e9547 | |||
949c5424f0 | |||
e6e42777d7 | |||
c590d60a7f | |||
6228cc5ede | |||
024790128a | |||
d2feb0f0b4 | |||
8a6f29ef79 | |||
124abf563e | |||
096fb6219f | |||
bebc746d57 | |||
d47e6c5ba1 | |||
cffad6219f | |||
ef8ac6041a
|
|||
41f4bbfdce
|
|||
6a37079ee5
|
|||
2d7bc06539
|
|||
bad302f512
|
|||
294aaf5bed
|
|||
d2864605b9
|
|||
2efd5ebc9a
|
|||
a625260c36 | |||
28006374fb | |||
b35838f840 | |||
e08ab0666f
|
|||
217232fe4f
|
|||
b0a7612329 | |||
0c5b35926b | |||
b38f5800d9 | |||
8dce0473ff
|
|||
e5a449118e
|
|||
9c436d5c69
|
|||
981be7b363
|
|||
74e25e706e
|
|||
5f8b86b839
|
|||
65aa0a1588
|
|||
d8b0e0671a
|
|||
29983cc2ad | |||
260a173a61 | |||
500b37601a | |||
5d41b37620 | |||
05e86a3360 | |||
9b061eeaae | |||
3816d68e18 | |||
7db7f34f62 | |||
6b958d193d | |||
1070d33670
|
|||
b93a822299
|
|||
fc7cfb1760
|
|||
76f1814848
|
|||
cd9611a669
|
|||
d3b68f8f8f
|
|||
2ce29f36ff
|
|||
d2323e91ca
|
|||
b9231a91a3
|
|||
b36e37d9c5
|
|||
899ed5d0a4
|
|||
9375d50112
|
|||
e53540ec74
|
|||
582b27fbd6
|
|||
19c6e3e6ba
|
|||
0711b7f84a
|
|||
608663d25c
|
|||
40b7c8ad8f
|
|||
412c55a1a5
|
|||
afa4b7ad2c
|
|||
0db1e3e0d7
|
|||
a2a660c954
|
|||
2c52a5bffa
|
|||
10a75f44e9
|
|||
1361e2bbf9
|
|||
37c1dfb0ba
|
|||
a197a6b418
|
|||
f8f04c69d0
|
|||
355ed03500
|
|||
d8062be131
|
|||
e72df84442
|
|||
d44f5d7af8
|
|||
d595c17cd4
|
|||
cbb89ecf35
|
|||
6f11dffcbd
|
|||
7c58880139
|
|||
76142c1264
|
|||
650e3a84c8
|
|||
6001e15907
|
|||
2a9e461d6f
|
|||
b85cd1b994
|
|||
e4e52234ad
|
|||
bc9b7b1776
|
|||
1f2ecb923e
|
|||
37419e06fc
|
|||
bad3cdca09
|
|||
711cdc3481
|
|||
149ed2bd75
|
|||
2f1f724860
|
|||
68e1384416
|
|||
0907d5b76a
|
|||
1c0fd57913
|
|||
d01172274d
|
|||
876ebca210
|
|||
364a67b83a
|
|||
6bedd673cd
|
|||
df9f30265f
|
|||
1b8acfab24
|
|||
690697cb35
|
|||
5314e7b501
|
|||
939a6753bd
|
|||
52d791f6d0
|
|||
80684f65fe
|
|||
b1a9749dc0
|
|||
2dfc228917
|
|||
3f2339bc60
|
|||
e2a739eeff
|
|||
847fd71364
|
|||
667104a595
|
|||
2c83b4c912
|
|||
e2d62d5792
|
|||
d1e09d7047
|
|||
5481d029e8
|
|||
ebe1c11ca6
|
|||
398bbd12d5
|
|||
c33330969c
|
|||
ea9c21e021
|
|||
410aa7098a
|
|||
ad1e5ecc95
|
|||
1e353ed74b
|
|||
5136907d62
|
|||
84dbfabd66
|
|||
43ac6726aa
|
|||
0e0b0b8874
|
|||
24cc6a816b
|
|||
f2d391ea2e
|
|||
e2b500ea5f
|
|||
dbccf7ff80
|
|||
65e6ad0fc4
|
|||
f68a163a30
|
|||
009a0326d9
|
|||
4b20db7a9c
|
|||
458a59fe1b
|
|||
378e417d5c
|
|||
cd7b91dd98
|
|||
4b989fe25c
|
|||
984c35f8bc
|
|||
770d64a2f8
|
|||
34c46f23e3
|
|||
333579de06
|
|||
836cc7199e
|
|||
7f96a895e1
|
|||
a0d4a995d3
|
|||
e839b03cc9
|
|||
55b8502896
|
|||
a9c8f464bb
|
|||
f570fe92a5
|
|||
157cdf6dfc
|
|||
c20f65eebb
|
|||
b6a094aeee
|
|||
0ed5544ad3
|
|||
6f2b538e27
|
|||
0e94e769cb
|
|||
abc067adae
|
|||
ae04172929
|
|||
dd21694544
|
|||
5f6e506300
|
|||
dba1d0548e
|
|||
507bd5c6b5
|
|||
9f63d9ed0f
|
|||
97dad842ea
|
|||
d08980c8d1
|
|||
da6f8511a8
|
|||
9690359dfa
|
|||
2ad82e8cc1
|
|||
169bf3c140
|
|||
9cdef5f951
|
|||
df529be2ce
|
|||
d87cd0c685
|
|||
7a5db59ac2
|
|||
4028cc8a8b
|
|||
48cd8aaa9f
|
|||
d048ee3b44
|
|||
aa553db659
|
|||
e45430f0c9
|
|||
13abc36529
|
|||
023a29cb78
|
|||
7b637d1287
|
|||
74ed34ba97
|
|||
6e6f19c499
|
|||
075aca493b
|
|||
224c2c74e8
|
|||
efaa01f4f6
|
|||
f04ef9c931
|
|||
9252e92da0
|
|||
4ab4554e63
|
|||
6d63177ff4
|
|||
81e8928344
|
|||
737f5f9275
|
|||
07c681fcec
|
|||
1c7d90a6ef
|
|||
24c33b306b
|
|||
7e19419861
|
|||
c35994203d
|
|||
9027cbd196
|
|||
dde3002100
|
|||
d8870e906f
|
5
.changes/unreleased/Fixed-20231105-230426.yaml
Normal file
5
.changes/unreleased/Fixed-20231105-230426.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
kind: Fixed
|
||||
body: Fix "problem during download" on some filters, which used a wrong data type
|
||||
time: 2023-11-05T23:04:26.346839079+01:00
|
||||
custom:
|
||||
Issue: "183"
|
5
.changes/unreleased/Fixed-20231105-232608.yaml
Normal file
5
.changes/unreleased/Fixed-20231105-232608.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
kind: Fixed
|
||||
body: Fix filter "activity by date"
|
||||
time: 2023-11-05T23:26:08.685518729+01:00
|
||||
custom:
|
||||
Issue: "184"
|
20
.changes/v2.10.0.md
Normal file
20
.changes/v2.10.0.md
Normal file
@@ -0,0 +1,20 @@
|
||||
## v2.10.0 - 2023-10-24
|
||||
### Feature
|
||||
* ([#172](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/172)) [export] Add a filter "grouping accompanying period by opening date" and "grouping accompanying period by closing date"
|
||||
* ([#172](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/172)) [export] add a filter and aggregator on accompanying period work: group/filter by handling third party
|
||||
* ([#172](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/172)) [export] add a filter and aggregator on activites: group/filter activities by people participating to the activities
|
||||
* ([#172](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/172)) [export] add a grouping on accompanying period export: group by activity type associated to at least one activity within the accompanying period
|
||||
* [export] sort filters and aggregators by title
|
||||
* ([#179](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/179)) [export] create a parameter that will force to skip the filtering by center (ACL) when generating an export
|
||||
### Fixed
|
||||
* ([#177](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/177)) [export] fix date range selection on filter and grouping "by status of the course at date", on accompanying periods
|
||||
|
||||
### Résumé francophone des changements
|
||||
|
||||
- Ajout d'un regroupement sur les parcours: par date de cloture et d'ouverture;
|
||||
- Ajouter d'un filtre et regroupement par tiers traitant sur les actions d'accompagnement;
|
||||
- ajout d'un filtre et regroupement par usager participant sur les échanges
|
||||
- ajout d'un regroupement: par type d'activité associé au parcours;
|
||||
- trie les filtre et regroupements par ordre alphabétique dans els exports
|
||||
- ajout d'un paramètre qui permet de désactiver le filtre par centre dans les exports
|
||||
- correction de l'interface de date dans les filtres et regroupements "par statut du parcours à la date"
|
3
.changes/v2.10.1.md
Normal file
3
.changes/v2.10.1.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## v2.10.1 - 2023-10-24
|
||||
### Fixed
|
||||
* Fix export controller when generating an export without any data in session
|
3
.changes/v2.10.2.md
Normal file
3
.changes/v2.10.2.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## v2.10.2 - 2023-10-26
|
||||
### Fixed
|
||||
* ([#175](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/175)) Use injection of translator instead of ->get().
|
3
.changes/v2.10.3.md
Normal file
3
.changes/v2.10.3.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## v2.10.3 - 2023-10-26
|
||||
### Fixed
|
||||
* ([#175](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/175)) Replace old method of getting translator with injection of translatorInterface
|
3
.changes/v2.10.4.md
Normal file
3
.changes/v2.10.4.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## v2.10.4 - 2023-10-26
|
||||
### Fixed
|
||||
* Fix null value constraint errors when merging relationships in doubles
|
19
.changes/v2.8.0.md
Normal file
19
.changes/v2.8.0.md
Normal file
@@ -0,0 +1,19 @@
|
||||
## v2.8.0 - 2023-10-05
|
||||
|
||||
### Feature
|
||||
|
||||
* ([#162](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/162)) Reassigning list: when reassigning courses to a new user, the job associated with the course become the one of the new user (if any)
|
||||
* Reassining list: the length of the list is increased to 100 courses
|
||||
|
||||
### Fixed
|
||||
|
||||
* ([#143](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/143)) Fix filter "accompanying course by social action" to avoid duplication in list
|
||||
* ([#164](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/164)) View a third party: avoid errors when a contact has a civility
|
||||
* ([#163](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/163)) Fix the filters and aggregators on exports "count peoples"
|
||||
* ([#143](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/143)) From the database, avoid the creation of location history for same period and at same dates
|
||||
|
||||
### Traduction francophone des principaux changements
|
||||
|
||||
- Fonctionnalité: Réassigner les parcours en lot: lorsque des parcours sont réassignés "en lot", les parcours sont maintenant associés au métier du nouveau référent;
|
||||
- Correction: certaines causes qui créaient des doublons dans les listes ont été corrigées;
|
||||
- Correction des associations entre l'export "nombre de personnes" et les filtres et regroupements associés
|
23
.changes/v2.9.0.md
Normal file
23
.changes/v2.9.0.md
Normal file
@@ -0,0 +1,23 @@
|
||||
## v2.9.0 - 2023-10-17
|
||||
### Feature
|
||||
* ([#147](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/147)) Add history to scopes and to jobs in administrator section. When user job or main scope of user is changed, automaticaly add a new row in history.
|
||||
* ([#146](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/146)) Allow closing motives to be identified as 'canceling the accompanying period' + don't take canceled accompanying periods into account
|
||||
* [export] add an aggregator for activities: group by job scope's creator aggregator
|
||||
* DX: prepare the code for the upgrade to symfony 5.4
|
||||
|
||||
### Traductions francophones des principaux changements
|
||||
|
||||
- ajout de l'historique des services et métiers pour les utilisateurs. Les exports, filtres et regroupements sont adaptés pour tenir compte du métier et du service
|
||||
de l'utilisateur au moment de l'échange, de sa désignation comme agent traitant de l'échange ou du moment du rendez-vous ([#147](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/147)))
|
||||
- modification des motifs de cloture des parcours: ajout d'un chanmp "annule le parcours", qui permet d'indiquer que le motif "annule" le parcours. Les parcours annulés n'apparaissent
|
||||
pas dans les statistiques
|
||||
- ajouter d'un regroupement pour les échanges: grouper par métier et service du créateur de l'échange
|
||||
|
||||
|
||||
### Possible BC break in configuration
|
||||
|
||||
This release remove the use of deprecated package [symfony/templating](https://symfony.com/components/Templating).
|
||||
|
||||
If you use this package in your own bundle (usually `src/` directory, or other dependencies), you should add this dependencies in your local composer.json (`composer require symfony/templating`).
|
||||
|
||||
But if you do not need this any more, you must ensure that the configuration key `framework.templating` is removed. This is usually located into `config/packages/framework.yaml`. [See here an example](https://gitea.champs-libres.be/Chill-project/chill-skeleton-basic/commit/cc716beaecc239e6a189f3db62ea95f169a37505#diff-df607fe73ff82c569824a7392edf5e760e998efe)
|
3
.changes/v2.9.1.md
Normal file
3
.changes/v2.9.1.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## v2.9.1 - 2023-10-17
|
||||
### Fixed
|
||||
* Fix the handling of activity form when editing or creating an activity in an accompanying period with multiple centers
|
3
.changes/v2.9.2.md
Normal file
3
.changes/v2.9.2.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## v2.9.2 - 2023-10-17
|
||||
### Fixed
|
||||
* Fix possible null values in string's entities
|
36
.env.test
36
.env.test
@@ -3,3 +3,39 @@
|
||||
# Run tests from root to adapt your own environment
|
||||
KERNEL_CLASS='App\Kernel'
|
||||
APP_SECRET='$ecretf0rt3st'
|
||||
|
||||
ADMIN_PASSWORD=password
|
||||
|
||||
LOCALE=fr
|
||||
REDIS_URL=redis
|
||||
REDIS_PORT=6379
|
||||
REDIS_URL=redis://${REDIS_HOST}:${REDIS_PORT}
|
||||
|
||||
JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem
|
||||
JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem
|
||||
JWT_PASSPHRASE=2a30f6ba26521a2613821da35f28386e
|
||||
|
||||
TWILIO_SID=~
|
||||
TWILIO_SECRET=~
|
||||
DEFAULT_CARRIER_CODE=BE
|
||||
|
||||
ADD_ADDRESS_DEFAULT_COUNTRY=BE
|
||||
|
||||
ADD_ADDRESS_MAP_CENTER_X=50.8443
|
||||
ADD_ADDRESS_MAP_CENTER_Y=4.3523
|
||||
ADD_ADDRESS_MAP_CENTER_Z=15
|
||||
|
||||
SHORT_MESSAGE_DSN=null://null
|
||||
MESSENGER_TRANSPORT_DSN=sync://
|
||||
###< symfony/messenger ###
|
||||
|
||||
###> doctrine/doctrine-bundle ###
|
||||
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
|
||||
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
|
||||
#
|
||||
DATABASE_URL="postgresql://postgres:postgres@db:5432/test?serverVersion=14&charset=utf8"
|
||||
###< doctrine/doctrine-bundle ###
|
||||
|
||||
ASYNC_UPLOAD_TEMP_URL_KEY=
|
||||
ASYNC_UPLOAD_TEMP_URL_BASE_PATH=
|
||||
ASYNC_UPLOAD_TEMP_URL_CONTAINER=
|
||||
|
@@ -3,7 +3,7 @@
|
||||
# Select what we should cache between builds
|
||||
cache:
|
||||
paths:
|
||||
- tests/app/vendor/
|
||||
- /vendor/
|
||||
- .cache
|
||||
|
||||
# Bring in any services we need http://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-a-service
|
||||
@@ -23,12 +23,10 @@ variables:
|
||||
# configure database access
|
||||
DATABASE_URL: postgresql://postgres:postgres@db:5432/postgres?serverVersion=14&charset=utf8
|
||||
# fetch the chill-app using git submodules
|
||||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
# GIT_SUBMODULE_STRATEGY: recursive
|
||||
REDIS_HOST: redis
|
||||
REDIS_PORT: 6379
|
||||
REDIS_URL: redis://redis:6379
|
||||
# change vendor dir to make the app install into tests/apps
|
||||
COMPOSER_VENDOR_DIR: tests/app/vendor
|
||||
DEFAULT_CARRIER_CODE: BE
|
||||
|
||||
stages:
|
||||
@@ -50,7 +48,7 @@ build:
|
||||
expire_in: 30 min
|
||||
paths:
|
||||
- bin
|
||||
- tests/app/vendor/
|
||||
- vendor/
|
||||
|
||||
code_style:
|
||||
stage: Tests
|
||||
@@ -64,7 +62,7 @@ code_style:
|
||||
expire_in: 30 min
|
||||
paths:
|
||||
- bin
|
||||
- tests/app/vendor/
|
||||
- vendor/
|
||||
|
||||
phpstan_tests:
|
||||
stage: Tests
|
||||
@@ -78,13 +76,14 @@ phpstan_tests:
|
||||
expire_in: 30 min
|
||||
paths:
|
||||
- bin
|
||||
- tests/app/vendor/
|
||||
- vendor/
|
||||
|
||||
rector_tests:
|
||||
stage: Tests
|
||||
image: gitea.champs-libres.be/chill-project/chill-skeleton-basic/base-image:php82
|
||||
script:
|
||||
- bin/rector --dry-run
|
||||
- tests/console cache:clear
|
||||
- bin/rector process --dry-run
|
||||
cache:
|
||||
paths:
|
||||
- .cache/
|
||||
@@ -92,7 +91,7 @@ rector_tests:
|
||||
expire_in: 30 min
|
||||
paths:
|
||||
- bin
|
||||
- tests/app/vendor/
|
||||
- vendor/
|
||||
|
||||
# psalm_tests:
|
||||
# stage: Tests
|
||||
@@ -109,19 +108,17 @@ rector_tests:
|
||||
unit_tests:
|
||||
stage: Tests
|
||||
image: gitea.champs-libres.be/chill-project/chill-skeleton-basic/base-image:php82
|
||||
# until we fix testes
|
||||
allow_failure: true
|
||||
script:
|
||||
- php tests/app/bin/console doctrine:migrations:migrate -n
|
||||
- php -d memory_limit=2G tests/app/bin/console cache:clear --env=dev
|
||||
- php -d memory_limit=3G tests/app/bin/console doctrine:fixtures:load -n
|
||||
- php -d memory_limit=2G tests/app/bin/console cache:clear --env=test
|
||||
- php -d memory_limit=4G bin/phpunit --colors=never
|
||||
- php tests/console doctrine:migrations:migrate -n --env=test
|
||||
- php tests/console chill:db:sync-views --env=test
|
||||
- php -d memory_limit=2G tests/console cache:clear --env=test
|
||||
- php -d memory_limit=3G tests/console doctrine:fixtures:load -n
|
||||
- php -d memory_limit=4G bin/phpunit --colors=never --exclude-group dbIntensive
|
||||
artifacts:
|
||||
expire_in: 30 min
|
||||
paths:
|
||||
- bin
|
||||
- tests/app/vendor/
|
||||
- vendor/
|
||||
|
||||
release:
|
||||
stage: Deploy
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,6 +1,3 @@
|
||||
[submodule "_exts/sphinx-php"]
|
||||
path = _exts/sphinx-php
|
||||
url = https://github.com/fabpot/sphinx-php.git
|
||||
[submodule "tests/app"]
|
||||
path = tests/app
|
||||
url = https://gitlab.com/Chill-projet/chill-app.git
|
||||
|
@@ -91,7 +91,7 @@ $rules = array_merge(
|
||||
[
|
||||
'@PhpCsFixer' => true,
|
||||
'@PhpCsFixer:risky' => false,
|
||||
'@Symfony' => false,
|
||||
'@Symfony' => true,
|
||||
'@Symfony:risky' => false,
|
||||
'ordered_class_elements' => [
|
||||
'order' => [
|
||||
@@ -111,13 +111,13 @@ $rules = array_merge(
|
||||
'method_private',
|
||||
],
|
||||
'sort_algorithm' => 'alpha',
|
||||
]
|
||||
],
|
||||
],
|
||||
$rules,
|
||||
$riskyRules,
|
||||
$untilFullSwitchToPhp8,
|
||||
);
|
||||
|
||||
$rules['header_comment']['header'] = trim(file_get_contents(__DIR__ . '/resource/header.txt'));
|
||||
$rules['header_comment']['header'] = trim(file_get_contents(__DIR__.'/resource/header.txt'));
|
||||
|
||||
return $config->setRules($rules);
|
||||
|
89
CHANGELOG.md
89
CHANGELOG.md
@@ -6,6 +6,95 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
|
||||
and is generated by [Changie](https://github.com/miniscruff/changie).
|
||||
|
||||
|
||||
## v2.10.4 - 2023-10-26
|
||||
### Fixed
|
||||
* Fix null value constraint errors when merging relationships in doubles
|
||||
|
||||
## v2.10.3 - 2023-10-26
|
||||
### Fixed
|
||||
* ([#175](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/175)) Replace old method of getting translator with injection of translatorInterface
|
||||
|
||||
## v2.10.2 - 2023-10-26
|
||||
### Fixed
|
||||
* ([#175](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/175)) Use injection of translator instead of ->get().
|
||||
|
||||
## v2.10.1 - 2023-10-24
|
||||
### Fixed
|
||||
* Fix export controller when generating an export without any data in session
|
||||
|
||||
## v2.10.0 - 2023-10-24
|
||||
### Feature
|
||||
* ([#172](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/172)) [export] Add a filter "grouping accompanying period by opening date" and "grouping accompanying period by closing date"
|
||||
* ([#172](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/172)) [export] add a filter and aggregator on accompanying period work: group/filter by handling third party
|
||||
* ([#172](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/172)) [export] add a filter and aggregator on activites: group/filter activities by people participating to the activities
|
||||
* ([#172](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/172)) [export] add a grouping on accompanying period export: group by activity type associated to at least one activity within the accompanying period
|
||||
* [export] sort filters and aggregators by title
|
||||
* ([#179](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/179)) [export] create a parameter that will force to skip the filtering by center (ACL) when generating an export
|
||||
### Fixed
|
||||
* ([#177](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/177)) [export] fix date range selection on filter and grouping "by status of the course at date", on accompanying periods
|
||||
|
||||
### Résumé francophone des changements
|
||||
|
||||
- Ajout d'un regroupement sur les parcours: par date de cloture et d'ouverture;
|
||||
- Ajouter d'un filtre et regroupement par tiers traitant sur les actions d'accompagnement;
|
||||
- ajout d'un filtre et regroupement par usager participant sur les échanges
|
||||
- ajout d'un regroupement: par type d'activité associé au parcours;
|
||||
- trie les filtre et regroupements par ordre alphabétique dans els exports
|
||||
- ajout d'un paramètre qui permet de désactiver le filtre par centre dans les exports
|
||||
- correction de l'interface de date dans les filtres et regroupements "par statut du parcours à la date"
|
||||
|
||||
## v2.9.2 - 2023-10-17
|
||||
### Fixed
|
||||
* Fix possible null values in string's entities
|
||||
|
||||
## v2.9.1 - 2023-10-17
|
||||
### Fixed
|
||||
* Fix the handling of activity form when editing or creating an activity in an accompanying period with multiple centers
|
||||
|
||||
## v2.9.0 - 2023-10-17
|
||||
### Feature
|
||||
* ([#147](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/147)) Add history to scopes and to jobs in administrator section. When user job or main scope of user is changed, automaticaly add a new row in history.
|
||||
* ([#146](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/146)) Allow closing motives to be identified as 'canceling the accompanying period' + don't take canceled accompanying periods into account
|
||||
* [export] add an aggregator for activities: group by job scope's creator aggregator
|
||||
* DX: prepare the code for the upgrade to symfony 5.4
|
||||
|
||||
### Traductions francophones des principaux changements
|
||||
|
||||
- ajout de l'historique des services et métiers pour les utilisateurs. Les exports, filtres et regroupements sont adaptés pour tenir compte du métier et du service
|
||||
de l'utilisateur au moment de l'échange, de sa désignation comme agent traitant de l'échange ou du moment du rendez-vous ([#147](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/147)))
|
||||
- modification des motifs de cloture des parcours: ajout d'un chanmp "annule le parcours", qui permet d'indiquer que le motif "annule" le parcours. Les parcours annulés n'apparaissent
|
||||
pas dans les statistiques
|
||||
- ajouter d'un regroupement pour les échanges: grouper par métier et service du créateur de l'échange
|
||||
|
||||
|
||||
### Possible BC break in configuration
|
||||
|
||||
This release remove the use of deprecated package [symfony/templating](https://symfony.com/components/Templating).
|
||||
|
||||
If you use this package in your own bundle (usually `src/` directory, or other dependencies), you should add this dependencies in your local composer.json (`composer require symfony/templating`).
|
||||
|
||||
But if you do not need this any more, you must ensure that the configuration key `framework.templating` is removed. This is usually located into `config/packages/framework.yaml`. [See here an example](https://gitea.champs-libres.be/Chill-project/chill-skeleton-basic/commit/cc716beaecc239e6a189f3db62ea95f169a37505#diff-df607fe73ff82c569824a7392edf5e760e998efe)
|
||||
|
||||
## v2.8.0 - 2023-10-05
|
||||
|
||||
### Feature
|
||||
|
||||
* ([#162](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/162)) Reassigning list: when reassigning courses to a new user, the job associated with the course become the one of the new user (if any)
|
||||
* Reassining list: the length of the list is increased to 100 courses
|
||||
|
||||
### Fixed
|
||||
|
||||
* ([#143](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/143)) Fix filter "accompanying course by social action" to avoid duplication in list
|
||||
* ([#164](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/164)) View a third party: avoid errors when a contact has a civility
|
||||
* ([#163](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/163)) Fix the filters and aggregators on exports "count peoples"
|
||||
* ([#143](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/143)) From the database, avoid the creation of location history for same period and at same dates
|
||||
|
||||
### Traduction francophone des principaux changements
|
||||
|
||||
- Fonctionnalité: Réassigner les parcours en lot: lorsque des parcours sont réassignés "en lot", les parcours sont maintenant associés au métier du nouveau référent;
|
||||
- Correction: certaines causes qui créaient des doublons dans les listes ont été corrigées;
|
||||
- Correction des associations entre l'export "nombre de personnes" et les filtres et regroupements associés
|
||||
|
||||
## v2.7.0 - 2023-09-27
|
||||
### Feature
|
||||
* ([#155](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/155)) The regulation list load accompanying periods by exact postal code (address associated with postal code), and not by the content of the postal code (postal code with same code's string)
|
||||
|
@@ -40,7 +40,7 @@ About once a year, the core team discusses the opportunity to invite new members
|
||||
|
||||
### Core Membership Revocation
|
||||
|
||||
A Symfony Core membership can be revoked for any of the following reasons:
|
||||
A Chill Core membership can be revoked for any of the following reasons:
|
||||
|
||||
- Refusal to follow the rules and policies stated in this document;
|
||||
- Lack of activity for the past six months;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
"social worker"
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.4|^8.2",
|
||||
"php": "^8.2",
|
||||
"ext-json": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-redis": "*",
|
||||
@@ -48,7 +48,6 @@
|
||||
"symfony/monolog-bundle": "^3.5",
|
||||
"symfony/security-bundle": "^4.4",
|
||||
"symfony/serializer": "^5.3",
|
||||
"symfony/templating": "^4.4",
|
||||
"symfony/translation": "^4.4",
|
||||
"symfony/twig-bundle": "^4.4",
|
||||
"symfony/validator": "^4.4",
|
||||
@@ -76,7 +75,7 @@
|
||||
"phpunit/phpunit": ">= 7.5",
|
||||
"psalm/plugin-phpunit": "^0.18.4",
|
||||
"psalm/plugin-symfony": "^4.0.2",
|
||||
"rector/rector": "^0.15.23",
|
||||
"rector/rector": "^0.17.7",
|
||||
"symfony/debug-bundle": "^5.1",
|
||||
"symfony/dotenv": "^4.4",
|
||||
"symfony/maker-bundle": "^1.20",
|
||||
@@ -98,7 +97,6 @@
|
||||
"Chill\\DocGeneratorBundle\\": "src/Bundle/ChillDocGeneratorBundle",
|
||||
"Chill\\DocStoreBundle\\": "src/Bundle/ChillDocStoreBundle",
|
||||
"Chill\\EventBundle\\": "src/Bundle/ChillEventBundle",
|
||||
"Chill\\FamilyMemberBundle\\": "src/Bundle/ChillFamilyMemberBundle",
|
||||
"Chill\\MainBundle\\": "src/Bundle/ChillMainBundle",
|
||||
"Chill\\PersonBundle\\": "src/Bundle/ChillPersonBundle",
|
||||
"Chill\\ReportBundle\\": "src/Bundle/ChillReportBundle",
|
||||
@@ -110,7 +108,7 @@
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"App\\": "tests/app/src/",
|
||||
"App\\": "tests/",
|
||||
"Chill\\DocGeneratorBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests",
|
||||
"Chill\\WopiBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests",
|
||||
"Chill\\Utils\\Rector\\Tests\\": "utils/rector/tests"
|
||||
@@ -128,12 +126,10 @@
|
||||
},
|
||||
"bin-dir": "bin",
|
||||
"optimize-autoloader": true,
|
||||
"sort-packages": true,
|
||||
"vendor-dir": "tests/app/vendor"
|
||||
"sort-packages": true
|
||||
},
|
||||
"scripts": {
|
||||
"auto-scripts": {
|
||||
"assets:install %PUBLIC_DIR%": "symfony-cmd",
|
||||
"cache:clear": "symfony-cmd"
|
||||
}
|
||||
}
|
||||
|
@@ -54,18 +54,9 @@ class CountPerson implements ExportInterface
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
// the Closure which will be executed by the formatter.
|
||||
return function ($value) {
|
||||
switch ($value) {
|
||||
case '_header':
|
||||
// we have to process specifically the '_header' string,
|
||||
// which will be used by the formatter to show a column title
|
||||
return $this->getTitle();
|
||||
|
||||
default:
|
||||
// for all value, we do not process them and return them
|
||||
// immediatly
|
||||
return $value;
|
||||
}
|
||||
return fn($value) => match ($value) {
|
||||
'_header' => $this->getTitle(),
|
||||
default => $value,
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -13,7 +13,7 @@ namespace Chill\MyBundle\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
|
||||
class example extends Controller
|
||||
class example extends \Symfony\Bundle\FrameworkBundle\Controller\AbstractController
|
||||
{
|
||||
public function yourAction()
|
||||
{
|
||||
|
@@ -16,7 +16,7 @@ use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class ConsultationController extends Controller
|
||||
class ConsultationController extends \Symfony\Bundle\FrameworkBundle\Controller\AbstractController
|
||||
{
|
||||
/**
|
||||
* @param int $id personId
|
||||
@@ -43,7 +43,7 @@ class ConsultationController extends Controller
|
||||
|
||||
$circles = $authorizationHelper->getReachableCircles(
|
||||
$this->getUser(),
|
||||
new Role(ConsultationVoter::SEE),
|
||||
ConsultationVoter::SEE,
|
||||
$person->getCenter()
|
||||
);
|
||||
|
||||
|
@@ -23,25 +23,18 @@ class ChillMainConfiguration implements ConfigurationInterface
|
||||
{
|
||||
use AddWidgetConfigurationTrait;
|
||||
|
||||
/**
|
||||
* @var ContainerBuilder
|
||||
*/
|
||||
private $containerBuilder;
|
||||
|
||||
public function __construct(
|
||||
array $widgetFactories,
|
||||
ContainerBuilder $containerBuilder
|
||||
private readonly ContainerBuilder $containerBuilder
|
||||
) {
|
||||
// we register here widget factories (see below)
|
||||
$this->setWidgetFactories($widgetFactories);
|
||||
// we will need the container builder later...
|
||||
$this->containerBuilder = $containerBuilder;
|
||||
}
|
||||
|
||||
public function getConfigTreeBuilder()
|
||||
{
|
||||
$treeBuilder = new TreeBuilder();
|
||||
$rootNode = $treeBuilder->root('chill_main');
|
||||
$treeBuilder = new TreeBuilder('chill_main');
|
||||
$rootNode = $treeBuilder->getRootNode();
|
||||
|
||||
$rootNode
|
||||
->children()
|
||||
|
@@ -87,7 +87,7 @@ class ChillPersonAddAPersonWidget implements WidgetInterface
|
||||
// show only the person from the authorized centers
|
||||
$and = $qb->expr()->andX();
|
||||
$centers = $this->authorizationHelper
|
||||
->getReachableCenters($this->getUser(), new Role(PersonVoter::SEE));
|
||||
->getReachableCenters($this->getUser(), PersonVoter::SEE);
|
||||
$and->add($qb->expr()->in('person.center', ':centers'));
|
||||
$qb->setParameter('centers', $centers);
|
||||
|
||||
|
@@ -1,63 +0,0 @@
|
||||
Entity,Join,Attribute,Alias
|
||||
AccompanyingPeriod::class,,,acp
|
||||
,AccompanyingPeriodWork::class,acp.works,acpw
|
||||
,AccompanyingPeriodParticipation::class,acp.participations,acppart
|
||||
,Location::class,acp.administrativeLocation,acploc
|
||||
,ClosingMotive::class,acp.closingMotive,acpmotive
|
||||
,UserJob::class,acp.job,acpjob
|
||||
,Origin::class,acp.origin,acporigin
|
||||
,Scope::class,acp.scopes,acpscope
|
||||
,SocialIssue::class,acp.socialIssues,acpsocialissue
|
||||
,User::class,acp.user,acpuser
|
||||
AccompanyingPeriodWork::class,,,acpw
|
||||
,AccompanyingPeriodWorkEvaluation::class,acpw.accompanyingPeriodWorkEvaluations,workeval
|
||||
,User::class,acpw.referrers,acpwuser
|
||||
,SocialAction::class,acpw.socialAction,acpwsocialaction
|
||||
,Goal::class,acpw.goals,goal
|
||||
,Result::class,acpw.results,result
|
||||
AccompanyingPeriodParticipation::class,,,acppart
|
||||
,Person::class,acppart.person,partperson
|
||||
AccompanyingPeriodWorkEvaluation::class,,,workeval
|
||||
,Evaluation::class,workeval.evaluation,eval
|
||||
Goal::class,,,goal
|
||||
,Result::class,goal.results,goalresult
|
||||
Person::class,,,person
|
||||
,Center::class,person.center,center
|
||||
,HouseholdMember::class,partperson.householdParticipations,householdmember
|
||||
,MaritalStatus::class,person.maritalStatus,personmarital
|
||||
,VendeePerson::class,,vp
|
||||
,VendeePersonMineur::class,,vpm
|
||||
ResidentialAddress::class,,,resaddr
|
||||
,ThirdParty::class,resaddr.hostThirdParty,tparty
|
||||
ThirdParty::class,,,tparty
|
||||
,ThirdPartyCategory::class,tparty.categories,tpartycat
|
||||
HouseholdMember::class,,,householdmember
|
||||
,Household::class,householdmember.household,household
|
||||
,Person::class,householdmember.person,memberperson
|
||||
,,memberperson.center,membercenter
|
||||
Household::class,,,household
|
||||
,HouseholdComposition::class,household.compositions,composition
|
||||
Activity::class,,,activity
|
||||
,Person::class,activity.person,actperson
|
||||
,AccompanyingPeriod::class,activity.accompanyingPeriod,acp
|
||||
,Person::class,activity_person_having_activity.person,person_person_having_activity
|
||||
,ActivityReason::class,activity_person_having_activity.reasons,reasons_person_having_activity
|
||||
,ActivityType::class,activity.activityType,acttype
|
||||
,Location::class,activity.location,actloc
|
||||
,SocialAction::class,activity.socialActions,actsocialaction
|
||||
,SocialIssue::class,activity.socialIssues,actsocialssue
|
||||
,ThirdParty::class,activity.thirdParties,acttparty
|
||||
,User::class,activity.user,actuser
|
||||
,User::class,activity.users,actusers
|
||||
,ActivityReason::class,activity.reasons,actreasons
|
||||
,Center::class,actperson.center,actcenter
|
||||
ActivityReason::class,,,actreasons
|
||||
,ActivityReasonCategory::class,actreason.category,actreasoncat
|
||||
Calendar::class,,,cal
|
||||
,CancelReason::class,cal.cancelReason,calcancel
|
||||
,Location::class,cal.location,calloc
|
||||
,User::class,cal.user,caluser
|
||||
VendeePerson::class,,,vp
|
||||
,SituationProfessionelle::class,vp.situationProfessionelle,vpprof
|
||||
,StatutLogement::class,vp.statutLogement,vplog
|
||||
,TempsDeTravail::class,vp.tempsDeTravail,vptt
|
|
@@ -21,7 +21,6 @@ These are alias conventions :
|
||||
| | AccompanyingPeriodInfo::class | not existing (using custom WITH clause) | acpinfo |
|
||||
| AccompanyingPeriodWork::class | | | acpw |
|
||||
| | AccompanyingPeriodWorkEvaluation::class | acpw.accompanyingPeriodWorkEvaluations | workeval |
|
||||
| | User::class | acpw.referrers | acpwuser |
|
||||
| | SocialAction::class | acpw.socialAction | acpwsocialaction |
|
||||
| | Goal::class | acpw.goals | goal |
|
||||
| | Result::class | acpw.results | result |
|
||||
|
@@ -2,26 +2,51 @@
|
||||
|
||||
<!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="tests/app/vendor/phpunit/phpunit/phpunit.xsd"
|
||||
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
|
||||
backupGlobals="false"
|
||||
colors="true"
|
||||
bootstrap="tests/app/tests/bootstrap.php"
|
||||
bootstrap="tests/bootstrap.php"
|
||||
>
|
||||
<php>
|
||||
<ini name="error_reporting" value="-1" />
|
||||
<server name="APP_ENV" value="test" force="true" />
|
||||
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" />
|
||||
<env name="SYMFONY_DEPRECATIONS_HELPER" value="max[direct]=0&max[indirect]=999999" />
|
||||
<server name="SHELL_VERBOSITY" value="-1" />
|
||||
<env name="KERNEL_CLASS" value="\App\Kernel" />
|
||||
</php>
|
||||
|
||||
<testsuites>
|
||||
<!--
|
||||
<testsuite name="ActivityBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillActivityBundle/Tests/</directory>
|
||||
</testsuite>
|
||||
-->
|
||||
<testsuite name="AsideActivityBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillAsideActivityBundle/src/Tests/</directory>
|
||||
</testsuite>
|
||||
<testsuite name="BudgetBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillBudgetBundle/Tests/</directory>
|
||||
</testsuite>
|
||||
<testsuite name="CalendarBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillCalendarBundle/Tests/</directory>
|
||||
</testsuite>
|
||||
<!-- Missing CustomFieldBundle -->
|
||||
<testsuite name="DocGeneratorBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillDocGeneratorBundle/tests/</directory>
|
||||
</testsuite>
|
||||
<testsuite name="DocStoreBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillDocStoreBundle/Tests/</directory>
|
||||
</testsuite>
|
||||
<!--
|
||||
<testsuite name="EventBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillEventBundle/tests/</directory>
|
||||
</testsuite>
|
||||
-->
|
||||
<testsuite name="MainBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillMainBundle/Tests/</directory>
|
||||
</testsuite>
|
||||
<testsuite name="PersonBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillPersonBundle/Tests/</directory>
|
||||
<!-- test for export will be runned later -->
|
||||
<exclude>src/Bundle/ChillPersonBundle/Tests/Export/*</exclude>
|
||||
<!-- we are rewriting accompanying periods... Work in progress -->
|
||||
<exclude>src/Bundle/ChillPersonBundle/Tests/Controller/AccompanyingPeriodControllerTest.php</exclude>
|
||||
<!-- we are rewriting address, Work in progress -->
|
||||
@@ -31,14 +56,18 @@
|
||||
<!-- temporarily removed, the time to find a fix -->
|
||||
<exclude>src/Bundle/ChillPersonBundle/Tests/Controller/PersonDuplicateControllerViewTest.php</exclude>
|
||||
</testsuite>
|
||||
<testsuite name="AsideActivityBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillAsideActivityBundle/src/Tests/</directory>
|
||||
<!--
|
||||
<testsuite name="ReportBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillReportBundle/Tests/</directory>
|
||||
</testsuite>
|
||||
<testsuite name="CalendarBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillCalendarBundle/Tests/</directory>
|
||||
-->
|
||||
<!--
|
||||
<testsuite name="TaskBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillTaskBundle/Tests</directory>
|
||||
</testsuite>
|
||||
<testsuite name="DocGeneratorBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillDocGeneratorBundle/tests/</directory>
|
||||
-->
|
||||
<testsuite name="ThirdPartyBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillThirdPartyBundle/Tests</directory>
|
||||
</testsuite>
|
||||
<testsuite name="WopiBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillWopiBundle/tests/</directory>
|
||||
|
43
rector.php
43
rector.php
@@ -19,6 +19,9 @@ return static function (RectorConfig $rectorConfig): void {
|
||||
__DIR__ . '/src',
|
||||
]);
|
||||
|
||||
$rectorConfig->symfonyContainerXml(__DIR__ . '/var/cache/dev/testsApp_KernelDevDebugContainer.xml');
|
||||
$rectorConfig->symfonyContainerPhp(__DIR__ . '/tests/symfony-container.php');
|
||||
|
||||
//$rectorConfig->cacheClass(\Rector\Caching\ValueObject\Storage\FileCacheStorage::class);
|
||||
//$rectorConfig->cacheDirectory(__DIR__ . '/.cache/rector');
|
||||
|
||||
@@ -28,43 +31,25 @@ return static function (RectorConfig $rectorConfig): void {
|
||||
|
||||
//define sets of rules
|
||||
$rectorConfig->sets([
|
||||
LevelSetList::UP_TO_PHP_74
|
||||
LevelSetList::UP_TO_PHP_82,
|
||||
\Rector\Symfony\Set\SymfonyLevelSetList::UP_TO_SYMFONY_44,
|
||||
\Rector\Doctrine\Set\DoctrineSetList::DOCTRINE_CODE_QUALITY,
|
||||
\Rector\PHPUnit\Set\PHPUnitLevelSetList::UP_TO_PHPUNIT_90,
|
||||
]);
|
||||
|
||||
// some routes are added twice if it remains activated
|
||||
// $rectorConfig->rule(\Rector\Symfony\Configs\Rector\ClassMethod\AddRouteAnnotationRector::class);
|
||||
|
||||
// chill rules
|
||||
$rectorConfig->rule(\Chill\Utils\Rector\Rector\ChillBundleAddFormDefaultDataOnExportFilterAggregatorRector::class);
|
||||
//$rectorConfig->rule(\Chill\Utils\Rector\Rector\ChillBundleAddFormDefaultDataOnExportFilterAggregatorRector::class);
|
||||
|
||||
// skip some path...
|
||||
$rectorConfig->skip([
|
||||
// make rector stuck for some files
|
||||
\Rector\Php56\Rector\FunctionLike\AddDefaultValueForUndefinedVariableRector::class,
|
||||
|
||||
// we need to discuss this: are we going to have FALSE in tests instead of an error ?
|
||||
\Rector\Php71\Rector\FuncCall\CountOnNullRector::class,
|
||||
|
||||
// must merge MR500 and review a typing of "ArrayCollection" in entities
|
||||
\Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
|
||||
|
||||
// remove all PHP80 rules, in order to activate them one by one
|
||||
\Rector\Php80\Rector\ClassMethod\AddParamBasedOnParentClassMethodRector::class,
|
||||
\Rector\Php80\Rector\Class_\AnnotationToAttributeRector::class,
|
||||
\Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
|
||||
\Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
|
||||
\Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
|
||||
\Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
|
||||
\Rector\Php80\Rector\Class_\DoctrineAnnotationClassToAttributeRector::class,
|
||||
\Rector\Php80\Rector\ClassMethod\FinalPrivateToPrivateVisibilityRector::class,
|
||||
\Rector\Php80\Rector\Ternary\GetDebugTypeRector::class,
|
||||
\Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
|
||||
\Rector\Php80\Rector\Property\NestedAnnotationToAttributeRector::class,
|
||||
\Rector\Php80\Rector\FuncCall\Php8ResourceReturnToObjectRector::class,
|
||||
\Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
|
||||
\Rector\Php80\Rector\ClassMethod\SetStateToStaticRector::class,
|
||||
\Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
|
||||
\Rector\Php80\Rector\Identical\StrEndsWithRector::class,
|
||||
\Rector\Php80\Rector\Identical\StrStartsWithRector::class,
|
||||
\Rector\Php80\Rector\Class_\StringableForToStringRector::class,
|
||||
\Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
|
||||
\Rector\Php80\Rector\FunctionLike\UnionTypesRector::class
|
||||
// we must adapt service definition
|
||||
\Rector\Symfony\Symfony28\Rector\MethodCall\GetToConstructorInjectionRector::class,
|
||||
\Rector\Symfony\Symfony34\Rector\Closure\ContainerGetNameToTypeInTestsRector::class,
|
||||
]);
|
||||
};
|
||||
|
@@ -18,7 +18,6 @@ use Chill\ActivityBundle\Repository\ActivityACLAwareRepositoryInterface;
|
||||
use Chill\ActivityBundle\Repository\ActivityRepository;
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeCategoryRepository;
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
|
||||
use Chill\ActivityBundle\Repository\ActivityUserJobRepository;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
|
||||
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
|
||||
use Chill\MainBundle\Entity\UserJob;
|
||||
@@ -35,11 +34,8 @@ use Chill\PersonBundle\Privacy\PrivacyEvent;
|
||||
use Chill\PersonBundle\Repository\AccompanyingPeriodRepository;
|
||||
use Chill\PersonBundle\Repository\PersonRepository;
|
||||
use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository;
|
||||
use DateTime;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use InvalidArgumentException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use RuntimeException;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
@@ -49,7 +45,6 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use function array_key_exists;
|
||||
|
||||
final class ActivityController extends AbstractController
|
||||
{
|
||||
@@ -77,9 +72,9 @@ final class ActivityController extends AbstractController
|
||||
/**
|
||||
* Deletes a Activity entity.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/activity/{id}/delete", name="chill_activity_activity_delete", methods={"GET", "POST", "DELETE"})
|
||||
*/
|
||||
public function deleteAction(Request $request, $id)
|
||||
public function deleteAction(Request $request, mixed $id)
|
||||
{
|
||||
$view = null;
|
||||
|
||||
@@ -92,10 +87,10 @@ final class ActivityController extends AbstractController
|
||||
}
|
||||
|
||||
if ($activity->getAccompanyingPeriod() instanceof AccompanyingPeriod) {
|
||||
$view = 'ChillActivityBundle:Activity:confirm_deleteAccompanyingCourse.html.twig';
|
||||
$view = '@ChillActivity/Activity/confirm_deleteAccompanyingCourse.html.twig';
|
||||
$accompanyingPeriod = $activity->getAccompanyingPeriod();
|
||||
} else {
|
||||
$view = 'ChillActivityBundle:Activity:confirm_deletePerson.html.twig';
|
||||
$view = '@ChillActivity/Activity/confirm_deletePerson.html.twig';
|
||||
}
|
||||
|
||||
// TODO
|
||||
@@ -103,7 +98,7 @@ final class ActivityController extends AbstractController
|
||||
|
||||
$form = $this->createDeleteForm($activity->getId(), $person, $accompanyingPeriod);
|
||||
|
||||
if ($request->getMethod() === Request::METHOD_DELETE) {
|
||||
if (Request::METHOD_DELETE === $request->getMethod()) {
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isValid()) {
|
||||
@@ -136,10 +131,6 @@ final class ActivityController extends AbstractController
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $view) {
|
||||
throw $this->createNotFoundException('Template not found');
|
||||
}
|
||||
|
||||
return $this->render($view, [
|
||||
'activity' => $activity,
|
||||
'delete_form' => $form->createView(),
|
||||
@@ -150,6 +141,8 @@ final class ActivityController extends AbstractController
|
||||
|
||||
/**
|
||||
* Displays a form to edit an existing Activity entity.
|
||||
*
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/activity/{id}/edit", name="chill_activity_activity_edit", methods={"GET", "POST", "PUT"})
|
||||
*/
|
||||
public function editAction(int $id, Request $request): Response
|
||||
{
|
||||
@@ -165,10 +158,10 @@ final class ActivityController extends AbstractController
|
||||
$person = $entity->getPerson();
|
||||
|
||||
if ($entity->getAccompanyingPeriod() instanceof AccompanyingPeriod) {
|
||||
$view = 'ChillActivityBundle:Activity:editAccompanyingCourse.html.twig';
|
||||
$view = '@ChillActivity/Activity/editAccompanyingCourse.html.twig';
|
||||
$accompanyingPeriod = $entity->getAccompanyingPeriod();
|
||||
} else {
|
||||
$view = 'ChillActivityBundle:Activity:editPerson.html.twig';
|
||||
$view = '@ChillActivity/Activity/editPerson.html.twig';
|
||||
}
|
||||
// TODO
|
||||
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_UPDATE', $entity);
|
||||
@@ -229,10 +222,6 @@ final class ActivityController extends AbstractController
|
||||
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
|
||||
*/
|
||||
|
||||
if (null === $view) {
|
||||
throw $this->createNotFoundException('Template not found');
|
||||
}
|
||||
|
||||
$activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']);
|
||||
|
||||
return $this->render($view, [
|
||||
@@ -247,6 +236,8 @@ final class ActivityController extends AbstractController
|
||||
|
||||
/**
|
||||
* Lists all Activity entities.
|
||||
*
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/activity/", name="chill_activity_activity_list")
|
||||
*/
|
||||
public function listAction(Request $request): Response
|
||||
{
|
||||
@@ -282,9 +273,9 @@ final class ActivityController extends AbstractController
|
||||
'element_class' => Activity::class,
|
||||
'action' => 'list',
|
||||
]);
|
||||
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
|
||||
$this->eventDispatcher->dispatch($event, PrivacyEvent::PERSON_PRIVACY_EVENT);
|
||||
|
||||
$view = 'ChillActivityBundle:Activity:listPerson.html.twig';
|
||||
$view = '@ChillActivity/Activity/listPerson.html.twig';
|
||||
} elseif ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$this->denyAccessUnlessGranted(ActivityVoter::SEE, $accompanyingPeriod);
|
||||
|
||||
@@ -300,9 +291,9 @@ final class ActivityController extends AbstractController
|
||||
$filterArgs
|
||||
);
|
||||
|
||||
$view = 'ChillActivityBundle:Activity:listAccompanyingCourse.html.twig';
|
||||
$view = '@ChillActivity/Activity/listAccompanyingCourse.html.twig';
|
||||
} else {
|
||||
throw new \LogicException("Unsupported");
|
||||
throw new \LogicException('Unsupported');
|
||||
}
|
||||
|
||||
return $this->render(
|
||||
@@ -332,25 +323,28 @@ final class ActivityController extends AbstractController
|
||||
->addEntityChoice('activity_types', 'activity_filter.Types', \Chill\ActivityBundle\Entity\ActivityType::class, $types, [
|
||||
'choice_label' => function (\Chill\ActivityBundle\Entity\ActivityType $activityType) {
|
||||
$text = match ($activityType->hasCategory()) {
|
||||
true => $this->translatableStringHelper->localize($activityType->getCategory()->getName()) . ' > ',
|
||||
true => $this->translatableStringHelper->localize($activityType->getCategory()->getName()).' > ',
|
||||
false => '',
|
||||
};
|
||||
|
||||
return $text . $this->translatableStringHelper->localize($activityType->getName());
|
||||
}
|
||||
return $text.$this->translatableStringHelper->localize($activityType->getName());
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
if (1 < count($jobs)) {
|
||||
$filterBuilder
|
||||
->addEntityChoice('jobs', 'activity_filter.Jobs', UserJob::class, $jobs, [
|
||||
'choice_label' => fn (UserJob $u) => $this->translatableStringHelper->localize($u->getLabel())
|
||||
'choice_label' => fn (UserJob $u) => $this->translatableStringHelper->localize($u->getLabel()),
|
||||
]);
|
||||
}
|
||||
|
||||
return $filterBuilder->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/activity/new", name="chill_activity_activity_new", methods={"POST", "GET"})
|
||||
*/
|
||||
public function newAction(Request $request): Response
|
||||
{
|
||||
$view = null;
|
||||
@@ -358,16 +352,16 @@ final class ActivityController extends AbstractController
|
||||
[$person, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$view = 'ChillActivityBundle:Activity:newAccompanyingCourse.html.twig';
|
||||
$view = '@ChillActivity/Activity/newAccompanyingCourse.html.twig';
|
||||
} elseif ($person instanceof Person) {
|
||||
$view = 'ChillActivityBundle:Activity:newPerson.html.twig';
|
||||
$view = '@ChillActivity/Activity/newPerson.html.twig';
|
||||
}
|
||||
|
||||
$activityType_id = $request->get('activityType_id', 0);
|
||||
$activityType = $this->activityTypeRepository->find($activityType_id);
|
||||
|
||||
if (isset($activityType) && !$activityType->isActive()) {
|
||||
throw new InvalidArgumentException('Activity type must be active');
|
||||
throw new \InvalidArgumentException('Activity type must be active');
|
||||
}
|
||||
|
||||
$activityData = null;
|
||||
@@ -402,45 +396,45 @@ final class ActivityController extends AbstractController
|
||||
}
|
||||
|
||||
$entity->setActivityType($activityType);
|
||||
$entity->setDate(new DateTime('now'));
|
||||
$entity->setDate(new \DateTime('now'));
|
||||
|
||||
if ($request->query->has('activityData')) {
|
||||
$activityData = $request->query->get('activityData');
|
||||
|
||||
if (array_key_exists('durationTime', $activityData) && $activityType->getDurationTimeVisible() > 0) {
|
||||
if (\array_key_exists('durationTime', $activityData) && $activityType->getDurationTimeVisible() > 0) {
|
||||
$durationTimeInMinutes = $activityData['durationTime'];
|
||||
$hours = floor($durationTimeInMinutes / 60);
|
||||
$minutes = $durationTimeInMinutes % 60;
|
||||
$duration = DateTime::createFromFormat('H:i', $hours . ':' . $minutes);
|
||||
$duration = \DateTime::createFromFormat('H:i', $hours.':'.$minutes);
|
||||
|
||||
if ($duration) {
|
||||
$entity->setDurationTime($duration);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('date', $activityData)) {
|
||||
$date = DateTime::createFromFormat('Y-m-d', $activityData['date']);
|
||||
if (\array_key_exists('date', $activityData)) {
|
||||
$date = \DateTime::createFromFormat('Y-m-d', $activityData['date']);
|
||||
|
||||
if ($date) {
|
||||
$entity->setDate($date);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('personsId', $activityData) && $activityType->getPersonsVisible() > 0) {
|
||||
if (\array_key_exists('personsId', $activityData) && $activityType->getPersonsVisible() > 0) {
|
||||
foreach ($activityData['personsId'] as $personId) {
|
||||
$concernedPerson = $this->personRepository->find($personId);
|
||||
$entity->addPerson($concernedPerson);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('professionalsId', $activityData) && $activityType->getThirdPartiesVisible() > 0) {
|
||||
if (\array_key_exists('professionalsId', $activityData) && $activityType->getThirdPartiesVisible() > 0) {
|
||||
foreach ($activityData['professionalsId'] as $professionalsId) {
|
||||
$professional = $this->thirdPartyRepository->find($professionalsId);
|
||||
$entity->addThirdParty($professional);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('usersId', $activityData) && $activityType->getUsersVisible() > 0) {
|
||||
if (\array_key_exists('usersId', $activityData) && $activityType->getUsersVisible() > 0) {
|
||||
foreach ($activityData['usersId'] as $userId) {
|
||||
$user = $this->userRepository->find($userId);
|
||||
|
||||
@@ -450,16 +444,16 @@ final class ActivityController extends AbstractController
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('location', $activityData) && $activityType->getLocationVisible() > 0) {
|
||||
if (\array_key_exists('location', $activityData) && $activityType->getLocationVisible() > 0) {
|
||||
$location = $this->locationRepository->find($activityData['location']);
|
||||
$entity->setLocation($location);
|
||||
}
|
||||
|
||||
if (array_key_exists('comment', $activityData) && $activityType->getCommentVisible() > 0) {
|
||||
if (\array_key_exists('comment', $activityData) && $activityType->getCommentVisible() > 0) {
|
||||
$comment = new CommentEmbeddable();
|
||||
$comment->setComment($activityData['comment']);
|
||||
$comment->setUserId($this->getUser()->getid());
|
||||
$comment->setDate(new DateTime('now'));
|
||||
$comment->setDate(new \DateTime('now'));
|
||||
$entity->setComment($comment);
|
||||
}
|
||||
}
|
||||
@@ -531,6 +525,9 @@ final class ActivityController extends AbstractController
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/activity/select-type", name="chill_activity_activity_select_type")
|
||||
*/
|
||||
public function selectTypeAction(Request $request): Response
|
||||
{
|
||||
$view = null;
|
||||
@@ -538,9 +535,9 @@ final class ActivityController extends AbstractController
|
||||
[$person, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$view = 'ChillActivityBundle:Activity:selectTypeAccompanyingCourse.html.twig';
|
||||
$view = '@ChillActivity/Activity/selectTypeAccompanyingCourse.html.twig';
|
||||
} elseif ($person instanceof Person) {
|
||||
$view = 'ChillActivityBundle:Activity:selectTypePerson.html.twig';
|
||||
$view = '@ChillActivity/Activity/selectTypePerson.html.twig';
|
||||
}
|
||||
|
||||
$data = [];
|
||||
@@ -575,6 +572,9 @@ final class ActivityController extends AbstractController
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/activity/{id}/show", name="chill_activity_activity_show")
|
||||
*/
|
||||
public function showAction(Request $request, int $id): Response
|
||||
{
|
||||
$entity = $this->activityRepository->find($id);
|
||||
@@ -587,11 +587,11 @@ final class ActivityController extends AbstractController
|
||||
$person = $entity->getPerson();
|
||||
|
||||
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$view = 'ChillActivityBundle:Activity:showAccompanyingCourse.html.twig';
|
||||
$view = '@ChillActivity/Activity/showAccompanyingCourse.html.twig';
|
||||
} elseif ($person instanceof Person) {
|
||||
$view = 'ChillActivityBundle:Activity:showPerson.html.twig';
|
||||
$view = '@ChillActivity/Activity/showPerson.html.twig';
|
||||
} else {
|
||||
throw new RuntimeException('the activity should be linked with a period or person');
|
||||
throw new \RuntimeException('the activity should be linked with a period or person');
|
||||
}
|
||||
|
||||
if (null !== $accompanyingPeriod) {
|
||||
@@ -614,10 +614,6 @@ final class ActivityController extends AbstractController
|
||||
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
|
||||
*/
|
||||
|
||||
if (null === $view) {
|
||||
throw $this->createNotFoundException('Template not found');
|
||||
}
|
||||
|
||||
return $this->render($view, [
|
||||
'person' => $person,
|
||||
'accompanyingCourse' => $accompanyingPeriod,
|
||||
@@ -677,8 +673,8 @@ final class ActivityController extends AbstractController
|
||||
throw $this->createNotFoundException('Accompanying Period not found');
|
||||
}
|
||||
|
||||
// TODO Add permission
|
||||
// $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
|
||||
// TODO Add permission
|
||||
// $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
|
||||
} else {
|
||||
throw $this->createNotFoundException('Person or Accompanying Period not found');
|
||||
}
|
||||
|
@@ -24,6 +24,8 @@ class ActivityReasonCategoryController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* Creates a new ActivityReasonCategory entity.
|
||||
*
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreasoncategory/create", name="chill_activity_activityreasoncategory_create", methods={"POST"})
|
||||
*/
|
||||
public function createAction(Request $request)
|
||||
{
|
||||
@@ -31,15 +33,15 @@ class ActivityReasonCategoryController extends AbstractController
|
||||
$form = $this->createCreateForm($entity);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isValid()) {
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$em->persist($entity);
|
||||
$em->flush();
|
||||
|
||||
return $this->redirect($this->generateUrl('chill_activity_activityreasoncategory_show', ['id' => $entity->getId()]));
|
||||
return $this->redirectToRoute('chill_activity_activityreasoncategory_show', ['id' => $entity->getId()]);
|
||||
}
|
||||
|
||||
return $this->render('ChillActivityBundle:ActivityReasonCategory:new.html.twig', [
|
||||
return $this->render('@ChillActivity/ActivityReasonCategory/new.html.twig', [
|
||||
'entity' => $entity,
|
||||
'form' => $form->createView(),
|
||||
]);
|
||||
@@ -48,9 +50,9 @@ class ActivityReasonCategoryController extends AbstractController
|
||||
/**
|
||||
* Displays a form to edit an existing ActivityReasonCategory entity.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreasoncategory/{id}/edit", name="chill_activity_activityreasoncategory_edit")
|
||||
*/
|
||||
public function editAction($id)
|
||||
public function editAction(mixed $id)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
@@ -62,7 +64,7 @@ class ActivityReasonCategoryController extends AbstractController
|
||||
|
||||
$editForm = $this->createEditForm($entity);
|
||||
|
||||
return $this->render('ChillActivityBundle:ActivityReasonCategory:edit.html.twig', [
|
||||
return $this->render('@ChillActivity/ActivityReasonCategory/edit.html.twig', [
|
||||
'entity' => $entity,
|
||||
'edit_form' => $editForm->createView(),
|
||||
]);
|
||||
@@ -70,6 +72,8 @@ class ActivityReasonCategoryController extends AbstractController
|
||||
|
||||
/**
|
||||
* Lists all ActivityReasonCategory entities.
|
||||
*
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreasoncategory/", name="chill_activity_activityreasoncategory")
|
||||
*/
|
||||
public function indexAction()
|
||||
{
|
||||
@@ -77,20 +81,22 @@ class ActivityReasonCategoryController extends AbstractController
|
||||
|
||||
$entities = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityReasonCategory::class)->findAll();
|
||||
|
||||
return $this->render('ChillActivityBundle:ActivityReasonCategory:index.html.twig', [
|
||||
return $this->render('@ChillActivity/ActivityReasonCategory/index.html.twig', [
|
||||
'entities' => $entities,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a form to create a new ActivityReasonCategory entity.
|
||||
*
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreasoncategory/new", name="chill_activity_activityreasoncategory_new")
|
||||
*/
|
||||
public function newAction()
|
||||
{
|
||||
$entity = new ActivityReasonCategory();
|
||||
$form = $this->createCreateForm($entity);
|
||||
|
||||
return $this->render('ChillActivityBundle:ActivityReasonCategory:new.html.twig', [
|
||||
return $this->render('@ChillActivity/ActivityReasonCategory/new.html.twig', [
|
||||
'entity' => $entity,
|
||||
'form' => $form->createView(),
|
||||
]);
|
||||
@@ -99,9 +105,9 @@ class ActivityReasonCategoryController extends AbstractController
|
||||
/**
|
||||
* Finds and displays a ActivityReasonCategory entity.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreasoncategory/{id}/show", name="chill_activity_activityreasoncategory_show")
|
||||
*/
|
||||
public function showAction($id)
|
||||
public function showAction(mixed $id)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
@@ -111,7 +117,7 @@ class ActivityReasonCategoryController extends AbstractController
|
||||
throw $this->createNotFoundException('Unable to find ActivityReasonCategory entity.');
|
||||
}
|
||||
|
||||
return $this->render('ChillActivityBundle:ActivityReasonCategory:show.html.twig', [
|
||||
return $this->render('@ChillActivity/ActivityReasonCategory/show.html.twig', [
|
||||
'entity' => $entity,
|
||||
]);
|
||||
}
|
||||
@@ -119,9 +125,9 @@ class ActivityReasonCategoryController extends AbstractController
|
||||
/**
|
||||
* Edits an existing ActivityReasonCategory entity.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreasoncategory/{id}/update", name="chill_activity_activityreasoncategory_update", methods={"POST", "PUT"})
|
||||
*/
|
||||
public function updateAction(Request $request, $id)
|
||||
public function updateAction(Request $request, mixed $id)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
@@ -134,13 +140,13 @@ class ActivityReasonCategoryController extends AbstractController
|
||||
$editForm = $this->createEditForm($entity);
|
||||
$editForm->handleRequest($request);
|
||||
|
||||
if ($editForm->isValid()) {
|
||||
if ($editForm->isSubmitted() && $editForm->isValid()) {
|
||||
$em->flush();
|
||||
|
||||
return $this->redirect($this->generateUrl('chill_activity_activityreasoncategory_edit', ['id' => $id]));
|
||||
return $this->redirectToRoute('chill_activity_activityreasoncategory_edit', ['id' => $id]);
|
||||
}
|
||||
|
||||
return $this->render('ChillActivityBundle:ActivityReasonCategory:edit.html.twig', [
|
||||
return $this->render('@ChillActivity/ActivityReasonCategory/edit.html.twig', [
|
||||
'entity' => $entity,
|
||||
'edit_form' => $editForm->createView(),
|
||||
]);
|
||||
|
@@ -24,15 +24,12 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
*/
|
||||
class ActivityReasonController extends AbstractController
|
||||
{
|
||||
private ActivityReasonRepository $activityReasonRepository;
|
||||
|
||||
public function __construct(ActivityReasonRepository $activityReasonRepository)
|
||||
{
|
||||
$this->activityReasonRepository = $activityReasonRepository;
|
||||
}
|
||||
public function __construct(private readonly ActivityReasonRepository $activityReasonRepository) {}
|
||||
|
||||
/**
|
||||
* Creates a new ActivityReason entity.
|
||||
*
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreason/create", name="chill_activity_activityreason_create", methods={"POST"})
|
||||
*/
|
||||
public function createAction(Request $request)
|
||||
{
|
||||
@@ -40,15 +37,15 @@ class ActivityReasonController extends AbstractController
|
||||
$form = $this->createCreateForm($entity);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isValid()) {
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$em->persist($entity);
|
||||
$em->flush();
|
||||
|
||||
return $this->redirect($this->generateUrl('chill_activity_activityreason', ['id' => $entity->getId()]));
|
||||
return $this->redirectToRoute('chill_activity_activityreason', ['id' => $entity->getId()]);
|
||||
}
|
||||
|
||||
return $this->render('ChillActivityBundle:ActivityReason:new.html.twig', [
|
||||
return $this->render('@ChillActivity/ActivityReason/new.html.twig', [
|
||||
'entity' => $entity,
|
||||
'form' => $form->createView(),
|
||||
]);
|
||||
@@ -57,9 +54,9 @@ class ActivityReasonController extends AbstractController
|
||||
/**
|
||||
* Displays a form to edit an existing ActivityReason entity.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreason/{id}/edit", name="chill_activity_activityreason_edit")
|
||||
*/
|
||||
public function editAction($id)
|
||||
public function editAction(mixed $id)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
@@ -71,7 +68,7 @@ class ActivityReasonController extends AbstractController
|
||||
|
||||
$editForm = $this->createEditForm($entity);
|
||||
|
||||
return $this->render('ChillActivityBundle:ActivityReason:edit.html.twig', [
|
||||
return $this->render('@ChillActivity/ActivityReason/edit.html.twig', [
|
||||
'entity' => $entity,
|
||||
'edit_form' => $editForm->createView(),
|
||||
]);
|
||||
@@ -79,6 +76,8 @@ class ActivityReasonController extends AbstractController
|
||||
|
||||
/**
|
||||
* Lists all ActivityReason entities.
|
||||
*
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreason/", name="chill_activity_activityreason")
|
||||
*/
|
||||
public function indexAction()
|
||||
{
|
||||
@@ -86,20 +85,22 @@ class ActivityReasonController extends AbstractController
|
||||
|
||||
$entities = $this->activityReasonRepository->findAll();
|
||||
|
||||
return $this->render('ChillActivityBundle:ActivityReason:index.html.twig', [
|
||||
return $this->render('@ChillActivity/ActivityReason/index.html.twig', [
|
||||
'entities' => $entities,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a form to create a new ActivityReason entity.
|
||||
*
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreason/new", name="chill_activity_activityreason_new")
|
||||
*/
|
||||
public function newAction()
|
||||
{
|
||||
$entity = new ActivityReason();
|
||||
$form = $this->createCreateForm($entity);
|
||||
|
||||
return $this->render('ChillActivityBundle:ActivityReason:new.html.twig', [
|
||||
return $this->render('@ChillActivity/ActivityReason/new.html.twig', [
|
||||
'entity' => $entity,
|
||||
'form' => $form->createView(),
|
||||
]);
|
||||
@@ -108,9 +109,9 @@ class ActivityReasonController extends AbstractController
|
||||
/**
|
||||
* Finds and displays a ActivityReason entity.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreason/{id}/show", name="chill_activity_activityreason_show")
|
||||
*/
|
||||
public function showAction($id)
|
||||
public function showAction(mixed $id)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
@@ -120,7 +121,7 @@ class ActivityReasonController extends AbstractController
|
||||
throw $this->createNotFoundException('Unable to find ActivityReason entity.');
|
||||
}
|
||||
|
||||
return $this->render('ChillActivityBundle:ActivityReason:show.html.twig', [
|
||||
return $this->render('@ChillActivity/ActivityReason/show.html.twig', [
|
||||
'entity' => $entity,
|
||||
]);
|
||||
}
|
||||
@@ -128,9 +129,9 @@ class ActivityReasonController extends AbstractController
|
||||
/**
|
||||
* Edits an existing ActivityReason entity.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activityreason/{id}/update", name="chill_activity_activityreason_update", methods={"POST", "PUT"})
|
||||
*/
|
||||
public function updateAction(Request $request, $id)
|
||||
public function updateAction(Request $request, mixed $id)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
@@ -143,13 +144,13 @@ class ActivityReasonController extends AbstractController
|
||||
$editForm = $this->createEditForm($entity);
|
||||
$editForm->handleRequest($request);
|
||||
|
||||
if ($editForm->isValid()) {
|
||||
if ($editForm->isSubmitted() && $editForm->isValid()) {
|
||||
$em->flush();
|
||||
|
||||
return $this->redirect($this->generateUrl('chill_activity_activityreason', ['id' => $id]));
|
||||
return $this->redirectToRoute('chill_activity_activityreason', ['id' => $id]);
|
||||
}
|
||||
|
||||
return $this->render('ChillActivityBundle:ActivityReason:edit.html.twig', [
|
||||
return $this->render('@ChillActivity/ActivityReason/edit.html.twig', [
|
||||
'entity' => $entity,
|
||||
'edit_form' => $editForm->createView(),
|
||||
]);
|
||||
|
@@ -24,7 +24,7 @@ class AdminActivityPresenceController extends CRUDController
|
||||
*/
|
||||
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
|
||||
{
|
||||
/** @var \Doctrine\ORM\QueryBuilder $query */
|
||||
/* @var \Doctrine\ORM\QueryBuilder $query */
|
||||
return $query->orderBy('e.id', 'ASC');
|
||||
}
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ class AdminActivityTypeCategoryController extends CRUDController
|
||||
*/
|
||||
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
|
||||
{
|
||||
/** @var \Doctrine\ORM\QueryBuilder $query */
|
||||
/* @var \Doctrine\ORM\QueryBuilder $query */
|
||||
return $query->orderBy('e.ordering', 'ASC');
|
||||
}
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ class AdminActivityTypeController extends CRUDController
|
||||
*/
|
||||
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
|
||||
{
|
||||
/** @var \Doctrine\ORM\QueryBuilder $query */
|
||||
/* @var \Doctrine\ORM\QueryBuilder $query */
|
||||
return $query->orderBy('e.ordering', 'ASC')
|
||||
->addOrderBy('e.id', 'ASC');
|
||||
}
|
||||
|
@@ -18,11 +18,18 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
*/
|
||||
class AdminController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activity", name="chill_activity_admin_index")
|
||||
*/
|
||||
public function indexActivityAction()
|
||||
{
|
||||
return $this->render('ChillActivityBundle:Admin:layout_activity.html.twig');
|
||||
return $this->render('@ChillActivity/Admin/layout_activity.html.twig');
|
||||
}
|
||||
|
||||
/**
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activity_redirect_to_main", name="chill_admin_aside_activity_redirect_to_admin_index", options={null})
|
||||
* @\Symfony\Component\Routing\Annotation\Route(path="/{_locale}/admin/activity_redirect_to_main", name="chill_admin_activity_redirect_to_admin_index")
|
||||
*/
|
||||
public function redirectToAdminIndexAction()
|
||||
{
|
||||
return $this->redirectToRoute('chill_main_admin_central');
|
||||
|
@@ -25,17 +25,11 @@ class LoadActivity extends AbstractFixture implements OrderedFixtureInterface
|
||||
{
|
||||
use \Symfony\Component\DependencyInjection\ContainerAwareTrait;
|
||||
|
||||
private EntityManagerInterface $em;
|
||||
private readonly \Faker\Generator $faker;
|
||||
|
||||
/**
|
||||
* @var \Faker\Generator
|
||||
*/
|
||||
private $faker;
|
||||
|
||||
public function __construct(EntityManagerInterface $em)
|
||||
public function __construct(private readonly EntityManagerInterface $em)
|
||||
{
|
||||
$this->faker = FakerFactory::create('fr_FR');
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
public function getOrder()
|
||||
|
@@ -52,13 +52,13 @@ class LoadActivityReason extends AbstractFixture implements OrderedFixtureInterf
|
||||
];
|
||||
|
||||
foreach ($reasons as $r) {
|
||||
echo 'Creating activity reason : ' . $r['name']['en'] . "\n";
|
||||
echo 'Creating activity reason : '.$r['name']['en']."\n";
|
||||
$activityReason = (new ActivityReason())
|
||||
->setName(($r['name']))
|
||||
->setName($r['name'])
|
||||
->setActive(true)
|
||||
->setCategory($this->getReference($r['category']));
|
||||
$manager->persist($activityReason);
|
||||
$reference = 'activity_reason_' . $r['name']['en'];
|
||||
$reference = 'activity_reason_'.$r['name']['en'];
|
||||
$this->addReference($reference, $activityReason);
|
||||
static::$references[] = $reference;
|
||||
}
|
||||
|
@@ -34,13 +34,13 @@ class LoadActivityReasonCategory extends AbstractFixture implements OrderedFixtu
|
||||
];
|
||||
|
||||
foreach ($categs as $c) {
|
||||
echo 'Creating activity reason category : ' . $c['name']['en'] . "\n";
|
||||
echo 'Creating activity reason category : '.$c['name']['en']."\n";
|
||||
$activityReasonCategory = (new ActivityReasonCategory())
|
||||
->setName(($c['name']))
|
||||
->setName($c['name'])
|
||||
->setActive(true);
|
||||
$manager->persist($activityReasonCategory);
|
||||
$this->addReference(
|
||||
'cat_' . $c['name']['en'],
|
||||
'cat_'.$c['name']['en'],
|
||||
$activityReasonCategory
|
||||
);
|
||||
}
|
||||
|
@@ -54,14 +54,14 @@ class LoadActivityType extends Fixture implements OrderedFixtureInterface
|
||||
];
|
||||
|
||||
foreach ($types as $t) {
|
||||
echo 'Creating activity type : ' . $t['name']['fr'] . ' (cat:' . $t['category'] . " \n";
|
||||
echo 'Creating activity type : '.$t['name']['fr'].' (cat:'.$t['category']." \n";
|
||||
$activityType = (new ActivityType())
|
||||
->setName(($t['name']))
|
||||
->setCategory($this->getReference('activity_type_cat_' . $t['category']))
|
||||
->setName($t['name'])
|
||||
->setCategory($this->getReference('activity_type_cat_'.$t['category']))
|
||||
->setSocialIssuesVisible(1)
|
||||
->setSocialActionsVisible(1);
|
||||
$manager->persist($activityType);
|
||||
$reference = 'activity_type_' . $t['name']['fr'];
|
||||
$reference = 'activity_type_'.$t['name']['fr'];
|
||||
$this->addReference($reference, $activityType);
|
||||
static::$references[] = $reference;
|
||||
}
|
||||
|
@@ -42,13 +42,13 @@ class LoadActivityTypeCategory extends Fixture implements OrderedFixtureInterfac
|
||||
];
|
||||
|
||||
foreach ($categories as $cat) {
|
||||
echo 'Creating activity type category : ' . $cat['ref'] . "\n";
|
||||
echo 'Creating activity type category : '.$cat['ref']."\n";
|
||||
|
||||
$newCat = (new ActivityTypeCategory())
|
||||
->setName(($cat['name']));
|
||||
->setName($cat['name']);
|
||||
|
||||
$manager->persist($newCat);
|
||||
$reference = 'activity_type_cat_' . $cat['ref'];
|
||||
$reference = 'activity_type_cat_'.$cat['ref'];
|
||||
|
||||
$this->addReference($reference, $newCat);
|
||||
static::$references[] = $reference;
|
||||
|
@@ -20,8 +20,6 @@ use Doctrine\Common\DataFixtures\AbstractFixture;
|
||||
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
use function in_array;
|
||||
|
||||
/**
|
||||
* Add a role CHILL_ACTIVITY_UPDATE & CHILL_ACTIVITY_CREATE for all groups except administrative,
|
||||
* and a role CHILL_ACTIVITY_SEE for administrative.
|
||||
@@ -40,10 +38,10 @@ class LoadActivitytACL extends AbstractFixture implements OrderedFixtureInterfac
|
||||
|
||||
foreach (LoadScopes::$references as $scopeRef) {
|
||||
$scope = $this->getReference($scopeRef);
|
||||
//create permission group
|
||||
// create permission group
|
||||
switch ($permissionsGroup->getName()) {
|
||||
case 'social':
|
||||
if ($scope->getName()['en'] === 'administrative') {
|
||||
if ('administrative' === $scope->getName()['en']) {
|
||||
break 2; // we do not want any power on administrative
|
||||
}
|
||||
|
||||
@@ -51,7 +49,7 @@ class LoadActivitytACL extends AbstractFixture implements OrderedFixtureInterfac
|
||||
|
||||
case 'administrative':
|
||||
case 'direction':
|
||||
if (in_array($scope->getName()['en'], ['administrative', 'social'], true)) {
|
||||
if (\in_array($scope->getName()['en'], ['administrative', 'social'], true)) {
|
||||
break 2; // we do not want any power on social or administrative
|
||||
}
|
||||
|
||||
@@ -60,7 +58,7 @@ class LoadActivitytACL extends AbstractFixture implements OrderedFixtureInterfac
|
||||
|
||||
printf(
|
||||
'Adding CHILL_ACTIVITY_UPDATE & CHILL_ACTIVITY_CREATE & CHILL_ACTIVITY_DELETE, and stats and list permissions to %s '
|
||||
. "permission group, scope '%s' \n",
|
||||
."permission group, scope '%s' \n",
|
||||
$permissionsGroup->getName(),
|
||||
$scope->getName()['en']
|
||||
);
|
||||
|
@@ -32,7 +32,7 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
|
||||
|
||||
$container->setParameter('chill_activity.form.time_duration', $config['form']['time_duration']);
|
||||
|
||||
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../config'));
|
||||
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config'));
|
||||
$loader->load('services.yaml');
|
||||
$loader->load('services/export.yaml');
|
||||
$loader->load('services/repositories.yaml');
|
||||
@@ -73,7 +73,7 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
|
||||
*/
|
||||
public function prependRoutes(ContainerBuilder $container)
|
||||
{
|
||||
//add routes for custom bundle
|
||||
// add routes for custom bundle
|
||||
$container->prependExtensionConfig('chill_main', [
|
||||
'routing' => [
|
||||
'resources' => [
|
||||
|
@@ -13,7 +13,6 @@ namespace Chill\ActivityBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||
|
||||
use function is_int;
|
||||
|
||||
/**
|
||||
@@ -59,7 +58,7 @@ class Configuration implements ConfigurationInterface
|
||||
->info('The number of seconds of this duration. Must be an integer.')
|
||||
->cannotBeEmpty()
|
||||
->validate()
|
||||
->ifTrue(static fn ($data) => !is_int($data))->thenInvalid('The value %s is not a valid integer')
|
||||
->ifTrue(static fn ($data) => !\is_int($data))->thenInvalid('The value %s is not a valid integer')
|
||||
->end()
|
||||
->end()
|
||||
->scalarNode('label')
|
||||
|
@@ -36,7 +36,6 @@ use DateTime;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Serializer\Annotation\SerializedName;
|
||||
@@ -46,11 +45,15 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
* Class Activity.
|
||||
*
|
||||
* @ORM\Entity(repositoryClass="Chill\ActivityBundle\Repository\ActivityRepository")
|
||||
*
|
||||
* @ORM\Table(name="activity")
|
||||
*
|
||||
* @ORM\HasLifecycleCallbacks
|
||||
*
|
||||
* @DiscriminatorMap(typeProperty="type", mapping={
|
||||
* "activity": Activity::class
|
||||
* })
|
||||
*
|
||||
* @ActivityValidator\ActivityValidity
|
||||
*
|
||||
* TODO see if necessary
|
||||
@@ -65,69 +68,84 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
||||
|
||||
use TrackUpdateTrait;
|
||||
|
||||
public const SENTRECEIVED_RECEIVED = 'received';
|
||||
final public const SENTRECEIVED_RECEIVED = 'received';
|
||||
|
||||
public const SENTRECEIVED_SENT = 'sent';
|
||||
final public const SENTRECEIVED_SENT = 'sent';
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod")
|
||||
*
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private ?AccompanyingPeriod $accompanyingPeriod = null;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\ActivityType")
|
||||
*
|
||||
* @Groups({"read", "docgen:read"})
|
||||
*
|
||||
* @SerializedName("activityType")
|
||||
*
|
||||
* @ORM\JoinColumn(name="type_id")
|
||||
*/
|
||||
private ActivityType $activityType;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\ActivityPresence")
|
||||
*
|
||||
* @Groups({"docgen:read"})
|
||||
*/
|
||||
private ?ActivityPresence $attendee = null;
|
||||
|
||||
/**
|
||||
* @ORM\Embedded(class="Chill\MainBundle\Entity\Embeddable\CommentEmbeddable", columnPrefix="comment_")
|
||||
*
|
||||
* @Groups({"docgen:read"})
|
||||
*/
|
||||
private CommentEmbeddable $comment;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetime")
|
||||
*
|
||||
* @Groups({"docgen:read"})
|
||||
*/
|
||||
private DateTime $date;
|
||||
private \DateTime $date;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToMany(targetEntity="Chill\DocStoreBundle\Entity\StoredObject", cascade={"persist"})
|
||||
*
|
||||
* @Assert\Valid(traverse=true)
|
||||
*
|
||||
* @var Collection<StoredObject>
|
||||
*/
|
||||
private Collection $documents;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="time", nullable=true)
|
||||
*/
|
||||
private ?DateTime $durationTime = null;
|
||||
private ?\DateTime $durationTime = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="boolean", options={"default": false})
|
||||
*
|
||||
* @Groups({"docgen:read"})
|
||||
*/
|
||||
private bool $emergency = false;
|
||||
|
||||
/**
|
||||
* @ORM\Id
|
||||
*
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
*
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*
|
||||
* @Groups({"read", "docgen:read"})
|
||||
*/
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Location")
|
||||
*
|
||||
* @groups({"read", "docgen:read"})
|
||||
*/
|
||||
private ?Location $location = null;
|
||||
@@ -139,9 +157,12 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
||||
|
||||
/**
|
||||
* @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\Person")
|
||||
*
|
||||
* @Groups({"read", "docgen:read"})
|
||||
*
|
||||
* @var Collection<Person>
|
||||
*/
|
||||
private ?Collection $persons = null;
|
||||
private Collection $persons;
|
||||
|
||||
/**
|
||||
* @ORM\Embedded(class="Chill\MainBundle\Entity\Embeddable\PrivateCommentEmbeddable", columnPrefix="privateComment_")
|
||||
@@ -150,58 +171,78 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
||||
|
||||
/**
|
||||
* @ORM\ManyToMany(targetEntity="Chill\ActivityBundle\Entity\ActivityReason")
|
||||
*
|
||||
* @Groups({"docgen:read"})
|
||||
*
|
||||
* @var Collection<ActivityReason>
|
||||
*/
|
||||
private Collection $reasons;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Scope")
|
||||
*
|
||||
* @Groups({"docgen:read"})
|
||||
*/
|
||||
private ?Scope $scope = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", options={"default": ""})
|
||||
*
|
||||
* @Groups({"docgen:read"})
|
||||
*/
|
||||
private string $sentReceived = '';
|
||||
|
||||
/**
|
||||
* @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\SocialWork\SocialAction")
|
||||
*
|
||||
* @ORM\JoinTable(name="chill_activity_activity_chill_person_socialaction")
|
||||
*
|
||||
* @Groups({"read", "docgen:read"})
|
||||
*
|
||||
* @var Collection<SocialAction>
|
||||
*/
|
||||
private Collection $socialActions;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToMany(targetEntity="Chill\PersonBundle\Entity\SocialWork\SocialIssue")
|
||||
*
|
||||
* @ORM\JoinTable(name="chill_activity_activity_chill_person_socialissue")
|
||||
*
|
||||
* @Groups({"read", "docgen:read"})
|
||||
*
|
||||
* @var Collection<SocialIssue>
|
||||
*/
|
||||
private Collection $socialIssues;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToMany(targetEntity="Chill\ThirdPartyBundle\Entity\ThirdParty")
|
||||
*
|
||||
* @Groups({"read", "docgen:read"})
|
||||
*
|
||||
* @var Collection<ThirdParty>
|
||||
*/
|
||||
private ?Collection $thirdParties = null;
|
||||
private Collection $thirdParties;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="time", nullable=true)
|
||||
*/
|
||||
private ?DateTime $travelTime = null;
|
||||
private ?\DateTime $travelTime = null;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User")
|
||||
*
|
||||
* @Groups({"docgen:read"})
|
||||
*/
|
||||
private ?User $user = null;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToMany(targetEntity="Chill\MainBundle\Entity\User")
|
||||
*
|
||||
* @Groups({"read", "docgen:read"})
|
||||
*
|
||||
* @var Collection<User>
|
||||
*/
|
||||
private ?Collection $users = null;
|
||||
private Collection $users;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
@@ -268,7 +309,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
||||
$this->socialIssues[] = $socialIssue;
|
||||
}
|
||||
|
||||
if ($this->getAccompanyingPeriod() !== null) {
|
||||
if (null !== $this->getAccompanyingPeriod()) {
|
||||
$this->getAccompanyingPeriod()->addSocialIssue($socialIssue);
|
||||
}
|
||||
|
||||
@@ -334,7 +375,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
||||
return $this->comment;
|
||||
}
|
||||
|
||||
public function getDate(): DateTime
|
||||
public function getDate(): \DateTime
|
||||
{
|
||||
return $this->date;
|
||||
}
|
||||
@@ -356,7 +397,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
||||
return (int) round(($this->durationTime->getTimestamp() + $this->durationTime->getOffset()) / 60.0, 0);
|
||||
}
|
||||
|
||||
public function getDurationTime(): ?DateTime
|
||||
public function getDurationTime(): ?\DateTime
|
||||
{
|
||||
return $this->durationTime;
|
||||
}
|
||||
@@ -410,7 +451,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
||||
|
||||
// TODO better semantic with: return $this->persons->filter(...);
|
||||
foreach ($this->persons as $person) {
|
||||
if ($this->accompanyingPeriod->getOpenParticipationContainsPerson($person) === null) {
|
||||
if (null === $this->accompanyingPeriod->getOpenParticipationContainsPerson($person)) {
|
||||
$personsNotAssociated[] = $person;
|
||||
}
|
||||
}
|
||||
@@ -469,7 +510,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
||||
return $this->thirdParties;
|
||||
}
|
||||
|
||||
public function getTravelTime(): ?DateTime
|
||||
public function getTravelTime(): ?\DateTime
|
||||
{
|
||||
return $this->travelTime;
|
||||
}
|
||||
@@ -580,7 +621,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDate(DateTime $date): self
|
||||
public function setDate(\DateTime $date): self
|
||||
{
|
||||
$this->date = $date;
|
||||
|
||||
@@ -594,7 +635,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDurationTime(?DateTime $durationTime): self
|
||||
public function setDurationTime(?\DateTime $durationTime): self
|
||||
{
|
||||
$this->durationTime = $durationTime;
|
||||
|
||||
@@ -664,7 +705,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setTravelTime(DateTime $travelTime): self
|
||||
public function setTravelTime(\DateTime $travelTime): self
|
||||
{
|
||||
$this->travelTime = $travelTime;
|
||||
|
||||
|
@@ -18,7 +18,9 @@ use Symfony\Component\Serializer\Annotation as Serializer;
|
||||
* Class ActivityPresence.
|
||||
*
|
||||
* @ORM\Entity
|
||||
*
|
||||
* @ORM\Table(name="activitytpresence")
|
||||
*
|
||||
* @ORM\HasLifecycleCallbacks
|
||||
*/
|
||||
class ActivityPresence
|
||||
@@ -30,15 +32,20 @@ class ActivityPresence
|
||||
|
||||
/**
|
||||
* @ORM\Id
|
||||
*
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
*
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*
|
||||
* @Serializer\Groups({"docgen:read"})
|
||||
*/
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="json")
|
||||
*
|
||||
* @Serializer\Groups({"docgen:read"})
|
||||
*
|
||||
* @Serializer\Context({"is-translatable": true}, groups={"docgen:read"})
|
||||
*/
|
||||
private array $name = [];
|
||||
|
@@ -17,39 +17,38 @@ use Doctrine\ORM\Mapping as ORM;
|
||||
* Class ActivityReason.
|
||||
*
|
||||
* @ORM\Entity
|
||||
*
|
||||
* @ORM\Table(name="activityreason")
|
||||
*
|
||||
* @ORM\HasLifecycleCallbacks
|
||||
*/
|
||||
class ActivityReason
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $active = true;
|
||||
private bool $active = true;
|
||||
|
||||
/**
|
||||
* @var ActivityReasonCategory
|
||||
* @ORM\ManyToOne(
|
||||
* targetEntity="Chill\ActivityBundle\Entity\ActivityReasonCategory",
|
||||
* inversedBy="reasons")
|
||||
*/
|
||||
private $category;
|
||||
private ?ActivityReasonCategory $category = null;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*
|
||||
* @ORM\Id
|
||||
*
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
*
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
private $id;
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @ORM\Column(type="json")
|
||||
*/
|
||||
private $name;
|
||||
private array $name;
|
||||
|
||||
/**
|
||||
* Get active.
|
||||
@@ -81,27 +80,9 @@ class ActivityReason
|
||||
|
||||
/**
|
||||
* Get name.
|
||||
*
|
||||
* @param mixed|null $locale
|
||||
*
|
||||
* @return array | string
|
||||
*/
|
||||
public function getName($locale = null)
|
||||
public function getName(): array
|
||||
{
|
||||
if ($locale) {
|
||||
if (isset($this->name[$locale])) {
|
||||
return $this->name[$locale];
|
||||
}
|
||||
|
||||
foreach ($this->name as $name) {
|
||||
if (!empty($name)) {
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
|
@@ -12,34 +12,37 @@ declare(strict_types=1);
|
||||
namespace Chill\ActivityBundle\Entity;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* Class ActivityReasonCategory.
|
||||
*
|
||||
* @ORM\Entity
|
||||
*
|
||||
* @ORM\Table(name="activityreasoncategory")
|
||||
*
|
||||
* @ORM\HasLifecycleCallbacks
|
||||
*/
|
||||
class ActivityReasonCategory
|
||||
class ActivityReasonCategory implements \Stringable
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $active = true;
|
||||
private bool $active = true;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*
|
||||
* @ORM\Id
|
||||
*
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
*
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
private $id;
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="json")
|
||||
*/
|
||||
private $name;
|
||||
@@ -47,12 +50,13 @@ class ActivityReasonCategory
|
||||
/**
|
||||
* Array of ActivityReason.
|
||||
*
|
||||
* @var ArrayCollection
|
||||
* @var Collection<ActivityReason>
|
||||
*
|
||||
* @ORM\OneToMany(
|
||||
* targetEntity="Chill\ActivityBundle\Entity\ActivityReason",
|
||||
* mappedBy="category")
|
||||
*/
|
||||
private $reasons;
|
||||
private Collection $reasons;
|
||||
|
||||
/**
|
||||
* ActivityReasonCategory constructor.
|
||||
@@ -62,12 +66,9 @@ class ActivityReasonCategory
|
||||
$this->reasons = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
public function __toString(): string
|
||||
{
|
||||
return 'ActivityReasonCategory(' . $this->getName('x') . ')';
|
||||
return 'ActivityReasonCategory('.$this->getName('x').')';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,11 +122,9 @@ class ActivityReasonCategory
|
||||
* as unactive, all the reason have this entity as category is also
|
||||
* set as unactive.
|
||||
*
|
||||
* @param bool $active
|
||||
*
|
||||
* @return ActivityReasonCategory
|
||||
*/
|
||||
public function setActive($active)
|
||||
public function setActive(bool $active)
|
||||
{
|
||||
if ($this->active !== $active && !$active) {
|
||||
foreach ($this->reasons as $reason) {
|
||||
|
@@ -12,7 +12,6 @@ declare(strict_types=1);
|
||||
namespace Chill\ActivityBundle\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use InvalidArgumentException;
|
||||
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
@@ -22,31 +21,36 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
* Class ActivityType.
|
||||
*
|
||||
* @ORM\Entity
|
||||
*
|
||||
* @ORM\Table(name="activitytype")
|
||||
*
|
||||
* @ORM\HasLifecycleCallbacks
|
||||
*/
|
||||
class ActivityType
|
||||
{
|
||||
public const FIELD_INVISIBLE = 0;
|
||||
final public const FIELD_INVISIBLE = 0;
|
||||
|
||||
public const FIELD_OPTIONAL = 1;
|
||||
final public const FIELD_OPTIONAL = 1;
|
||||
|
||||
public const FIELD_REQUIRED = 2;
|
||||
final public const FIELD_REQUIRED = 2;
|
||||
|
||||
/**
|
||||
* @deprecated not in use
|
||||
*
|
||||
* @ORM\Column(type="string", nullable=false, options={"default": ""})
|
||||
*/
|
||||
private string $accompanyingPeriodLabel = '';
|
||||
|
||||
/**
|
||||
* @deprecated not in use
|
||||
*
|
||||
* @ORM\Column(type="smallint", nullable=false, options={"default": 1})
|
||||
*/
|
||||
private int $accompanyingPeriodVisible = self::FIELD_INVISIBLE;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="boolean")
|
||||
*
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private bool $active = true;
|
||||
@@ -118,8 +122,11 @@ class ActivityType
|
||||
|
||||
/**
|
||||
* @ORM\Id
|
||||
*
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
*
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*
|
||||
* @Groups({"docgen:read"})
|
||||
*/
|
||||
private ?int $id = null;
|
||||
@@ -136,7 +143,9 @@ class ActivityType
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="json")
|
||||
*
|
||||
* @Groups({"read", "docgen:read"})
|
||||
*
|
||||
* @Serializer\Context({"is-translatable": true}, groups={"docgen:read"})
|
||||
*/
|
||||
private array $name = [];
|
||||
@@ -158,6 +167,7 @@ class ActivityType
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="smallint", nullable=false, options={"default": 1})
|
||||
*
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private int $personsVisible = self::FIELD_OPTIONAL;
|
||||
@@ -238,6 +248,7 @@ class ActivityType
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="smallint", nullable=false, options={"default": 1})
|
||||
*
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private int $thirdPartiesVisible = self::FIELD_INVISIBLE;
|
||||
@@ -264,6 +275,7 @@ class ActivityType
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="smallint", nullable=false, options={"default": 1})
|
||||
*
|
||||
* @Groups({"read"})
|
||||
*/
|
||||
private int $usersVisible = self::FIELD_OPTIONAL;
|
||||
@@ -275,10 +287,8 @@ class ActivityType
|
||||
|
||||
/**
|
||||
* @Assert\Callback
|
||||
*
|
||||
* @param mixed $payload
|
||||
*/
|
||||
public function checkSocialActionsVisibility(ExecutionContextInterface $context, $payload)
|
||||
public function checkSocialActionsVisibility(ExecutionContextInterface $context, mixed $payload)
|
||||
{
|
||||
if ($this->socialIssuesVisible !== $this->socialActionsVisible) {
|
||||
if (!(2 === $this->socialIssuesVisible && 1 === $this->socialActionsVisible)) {
|
||||
@@ -374,13 +384,13 @@ class ActivityType
|
||||
|
||||
public function getLabel(string $field): ?string
|
||||
{
|
||||
$property = $field . 'Label';
|
||||
$property = $field.'Label';
|
||||
|
||||
if (!property_exists($this, $property)) {
|
||||
throw new InvalidArgumentException('Field "' . $field . '" not found');
|
||||
throw new \InvalidArgumentException('Field "'.$field.'" not found');
|
||||
}
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
/* @phpstan-ignore-next-line */
|
||||
return $this->{$property};
|
||||
}
|
||||
|
||||
@@ -533,25 +543,25 @@ class ActivityType
|
||||
|
||||
public function isRequired(string $field): bool
|
||||
{
|
||||
$property = $field . 'Visible';
|
||||
$property = $field.'Visible';
|
||||
|
||||
if (!property_exists($this, $property)) {
|
||||
throw new InvalidArgumentException('Field "' . $field . '" not found');
|
||||
throw new \InvalidArgumentException('Field "'.$field.'" not found');
|
||||
}
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
/* @phpstan-ignore-next-line */
|
||||
return self::FIELD_REQUIRED === $this->{$property};
|
||||
}
|
||||
|
||||
public function isVisible(string $field): bool
|
||||
{
|
||||
$property = $field . 'Visible';
|
||||
$property = $field.'Visible';
|
||||
|
||||
if (!property_exists($this, $property)) {
|
||||
throw new InvalidArgumentException('Field "' . $field . '" not found');
|
||||
throw new \InvalidArgumentException('Field "'.$field.'" not found');
|
||||
}
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
/* @phpstan-ignore-next-line */
|
||||
return self::FIELD_INVISIBLE !== $this->{$property};
|
||||
}
|
||||
|
||||
|
@@ -15,7 +15,9 @@ use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
*
|
||||
* @ORM\Table(name="activitytypecategory")
|
||||
*
|
||||
* @ORM\HasLifecycleCallbacks
|
||||
*/
|
||||
class ActivityTypeCategory
|
||||
@@ -27,7 +29,9 @@ class ActivityTypeCategory
|
||||
|
||||
/**
|
||||
* @ORM\Id
|
||||
*
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
*
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
private ?int $id = null;
|
||||
|
@@ -15,22 +15,11 @@ use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
|
||||
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
use function in_array;
|
||||
|
||||
class ActivityEntityListener
|
||||
{
|
||||
private EntityManagerInterface $em;
|
||||
|
||||
private AccompanyingPeriodWorkRepository $workRepository;
|
||||
|
||||
public function __construct(EntityManagerInterface $em, AccompanyingPeriodWorkRepository $workRepository)
|
||||
{
|
||||
$this->em = $em;
|
||||
$this->workRepository = $workRepository;
|
||||
}
|
||||
public function __construct(private readonly EntityManagerInterface $em, private readonly AccompanyingPeriodWorkRepository $workRepository) {}
|
||||
|
||||
public function persistActionToCourse(Activity $activity)
|
||||
{
|
||||
@@ -39,11 +28,11 @@ class ActivityEntityListener
|
||||
|
||||
$accompanyingCourseWorks = $this->workRepository->findByAccompanyingPeriod($period);
|
||||
$periodActions = [];
|
||||
$now = new DateTimeImmutable();
|
||||
$now = new \DateTimeImmutable();
|
||||
|
||||
foreach ($accompanyingCourseWorks as $key => $work) {
|
||||
// take only the actions which are still opened
|
||||
if ($work->getEndDate() === null || $work->getEndDate() > ($activity->getDate() ?? $now)) {
|
||||
if (null === $work->getEndDate() || $work->getEndDate() > ($activity->getDate() ?? $now)) {
|
||||
$periodActions[$key] = spl_object_hash($work->getSocialAction());
|
||||
}
|
||||
}
|
||||
@@ -52,14 +41,14 @@ class ActivityEntityListener
|
||||
$associatedThirdparties = $activity->getThirdParties();
|
||||
|
||||
foreach ($activity->getSocialActions() as $action) {
|
||||
if (in_array(spl_object_hash($action), $periodActions, true)) {
|
||||
if (\in_array(spl_object_hash($action), $periodActions, true)) {
|
||||
continue;
|
||||
}
|
||||
$newAction = new AccompanyingPeriodWork();
|
||||
$newAction->setSocialAction($action);
|
||||
$period->addWork($newAction);
|
||||
|
||||
$date = DateTimeImmutable::createFromMutable($activity->getDate());
|
||||
$date = \DateTimeImmutable::createFromMutable($activity->getDate());
|
||||
$newAction->setStartDate($date);
|
||||
|
||||
foreach ($associatedPersons as $person) {
|
||||
|
@@ -27,7 +27,7 @@ class ByActivityNumberAggregator implements AggregatorInterface
|
||||
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')
|
||||
->addSelect('(SELECT COUNT(activity.id) FROM '.Activity::class.' activity WHERE activity.accompanyingPeriod = acp) AS activity_by_number_aggregator')
|
||||
->addGroupBy('activity_by_number_aggregator');
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ class ByActivityNumberAggregator implements AggregatorInterface
|
||||
{
|
||||
// No form needed
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
|
@@ -0,0 +1,122 @@
|
||||
<?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\ActivityBundle\Entity\ActivityType;
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Form\Type\PickRollingDateType;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
final readonly class ByActivityTypeAggregator implements AggregatorInterface
|
||||
{
|
||||
private const PREFIX = 'acp_by_activity_type_agg';
|
||||
|
||||
public function __construct(
|
||||
private RollingDateConverterInterface $rollingDateConverter,
|
||||
private ActivityTypeRepositoryInterface $activityTypeRepository,
|
||||
private TranslatableStringHelperInterface $translatableStringHelper,
|
||||
) {}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder
|
||||
->add('after_date', PickRollingDateType::class, [
|
||||
'required' => false,
|
||||
'label' => 'export.aggregator.acp.by_activity_type.after_date',
|
||||
])
|
||||
->add('before_date', PickRollingDateType::class, [
|
||||
'required' => false,
|
||||
'label' => 'export.aggregator.acp.by_activity_type.before_date',
|
||||
]);
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [
|
||||
'before_date' => null,
|
||||
'after_date' => null,
|
||||
];
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, mixed $data)
|
||||
{
|
||||
return function (null|int|string $value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'export.aggregator.acp.by_activity_type.activity_type';
|
||||
}
|
||||
|
||||
if ('' === $value || null === $value || null === $activityType = $this->activityTypeRepository->find($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->translatableStringHelper->localize($activityType->getName());
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
{
|
||||
return [self::PREFIX.'_actype_id'];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return 'export.aggregator.acp.by_activity_type.title';
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$p = self::PREFIX;
|
||||
|
||||
// we make a left join, with acp having at least one activity of the given type
|
||||
$exists = 'EXISTS (SELECT 1 FROM '.Activity::class." {$p}_activity WHERE {$p}_activity.accompanyingPeriod = acp AND {$p}_activity.activityType = {$p}_activity_type";
|
||||
|
||||
if (null !== $data['after_date']) {
|
||||
$exists .= " AND {$p}_activity.date > :{$p}_after_date";
|
||||
$qb->setParameter("{$p}_after_date", $this->rollingDateConverter->convert($data['after_date']));
|
||||
}
|
||||
|
||||
if (null !== $data['before_date']) {
|
||||
$exists .= " AND {$p}_activity.date < :{$p}_before_date";
|
||||
$qb->setParameter("{$p}_before_date", $this->rollingDateConverter->convert($data['before_date']));
|
||||
}
|
||||
|
||||
$exists .= ')';
|
||||
|
||||
$qb->leftJoin(
|
||||
ActivityType::class,
|
||||
"{$p}_activity_type",
|
||||
Join::WITH,
|
||||
$exists
|
||||
);
|
||||
|
||||
$qb
|
||||
->addSelect("{$p}_activity_type.id AS {$p}_actype_id")
|
||||
->addGroupBy("{$p}_actype_id");
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return Declarations::ACP_TYPE;
|
||||
}
|
||||
}
|
@@ -17,21 +17,10 @@ use Chill\PersonBundle\Repository\SocialWork\SocialActionRepository;
|
||||
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class BySocialActionAggregator implements AggregatorInterface
|
||||
{
|
||||
private SocialActionRender $actionRender;
|
||||
|
||||
private SocialActionRepository $actionRepository;
|
||||
|
||||
public function __construct(
|
||||
SocialActionRender $actionRender,
|
||||
SocialActionRepository $actionRepository
|
||||
) {
|
||||
$this->actionRender = $actionRender;
|
||||
$this->actionRepository = $actionRepository;
|
||||
}
|
||||
public function __construct(private readonly SocialActionRender $actionRender, private readonly SocialActionRepository $actionRepository) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -40,7 +29,7 @@ class BySocialActionAggregator implements AggregatorInterface
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('actsocialaction', $qb->getAllAliases(), true)) {
|
||||
if (!\in_array('actsocialaction', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('activity.socialActions', 'actsocialaction');
|
||||
}
|
||||
|
||||
@@ -57,6 +46,7 @@ class BySocialActionAggregator implements AggregatorInterface
|
||||
{
|
||||
// no form
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
|
@@ -17,21 +17,10 @@ use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
|
||||
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class BySocialIssueAggregator implements AggregatorInterface
|
||||
{
|
||||
private SocialIssueRender $issueRender;
|
||||
|
||||
private SocialIssueRepository $issueRepository;
|
||||
|
||||
public function __construct(
|
||||
SocialIssueRepository $issueRepository,
|
||||
SocialIssueRender $issueRender
|
||||
) {
|
||||
$this->issueRepository = $issueRepository;
|
||||
$this->issueRender = $issueRender;
|
||||
}
|
||||
public function __construct(private readonly SocialIssueRepository $issueRepository, private readonly SocialIssueRender $issueRender) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -40,7 +29,7 @@ class BySocialIssueAggregator implements AggregatorInterface
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('actsocialissue', $qb->getAllAliases(), true)) {
|
||||
if (!\in_array('actsocialissue', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('activity.socialIssues', 'actsocialissue');
|
||||
}
|
||||
|
||||
@@ -57,6 +46,7 @@ class BySocialIssueAggregator implements AggregatorInterface
|
||||
{
|
||||
// no form
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
|
@@ -12,14 +12,9 @@ declare(strict_types=1);
|
||||
namespace Chill\ActivityBundle\Export\Aggregator;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Repository\LocationRepository;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Closure;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
final readonly class ActivityLocationAggregator implements AggregatorInterface
|
||||
{
|
||||
@@ -32,7 +27,7 @@ final readonly class ActivityLocationAggregator implements AggregatorInterface
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('actloc', $qb->getAllAliases(), true)) {
|
||||
if (!\in_array('actloc', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('activity.location', 'actloc');
|
||||
}
|
||||
$qb->addSelect(sprintf('actloc.name AS %s', self::KEY));
|
||||
@@ -48,12 +43,13 @@ final readonly class ActivityLocationAggregator implements AggregatorInterface
|
||||
{
|
||||
// no form required for this aggregator
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data): Closure
|
||||
public function getLabels($key, array $values, $data): \Closure
|
||||
{
|
||||
return function ($value): string {
|
||||
if ('_header' === $value) {
|
||||
|
@@ -15,26 +15,14 @@ use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Closure;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class ActivityTypeAggregator implements AggregatorInterface
|
||||
{
|
||||
public const KEY = 'activity_type_aggregator';
|
||||
final public const KEY = 'activity_type_aggregator';
|
||||
|
||||
protected ActivityTypeRepositoryInterface $activityTypeRepository;
|
||||
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
ActivityTypeRepositoryInterface $activityTypeRepository,
|
||||
TranslatableStringHelperInterface $translatableStringHelper
|
||||
) {
|
||||
$this->activityTypeRepository = $activityTypeRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
public function __construct(protected ActivityTypeRepositoryInterface $activityTypeRepository, protected TranslatableStringHelperInterface $translatableStringHelper) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -43,7 +31,7 @@ class ActivityTypeAggregator implements AggregatorInterface
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('acttype', $qb->getAllAliases(), true)) {
|
||||
if (!\in_array('acttype', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('activity.activityType', 'acttype');
|
||||
}
|
||||
|
||||
@@ -60,12 +48,13 @@ class ActivityTypeAggregator implements AggregatorInterface
|
||||
{
|
||||
// no form required for this aggregator
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data): Closure
|
||||
public function getLabels($key, array $values, $data): \Closure
|
||||
{
|
||||
// for performance reason, we load data from db only once
|
||||
$this->activityTypeRepository->findBy(['id' => $values]);
|
||||
|
@@ -15,25 +15,14 @@ use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Repository\UserRepository;
|
||||
use Chill\MainBundle\Templating\Entity\UserRender;
|
||||
use Closure;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class ActivityUserAggregator implements AggregatorInterface
|
||||
{
|
||||
public const KEY = 'activity_user_id';
|
||||
final public const KEY = 'activity_user_id';
|
||||
|
||||
private UserRender $userRender;
|
||||
|
||||
private UserRepository $userRepository;
|
||||
|
||||
public function __construct(
|
||||
UserRepository $userRepository,
|
||||
UserRender $userRender
|
||||
) {
|
||||
$this->userRepository = $userRepository;
|
||||
$this->userRender = $userRender;
|
||||
}
|
||||
public function __construct(private readonly UserRepository $userRepository, private readonly UserRender $userRender) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -58,12 +47,13 @@ class ActivityUserAggregator implements AggregatorInterface
|
||||
{
|
||||
// nothing to add
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getLabels($key, $values, $data): Closure
|
||||
public function getLabels($key, $values, $data): \Closure
|
||||
{
|
||||
return function ($value) {
|
||||
if ('_header' === $value) {
|
||||
|
@@ -17,19 +17,10 @@ use Chill\MainBundle\Repository\UserRepositoryInterface;
|
||||
use Chill\MainBundle\Templating\Entity\UserRender;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class ActivityUsersAggregator implements AggregatorInterface
|
||||
{
|
||||
private UserRender $userRender;
|
||||
|
||||
private UserRepositoryInterface $userRepository;
|
||||
|
||||
public function __construct(UserRepositoryInterface $userRepository, UserRender $userRender)
|
||||
{
|
||||
$this->userRepository = $userRepository;
|
||||
$this->userRender = $userRender;
|
||||
}
|
||||
public function __construct(private readonly UserRepositoryInterface $userRepository, private readonly UserRender $userRender) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -38,7 +29,7 @@ class ActivityUsersAggregator implements AggregatorInterface
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('actusers', $qb->getAllAliases(), true)) {
|
||||
if (!\in_array('actusers', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('activity.users', 'actusers');
|
||||
}
|
||||
|
||||
@@ -56,6 +47,7 @@ class ActivityUsersAggregator implements AggregatorInterface
|
||||
{
|
||||
// nothing to add on the form
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
|
@@ -12,23 +12,22 @@ declare(strict_types=1);
|
||||
namespace Chill\ActivityBundle\Export\Aggregator;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Entity\User\UserJobHistory;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Repository\UserJobRepositoryInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class ActivityUsersJobAggregator implements \Chill\MainBundle\Export\AggregatorInterface
|
||||
class ActivityUsersJobAggregator implements AggregatorInterface
|
||||
{
|
||||
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||
private const PREFIX = 'act_agg_user_job';
|
||||
|
||||
private UserJobRepositoryInterface $userJobRepository;
|
||||
|
||||
public function __construct(UserJobRepositoryInterface $userJobRepository, TranslatableStringHelperInterface $translatableStringHelper)
|
||||
{
|
||||
$this->userJobRepository = $userJobRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
public function __construct(
|
||||
private readonly UserJobRepositoryInterface $userJobRepository,
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -37,24 +36,37 @@ class ActivityUsersJobAggregator implements \Chill\MainBundle\Export\AggregatorI
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('actusers', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('activity.users', 'actusers');
|
||||
}
|
||||
$p = self::PREFIX;
|
||||
|
||||
$qb
|
||||
->addSelect('IDENTITY(actusers.userJob) AS activity_users_job_aggregator')
|
||||
->addGroupBy('activity_users_job_aggregator');
|
||||
->leftJoin('activity.users', "{$p}_user")
|
||||
->leftJoin(
|
||||
UserJobHistory::class,
|
||||
"{$p}_history",
|
||||
Expr\Join::WITH,
|
||||
$qb->expr()->eq("{$p}_history.user", "{$p}_user")
|
||||
)
|
||||
// job_at based on activity.date
|
||||
->andWhere(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte("{$p}_history.startDate", 'activity.date'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull("{$p}_history.endDate"),
|
||||
$qb->expr()->gt("{$p}_history.endDate", 'activity.date')
|
||||
)
|
||||
)
|
||||
)
|
||||
->addSelect("IDENTITY({$p}_history.job) AS {$p}_select")
|
||||
->addGroupBy("{$p}_select");
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::ACTIVITY;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
// nothing to add in the form
|
||||
}
|
||||
public function buildForm(FormBuilderInterface $builder) {}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
@@ -81,11 +93,11 @@ class ActivityUsersJobAggregator implements \Chill\MainBundle\Export\AggregatorI
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['activity_users_job_aggregator'];
|
||||
return [self::PREFIX.'_select'];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Aggregate by users job';
|
||||
return 'export.aggregator.activity.by_user_job.Aggregate by users job';
|
||||
}
|
||||
}
|
||||
|
@@ -12,23 +12,22 @@ declare(strict_types=1);
|
||||
namespace Chill\ActivityBundle\Export\Aggregator;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Entity\User\UserScopeHistory;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Repository\ScopeRepositoryInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class ActivityUsersScopeAggregator implements \Chill\MainBundle\Export\AggregatorInterface
|
||||
class ActivityUsersScopeAggregator implements AggregatorInterface
|
||||
{
|
||||
private ScopeRepositoryInterface $scopeRepository;
|
||||
private const PREFIX = 'act_agg_user_scope';
|
||||
|
||||
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(ScopeRepositoryInterface $scopeRepository, TranslatableStringHelperInterface $translatableStringHelper)
|
||||
{
|
||||
$this->scopeRepository = $scopeRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
public function __construct(
|
||||
private readonly ScopeRepositoryInterface $scopeRepository,
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -37,24 +36,37 @@ class ActivityUsersScopeAggregator implements \Chill\MainBundle\Export\Aggregato
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('actusers', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('activity.users', 'actusers');
|
||||
}
|
||||
$p = self::PREFIX;
|
||||
|
||||
$qb
|
||||
->addSelect('IDENTITY(actusers.mainScope) AS activity_users_main_scope_aggregator')
|
||||
->addGroupBy('activity_users_main_scope_aggregator');
|
||||
->leftJoin('activity.users', "{$p}_user")
|
||||
->leftJoin(
|
||||
UserScopeHistory::class,
|
||||
"{$p}_history",
|
||||
Expr\Join::WITH,
|
||||
$qb->expr()->eq("{$p}_history.user", "{$p}_user")
|
||||
)
|
||||
// scope_at based on activity.date
|
||||
->andWhere(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte("{$p}_history.startDate", 'activity.date'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull("{$p}_history.endDate"),
|
||||
$qb->expr()->gt("{$p}_history.endDate", 'activity.date')
|
||||
)
|
||||
)
|
||||
)
|
||||
->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select")
|
||||
->addGroupBy("{$p}_select");
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::ACTIVITY;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
// nothing to add in the form
|
||||
}
|
||||
public function buildForm(FormBuilderInterface $builder) {}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
@@ -81,11 +93,11 @@ class ActivityUsersScopeAggregator implements \Chill\MainBundle\Export\Aggregato
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['activity_users_main_scope_aggregator'];
|
||||
return [self::PREFIX.'_select'];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Aggregate by users scope';
|
||||
return 'export.aggregator.activity.by_user_scope.Aggregate by users scope';
|
||||
}
|
||||
}
|
||||
|
@@ -20,17 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class ByCreatorAggregator implements AggregatorInterface
|
||||
{
|
||||
private UserRender $userRender;
|
||||
|
||||
private UserRepositoryInterface $userRepository;
|
||||
|
||||
public function __construct(
|
||||
UserRepositoryInterface $userRepository,
|
||||
UserRender $userRender
|
||||
) {
|
||||
$this->userRepository = $userRepository;
|
||||
$this->userRender = $userRender;
|
||||
}
|
||||
public function __construct(private readonly UserRepositoryInterface $userRepository, private readonly UserRender $userRender) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -52,6 +42,7 @@ class ByCreatorAggregator implements AggregatorInterface
|
||||
{
|
||||
// no form
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
|
@@ -17,21 +17,10 @@ use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository;
|
||||
use Chill\ThirdPartyBundle\Templating\Entity\ThirdPartyRender;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class ByThirdpartyAggregator implements AggregatorInterface
|
||||
{
|
||||
private ThirdPartyRender $thirdPartyRender;
|
||||
|
||||
private ThirdPartyRepository $thirdPartyRepository;
|
||||
|
||||
public function __construct(
|
||||
ThirdPartyRepository $thirdPartyRepository,
|
||||
ThirdPartyRender $thirdPartyRender
|
||||
) {
|
||||
$this->thirdPartyRepository = $thirdPartyRepository;
|
||||
$this->thirdPartyRender = $thirdPartyRender;
|
||||
}
|
||||
public function __construct(private readonly ThirdPartyRepository $thirdPartyRepository, private readonly ThirdPartyRender $thirdPartyRender) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -40,7 +29,7 @@ class ByThirdpartyAggregator implements AggregatorInterface
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('acttparty', $qb->getAllAliases(), true)) {
|
||||
if (!\in_array('acttparty', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('activity.thirdParties', 'acttparty');
|
||||
}
|
||||
|
||||
@@ -57,6 +46,7 @@ class ByThirdpartyAggregator implements AggregatorInterface
|
||||
{
|
||||
// no form
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
|
@@ -12,26 +12,22 @@ declare(strict_types=1);
|
||||
namespace Chill\ActivityBundle\Export\Aggregator;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Entity\User\UserScopeHistory;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Repository\ScopeRepository;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class CreatorScopeAggregator implements AggregatorInterface
|
||||
{
|
||||
private ScopeRepository $scopeRepository;
|
||||
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
private const PREFIX = 'acp_agg_creator_scope';
|
||||
|
||||
public function __construct(
|
||||
ScopeRepository $scopeRepository,
|
||||
TranslatableStringHelper $translatableStringHelper
|
||||
) {
|
||||
$this->scopeRepository = $scopeRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
private readonly ScopeRepository $scopeRepository,
|
||||
private readonly TranslatableStringHelper $translatableStringHelper
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -40,12 +36,28 @@ class CreatorScopeAggregator implements AggregatorInterface
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('actcreator', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('activity.createdBy', 'actcreator');
|
||||
}
|
||||
$p = self::PREFIX;
|
||||
|
||||
$qb->addSelect('IDENTITY(actcreator.mainScope) AS creatorscope_aggregator');
|
||||
$qb->addGroupBy('creatorscope_aggregator');
|
||||
$qb
|
||||
->leftJoin('activity.createdBy', "{$p}_user")
|
||||
->leftJoin(
|
||||
UserScopeHistory::class,
|
||||
"{$p}_history",
|
||||
Join::WITH,
|
||||
$qb->expr()->eq("{$p}_history.user", "{$p}_user")
|
||||
)
|
||||
// scope_at based on activity.date
|
||||
->andWhere(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte("{$p}_history.startDate", 'activity.date'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull("{$p}_history.endDate"),
|
||||
$qb->expr()->gt("{$p}_history.endDate", 'activity.date')
|
||||
)
|
||||
)
|
||||
)
|
||||
->addSelect("IDENTITY({$p}_history.scope) AS {$p}_select")
|
||||
->addGroupBy("{$p}_select");
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@@ -53,10 +65,8 @@ class CreatorScopeAggregator implements AggregatorInterface
|
||||
return Declarations::ACTIVITY;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
// no form
|
||||
}
|
||||
public function buildForm(FormBuilderInterface $builder) {}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
@@ -83,11 +93,11 @@ class CreatorScopeAggregator implements AggregatorInterface
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['creatorscope_aggregator'];
|
||||
return [self::PREFIX.'_select'];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Group activity by creator scope';
|
||||
return 'export.aggregator.activity.by_creator_scope.Group activity by creator scope';
|
||||
}
|
||||
}
|
||||
|
@@ -14,10 +14,8 @@ namespace Chill\ActivityBundle\Export\Aggregator;
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class DateAggregator implements AggregatorInterface
|
||||
{
|
||||
@@ -56,7 +54,7 @@ class DateAggregator implements AggregatorInterface
|
||||
break; // order DESC does not works !
|
||||
|
||||
default:
|
||||
throw new RuntimeException(sprintf("The frequency data '%s' is invalid.", $data['frequency']));
|
||||
throw new \RuntimeException(sprintf("The frequency data '%s' is invalid.", $data['frequency']));
|
||||
}
|
||||
|
||||
$qb->addSelect(sprintf("TO_CHAR(activity.date, '%s') AS date_aggregator", $fmt));
|
||||
@@ -75,9 +73,9 @@ class DateAggregator implements AggregatorInterface
|
||||
'choices' => self::CHOICES,
|
||||
'multiple' => false,
|
||||
'expanded' => true,
|
||||
'empty_data' => self::DEFAULT_CHOICE,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return ['frequency' => self::DEFAULT_CHOICE];
|
||||
@@ -87,24 +85,16 @@ class DateAggregator implements AggregatorInterface
|
||||
{
|
||||
return static function ($value) use ($data): string {
|
||||
if ('_header' === $value) {
|
||||
return 'by ' . $data['frequency'];
|
||||
return 'by '.$data['frequency'];
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
switch ($data['frequency']) {
|
||||
case 'month':
|
||||
case 'week':
|
||||
//return $this->translator->trans('for week') .' '. $value ;
|
||||
|
||||
case 'year':
|
||||
//return $this->translator->trans('in year') .' '. $value ;
|
||||
|
||||
default:
|
||||
return $value;
|
||||
}
|
||||
return match ($data['frequency']) {
|
||||
default => $value,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,103 @@
|
||||
<?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\Entity\User\UserJobHistory;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Repository\ScopeRepository;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class JobScopeAggregator implements AggregatorInterface
|
||||
{
|
||||
private const PREFIX = 'acp_agg_creator_job';
|
||||
|
||||
public function __construct(
|
||||
private readonly ScopeRepository $scopeRepository,
|
||||
private readonly TranslatableStringHelper $translatableStringHelper
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$p = self::PREFIX;
|
||||
|
||||
$qb
|
||||
->leftJoin('activity.createdBy', "{$p}_user")
|
||||
->leftJoin(
|
||||
UserJobHistory::class,
|
||||
"{$p}_history",
|
||||
Join::WITH,
|
||||
$qb->expr()->eq("{$p}_history.user", "{$p}_user")
|
||||
)
|
||||
// job_at based on activity.date
|
||||
->andWhere(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte("{$p}_history.startDate", 'activity.date'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull("{$p}_history.endDate"),
|
||||
$qb->expr()->gt("{$p}_history.endDate", 'activity.date')
|
||||
)
|
||||
)
|
||||
)
|
||||
->addSelect("IDENTITY({$p}_history.job) AS {$p}_select")
|
||||
->addGroupBy("{$p}_select");
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::ACTIVITY;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder) {}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return function ($value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'Scope';
|
||||
}
|
||||
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$s = $this->scopeRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
$s->getName()
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return [self::PREFIX.'_select'];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'export.aggregator.activity.by_creator_job.Group activity by creator job';
|
||||
}
|
||||
}
|
@@ -17,21 +17,10 @@ use Chill\MainBundle\Repository\LocationTypeRepository;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class LocationTypeAggregator implements AggregatorInterface
|
||||
{
|
||||
private LocationTypeRepository $locationTypeRepository;
|
||||
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
LocationTypeRepository $locationTypeRepository,
|
||||
TranslatableStringHelper $translatableStringHelper
|
||||
) {
|
||||
$this->locationTypeRepository = $locationTypeRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
public function __construct(private readonly LocationTypeRepository $locationTypeRepository, private readonly TranslatableStringHelper $translatableStringHelper) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -40,7 +29,7 @@ class LocationTypeAggregator implements AggregatorInterface
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('actloc', $qb->getAllAliases(), true)) {
|
||||
if (!\in_array('actloc', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('activity.location', 'actloc');
|
||||
}
|
||||
|
||||
@@ -57,6 +46,7 @@ class LocationTypeAggregator implements AggregatorInterface
|
||||
{
|
||||
// no form
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
|
@@ -17,34 +17,15 @@ use Chill\ActivityBundle\Repository\ActivityReasonRepository;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
use function count;
|
||||
use function in_array;
|
||||
|
||||
class ActivityReasonAggregator implements AggregatorInterface, ExportElementValidatedInterface
|
||||
{
|
||||
protected ActivityReasonCategoryRepository $activityReasonCategoryRepository;
|
||||
|
||||
protected ActivityReasonRepository $activityReasonRepository;
|
||||
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
ActivityReasonCategoryRepository $activityReasonCategoryRepository,
|
||||
ActivityReasonRepository $activityReasonRepository,
|
||||
TranslatableStringHelper $translatableStringHelper
|
||||
) {
|
||||
$this->activityReasonCategoryRepository = $activityReasonCategoryRepository;
|
||||
$this->activityReasonRepository = $activityReasonRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
public function __construct(protected ActivityReasonCategoryRepository $activityReasonCategoryRepository, protected ActivityReasonRepository $activityReasonRepository, protected TranslatableStringHelper $translatableStringHelper) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -61,20 +42,20 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
|
||||
$elem = 'actreasoncat.id';
|
||||
$alias = 'activity_categories_id';
|
||||
} else {
|
||||
throw new RuntimeException('The data provided are not recognized.');
|
||||
throw new \RuntimeException('The data provided are not recognized.');
|
||||
}
|
||||
|
||||
$qb->addSelect($elem . ' as ' . $alias);
|
||||
$qb->addSelect($elem.' as '.$alias);
|
||||
|
||||
// make a jointure only if needed
|
||||
if (!in_array('actreasons', $qb->getAllAliases(), true)) {
|
||||
if (!\in_array('actreasons', $qb->getAllAliases(), true)) {
|
||||
$qb->innerJoin('activity.reasons', 'actreasons');
|
||||
}
|
||||
|
||||
// join category if necessary
|
||||
if ('activity_categories_id' === $alias) {
|
||||
// add join only if needed
|
||||
if (!in_array('actreasoncat', $qb->getAllAliases(), true)) {
|
||||
if (!\in_array('actreasoncat', $qb->getAllAliases(), true)) {
|
||||
$qb->join('actreasons.category', 'actreasoncat');
|
||||
}
|
||||
}
|
||||
@@ -82,7 +63,7 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
|
||||
// add the "group by" part
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (count($groupBy) > 0) {
|
||||
if (\count($groupBy) > 0) {
|
||||
$qb->addGroupBy($alias);
|
||||
} else {
|
||||
$qb->groupBy($alias);
|
||||
@@ -110,6 +91,7 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
@@ -117,21 +99,11 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
// for performance reason, we load data from db only once
|
||||
switch ($data['level']) {
|
||||
case 'reasons':
|
||||
$this->activityReasonRepository->findBy(['id' => $values]);
|
||||
|
||||
break;
|
||||
|
||||
case 'categories':
|
||||
$this->activityReasonCategoryRepository->findBy(['id' => $values]);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new RuntimeException(sprintf("The level data '%s' is invalid.", $data['level']));
|
||||
}
|
||||
match ($data['level']) {
|
||||
'reasons' => $this->activityReasonRepository->findBy(['id' => $values]),
|
||||
'categories' => $this->activityReasonCategoryRepository->findBy(['id' => $values]),
|
||||
default => throw new \RuntimeException(sprintf("The level data '%s' is invalid.", $data['level'])),
|
||||
};
|
||||
|
||||
return function ($value) use ($data) {
|
||||
if ('_header' === $value) {
|
||||
@@ -171,7 +143,7 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
|
||||
return ['activity_categories_id'];
|
||||
}
|
||||
|
||||
throw new RuntimeException('The data provided are not recognised.');
|
||||
throw new \RuntimeException('The data provided are not recognised.');
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
|
@@ -0,0 +1,78 @@
|
||||
<?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\ActivityBundle\Tests\Export\Aggregator\PersonsAggregatorTest;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\PersonBundle\Export\Helper\LabelPersonHelper;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
/**
|
||||
* @see PersonsAggregatorTest
|
||||
*/
|
||||
final readonly class PersonsAggregator implements AggregatorInterface
|
||||
{
|
||||
private const PREFIX = 'act_persons_agg';
|
||||
|
||||
public function __construct(private LabelPersonHelper $labelPersonHelper) {}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
// nothing to add here
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, mixed $data)
|
||||
{
|
||||
if ($key !== self::PREFIX.'_pid') {
|
||||
throw new \UnexpectedValueException('this key should not be handled: '.$key);
|
||||
}
|
||||
|
||||
return $this->labelPersonHelper->getLabel($key, $values, 'export.aggregator.activity.by_persons.Persons');
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
{
|
||||
return [self::PREFIX.'_pid'];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return 'export.aggregator.activity.by_persons.Group activity by persons';
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$p = self::PREFIX;
|
||||
|
||||
$qb
|
||||
->leftJoin('activity.persons', "{$p}_p")
|
||||
->addSelect("{$p}_p.id AS {$p}_pid")
|
||||
->addGroupBy("{$p}_pid");
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return Declarations::ACTIVITY;
|
||||
}
|
||||
}
|
@@ -14,18 +14,12 @@ 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 __construct(private readonly TranslatorInterface $translator) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -47,6 +41,7 @@ class SentReceivedAggregator implements AggregatorInterface
|
||||
{
|
||||
// No form needed
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
@@ -71,7 +66,7 @@ class SentReceivedAggregator implements AggregatorInterface
|
||||
return $this->translator->trans('export.aggregator.activity.by_sent_received.is received');
|
||||
|
||||
default:
|
||||
throw new LogicException(sprintf('The value %s is not valid', $value));
|
||||
throw new \LogicException(sprintf('The value %s is not valid', $value));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@@ -16,9 +16,9 @@ namespace Chill\ActivityBundle\Export;
|
||||
*/
|
||||
abstract class Declarations
|
||||
{
|
||||
public const ACTIVITY = 'activity';
|
||||
final public const ACTIVITY = 'activity';
|
||||
|
||||
public const ACTIVITY_ACP = 'activity_linked_to_acp';
|
||||
final public const ACTIVITY_ACP = 'activity_linked_to_acp';
|
||||
|
||||
public const ACTIVITY_PERSON = 'activity_linked_to_person';
|
||||
final public const ACTIVITY_PERSON = 'activity_linked_to_person';
|
||||
}
|
||||
|
@@ -11,32 +11,33 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\ActivityBundle\Repository\ActivityRepository;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
|
||||
use Chill\MainBundle\Export\ExportInterface;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
|
||||
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use LogicException;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class AvgActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
protected EntityRepository $repository;
|
||||
private readonly bool $filterStatsByCenters;
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em
|
||||
private readonly ActivityRepository $activityRepository,
|
||||
ParameterBagInterface $parameterBag,
|
||||
) {
|
||||
$this->repository = $em->getRepository(Activity::class);
|
||||
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder) {}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
@@ -60,7 +61,7 @@ class AvgActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
if ('export_avg_activity_duration' !== $key) {
|
||||
throw new LogicException("the key {$key} is not used by this export");
|
||||
throw new \LogicException("the key {$key} is not used by this export");
|
||||
}
|
||||
|
||||
return static fn ($value) => '_header' === $value ? 'Average activities linked to an accompanying period duration' : $value;
|
||||
@@ -90,23 +91,27 @@ class AvgActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
$centers = array_map(static fn ($el) => $el['center'], $acl);
|
||||
|
||||
$qb = $this->repository->createQueryBuilder('activity');
|
||||
$qb = $this->activityRepository->createQueryBuilder('activity');
|
||||
|
||||
$qb
|
||||
->join('activity.accompanyingPeriod', 'acp')
|
||||
->select('AVG(activity.durationTime) as export_avg_activity_duration')
|
||||
->andWhere($qb->expr()->isNotNull('activity.durationTime'));
|
||||
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part
|
||||
JOIN ' . PersonCenterHistory::class . ' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||
if ($this->filterStatsByCenters) {
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part
|
||||
JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||
WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
|
||||
'
|
||||
)
|
||||
)
|
||||
)
|
||||
->setParameter('authorized_centers', $centers);
|
||||
->setParameter('authorized_centers', $centers);
|
||||
}
|
||||
|
||||
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@ namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
|
||||
use Chill\MainBundle\Export\ExportInterface;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
@@ -23,23 +24,28 @@ use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use LogicException;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
protected EntityRepository $repository;
|
||||
|
||||
private readonly bool $filterStatsByCenters;
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em
|
||||
EntityManagerInterface $em,
|
||||
ParameterBagInterface $parameterBag,
|
||||
) {
|
||||
$this->repository = $em->getRepository(Activity::class);
|
||||
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
// TODO: Implement buildForm() method.
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
@@ -63,7 +69,7 @@ class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterfac
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
if ('export_avg_activity_visit_duration' !== $key) {
|
||||
throw new LogicException("the key {$key} is not used by this export");
|
||||
throw new \LogicException("the key {$key} is not used by this export");
|
||||
}
|
||||
|
||||
return static fn ($value) => '_header' === $value ? 'Average activities linked to an accompanying period visit duration' : $value;
|
||||
@@ -100,16 +106,20 @@ class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterfac
|
||||
->select('AVG(activity.travelTime) as export_avg_activity_visit_duration')
|
||||
->andWhere($qb->expr()->isNotNull('activity.travelTime'));
|
||||
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part
|
||||
JOIN ' . PersonCenterHistory::class . ' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||
if ($this->filterStatsByCenters) {
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part
|
||||
JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||
WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
|
||||
'
|
||||
)
|
||||
)
|
||||
)
|
||||
->setParameter('authorized_centers', $centers);
|
||||
->setParameter('authorized_centers', $centers);
|
||||
}
|
||||
|
||||
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@ namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
|
||||
use Chill\MainBundle\Export\ExportInterface;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
@@ -23,20 +24,25 @@ use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use LogicException;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class CountActivity implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
protected EntityRepository $repository;
|
||||
|
||||
private readonly bool $filterStatsByCenters;
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em
|
||||
EntityManagerInterface $em,
|
||||
ParameterBagInterface $parameterBag,
|
||||
) {
|
||||
$this->repository = $em->getRepository(Activity::class);
|
||||
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder) {}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
@@ -60,7 +66,7 @@ class CountActivity implements ExportInterface, GroupedExportInterface
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
if ('export_count_activity' !== $key) {
|
||||
throw new LogicException("the key {$key} is not used by this export");
|
||||
throw new \LogicException("the key {$key} is not used by this export");
|
||||
}
|
||||
|
||||
return static fn ($value) => '_header' === $value ? 'Number of activities linked to an accompanying period' : $value;
|
||||
@@ -94,16 +100,20 @@ class CountActivity implements ExportInterface, GroupedExportInterface
|
||||
->createQueryBuilder('activity')
|
||||
->join('activity.accompanyingPeriod', 'acp');
|
||||
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part
|
||||
JOIN ' . PersonCenterHistory::class . ' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||
if ($this->filterStatsByCenters) {
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part
|
||||
JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||
WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
|
||||
'
|
||||
)
|
||||
)
|
||||
)
|
||||
->setParameter('authorized_centers', $centers);
|
||||
->setParameter('authorized_centers', $centers);
|
||||
}
|
||||
|
||||
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
|
||||
|
||||
$qb->select('COUNT(DISTINCT activity.id) as export_count_activity');
|
||||
|
||||
|
@@ -16,35 +16,33 @@ use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\ActivityBundle\Export\Export\ListActivityHelper;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
|
||||
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\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class ListActivity implements ListInterface, GroupedExportInterface
|
||||
{
|
||||
private EntityManagerInterface $entityManager;
|
||||
|
||||
private ListActivityHelper $helper;
|
||||
|
||||
private TranslatableStringExportLabelHelper $translatableStringExportLabelHelper;
|
||||
private readonly bool $filterStatsByCenters;
|
||||
|
||||
public function __construct(
|
||||
ListActivityHelper $helper,
|
||||
EntityManagerInterface $entityManager,
|
||||
TranslatableStringExportLabelHelper $translatableStringExportLabelHelper
|
||||
private readonly ListActivityHelper $helper,
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly TranslatableStringExportLabelHelper $translatableStringExportLabelHelper,
|
||||
ParameterBagInterface $parameterBag,
|
||||
) {
|
||||
$this->helper = $helper;
|
||||
$this->entityManager = $entityManager;
|
||||
$this->translatableStringExportLabelHelper = $translatableStringExportLabelHelper;
|
||||
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$this->helper->buildForm($builder);
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
@@ -57,7 +55,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
|
||||
public function getDescription()
|
||||
{
|
||||
return ListActivityHelper::MSG_KEY . 'List activities linked to an accompanying course';
|
||||
return ListActivityHelper::MSG_KEY.'List activities linked to an accompanying course';
|
||||
}
|
||||
|
||||
public function getGroup(): string
|
||||
@@ -67,22 +65,17 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
|
||||
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 match ($key) {
|
||||
'acpId' => 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);
|
||||
}
|
||||
return $value ?? '';
|
||||
},
|
||||
'scopesNames' => $this->translatableStringExportLabelHelper->getLabelMulti($key, $values, ListActivityHelper::MSG_KEY.'course circles'),
|
||||
default => $this->helper->getLabels($key, $values, $data),
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
@@ -104,7 +97,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return ListActivityHelper::MSG_KEY . 'List activity linked to a course';
|
||||
return ListActivityHelper::MSG_KEY.'List activity linked to a course';
|
||||
}
|
||||
|
||||
public function getType()
|
||||
@@ -124,30 +117,38 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
->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
|
||||
->andWhere('acppart.startDate != acppart.endDate OR acppart.endDate IS NULL');
|
||||
|
||||
if ($this->filterStatsByCenters) {
|
||||
$qb
|
||||
->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)
|
||||
'
|
||||
)
|
||||
)
|
||||
)
|
||||
->setParameter('authorized_centers', $centers);
|
||||
}
|
||||
|
||||
$qb
|
||||
// some grouping are necessary
|
||||
->addGroupBy('acp.id')
|
||||
->addOrderBy('activity.date')
|
||||
->addOrderBy('activity.id')
|
||||
->setParameter('authorized_centers', $centers);
|
||||
->addOrderBy('activity.id');
|
||||
|
||||
$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')
|
||||
->addSelect('(SELECT AGGREGATE(acpScope.name) FROM '.Scope::class.' acpScope WHERE acpScope MEMBER OF acp.scopes) AS scopesNames')
|
||||
->addGroupBy('scopesNames');
|
||||
|
||||
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
|
@@ -14,6 +14,7 @@ namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
|
||||
use Chill\MainBundle\Export\ExportInterface;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
@@ -23,23 +24,27 @@ use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use LogicException;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class SumActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
protected EntityRepository $repository;
|
||||
private readonly bool $filterStatsByCenters;
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em
|
||||
EntityManagerInterface $em,
|
||||
ParameterBagInterface $parameterBag,
|
||||
) {
|
||||
$this->repository = $em->getRepository(Activity::class);
|
||||
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
// TODO: Implement buildForm() method.
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
@@ -63,7 +68,7 @@ class SumActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
if ('export_sum_activity_duration' !== $key) {
|
||||
throw new LogicException("the key {$key} is not used by this export");
|
||||
throw new \LogicException("the key {$key} is not used by this export");
|
||||
}
|
||||
|
||||
return static fn ($value) => '_header' === $value ? 'Sum activities linked to an accompanying period duration' : $value;
|
||||
@@ -100,16 +105,20 @@ class SumActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
$qb->select('SUM(activity.durationTime) as export_sum_activity_duration')
|
||||
->andWhere($qb->expr()->isNotNull('activity.durationTime'));
|
||||
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part
|
||||
JOIN ' . PersonCenterHistory::class . ' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||
if ($this->filterStatsByCenters) {
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part
|
||||
JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||
WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
|
||||
'
|
||||
)
|
||||
)
|
||||
)
|
||||
->setParameter('authorized_centers', $centers);
|
||||
->setParameter('authorized_centers', $centers);
|
||||
}
|
||||
|
||||
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@ namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Chill\MainBundle\Export\AccompanyingCourseExportHelper;
|
||||
use Chill\MainBundle\Export\ExportInterface;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
@@ -23,23 +24,27 @@ use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use LogicException;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class SumActivityVisitDuration implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
protected EntityRepository $repository;
|
||||
private readonly bool $filterStatsByCenters;
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em
|
||||
EntityManagerInterface $em,
|
||||
ParameterBagInterface $parameterBag,
|
||||
) {
|
||||
$this->repository = $em->getRepository(Activity::class);
|
||||
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
// TODO: Implement buildForm() method.
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
@@ -63,7 +68,7 @@ class SumActivityVisitDuration implements ExportInterface, GroupedExportInterfac
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
if ('export_sum_activity_visit_duration' !== $key) {
|
||||
throw new LogicException("the key {$key} is not used by this export");
|
||||
throw new \LogicException("the key {$key} is not used by this export");
|
||||
}
|
||||
|
||||
return static fn ($value) => '_header' === $value ? 'Sum activities linked to an accompanying period visit duration' : $value;
|
||||
@@ -100,16 +105,20 @@ class SumActivityVisitDuration implements ExportInterface, GroupedExportInterfac
|
||||
$qb->select('SUM(activity.travelTime) as export_sum_activity_visit_duration')
|
||||
->andWhere($qb->expr()->isNotNull('activity.travelTime'));
|
||||
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part
|
||||
JOIN ' . PersonCenterHistory::class . ' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||
if ($this->filterStatsByCenters) {
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM '.AccompanyingPeriodParticipation::class.' acl_count_part
|
||||
JOIN '.PersonCenterHistory::class.' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||
WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
|
||||
'
|
||||
)
|
||||
)
|
||||
)
|
||||
->setParameter('authorized_centers', $centers);
|
||||
->setParameter('authorized_centers', $centers);
|
||||
}
|
||||
|
||||
AccompanyingCourseExportHelper::addClosingMotiveExclusionClause($qb);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
@@ -19,20 +19,22 @@ use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||
use Doctrine\ORM\Query;
|
||||
use LogicException;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class CountActivity implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
protected ActivityRepository $activityRepository;
|
||||
private readonly bool $filterStatsByCenters;
|
||||
|
||||
public function __construct(
|
||||
ActivityRepository $activityRepository
|
||||
private readonly ActivityRepository $activityRepository,
|
||||
ParameterBagInterface $parameterBag,
|
||||
) {
|
||||
$this->activityRepository = $activityRepository;
|
||||
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder) {}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
@@ -56,7 +58,7 @@ class CountActivity implements ExportInterface, GroupedExportInterface
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
if ('export_count_activity' !== $key) {
|
||||
throw new LogicException("the key {$key} is not used by this export");
|
||||
throw new \LogicException("the key {$key} is not used by this export");
|
||||
}
|
||||
|
||||
return static fn ($value) => '_header' === $value ? 'Number of activities linked to a person' : $value;
|
||||
@@ -88,23 +90,25 @@ class CountActivity implements ExportInterface, GroupedExportInterface
|
||||
|
||||
$qb = $this->activityRepository
|
||||
->createQueryBuilder('activity')
|
||||
->join('activity.person', 'person')
|
||||
->join('person.centerHistory', 'centerHistory');
|
||||
->join('activity.person', 'person');
|
||||
|
||||
$qb->select('COUNT(activity.id) as export_count_activity');
|
||||
|
||||
$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')
|
||||
if ($this->filterStatsByCenters) {
|
||||
$qb
|
||||
->join('person.centerHistory', 'centerHistory')
|
||||
->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);
|
||||
->andWhere($qb->expr()->in('centerHistory.center', ':centers'))
|
||||
->setParameter('centers', $centers);
|
||||
}
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
@@ -20,24 +20,18 @@ use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
use Chill\MainBundle\Export\ListInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||
use DateTime;
|
||||
use Doctrine\DBAL\Exception\InvalidArgumentException;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Query;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Validator\Constraints\Callback;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
use function array_key_exists;
|
||||
use function count;
|
||||
use function in_array;
|
||||
|
||||
class ListActivity implements ListInterface, GroupedExportInterface
|
||||
{
|
||||
protected EntityManagerInterface $entityManager;
|
||||
|
||||
protected array $fields = [
|
||||
'id',
|
||||
'date',
|
||||
@@ -51,23 +45,16 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
'person_lastname',
|
||||
'person_id',
|
||||
];
|
||||
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
protected TranslatorInterface $translator;
|
||||
|
||||
private ActivityRepository $activityRepository;
|
||||
private readonly bool $filterStatsByCenters;
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
TranslatorInterface $translator,
|
||||
TranslatableStringHelperInterface $translatableStringHelper,
|
||||
ActivityRepository $activityRepository
|
||||
protected EntityManagerInterface $entityManager,
|
||||
protected TranslatorInterface $translator,
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper,
|
||||
private readonly ActivityRepository $activityRepository,
|
||||
ParameterBagInterface $parameterBag,
|
||||
) {
|
||||
$this->entityManager = $em;
|
||||
$this->translator = $translator;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->activityRepository = $activityRepository;
|
||||
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
@@ -79,7 +66,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
'label' => 'Fields to include in export',
|
||||
'constraints' => [new Callback([
|
||||
'callback' => static function ($selected, ExecutionContextInterface $context) {
|
||||
if (count($selected) === 0) {
|
||||
if (0 === \count($selected)) {
|
||||
$context->buildViolation('You must select at least one element')
|
||||
->atPath('fields')
|
||||
->addViolation();
|
||||
@@ -88,6 +75,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
])],
|
||||
]);
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
@@ -117,7 +105,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
return 'date';
|
||||
}
|
||||
|
||||
$date = DateTime::createFromFormat('Y-m-d H:i:s', $value);
|
||||
$date = \DateTime::createFromFormat('Y-m-d H:i:s', $value);
|
||||
|
||||
return $date->format('d-m-Y');
|
||||
};
|
||||
@@ -141,11 +129,11 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
|
||||
$activity = $activityRepository->find($value);
|
||||
|
||||
return implode(', ', array_map(fn (ActivityReason $r) => '"' .
|
||||
return implode(', ', array_map(fn (ActivityReason $r) => '"'.
|
||||
$this->translatableStringHelper->localize($r->getCategory()->getName())
|
||||
. ' > ' .
|
||||
.' > '.
|
||||
$this->translatableStringHelper->localize($r->getName())
|
||||
. '"', $activity->getReasons()->toArray()));
|
||||
.'"', $activity->getReasons()->toArray()));
|
||||
};
|
||||
|
||||
case 'circle_name':
|
||||
@@ -154,7 +142,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
return 'circle';
|
||||
}
|
||||
|
||||
return $this->translatableStringHelper->localize(json_decode($value, true, 512, JSON_THROW_ON_ERROR));
|
||||
return $this->translatableStringHelper->localize(json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR));
|
||||
};
|
||||
|
||||
case 'type_name':
|
||||
@@ -163,7 +151,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
return 'activity type';
|
||||
}
|
||||
|
||||
return $this->translatableStringHelper->localize(json_decode($value, true, 512, JSON_THROW_ON_ERROR));
|
||||
return $this->translatableStringHelper->localize(json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR));
|
||||
};
|
||||
|
||||
default:
|
||||
@@ -202,7 +190,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
$centers = array_map(static fn ($el) => $el['center'], $acl);
|
||||
|
||||
// throw an error if any fields are present
|
||||
if (!array_key_exists('fields', $data)) {
|
||||
if (!\array_key_exists('fields', $data)) {
|
||||
throw new InvalidArgumentException('Any fields have been checked.');
|
||||
}
|
||||
|
||||
@@ -210,23 +198,25 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
|
||||
$qb
|
||||
->from('ChillActivityBundle:Activity', 'activity')
|
||||
->join('activity.person', 'actperson')
|
||||
->join('actperson.centerHistory', 'centerHistory');
|
||||
->join('activity.person', 'actperson');
|
||||
|
||||
$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')
|
||||
if ($this->filterStatsByCenters) {
|
||||
$qb->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);
|
||||
->andWhere($qb->expr()->in('centerHistory.center', ':centers'))
|
||||
->setParameter('centers', $centers);
|
||||
}
|
||||
|
||||
foreach ($this->fields as $f) {
|
||||
if (in_array($f, $data['fields'], true)) {
|
||||
if (\in_array($f, $data['fields'], true)) {
|
||||
switch ($f) {
|
||||
case 'id':
|
||||
$qb->addSelect('activity.id AS id');
|
||||
|
@@ -20,7 +20,7 @@ use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||
use Doctrine\ORM\Query;
|
||||
use LogicException;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
/**
|
||||
@@ -30,27 +30,25 @@ use Symfony\Component\Form\FormBuilderInterface;
|
||||
*/
|
||||
class StatActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
public const SUM = 'sum';
|
||||
|
||||
/**
|
||||
* The action for this report.
|
||||
*/
|
||||
protected string $action;
|
||||
|
||||
private ActivityRepository $activityRepository;
|
||||
final public const SUM = 'sum';
|
||||
private readonly bool $filterStatsByCenters;
|
||||
|
||||
/**
|
||||
* @param string $action the stat to perform
|
||||
*/
|
||||
public function __construct(
|
||||
ActivityRepository $activityRepository,
|
||||
string $action = 'sum'
|
||||
private readonly ActivityRepository $activityRepository,
|
||||
ParameterBagInterface $parameterBag,
|
||||
/**
|
||||
* The action for this report.
|
||||
*/
|
||||
protected string $action = 'sum'
|
||||
) {
|
||||
$this->action = $action;
|
||||
$this->activityRepository = $activityRepository;
|
||||
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder) {}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
@@ -67,7 +65,7 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
return 'Sum activities linked to a person duration by various parameters.';
|
||||
}
|
||||
|
||||
throw new LogicException('this action is not supported: ' . $this->action);
|
||||
throw new \LogicException('this action is not supported: '.$this->action);
|
||||
}
|
||||
|
||||
public function getGroup(): string
|
||||
@@ -78,7 +76,7 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
if ('export_stat_activity' !== $key) {
|
||||
throw new LogicException(sprintf('The key %s is not used by this export', $key));
|
||||
throw new \LogicException(sprintf('The key %s is not used by this export', $key));
|
||||
}
|
||||
|
||||
$header = self::SUM === $this->action ? 'Sum activities linked to a person duration' : false;
|
||||
@@ -102,7 +100,7 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
return 'Sum activity linked to a person duration';
|
||||
}
|
||||
|
||||
throw new LogicException('This action is not supported: ' . $this->action);
|
||||
throw new \LogicException('This action is not supported: '.$this->action);
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
@@ -126,21 +124,23 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
}
|
||||
|
||||
$qb->select($select)
|
||||
->join('activity.person', 'person')
|
||||
->join('person.centerHistory', 'centerHistory');
|
||||
->join('activity.person', 'person');
|
||||
|
||||
$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')
|
||||
if ($this->filterStatsByCenters) {
|
||||
$qb
|
||||
->join('person.centerHistory', 'centerHistory')
|
||||
->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);
|
||||
->andWhere($qb->expr()->in('centerHistory.center', ':centers'))
|
||||
->setParameter('centers', $centers);
|
||||
}
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
@@ -23,54 +23,24 @@ 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;
|
||||
final public const MSG_KEY = 'export.list.activity.';
|
||||
|
||||
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;
|
||||
}
|
||||
private readonly ActivityPresenceRepositoryInterface $activityPresenceRepository,
|
||||
private readonly ActivityTypeRepositoryInterface $activityTypeRepository,
|
||||
private readonly DateTimeHelper $dateTimeHelper,
|
||||
private readonly LabelPersonHelper $labelPersonHelper,
|
||||
private readonly LabelThirdPartyHelper $labelThirdPartyHelper,
|
||||
private readonly TranslatorInterface $translator,
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||
private readonly TranslatableStringExportLabelHelper $translatableStringLabelHelper,
|
||||
private readonly UserHelper $userHelper
|
||||
) {}
|
||||
|
||||
public function addSelect(QueryBuilder $qb): void
|
||||
{
|
||||
@@ -85,7 +55,7 @@ class ListActivityHelper
|
||||
->addSelect('AGGREGATE(actPerson.id) AS personsNames')
|
||||
->leftJoin('activity.users', 'users_u')
|
||||
->addSelect('AGGREGATE(users_u.id) AS usersIds')
|
||||
->addSelect('AGGREGATE(users_u.id) AS usersNames')
|
||||
->addSelect('AGGREGATE(JSON_BUILD_OBJECT(\'uid\', users_u.id, \'d\', activity.date)) AS usersNames')
|
||||
->leftJoin('activity.thirdParties', 'thirdparty')
|
||||
->addSelect('AGGREGATE(thirdparty.id) AS thirdPartiesIds')
|
||||
->addSelect('AGGREGATE(thirdparty.id) AS thirdPartiesNames')
|
||||
@@ -96,9 +66,9 @@ class ListActivityHelper
|
||||
->leftJoin('activity.location', 'location')
|
||||
->addSelect('location.name AS locationName')
|
||||
->addSelect('activity.sentReceived')
|
||||
->addSelect('IDENTITY(activity.createdBy) AS createdBy')
|
||||
->addSelect('JSON_BUILD_OBJECT(\'uid\', IDENTITY(activity.createdBy), \'d\', activity.createdAt) AS createdBy')
|
||||
->addSelect('activity.createdAt')
|
||||
->addSelect('IDENTITY(activity.updatedBy) AS updatedBy')
|
||||
->addSelect('JSON_BUILD_OBJECT(\'uid\', IDENTITY(activity.updatedBy), \'d\', activity.updatedAt) AS updatedBy')
|
||||
->addSelect('activity.updatedAt')
|
||||
->addGroupBy('activity.id')
|
||||
->addGroupBy('location.id');
|
||||
@@ -113,113 +83,78 @@ class ListActivityHelper
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
switch ($key) {
|
||||
case 'createdAt':
|
||||
case 'updatedAt':
|
||||
return $this->dateTimeHelper->getLabel($key);
|
||||
return match ($key) {
|
||||
'createdAt', 'updatedAt' => $this->dateTimeHelper->getLabel($key),
|
||||
'createdBy', 'updatedBy' => $this->userHelper->getLabel($key, $values, $key),
|
||||
'date' => $this->dateTimeHelper->getLabel(self::MSG_KEY.$key),
|
||||
'attendeeName' => function ($value) {
|
||||
if ('_header' === $value) {
|
||||
return 'Attendee';
|
||||
}
|
||||
|
||||
case 'createdBy':
|
||||
case 'updatedBy':
|
||||
return $this->userHelper->getLabel($key, $values, $key);
|
||||
if (null === $value || null === $presence = $this->activityPresenceRepository->find($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
case 'date':
|
||||
return $this->dateTimeHelper->getLabel(self::MSG_KEY . $key);
|
||||
return $this->translatableStringHelper->localize($presence->getName());
|
||||
},
|
||||
'listReasons' => $this->translatableStringLabelHelper->getLabelMulti($key, $values, 'Activity Reasons'),
|
||||
'typeName' => function ($value) {
|
||||
if ('_header' === $value) {
|
||||
return 'Activity type';
|
||||
}
|
||||
|
||||
case 'attendeeName':
|
||||
return function ($value) {
|
||||
if ('_header' === $value) {
|
||||
return 'Attendee';
|
||||
}
|
||||
if (null === $value || null === $type = $this->activityTypeRepository->find($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (null === $value || null === $presence = $this->activityPresenceRepository->find($value)) {
|
||||
return '';
|
||||
}
|
||||
return $this->translatableStringHelper->localize($type->getName());
|
||||
},
|
||||
'usersNames' => $this->userHelper->getLabelMulti($key, $values, self::MSG_KEY.'users name'),
|
||||
'usersIds', 'thirdPartiesIds', 'personsIds' => static function ($value) use ($key) {
|
||||
if ('_header' === $value) {
|
||||
return match ($key) {
|
||||
'usersIds' => self::MSG_KEY.'users ids',
|
||||
'thirdPartiesIds' => self::MSG_KEY.'third parties ids',
|
||||
'personsIds' => self::MSG_KEY.'persons ids',
|
||||
};
|
||||
}
|
||||
|
||||
return $this->translatableStringHelper->localize($presence->getName());
|
||||
};
|
||||
$decoded = json_decode((string) $value, null, 512, JSON_THROW_ON_ERROR);
|
||||
|
||||
case 'listReasons':
|
||||
return $this->translatableStringLabelHelper->getLabelMulti($key, $values, 'Activity Reasons');
|
||||
return implode(
|
||||
'|',
|
||||
array_unique(
|
||||
array_filter($decoded, static fn (?int $id) => null !== $id),
|
||||
\SORT_NUMERIC
|
||||
)
|
||||
);
|
||||
},
|
||||
'personsNames' => $this->labelPersonHelper->getLabelMulti($key, $values, self::MSG_KEY.'persons name'),
|
||||
'thirdPartiesNames' => $this->labelThirdPartyHelper->getLabelMulti($key, $values, self::MSG_KEY.'thirds parties'),
|
||||
'sentReceived' => function ($value) {
|
||||
if ('_header' === $value) {
|
||||
return self::MSG_KEY.'sent received';
|
||||
}
|
||||
|
||||
case 'typeName':
|
||||
return function ($value) {
|
||||
if ('_header' === $value) {
|
||||
return 'Activity type';
|
||||
}
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (null === $value || null === $type = $this->activityTypeRepository->find($value)) {
|
||||
return '';
|
||||
}
|
||||
return $this->translator->trans($value);
|
||||
},
|
||||
default => function ($value) use ($key) {
|
||||
if ('_header' === $value) {
|
||||
return self::MSG_KEY.$key;
|
||||
}
|
||||
|
||||
return $this->translatableStringHelper->localize($type->getName());
|
||||
};
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
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, null, 512, JSON_THROW_ON_ERROR);
|
||||
|
||||
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);
|
||||
};
|
||||
}
|
||||
return $this->translator->trans($value);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
|
@@ -21,9 +21,6 @@ use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
/**
|
||||
* Filter accompanying period to keep only the one having at list one activity from the given ActivityType.
|
||||
*/
|
||||
class ActivityTypeFilter implements FilterInterface
|
||||
{
|
||||
public function __construct(
|
||||
@@ -40,7 +37,7 @@ class ActivityTypeFilter implements FilterInterface
|
||||
{
|
||||
$qb->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM ' . Activity::class . ' act_type_filter_activity
|
||||
'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'
|
||||
)
|
||||
);
|
||||
@@ -57,13 +54,14 @@ class ActivityTypeFilter implements FilterInterface
|
||||
$builder->add('accepted_activitytypes', EntityType::class, [
|
||||
'class' => ActivityType::class,
|
||||
'choices' => $this->activityTypeRepository->findAllActive(),
|
||||
'choice_label' => fn (ActivityType $aty) => ($aty->hasCategory() ? $this->translatableStringHelper->localize($aty->getCategory()->getName()) . ' > ' : '')
|
||||
'choice_label' => fn (ActivityType $aty) => ($aty->hasCategory() ? $this->translatableStringHelper->localize($aty->getCategory()->getName()).' > ' : '')
|
||||
.
|
||||
$this->translatableStringHelper->localize($aty->getName()),
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
|
@@ -18,16 +18,10 @@ use Chill\PersonBundle\Form\Type\PickSocialActionType;
|
||||
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class BySocialActionFilter implements FilterInterface
|
||||
{
|
||||
private SocialActionRender $actionRender;
|
||||
|
||||
public function __construct(SocialActionRender $actionRender)
|
||||
{
|
||||
$this->actionRender = $actionRender;
|
||||
}
|
||||
public function __construct(private readonly SocialActionRender $actionRender) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -36,7 +30,7 @@ class BySocialActionFilter implements FilterInterface
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('actsocialaction', $qb->getAllAliases(), true)) {
|
||||
if (!\in_array('actsocialaction', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.socialActions', 'actsocialaction');
|
||||
}
|
||||
|
||||
@@ -60,6 +54,7 @@ class BySocialActionFilter implements FilterInterface
|
||||
'multiple' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
|
@@ -18,16 +18,10 @@ use Chill\PersonBundle\Form\Type\PickSocialIssueType;
|
||||
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class BySocialIssueFilter implements FilterInterface
|
||||
{
|
||||
private SocialIssueRender $issueRender;
|
||||
|
||||
public function __construct(SocialIssueRender $issueRender)
|
||||
{
|
||||
$this->issueRender = $issueRender;
|
||||
}
|
||||
public function __construct(private readonly SocialIssueRender $issueRender) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -36,7 +30,7 @@ class BySocialIssueFilter implements FilterInterface
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('actsocialissue', $qb->getAllAliases(), true)) {
|
||||
if (!\in_array('actsocialissue', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.socialIssues', 'actsocialissue');
|
||||
}
|
||||
|
||||
@@ -60,6 +54,7 @@ class BySocialIssueFilter implements FilterInterface
|
||||
'multiple' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
|
@@ -18,7 +18,7 @@ use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
/**
|
||||
* Filter accompanying periods to keep only the one without any activity
|
||||
* Filter accompanying periods to keep only the one without any activity.
|
||||
*/
|
||||
class HasNoActivityFilter implements FilterInterface
|
||||
{
|
||||
@@ -32,7 +32,7 @@ class HasNoActivityFilter implements FilterInterface
|
||||
$qb
|
||||
->andWhere('
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM ' . Activity::class . ' activity
|
||||
SELECT 1 FROM '.Activity::class.' activity
|
||||
WHERE activity.accompanyingPeriod = acp
|
||||
)
|
||||
');
|
||||
@@ -45,8 +45,9 @@ class HasNoActivityFilter implements FilterInterface
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
//no form needed
|
||||
// no form needed
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
|
@@ -34,10 +34,10 @@ final readonly class PeriodHavingActivityBetweenDatesFilter implements FilterInt
|
||||
{
|
||||
$builder
|
||||
->add('start_date', PickRollingDateType::class, [
|
||||
'label' => 'export.filter.activity.course_having_activity_between_date.Receiving an activity after'
|
||||
'label' => 'export.filter.activity.course_having_activity_between_date.Receiving an activity after',
|
||||
])
|
||||
->add('end_date', PickRollingDateType::class, [
|
||||
'label' => 'export.filter.activity.course_having_activity_between_date.Receiving an activity before'
|
||||
'label' => 'export.filter.activity.course_having_activity_between_date.Receiving an activity before',
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ final readonly class PeriodHavingActivityBetweenDatesFilter implements FilterInt
|
||||
{
|
||||
return [
|
||||
'start_date' => new RollingDate(RollingDate::T_YEAR_CURRENT_START),
|
||||
'end_date' => new RollingDate(RollingDate::T_TODAY)
|
||||
'end_date' => new RollingDate(RollingDate::T_TODAY),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ final readonly class PeriodHavingActivityBetweenDatesFilter implements FilterInt
|
||||
[
|
||||
'from' => $this->rollingDateConverter->convert($data['start_date']),
|
||||
'to' => $this->rollingDateConverter->convert($data['end_date']),
|
||||
]
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ final readonly class PeriodHavingActivityBetweenDatesFilter implements FilterInt
|
||||
|
||||
$qb->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM ' . Activity::class . " {$alias} WHERE {$alias}.date >= :{$from} AND {$alias}.date < :{$to} AND {$alias}.accompanyingPeriod = acp"
|
||||
'SELECT 1 FROM '.Activity::class." {$alias} WHERE {$alias}.date >= :{$from} AND {$alias}.date < :{$to} AND {$alias}.accompanyingPeriod = acp"
|
||||
)
|
||||
);
|
||||
|
||||
|
@@ -13,31 +13,17 @@ namespace Chill\ActivityBundle\Export\Filter;
|
||||
|
||||
use Chill\ActivityBundle\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\Query\Expr;
|
||||
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 ActivityDateFilter implements FilterInterface
|
||||
{
|
||||
protected TranslatorInterface $translator;
|
||||
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
public function __construct(
|
||||
TranslatorInterface $translator,
|
||||
RollingDateConverterInterface $rollingDateConverter
|
||||
) {
|
||||
$this->translator = $translator;
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
public function __construct(protected TranslatorInterface $translator, private readonly RollingDateConverterInterface $rollingDateConverter) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -84,47 +70,8 @@ class ActivityDateFilter implements FilterInterface
|
||||
->add('date_to', PickRollingDateType::class, [
|
||||
'label' => 'Activities before this date',
|
||||
]);
|
||||
|
||||
$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('This date should be after '
|
||||
. 'the date given in "Implied in an activity after '
|
||||
. 'this date" field')
|
||||
));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return ['date_from' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START), 'date_to' => new RollingDate(RollingDate::T_TODAY)];
|
||||
|
@@ -22,21 +22,12 @@ use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
use function count;
|
||||
|
||||
class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInterface
|
||||
{
|
||||
protected ActivityTypeRepositoryInterface $activityTypeRepository;
|
||||
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
TranslatableStringHelperInterface $translatableStringHelper,
|
||||
ActivityTypeRepositoryInterface $activityTypeRepository
|
||||
) {
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->activityTypeRepository = $activityTypeRepository;
|
||||
}
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper,
|
||||
protected ActivityTypeRepositoryInterface $activityTypeRepository
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -61,7 +52,7 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
|
||||
$builder->add('types', EntityType::class, [
|
||||
'choices' => $this->activityTypeRepository->findAllActive(),
|
||||
'class' => ActivityType::class,
|
||||
'choice_label' => fn (ActivityType $aty) => ($aty->hasCategory() ? $this->translatableStringHelper->localize($aty->getCategory()->getName()) . ' > ' : '')
|
||||
'choice_label' => fn (ActivityType $aty) => ($aty->hasCategory() ? $this->translatableStringHelper->localize($aty->getCategory()->getName()).' > ' : '')
|
||||
.
|
||||
$this->translatableStringHelper->localize($aty->getName()),
|
||||
'group_by' => function (ActivityType $type) {
|
||||
@@ -78,6 +69,7 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
@@ -88,7 +80,7 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
|
||||
// collect all the reasons'name used in this filter in one array
|
||||
$reasonsNames = array_map(
|
||||
fn (ActivityType $t): string => $this->translatableStringHelper->localize($t->getName()),
|
||||
$this->activityTypeRepository->findBy(['id' => $data['types']->toArray()])
|
||||
$this->activityTypeRepository->findBy(['id' => $data['types'] instanceof \Doctrine\Common\Collections\Collection ? $data['types']->toArray() : $data['types']])
|
||||
);
|
||||
|
||||
return ['Filtered by activity type: only %list%', [
|
||||
@@ -103,7 +95,7 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
|
||||
|
||||
public function validateForm($data, ExecutionContextInterface $context)
|
||||
{
|
||||
if (null === $data['types'] || count($data['types']) === 0) {
|
||||
if (null === $data['types'] || 0 === \count($data['types'])) {
|
||||
$context
|
||||
->buildViolation('At least one type must be chosen')
|
||||
->addViolation();
|
||||
|
@@ -20,12 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class ActivityUsersFilter implements FilterInterface
|
||||
{
|
||||
private UserRender $userRender;
|
||||
|
||||
public function __construct(UserRender $userRender)
|
||||
{
|
||||
$this->userRender = $userRender;
|
||||
}
|
||||
public function __construct(private readonly UserRender $userRender) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -37,8 +32,8 @@ class ActivityUsersFilter implements FilterInterface
|
||||
$orX = $qb->expr()->orX();
|
||||
|
||||
foreach ($data['accepted_users'] as $key => $user) {
|
||||
$orX->add($qb->expr()->isMemberOf(':activity_users_filter_u' . $key, 'activity.users'));
|
||||
$qb->setParameter('activity_users_filter_u' . $key, $user);
|
||||
$orX->add($qb->expr()->isMemberOf(':activity_users_filter_u'.$key, 'activity.users'));
|
||||
$qb->setParameter('activity_users_filter_u'.$key, $user);
|
||||
}
|
||||
|
||||
$qb->andWhere($orX);
|
||||
@@ -56,6 +51,7 @@ class ActivityUsersFilter implements FilterInterface
|
||||
'label' => 'Users',
|
||||
]);
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
|
@@ -20,12 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class ByCreatorFilter implements FilterInterface
|
||||
{
|
||||
private UserRender $userRender;
|
||||
|
||||
public function __construct(UserRender $userRender)
|
||||
{
|
||||
$this->userRender = $userRender;
|
||||
}
|
||||
public function __construct(private readonly UserRender $userRender) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -52,6 +47,7 @@ class ByCreatorFilter implements FilterInterface
|
||||
'multiple' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
|
@@ -0,0 +1,112 @@
|
||||
<?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;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Entity\User\UserScopeHistory;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class CreatorScopeFilter implements FilterInterface
|
||||
{
|
||||
private const PREFIX = 'acp_act_filter_creator_scope';
|
||||
|
||||
public function __construct(
|
||||
private readonly TranslatableStringHelper $translatableStringHelper
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$p = self::PREFIX;
|
||||
|
||||
$qb
|
||||
->leftJoin('activity.createdBy', "{$p}_user")
|
||||
->leftJoin(
|
||||
UserScopeHistory::class,
|
||||
"{$p}_history",
|
||||
Join::WITH,
|
||||
$qb->expr()->eq("{$p}_history.user", "{$p}_user")
|
||||
)
|
||||
// scope_at based on activity.date
|
||||
->andWhere(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte("{$p}_history.startDate", 'activity.date'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull("{$p}_history.endDate"),
|
||||
$qb->expr()->gt("{$p}_history.endDate", 'activity.date')
|
||||
)
|
||||
)
|
||||
)
|
||||
->andWhere(
|
||||
$qb->expr()->in("{$p}_history.scope", ":{$p}_scopes")
|
||||
)
|
||||
->setParameter(
|
||||
"{$p}_scopes",
|
||||
$data['scopes'],
|
||||
);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::ACTIVITY;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder
|
||||
->add('scopes', EntityType::class, [
|
||||
'class' => Scope::class,
|
||||
'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize(
|
||||
$s->getName()
|
||||
),
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
$scopes = [];
|
||||
|
||||
foreach ($data['scopes'] as $s) {
|
||||
$scopes[] = $this->translatableStringHelper->localize(
|
||||
$s->getName()
|
||||
);
|
||||
}
|
||||
|
||||
return ['export.filter.activity.by_creator_scope.Filtered activity by user scope: only %scopes%', [
|
||||
'%scopes%' => implode(', ', $scopes),
|
||||
]];
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [
|
||||
'scopes' => [],
|
||||
];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'export.filter.activity.by_creator_scope.Filter activity by user scope';
|
||||
}
|
||||
}
|
@@ -28,12 +28,7 @@ class EmergencyFilter implements FilterInterface
|
||||
|
||||
private const DEFAULT_CHOICE = 'false';
|
||||
|
||||
private TranslatorInterface $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
}
|
||||
public function __construct(private readonly TranslatorInterface $translator) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -70,6 +65,7 @@ class EmergencyFilter implements FilterInterface
|
||||
'empty_data' => self::DEFAULT_CHOICE,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return ['accepted_emergency' => self::DEFAULT_CHOICE];
|
||||
|
@@ -14,7 +14,6 @@ namespace Chill\ActivityBundle\Export\Filter;
|
||||
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;
|
||||
|
||||
@@ -46,6 +45,7 @@ class LocationFilter implements FilterInterface
|
||||
'label' => 'pick location',
|
||||
]);
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
|
@@ -18,16 +18,10 @@ use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class LocationTypeFilter implements FilterInterface
|
||||
{
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
|
||||
public function __construct(TranslatableStringHelper $translatableStringHelper)
|
||||
{
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
public function __construct(private readonly TranslatableStringHelper $translatableStringHelper) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -36,7 +30,7 @@ class LocationTypeFilter implements FilterInterface
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('actloc', $qb->getAllAliases(), true)) {
|
||||
if (!\in_array('actloc', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.location', 'actloc');
|
||||
}
|
||||
|
||||
@@ -62,9 +56,10 @@ class LocationTypeFilter implements FilterInterface
|
||||
{
|
||||
$builder->add('accepted_locationtype', PickLocationTypeType::class, [
|
||||
'multiple' => true,
|
||||
//'label' => false,
|
||||
// 'label' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
|
@@ -17,29 +17,16 @@ use Chill\ActivityBundle\Repository\ActivityReasonRepository;
|
||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
use function count;
|
||||
use function in_array;
|
||||
|
||||
class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInterface
|
||||
{
|
||||
protected ActivityReasonRepository $activityReasonRepository;
|
||||
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
TranslatableStringHelper $helper,
|
||||
ActivityReasonRepository $activityReasonRepository
|
||||
) {
|
||||
$this->translatableStringHelper = $helper;
|
||||
$this->activityReasonRepository = $activityReasonRepository;
|
||||
}
|
||||
public function __construct(protected TranslatableStringHelper $translatableStringHelper, protected ActivityReasonRepository $activityReasonRepository) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -52,7 +39,7 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
|
||||
$join = $qb->getDQLPart('join');
|
||||
$clause = $qb->expr()->in('actreasons', ':selected_activity_reasons');
|
||||
|
||||
if (!in_array('actreasons', $qb->getAllAliases(), true)) {
|
||||
if (!\in_array('actreasons', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.reasons', 'actreasons');
|
||||
}
|
||||
|
||||
@@ -82,6 +69,7 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
|
||||
'expanded' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
@@ -91,8 +79,8 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
|
||||
{
|
||||
// collect all the reasons'name used in this filter in one array
|
||||
$reasonsNames = array_map(
|
||||
fn (ActivityReason $r): string => '"' . $this->translatableStringHelper->localize($r->getName()) . '"',
|
||||
$this->activityReasonRepository->findBy(['id' => $data['reasons']->toArray()])
|
||||
fn (ActivityReason $r): string => '"'.$this->translatableStringHelper->localize($r->getName()).'"',
|
||||
$this->activityReasonRepository->findBy(['id' => $data['reasons'] instanceof Collection ? $data['reasons']->toArray() : $data['reasons']])
|
||||
);
|
||||
|
||||
return [
|
||||
@@ -110,7 +98,7 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
|
||||
|
||||
public function validateForm($data, ExecutionContextInterface $context)
|
||||
{
|
||||
if (null === $data['reasons'] || count($data['reasons']) === 0) {
|
||||
if (null === $data['reasons'] || 0 === \count($data['reasons'])) {
|
||||
$context
|
||||
->buildViolation('At least one reason must be chosen')
|
||||
->addViolation();
|
||||
|
@@ -16,42 +16,23 @@ use Chill\ActivityBundle\Entity\ActivityReason;
|
||||
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
|
||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||
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 Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use DateTime;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormError;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
use function count;
|
||||
|
||||
class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInterface, FilterInterface
|
||||
final readonly class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInterface, FilterInterface
|
||||
{
|
||||
protected ActivityReasonRepository $activityReasonRepository;
|
||||
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
protected TranslatorInterface $translator;
|
||||
|
||||
public function __construct(
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
ActivityReasonRepository $activityReasonRepository,
|
||||
TranslatorInterface $translator
|
||||
) {
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->activityReasonRepository = $activityReasonRepository;
|
||||
$this->translator = $translator;
|
||||
}
|
||||
private TranslatableStringHelper $translatableStringHelper,
|
||||
private ActivityReasonRepository $activityReasonRepository,
|
||||
private RollingDateConverterInterface $rollingDateConverter,
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -62,134 +43,97 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt
|
||||
{
|
||||
// create a subquery for activity
|
||||
$sqb = $qb->getEntityManager()->createQueryBuilder();
|
||||
$sqb->select('person_person_having_activity.id')
|
||||
$sqb->select('1')
|
||||
->from(Activity::class, 'activity_person_having_activity')
|
||||
->join('activity_person_having_activity.person', 'person_person_having_activity');
|
||||
->leftJoin('activity_person_having_activity.person', 'person_person_having_activity');
|
||||
|
||||
// add clause between date
|
||||
$sqb->where('activity_person_having_activity.date BETWEEN '
|
||||
. ':person_having_activity_between_date_from'
|
||||
. ' AND '
|
||||
. ':person_having_activity_between_date_to');
|
||||
.':person_having_activity_between_date_from'
|
||||
.' AND '
|
||||
.':person_having_activity_between_date_to'
|
||||
.' AND '
|
||||
.'(person_person_having_activity.id = person.id OR person MEMBER OF activity_person_having_activity.persons)');
|
||||
|
||||
// add clause activity reason
|
||||
$sqb->join('activity_person_having_activity.reasons', 'reasons_person_having_activity');
|
||||
if (isset($data['reasons']) && [] !== $data['reasons']) {
|
||||
// add clause activity reason
|
||||
$sqb->join('activity_person_having_activity.reasons', 'reasons_person_having_activity');
|
||||
|
||||
$sqb->andWhere(
|
||||
$sqb->expr()->in(
|
||||
'reasons_person_having_activity',
|
||||
':person_having_activity_reasons'
|
||||
)
|
||||
);
|
||||
$sqb->andWhere(
|
||||
$sqb->expr()->in(
|
||||
'reasons_person_having_activity',
|
||||
':person_having_activity_reasons'
|
||||
)
|
||||
);
|
||||
|
||||
$where = $qb->getDQLPart('where');
|
||||
$clause = $qb->expr()->in('person.id', $sqb->getDQL());
|
||||
|
||||
if ($where instanceof Expr\Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
$qb->setParameter('person_having_activity_reasons', $data['reasons']);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->andWhere(
|
||||
$qb->expr()->exists($sqb->getDQL())
|
||||
);
|
||||
|
||||
$qb->setParameter(
|
||||
'person_having_activity_between_date_from',
|
||||
$data['date_from']
|
||||
$this->rollingDateConverter->convert($data['date_from_rolling'])
|
||||
);
|
||||
$qb->setParameter(
|
||||
'person_having_activity_between_date_to',
|
||||
$data['date_to']
|
||||
$this->rollingDateConverter->convert($data['date_to_rolling'])
|
||||
);
|
||||
$qb->setParameter('person_having_activity_reasons', $data['reasons']);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::PERSON_IMPLIED_IN;
|
||||
return Declarations::PERSON_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('date_from', DateType::class, [
|
||||
'label' => 'Implied in an activity after this date',
|
||||
'attr' => ['class' => 'datepicker'],
|
||||
'widget' => 'single_text',
|
||||
'format' => 'dd-MM-yyyy',
|
||||
$builder->add('date_from_rolling', PickRollingDateType::class, [
|
||||
'label' => 'export.filter.activity.person_between_dates.Implied in an activity after this date',
|
||||
]);
|
||||
|
||||
$builder->add('date_to', DateType::class, [
|
||||
'label' => 'Implied in an activity before this date',
|
||||
'attr' => ['class' => 'datepicker'],
|
||||
'widget' => 'single_text',
|
||||
'format' => 'dd-MM-yyyy',
|
||||
$builder->add('date_to_rolling', PickRollingDateType::class, [
|
||||
'label' => 'export.filter.activity.person_between_dates.Implied in an activity before this date',
|
||||
]);
|
||||
|
||||
$builder->add('reasons', EntityType::class, [
|
||||
'class' => ActivityReason::class,
|
||||
'choice_label' => fn (ActivityReason $reason): ?string => $this->translatableStringHelper->localize($reason->getName()),
|
||||
'group_by' => fn (ActivityReason $reason): ?string => $this->translatableStringHelper->localize($reason->getCategory()->getName()),
|
||||
'multiple' => true,
|
||||
'expanded' => false,
|
||||
'label' => 'Activity reasons for those activities',
|
||||
]);
|
||||
|
||||
$builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
|
||||
/** @var 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('This date '
|
||||
. 'should be after the date given in "Implied in an '
|
||||
. 'activity after this date" field')
|
||||
));
|
||||
}
|
||||
}
|
||||
});
|
||||
if ([] !== $reasons = $this->activityReasonRepository->findAll()) {
|
||||
$builder->add('reasons', EntityType::class, [
|
||||
'class' => ActivityReason::class,
|
||||
'choices' => $reasons,
|
||||
'choice_label' => fn (ActivityReason $reason): ?string => $this->translatableStringHelper->localize($reason->getName()),
|
||||
'group_by' => fn (ActivityReason $reason): ?string => $this->translatableStringHelper->localize($reason->getCategory()->getName()),
|
||||
'multiple' => true,
|
||||
'expanded' => false,
|
||||
'label' => 'export.filter.activity.person_between_dates.Activity reasons for those activities',
|
||||
'help' => 'export.filter.activity.person_between_dates.if no reasons',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return ['date_from' => new DateTime(), 'date_to' => new DateTime(), 'reasons' => $this->activityReasonRepository->findAll()];
|
||||
return [
|
||||
'date_from_rolling' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START),
|
||||
'date_to_rolling' => new RollingDate(RollingDate::T_TODAY),
|
||||
'reasons' => [],
|
||||
];
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
return [
|
||||
'Filtered by person having an activity between %date_from% and '
|
||||
. '%date_to% with reasons %reasons_name%',
|
||||
[] === $data['reasons'] ?
|
||||
'export.filter.person_between_dates.describe_action_with_no_subject'
|
||||
: 'export.filter.person_between_dates.describe_action_with_subject',
|
||||
[
|
||||
'%date_from%' => $data['date_from']->format('d-m-Y'),
|
||||
'%date_to%' => $data['date_to']->format('d-m-Y'),
|
||||
'%reasons_name%' => implode(
|
||||
'date_from' => $this->rollingDateConverter->convert($data['date_from_rolling']),
|
||||
'date_to' => $this->rollingDateConverter->convert($data['date_to_rolling']),
|
||||
'reasons' => implode(
|
||||
', ',
|
||||
array_map(
|
||||
fn (ActivityReason $r): string => '"' . $this->translatableStringHelper->localize($r->getName()) . '"',
|
||||
fn (ActivityReason $r): string => '"'.$this->translatableStringHelper->localize($r->getName()).'"',
|
||||
$data['reasons']
|
||||
)
|
||||
),
|
||||
@@ -199,13 +143,15 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return 'Filter by person having an activity in a period';
|
||||
return 'export.filter.activity.person_between_dates.title';
|
||||
}
|
||||
|
||||
public function validateForm($data, ExecutionContextInterface $context)
|
||||
{
|
||||
if (null === $data['reasons'] || count($data['reasons']) === 0) {
|
||||
$context->buildViolation('At least one reason must be chosen')
|
||||
if ($this->rollingDateConverter->convert($data['date_from_rolling'])
|
||||
>= $this->rollingDateConverter->convert($data['date_to_rolling'])) {
|
||||
$context->buildViolation('export.filter.activity.person_between_dates.date mismatch')
|
||||
->setTranslationDomain('messages')
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,87 @@
|
||||
<?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;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\ActivityBundle\Tests\Export\Filter\PersonsFilterTest;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\PersonBundle\Form\Type\PickPersonDynamicType;
|
||||
use Chill\PersonBundle\Templating\Entity\PersonRenderInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
/**
|
||||
* @see PersonsFilterTest
|
||||
*/
|
||||
final readonly class PersonsFilter implements FilterInterface
|
||||
{
|
||||
private const PREFIX = 'act_persons_filter';
|
||||
|
||||
public function __construct(private PersonRenderInterface $personRender) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$p = self::PREFIX;
|
||||
|
||||
$orX = $qb->expr()->orX();
|
||||
|
||||
foreach (array_values($data['accepted_persons']) as $key => $person) {
|
||||
$orX->add($qb->expr()->isMemberOf(":{$p}_p_{$key}", 'activity.persons'));
|
||||
$qb->setParameter(":{$p}_p_{$key}", $person);
|
||||
}
|
||||
|
||||
$qb->andWhere($orX);
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return Declarations::ACTIVITY;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('accepted_persons', PickPersonDynamicType::class, [
|
||||
'multiple' => true,
|
||||
'label' => 'export.filter.activity.by_persons.persons taking part on the activity',
|
||||
]);
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [
|
||||
'accepted_persons' => [],
|
||||
];
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
$users = [];
|
||||
|
||||
foreach ($data['accepted_persons'] as $u) {
|
||||
$users[] = $this->personRender->renderString($u, []);
|
||||
}
|
||||
|
||||
return ['export.filter.activity.by_persons.Filtered activity by persons: only %persons%', [
|
||||
'%persons%' => implode(', ', $users),
|
||||
]];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'export.filter.activity.by_persons.Filter activity by persons';
|
||||
}
|
||||
}
|
@@ -23,18 +23,13 @@ use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
class SentReceivedFilter implements FilterInterface
|
||||
{
|
||||
private const CHOICES = [
|
||||
'is sent' => Activity::SENTRECEIVED_SENT,
|
||||
'is received' => Activity::SENTRECEIVED_RECEIVED,
|
||||
'export.filter.activity.by_sent_received.is sent' => Activity::SENTRECEIVED_SENT,
|
||||
'export.filter.activity.by_sent_received.is received' => Activity::SENTRECEIVED_RECEIVED,
|
||||
];
|
||||
|
||||
private const DEFAULT_CHOICE = Activity::SENTRECEIVED_SENT;
|
||||
|
||||
private TranslatorInterface $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
}
|
||||
public function __construct(private readonly TranslatorInterface $translator) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -69,8 +64,10 @@ class SentReceivedFilter implements FilterInterface
|
||||
'multiple' => false,
|
||||
'expanded' => true,
|
||||
'empty_data' => self::DEFAULT_CHOICE,
|
||||
'label' => 'export.filter.activity.by_sent_received.Sent or received',
|
||||
]);
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return ['accepted_sentreceived' => self::DEFAULT_CHOICE];
|
||||
|
@@ -21,12 +21,7 @@ use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class UserFilter implements FilterInterface
|
||||
{
|
||||
private UserRender $userRender;
|
||||
|
||||
public function __construct(UserRender $userRender)
|
||||
{
|
||||
$this->userRender = $userRender;
|
||||
}
|
||||
public function __construct(private readonly UserRender $userRender) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -61,6 +56,7 @@ class UserFilter implements FilterInterface
|
||||
'label' => 'Creators',
|
||||
]);
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
|
@@ -1,98 +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;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class UserScopeFilter 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)
|
||||
{
|
||||
if (!in_array('actuser', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.user', 'actuser');
|
||||
}
|
||||
|
||||
$where = $qb->getDQLPart('where');
|
||||
|
||||
$clause = $qb->expr()->in('actuser.mainScope', ':userscope');
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('userscope', $data['accepted_userscope']);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::ACTIVITY;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('accepted_userscope', EntityType::class, [
|
||||
'class' => Scope::class,
|
||||
'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize(
|
||||
$s->getName()
|
||||
),
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
]);
|
||||
}
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
$scopes = [];
|
||||
|
||||
foreach ($data['accepted_userscope'] as $s) {
|
||||
$scopes[] = $this->translatableStringHelper->localize(
|
||||
$s->getName()
|
||||
);
|
||||
}
|
||||
|
||||
return ['Filtered activity by userscope: only %scopes%', [
|
||||
'%scopes%' => implode(', ', $scopes),
|
||||
]];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Filter activity by userscope';
|
||||
}
|
||||
}
|
@@ -13,21 +13,22 @@ namespace Chill\ActivityBundle\Export\Filter;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Entity\User\UserJobHistory;
|
||||
use Chill\MainBundle\Entity\UserJob;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class UsersJobFilter implements FilterInterface
|
||||
{
|
||||
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||
private const PREFIX = 'act_filter_user_job';
|
||||
|
||||
public function __construct(TranslatableStringHelperInterface $translatableStringHelper)
|
||||
{
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
public function __construct(
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -36,14 +37,25 @@ class UsersJobFilter implements FilterInterface
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$p = self::PREFIX;
|
||||
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM ' . Activity::class . ' activity_users_job_filter_act
|
||||
JOIN activity_users_job_filter_act.users users WHERE users.userJob IN (:activity_users_job_filter_jobs) AND activity_users_job_filter_act = activity '
|
||||
'SELECT 1 FROM '.Activity::class." {$p}_act "
|
||||
."JOIN {$p}_act.users {$p}_user "
|
||||
.'JOIN '.UserJobHistory::class." {$p}_history WITH {$p}_history.user = {$p}_user "
|
||||
."WHERE {$p}_act = activity "
|
||||
// job_at based on activity.date
|
||||
."AND {$p}_history.startDate <= activity.date "
|
||||
."AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > activity.date) "
|
||||
."AND {$p}_history.job IN ( :{$p}_jobs )"
|
||||
)
|
||||
)
|
||||
->setParameter('activity_users_job_filter_jobs', $data['jobs']);
|
||||
->setParameter(
|
||||
"{$p}_jobs",
|
||||
$data['jobs']
|
||||
);
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
@@ -53,33 +65,37 @@ class UsersJobFilter implements FilterInterface
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('jobs', EntityType::class, [
|
||||
'class' => UserJob::class,
|
||||
'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize($j->getLabel()),
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
]);
|
||||
}
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
$builder
|
||||
->add('jobs', EntityType::class, [
|
||||
'class' => UserJob::class,
|
||||
'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize($j->getLabel()),
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
return ['export.filter.activity.by_usersjob.Filtered activity by users job: only %jobs%', [
|
||||
return ['export.filter.activity.by_users_job.Filtered activity by users job: only %jobs%', [
|
||||
'%jobs%' => implode(
|
||||
', ',
|
||||
array_map(
|
||||
fn (UserJob $job) => $this->translatableStringHelper->localize($job->getLabel()),
|
||||
$data['jobs']->toArray()
|
||||
$data['jobs'] instanceof Collection ? $data['jobs']->toArray() : $data['jobs']
|
||||
)
|
||||
),
|
||||
]];
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [
|
||||
'jobs' => [],
|
||||
];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return 'export.filter.activity.by_usersjob.Filter by users job';
|
||||
return 'export.filter.activity.by_users_job.Filter by users job';
|
||||
}
|
||||
}
|
||||
|
@@ -14,26 +14,23 @@ namespace Chill\ActivityBundle\Export\Filter;
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Entity\User\UserScopeHistory;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Repository\ScopeRepositoryInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class UsersScopeFilter implements FilterInterface
|
||||
{
|
||||
private ScopeRepositoryInterface $scopeRepository;
|
||||
|
||||
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||
private const PREFIX = 'act_filter_user_scope';
|
||||
|
||||
public function __construct(
|
||||
ScopeRepositoryInterface $scopeRepository,
|
||||
TranslatableStringHelperInterface $translatableStringHelper
|
||||
) {
|
||||
$this->scopeRepository = $scopeRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
private readonly ScopeRepositoryInterface $scopeRepository,
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
@@ -42,51 +39,66 @@ class UsersScopeFilter implements FilterInterface
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$p = self::PREFIX;
|
||||
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM ' . Activity::class . ' activity_users_scope_filter_act
|
||||
JOIN activity_users_scope_filter_act.users users WHERE users.mainScope IN (:activity_users_scope_filter_scopes) AND activity_users_scope_filter_act = activity '
|
||||
'SELECT 1 FROM '.Activity::class." {$p}_act "
|
||||
."JOIN {$p}_act.users {$p}_user "
|
||||
.'JOIN '.UserScopeHistory::class." {$p}_history WITH {$p}_history.user = {$p}_user "
|
||||
."WHERE {$p}_act = activity "
|
||||
// scope_at based on activity.date
|
||||
."AND {$p}_history.startDate <= activity.date "
|
||||
."AND ({$p}_history.endDate IS NULL OR {$p}_history.endDate > activity.date) "
|
||||
."AND {$p}_history.scope IN ( :{$p}_scopes )"
|
||||
)
|
||||
)
|
||||
->setParameter('activity_users_scope_filter_scopes', $data['scopes']);
|
||||
->setParameter(
|
||||
"{$p}_scopes",
|
||||
$data['scopes']
|
||||
);
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::ACTIVITY;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('scopes', EntityType::class, [
|
||||
'class' => Scope::class,
|
||||
'choices' => $this->scopeRepository->findAllActive(),
|
||||
'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()),
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
]);
|
||||
}
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
$builder
|
||||
->add('scopes', EntityType::class, [
|
||||
'class' => Scope::class,
|
||||
'choices' => $this->scopeRepository->findAllActive(),
|
||||
'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()),
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
return ['export.filter.activity.by_usersscope.Filtered activity by users scope: only %scopes%', [
|
||||
return ['export.filter.activity.by_users_scope.Filtered activity by users scope: only %scopes%', [
|
||||
'%scopes%' => implode(
|
||||
', ',
|
||||
array_map(
|
||||
fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()),
|
||||
$data['scopes']->toArray()
|
||||
$data['scopes'] instanceof Collection ? $data['scopes']->toArray() : $data['scopes']
|
||||
)
|
||||
),
|
||||
]];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return 'export.filter.activity.by_usersscope.Filter by users scope';
|
||||
return [
|
||||
'scopes' => [],
|
||||
];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'export.filter.activity.by_users_scope.Filter by users scope';
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user