Compare commits

...

527 Commits

Author SHA1 Message Date
nobohan
b59c69bce4 Feature: show 'Cc' for notications as Cc 2023-03-24 14:57:02 +01:00
nobohan
6f9da67942 Feature: add cc users in workflow: show in workflow history and breadcrumb 2023-03-24 09:46:39 +01:00
nobohan
609e2e1610 Add users in cc in workflow: fix code style 2023-03-23 11:24:21 +01:00
nobohan
d940d13d7d Feature: add cc users in workflow form: not required 2023-03-23 11:20:23 +01:00
nobohan
1cf99b4383 Feature: show my workflows in Cc in my workflow page 2023-03-23 10:47:52 +01:00
nobohan
c969b35fd1 Feature: show my workflows in Cc in homepage vue widget 2023-03-23 10:15:31 +01:00
nobohan
cbf8a9ff71 Feature: create a new API endpoint for my workflows in Cc 2023-03-23 10:14:40 +01:00
nobohan
7c18899249 Feature: send notification on ccuser for workflows 2023-03-21 20:14:11 +01:00
nobohan
f4f465b33a Feature: Add new field ccuser in workflow step form 2023-03-21 16:08:26 +01:00
nobohan
aed7fcebae Feature: Add new field ccuser in workflow step entity 2023-03-21 15:11:18 +01:00
44ecad2bca Fixed: re-introduce creator in async doc generation 2023-03-15 13:38:19 +01:00
d1bdf41c4c Feature: Force language when converting documents 2023-03-15 13:36:41 +01:00
4a30f310b8 FIX [referrer][deselect] allow referrer to be deselected in parcours edit form 2023-03-13 16:41:43 +01:00
896b4cdfe3 FIX [regroupment][datamapper] add condition to check if key exists in forms array 2023-03-10 15:36:18 +01:00
a272dabcaf Merge branch 'master' of gitlab.com:Chill-Projet/chill-bundles 2023-03-10 12:04:10 +01:00
3901fe2d32 FIX [translations][dutch] change some dutch translations 2023-03-10 12:03:33 +01:00
78858e84f2 Fixed: force a name when downloading a document without filename
see https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/1005
2023-03-09 18:01:39 +01:00
cc98f64be5 Merge branch 'issue702_document_title_activity_listing' into 'master'
Show document titles in activity listing

See merge request Chill-Projet/chill-bundles!498
2023-03-09 16:49:39 +00:00
6e812b54e1 Fixed: add small button and ACL on document edit 2023-03-09 17:47:52 +01:00
83e0a50b57 Fixed: do not alter layout for bootstrap 2023-03-09 17:47:32 +01:00
3aac4d5d35 FEATURE add download button to document listing 2023-03-09 17:41:31 +01:00
23cee274a5 FEATURE [documents][listing] show document titles in activity listing if there are any and user has see_detail rights 2023-03-09 17:41:31 +01:00
aacb54037b Merge branch '56-user-badges' into 'master'
Fixed: uniformize user badge #56

Closes #56

See merge request Chill-Projet/chill-bundles!503
2023-03-09 16:09:28 +00:00
57cb96320c Merge branch '54-display-action-button' into 'master'
Fixed: graphical bug: the download action button is overflowed #54

See merge request Chill-Projet/chill-bundles!501
2023-03-09 15:54:59 +00:00
5a2d80cb4d Merge branch '721-bug-location' into 'master'
Bug on Location admin page

See merge request Chill-Projet/chill-bundles!505
2023-03-09 14:26:32 +00:00
2e822a9486 Fix bug on admin Location Page with availableForUsers value 2023-03-09 12:35:29 +01:00
f376b1af49 UX: [badges] uniformize user badges in lists, shows and dashboards 2023-03-07 16:23:41 +01:00
dd621186e8 improve 2023-03-06 18:07:06 +01:00
1b15abe635 oops.. with condition 2023-03-06 17:59:55 +01:00
1965fc55f4 Fixed button DocumentActionsButtonsGroup display bug
- improve document table
- add a smallfont css classe to handle table style
when called from index or from show page
2023-03-06 17:47:33 +01:00
a9290eb3fe Merge branch 'issue704_private_comment_listing' into 'master'
Show private comment in activity listing

See merge request Chill-Projet/chill-bundles!497
2023-03-06 12:41:37 +00:00
e78eb8789d FIX [private comment] show private comment in activity listings 2023-03-06 13:39:34 +01:00
9911112e08 Merge branch 'issue711_confirm_referrer' into 'master'
Confirmation popup when referrer is changed for parcours

See merge request Chill-Projet/chill-bundles!496
2023-03-06 12:30:30 +00:00
c0675aee9b Fixed: set referrer from suggestion 2023-03-06 13:28:47 +01:00
03ee04978c FEATURE [confirm][popup] Add a popup asking for confirmation when referrer is changed to prevent mistakes and unecessary notifications 2023-03-06 13:20:10 +01:00
15d68df8c6 Merge branch 'issue716_change_field_thirdparty' into 'master'
Change profession field into string type

See merge request Chill-Projet/chill-bundles!492
2023-03-06 12:12:29 +00:00
1b2c0ecc87 fixed: use TEXT instead of VARCHAR to store profession 2023-03-06 13:01:22 +01:00
f15017ebd7 FIX don't delete profession_id column yet 2023-03-06 13:01:22 +01:00
9a56a1b115 FEATURE [migration] migrate the old profession_id to inserting the corresponding string into new profession column string type 2023-03-06 13:01:22 +01:00
11e7f2179c FIX [obsolete] remove obsolete code since thirdparty entity will be removed 2023-03-06 13:01:22 +01:00
e982e81900 FIX [post] adjust vue components to allow thirdparty to be posted with new profession type as string 2023-03-06 13:01:21 +01:00
e50b02a8c7 FIX [rendering] adjust vue components to correctly render profession string 2023-03-06 13:01:21 +01:00
bea839663f FEATURE [form] adjust symfony form to use text type 2023-03-06 13:01:21 +01:00
ac4c821290 FEATURE [profession] change field type of profession into string 2023-03-06 13:01:20 +01:00
c953da3fd0 Merge branch 'issue715_household_move_email' into 'master'
Issue715 household move email

See merge request Chill-Projet/chill-bundles!495
2023-03-06 11:38:13 +00:00
f5d17eb38c Merge remote-tracking branch 'origin/master' into issue715_household_move_email 2023-03-06 12:20:20 +01:00
73f332927d FIX [personMatcher] wrong syntax was used to setParameter for query in similar person matcher 2023-03-02 11:45:41 +01:00
ef75deda26 FIX [regroupment] remove CenterCompilerPass - no longer in use 2023-03-02 11:23:29 +01:00
6264a95d62 Merge branch 'master' of gitlab.com:Chill-Projet/chill-bundles 2023-03-02 11:12:12 +01:00
26a6169b95 FIX [budget][calculator] fix method call getAlias() 2023-03-02 11:11:40 +01:00
678defdee7 FIX [regroupment][form] add check to display regroupment field in the form or not. Only if regroupments exist 2023-03-02 10:52:48 +01:00
88ccbd450a Merge branch 'integrate_regroupment_entity' into 'master'
Feature: ask for center regroupment in exports

See merge request Chill-Projet/chill-bundles!486
2023-03-01 16:13:32 +00:00
62532e0a90 Fixes for feature "Regroupment of center"
* allow more than 15 character in regroupment name
* remove unused methods in PickCenterType
* show only active Regroupment in form
* remove dead code and commented code
2023-03-01 17:11:29 +01:00
73fa585707 Merge remote-tracking branch 'origin/master' into integrate_regroupment_entity 2023-03-01 16:50:53 +01:00
21a16dcbe2 Merge branch 'user_absences' into 'master'
Feature: allow users to say they are out of office

See merge request Chill-Projet/chill-bundles!476
2023-03-01 15:40:22 +00:00
b30e966316 DX: [absence] Remove unneccessary $em->persist() 2023-03-01 16:32:20 +01:00
9696a8194c DX: use the UserRenderBoxBadge to display user in AddPerson 2023-03-01 16:10:51 +01:00
6749758b46 Fixes for features "allow to set user absences" 2023-03-01 16:08:49 +01:00
f1ebc089c3 Merge remote-tracking branch 'origin/master' into user_absences 2023-03-01 14:59:43 +01:00
813adc70f4 Merge branch '52-repair-fixtures' into 'master'
Repair fixtures

See merge request Chill-Projet/chill-bundles!494
2023-03-01 13:57:21 +00:00
95984eff6d Apply 1 suggestion(s) to 1 file(s) 2023-03-01 13:55:35 +00:00
3db5b62d57 Feature: [UI] use download button group in calendar list 2023-02-28 22:37:46 +01:00
cf1cc937ca DX: ignore file in .cache directory (in use with php82 branch) 2023-02-28 22:37:00 +01:00
14df8fe9ad DX: remove implicit creation of a variable 2023-02-28 22:09:07 +01:00
fe4388c884 Feature: [docgen] implements normalization of data on CalendarContext 2023-02-28 22:01:52 +01:00
dbcc425f5f DX: improve performance for counting feature linked to person 2023-02-28 17:22:54 +01:00
77c545344c DX: adapt to php 7.4 2023-02-28 16:44:37 +01:00
c13d672db2 Merge branch '49-decouple-docgen' into 'master'
Resolve "Génération de document: mémoire disponible dépassée"

Closes #49

See merge request Chill-Projet/chill-bundles!493
2023-02-28 15:25:47 +00:00
a16244a3f5 Feature: [docgen] generate documents in an async queue
The documents are now generated in a queue, using symfony messenger. This queue should be configured:

```yaml
# app/config/messenger.yaml
framework:
    messenger:
        # reset services after consuming messages
        # reset_on_message: true

        failure_transport: failed

        transports:
            # https://symfony.com/doc/current/messenger.html#transport-configuration
            async: '%env(MESSENGER_TRANSPORT_DSN)%'
            priority:
                dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
            failed: 'doctrine://default?queue_name=failed'

        routing:
            # ... other messages
            'Chill\DocGeneratorBundle\Service\Messenger\RequestGenerationMessage': priority
```

`StoredObject`s now have additionnal properties:

* status (pending, failure, ready (by default) ), which explain if the document is generated;
* a generationTrialCounter, which is incremented on each generation trial, which prevent each generation more than 5 times;

The generator computation is moved from the `DocGenTemplateController` to a `Generator` (implementing `GeneratorInterface`. 

There are new methods to `Context` which allow to normalize/denormalize context data to/from a messenger's `Message`.
2023-02-28 15:25:47 +00:00
27f13e0dd1 FEATURE [menu][counters] show counter icon for person resources and residential address if there are any 2023-02-24 13:54:44 +01:00
f07ea3259e php cs fixes 2023-02-22 11:54:03 +01:00
1f4438690e FEATURE [email] add a line notifying referrer which user has moved a person or household 2023-02-22 11:36:57 +01:00
744b62184a fix LoadHousehold fixture 2023-02-17 14:48:02 +01:00
5ee0ab5ab8 fix LoadInvite fixture (CalendarBundle) 2023-02-17 13:32:33 +01:00
4370349f10 fix LoadCalendarRange fixture 2023-02-17 13:32:05 +01:00
6254303392 Revert "Feature: [docgen][stored object] update model to store status, template_id and fix defaults"
This reverts commit 55918bcafb.
2023-02-16 14:08:16 +01:00
9676975cd8 Revert "Feature: [docgen][stored object] handler for request generator and required fixes"
This reverts commit 91d21ba939.
2023-02-16 14:08:11 +01:00
7c4bc8f46a Revert commits linked to decoupling of docgen (changes not reviewed)
This reverts commit 55a845fcd6.
2023-02-16 14:07:47 +01:00
55a845fcd6 Sanitize DocGeneratorTemplateController constructor 2023-02-14 23:34:21 +01:00
91d21ba939 Feature: [docgen][stored object] handler for request generator and required fixes 2023-02-14 23:26:00 +01:00
55918bcafb Feature: [docgen][stored object] update model to store status, template_id and fix defaults 2023-02-14 20:57:34 +01:00
bb05ba0f17 Feature: [docgen] create a service to generate a document from a template 2023-02-14 19:35:28 +01:00
eac3471cbb FIX [person][contactinfo] place the contactinfo fields underneath birthdate for easier access 2023-02-10 11:37:32 +01:00
f653f8fd7a FIX [translations][wording] make distinction between parties concernees for an activity and an appointment in the translations 2023-02-10 11:30:26 +01:00
6d2c6fb6e1 FIX [renaming][translation] changing a translation for concerned groups in activities 2023-02-10 10:51:16 +01:00
aea6272c4d Merge improvements for admin's budget bundle 2023-02-09 18:20:33 +01:00
25cbb528ec Fixed: [budget] in admin list, show pagination and kind in resource_kind and charge_kind pages 2023-02-09 18:18:30 +01:00
2d013e110a Fixed: [budget] force budget kind and resource kind to have a unique kind field in database 2023-02-09 18:08:44 +01:00
d6df16973a Merge branch '693-filter-acp-by-user-job' into 'master'
693 on doit utiliser le métier du référent, et pas le métier du parcours

See merge request Chill-Projet/chill-bundles!482
2023-02-08 15:59:43 +00:00
80835dd7c3 Fixed: [export][filter by user's job] take into account the job associated to the user instead of the one associated to the course 2023-02-08 15:59:42 +00:00
9e63480c70 Merge remote-tracking branch 'origin/master' into 693-filter-acp-by-user-job 2023-02-08 16:44:50 +01:00
988495df27 Merge branch '697-add-filter-location' into 'master'
697 Filtrer les échanges par localisation

See merge request Chill-Projet/chill-bundles!481
2023-02-08 15:42:44 +00:00
cc62c9cc4a Feature: [export][activity] Add filter on localisation for activities 2023-02-08 15:42:44 +00:00
40924d9d39 Merge branch '698-filter-correction' into 'master'
698 Filtrer les actions par agent traitant: utiliser le formulaire avec AddPersons, et pas un EntityType

See merge request Chill-Projet/chill-bundles!480
2023-02-08 15:39:29 +00:00
8b505410ca Fixed: [export] filter referrer using dynamic picker in filter "agent traitant" for social works 2023-02-08 15:39:29 +00:00
d535ec6cfb Merge branch '676-docgen-center' into 'master'
676 fix docgen person center

See merge request Chill-Projet/chill-bundles!479
2023-02-08 15:22:09 +00:00
9029426d03 Feature: [docgen] add center when normalizing person 2023-02-08 15:22:08 +00:00
9ae2e51819 Merge branch '669-no-limit-for-location-endpoint' into 'master'
669 no limit for location endpoint

See merge request Chill-Projet/chill-bundles!478
2023-02-08 14:42:16 +00:00
68f7a832b4 Fixed: [activity] fetch all the available location, beyond the first page 2023-02-08 14:42:16 +00:00
af5f27ff49 Merge branch 'exports_activite_annexe' into 'master'
Feature: exports for aside activities

See merge request Chill-Projet/chill-bundles!485
2023-02-08 14:28:21 +00:00
5e58d36e79 Feature: exports for aside activities 2023-02-08 14:28:21 +00:00
b0ab591cbd Feature: [Document action buttons] do now show "Editer en ligne" for document which are not editable 2023-02-07 16:50:07 +01:00
d8af7d455e Fixed: [doc generation] fix summary budget 2023-02-07 16:22:26 +01:00
5830c3e177 Feature: [doc generation] show all the deps of the tree for debug information 2023-02-07 15:49:57 +01:00
1285100801 Merge branch 'integrate_regroupment_entity' of gitlab.com:Chill-Projet/chill-bundles into integrate_regroupment_entity 2023-02-07 15:49:08 +01:00
a4e21b7834 FEATURE [datamapper][regroupment] minor fix 2023-02-07 15:42:58 +01:00
1a44a516c2 FEATURE [datamapper][regroupment] make the datamapper work 2023-02-07 15:42:58 +01:00
fb9b9b9226 FEATURE [datamapper][regroupment] moved datamapper to seperate class. Still not working 2023-02-07 15:42:58 +01:00
0ace1c1f6a FEATURE [regroupment][form] integrate in regroupment admin entity into PickCenterType, datamapping not working 2023-02-07 15:42:58 +01:00
7d80507517 FEATURE [regroupment][exports] first commit to implement regroupment entity in exports 2023-02-07 15:42:58 +01:00
b5ec0919e7 FEATURE [datamapper][regroupment] minor fix 2023-02-07 15:41:28 +01:00
068311d071 FEATURE [datamapper][regroupment] make the datamapper work 2023-02-07 15:36:57 +01:00
88eefa698b Fixed: add string key for summary of charges and resources into doc generation 2023-02-07 15:09:40 +01:00
5756a37178 FEATURE [datamapper][regroupment] moved datamapper to seperate class. Still not working 2023-02-07 10:23:19 +01:00
c83e8ad9a4 FEATURE [regroupment][form] integrate in regroupment admin entity into PickCenterType, datamapping not working 2023-02-03 12:29:38 +01:00
c64ec89274 Merge branch 'master' of gitlab.com:Chill-Projet/chill-bundles 2023-02-01 14:14:43 +01:00
16ec858ee8 FIX [migration][budget] migration to change the comment on tags column from jsonb to json 2023-02-01 14:14:14 +01:00
de55ff920f Fixed: [budget] remove deprecated config repository and fix summary budget when generating document 2023-01-31 19:41:43 +01:00
885256ac0d Fixed: default value for type 2023-01-31 18:22:14 +01:00
f53d3852c3 Merge branch 'feature/add-convert-to-pdf-buttons' into 'master'
Feature: allow to convert to PDF from Chill and group action button on document

See merge request Chill-Projet/chill-bundles!487
2023-01-31 16:30:19 +00:00
9f5b11e6cc Feature: allow to convert to PDF from Chill and group action button on document
BREAKING CHANGE: avoid using the macro for download button. To keep the UI clean, use always the new "group of action buttons".
2023-01-31 16:30:19 +00:00
e5bc74d11d FIX [duplicates][birthdate] also verify duplication based on birthdate if available. Modified precision from .15 to .30 2023-01-31 16:11:11 +01:00
5c0d89a88b [phpcsfixer] 2023-01-31 14:40:21 +01:00
56a17a0bcd FIX [parcours][repo] if user is not within scope of the parcours, but (s)he is the referrer the parcours will appear in the list of parcours of a person 2023-01-31 14:38:51 +01:00
5bfd2aefe6 DX: [html] change deprecated tag 2023-01-30 15:20:13 +01:00
2165e04ec3 Fixed: [template] integration of absence alert box 2023-01-30 15:16:38 +01:00
1a8e21a77f Fixed: [vue] title hover translation for absent pill 2023-01-30 15:01:24 +01:00
9ffe1ff8a8 Fixed: fix loading of AddAddress
A conflict was not resolved correctly during a merge.
2023-01-30 12:20:50 +01:00
50bb8f10cf FEATURE [admin] add absence in user index admin 2023-01-27 12:25:05 +01:00
1c673db628 FIX [phpcsfixer][phpstan] 2023-01-27 12:18:19 +01:00
fa8a2c5cc5 FIX remove some whitespaces or empty lines + add btn in absence message homepage (still commented out) 2023-01-27 12:04:11 +01:00
d46304e229 FEATURE [banner][render] display the A icon within accourse banner if user is absent instead of string 2023-01-27 12:03:12 +01:00
4dd81da1ef FIX [routes][redirect] fix route naming and redirection after delete action 2023-01-27 11:23:29 +01:00
882e72b609 FIX fix condition to show form or not + sticky button for delete 2023-01-27 11:15:59 +01:00
bb7d072cc8 FIX [render] use isAbsent method to render user as absent or not + place homepage msg above searchbar 2023-01-27 11:10:17 +01:00
f76c031ff3 FIX [translations][types] remove redundant translator and change datetime field to date field 2023-01-27 10:51:59 +01:00
86b5f4dfac FIX [template][translations] fixes to template and translations 2023-01-27 10:44:25 +01:00
ded71c5997 Fixed: [migration] fix the required comment for doctrine on new column 2023-01-26 17:11:50 +01:00
5ae4eb1bf7 Merge branch 'master' into user_absences 2023-01-26 17:09:54 +01:00
c790b22496 Merge branch '685-export-list-evaluations' into 'master'
List exports (685 evaluation, 684 actions et 686 ménages)

See merge request Chill-Projet/chill-bundles!473
2023-01-26 14:22:31 +00:00
e54c2ca712 Feature: Add a list export for evaluation, actions and household 2023-01-26 14:22:30 +00:00
2f091a639b remove unused private function 2023-01-26 11:52:45 +01:00
7f9e045d5d FEATURE [regroupment][exports] first commit to implement regroupment entity in exports 2023-01-26 11:28:13 +01:00
9ada19ef23 FIX: [dump] remove dump 2023-01-25 18:32:57 +01:00
8ee184e665 Merge branch 'master' of gitlab.com:Chill-Projet/chill-bundles 2023-01-25 16:15:43 +01:00
c5f842076f FIX [phonenumber][search] fix advanced search when using a phonenumber 2023-01-25 16:14:59 +01:00
f9b151e4db Merge branch 'VSR-issues' into 'master'
VSR issues

See merge request Chill-Projet/chill-bundles!471
2023-01-25 12:50:59 +00:00
2c360e979b DX: remove comments which contains previous admin icons 2023-01-25 13:41:44 +01:00
459df26fef DX: fix cs 2023-01-25 13:36:35 +01:00
e36d2a5eec Fixed: missing key for user's data 2023-01-25 13:36:23 +01:00
0301641290 DX: keep the same case between translation key and translation 2023-01-25 13:34:36 +01:00
5c413edb32 Fixed: check for empty command
Use the the EmbeddableComment api for getting comment.
2023-01-25 13:26:57 +01:00
8e3a83de85 DX: [export] Rename JobAggregator to more logical UserJobAggregator 2023-01-25 12:03:39 +01:00
050a4feab5 Fix: [export][aggregator] group by user job, not by job 2023-01-25 11:55:13 +01:00
06238c8355 DX: more portable PickAsideActivityCategory
The label and required configuration options are set in the form type which calls the new type PickAsideActivityCategoryType
2023-01-24 15:47:39 +01:00
6b90a7d2a7 Merge branch 'master' into VSR-issues 2023-01-24 15:36:22 +01:00
de5f818c5a Merge branch 'budget_regroupment_admin' into 'master'
Budget regroupment admin

See merge request Chill-Projet/chill-bundles!477
2023-01-23 20:40:02 +00:00
c4eb45edcc Feature: allow to administrate budget resources and charges from the admin 2023-01-23 20:40:01 +00:00
99482edf0d Fixed: remove the "preload" component, and do not preload the period's json
This didn't accelerated the loading of period's pages, and make the period's json loaded twice.
2023-01-19 23:21:28 +01:00
e87f0bf348 Fixed: a userid can be null 2023-01-19 13:52:24 +01:00
bd324753f3 DX: fix cs 2023-01-19 13:28:13 +01:00
7915aae86f Feature: [workflow] do not send a notification for each step to creator's workflow
Now, by default:

- the creator will receive a notification for the last step only;
- the participant / assignee for each step won't receive a notification (unless they explicitly choose to receive one)
2023-01-19 13:27:08 +01:00
4fec18f3aa Fixed: [wopi] add a "graceful period" when removing a lock
This ensure that requests like putFile, which comes in the same time frame, encounter a "document is unlocked" error.
2023-01-19 13:21:11 +01:00
583d7b24ba Merge remote-tracking branch 'origin/export-2023-01-fixes' 2023-01-16 12:06:55 +01:00
4a56c4c945 Fixed: correct link for "edit wopi document" in javascript
The link was hardcoded, but not correctly adapted
2023-01-16 11:19:25 +01:00
239a978adb Fixed: [wopi] effectively use the ChillDocumentLockManager 2023-01-13 18:15:51 +01:00
b2dec3e587 Fixed: [social issue][admin] do not remove the parent when editing a social issue
https://gitlab.com/Chill-Projet/chill-bundles/-/issues/46
2023-01-13 16:43:02 +01:00
6bba6f68b3 DX: Remove deprecation on $this->get inside controller 2023-01-13 16:40:13 +01:00
164beb3ca9 Fixed: [Activity] fix appearance of reason list in Activity form
Fix https://gitlab.com/Chill-Projet/chill-bundles/-/issues/44
2023-01-13 16:15:05 +01:00
25dd65fbd8 Feature: [admin][ActivityReason] improve administration for activity reason
* list alphabetically;
* show "active" in index
2023-01-13 15:40:51 +01:00
e99fb75ebd Fixed: Fixed loading the list of activity reason category, in dedicated type
fix https://gitlab.com/Chill-Projet/chill-bundles/-/issues/35
2023-01-13 15:33:14 +01:00
08ddbee6af DX: Fix CS 2023-01-13 14:39:30 +01:00
a2b2cafbce Fixe: [regulation list] fix query when selecting a scope
Fix https://gitlab.com/Chill-Projet/chill-bundles/-/issues/45
2023-01-13 14:39:15 +01:00
a913d2820d Merge branch '43-wopi-use-access-token' 2023-01-13 13:22:08 +01:00
de9d53936f FEATURE [styling][absence] give styling 2023-01-12 19:51:43 +01:00
6c1108b8aa FEATURE: [homepage][absence] display message to let user know they are still marked as absent 2023-01-12 13:50:29 +01:00
5bbe5af124 FEATURE [absence][render] add absence tag to renderbox and renderstring 2023-01-12 13:30:28 +01:00
2c5c815f68 FEATURE [admin][absence] add possibility for admin to set absence of a user 2023-01-12 12:02:52 +01:00
44ef21f940 FEATURE [delete][absence] add functionality to unset absence 2023-01-12 11:51:42 +01:00
68998c9156 FEATURE [translations][absence] add translations 2023-01-12 11:50:06 +01:00
b93b78615b FIX [migration][absence] fix the typing in db for absence datetime immuatable 2023-01-12 11:12:32 +01:00
b2924ede70 FEAUTURE [routing][absence] use routing annotation instead of config file 2023-01-12 11:10:41 +01:00
01790fa0cf Fixed: [export] Fix checking of null value: take also empty string value 2023-01-11 17:42:50 +01:00
582983f5ef Fixed: [export] fixed translation message 2023-01-11 17:17:09 +01:00
fb51e44e45 FEATURE [absence][in_progress] add absence property to user, create form, controller, template, migration and menu entry 2023-01-11 17:16:37 +01:00
1f48900434 DX: fix CS 2023-01-11 16:55:10 +01:00
91494c07d5 Fixed: [export][Agreggator by type] handle correctly case when an acp or an activity does not have any location type 2023-01-11 16:55:03 +01:00
c05d153029 Fixed: [export][acp][group by scope] Fixed bug when no referrer or no scope for a referrer 2023-01-11 16:47:11 +01:00
5fea61c450 Fixed: [export][activity type filter for acp] fix filter for acp, by activity type
Use an `EXISTS` subquery instead of a JOIN.
2023-01-11 16:34:10 +01:00
e7ac8aafe1 DX: Fix missing import for AuthorizationHelperForCurrentUserInterface 2023-01-11 16:16:48 +01:00
34296e7841 Feature: [wopi] Implements the new required AuthorizationManager and UserManager for wopi 2023-01-10 20:26:44 +01:00
a34c102c4b DX: fix cs 2023-01-09 20:55:41 +01:00
c1c92dc296 Feature: use JWT access token for securing wopi endpoints 2023-01-09 20:55:25 +01:00
99455ca685 Fixed: [export][ACP by geographical unit] Fix the comparison of end date
There was a bug: the comparison of end date was "lower than" the given date, instead of "greater than".
2023-01-09 14:52:52 +01:00
e542ebe531 Deps: add lexix jwt bundle for handling access token 2023-01-07 21:03:58 +01:00
77e4b1d4ff Fixed: use the new native implementation of putFile to handle last-modified-timestamp correctly 2023-01-07 20:53:03 +01:00
b23019cb3a Fixed: use correct method for generating signature 2023-01-07 20:51:37 +01:00
1fad0f88a4 Deps: fix version of some deps 2022-12-30 00:14:15 +01:00
bbd2599e7e Fixed: [cron] store the last store of executed tasks correctly 2022-12-27 00:09:45 +01:00
5aa59aa0ff Deploy: upgrade chill bundles and adapt skeleton 2022-12-24 15:40:17 +01:00
351df930a1 DX: Fix CS 2022-12-23 13:36:32 +01:00
c8127a1d9d Fixed: ensure to execute Refresh Address To Geographical Unit Cronjob even during the day 2022-12-23 13:36:23 +01:00
f12f640cb4 Fixed: use correct comparison of body in makeFetch 2022-12-23 11:32:31 +01:00
4da9b6587d DX: remove console comment in file Person.vue 2022-12-23 11:30:40 +01:00
0fec753118 Merge branch 'cire16' into 'master'
Cire issue #16 : fix some stuffs for staging cire instance

See merge request Chill-Projet/chill-bundles!467
2022-12-22 18:51:33 +00:00
4d3d9db1b3 Fixed: Fix map center on opening or editing address 2022-12-22 19:29:56 +01:00
ce17f5f5c0 Fixed: [vue][add-address] fix map center when editing existing address (corrections post review)
52512e45fc (note_1205935758)
2022-12-22 11:31:44 +01:00
6a14c2b9b3 Fixed: [vue][add-address] fix map center when editing existing address
https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/674
2022-12-22 11:31:27 +01:00
ad94c7bcb7 DX: Fix CS and type hinting 2022-12-22 11:22:49 +01:00
3ca2811494 Feature: set parameters for add_address as global
The parameter `window.addaddress` is now global and can be reached to all page. This ensure backward compatibility.
2022-12-22 11:22:24 +01:00
1bc7221315 Feature: Set defaults values for add_address configuration
The default values were not set at the root of the array config. This create a default value to the array config
2022-12-22 11:21:05 +01:00
7a1cc9b076 Merge remote-tracking branch 'origin/master' into cire16 2022-12-22 10:22:58 +01:00
f7fa9c31f3 Merge branch '29-person-modal-on-the-fly-add-center' into 'master'
Resolve "La modale "on the fly" pour créer une personne ne fonctionne pas: il manque le centre"

Closes #29

See merge request Chill-Projet/chill-bundles!468
2022-12-21 16:34:52 +00:00
fa237bf27b Fix: missing translation of validation of center 2022-12-21 17:27:15 +01:00
64e65d08fe Fix: [center denormalizer] do not throw an error if deserializing a null center 2022-12-21 17:27:14 +01:00
1f58acd871 Feature: [person][creation] Add center field to OnTheFly/Person 2022-12-21 17:27:11 +01:00
b06a76784a Feature: [person][creation] api for listing availables centers for person creation 2022-12-21 17:25:23 +01:00
1585a73974 DX: [authorization helper] Create an authorization helper with current user already available
See https://gitlab.com/Chill-Projet/chill-bundles/-/issues/14
2022-12-21 17:25:22 +01:00
2deed644b6 Merge branch 'master' into VSR-issues 2022-12-15 15:19:43 +01:00
5211d092e3 Merge branch 'testing' into VSR-issues 2022-12-15 14:46:30 +01:00
ac084a1309 update gitignore 2022-12-14 18:30:17 +01:00
2ca3cced2e Merge branch '689-work-show-page' into VSR-issues 2022-12-14 18:29:04 +01:00
f17c08f530 Feature: [accompanying-course-work] add new page to show an accompanying-course work 2022-12-14 18:26:39 +01:00
2a9ebe436e prepare accompanying-course-work context for new template
* batch renaming css class name accompanying-course-work
* remove unused classes
* remove -list class
* remove double class
2022-12-14 15:00:38 +01:00
6ab5e708ec [backend] prepare new page: controller, route, link and minimal template 2022-12-14 14:58:50 +01:00
ba261ddeb9 Fixed: show list of workflow, event if some accompanying course document associated to a workflow are deleted 2022-12-14 13:52:37 +01:00
58ede06dfe Fixed: show list of workflow, event if some social action associated to a workflow are deleted 2022-12-14 13:46:31 +01:00
2dec6a017d Merge branch 'master' of gitlab.com:Chill-Projet/chill-bundles 2022-12-13 14:43:03 +01:00
fb42cb1baf Merge branch '25-bug-composition' 2022-12-13 14:42:10 +01:00
ae1df1f47a Fixed: [zone admin] fix edit link in composition index template 2022-12-13 14:41:54 +01:00
f2cbd7f4a3 Merge branch '30-add-cron-system' into 'master'
Handle cron within chill-bundle code

Closes #30

See merge request Chill-Projet/chill-bundles!472
2022-12-13 12:45:49 +00:00
7abecdea02 UX: [zone admin] column header more thin to improve placement 2022-12-13 12:29:25 +01:00
2be8aefb38 Fixed: [vue][add-address] fix map center when editing existing address (corrections post review)
52512e45fc (note_1205935758)
2022-12-13 11:45:32 +01:00
ff930e94f6 FEATURE: [export][form] use select2 for more user friendly form field 2022-12-13 10:07:00 +01:00
38ff46f03f FIX: [export][activity] mistake in the alias 2022-12-13 10:00:55 +01:00
d41dc7035c Doc: doc for CronJobManagerInterface 2022-12-12 23:29:03 +01:00
23d7d1c8f0 Doc: doc for installation and cronjob, and addresses 2022-12-12 22:49:50 +01:00
acfa3d6849 Fixed: [cronjob command] force command name 2022-12-12 22:49:30 +01:00
0bfb5c617e Doc: [cronjob manager] Doc for implementing cronjob 2022-12-12 22:48:57 +01:00
17461aa21e Fixed: [cronjob manager] Fix execution of one single job 2022-12-12 22:21:46 +01:00
7d469df62a Feature: CronJob for refreshing materialized view association between address and geographical unit 2022-12-12 21:17:03 +01:00
204ebd4415 Feature: bootstrap dependency injection for CronJobManager and create a command 2022-12-12 21:16:27 +01:00
b789250b8d Feature: bootstrap dependency injection for CronJobManager 2022-12-12 21:15:58 +01:00
1ebdcd1530 Feature: create table for CronJobExecution 2022-12-12 21:15:32 +01:00
e93458f943 Fixes: Fix doctrine annotation and repository for CronJobExecution 2022-12-12 21:15:05 +01:00
ceee5e7eea Feature: [cron] Create an interface for CronManagerInterface 2022-12-12 21:14:33 +01:00
9f00754eb7 Merge branch '675-active-scope' into VSR-issues 2022-12-12 20:33:35 +01:00
0f7d4ce5ee Admin Section: misc templates corrections and improvments
* reset admin vertical menu custom styles
* disable icons in admin vertical menu
* fix main content positioning in admin section
* fix table appearance in admin crud template
* new scope/center form: move submit button in record_action sticky area
* edit scope/center form: move submit button in record_action sticky area
* improve homogeneity in admin index pages: centers/scopes/users/jobs
* remove centered div old tags
2022-12-12 20:31:30 +01:00
1eb1e2ec24 Fixed: [scope] api, picker and admin form consider 'active' property
* add active field in admin scope form
* issue: https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/675
2022-12-12 20:29:17 +01:00
52512e45fc Fixed: [vue][add-address] fix map center when editing existing address
https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/674
2022-12-12 16:37:06 +01:00
49380f5f61 fix template regressions with add_address component
Component works in modal or in main frame. CSS Flex position parent-children directives were broken.
Hope that fix don't introduce others display bug in any cases !
2022-12-12 15:04:30 +01:00
e0c9e12008 Feature: [cron] Create a cron job to refresh materialized view address - geographical unit association 2022-12-12 14:35:46 +01:00
4fcfe3f5d2 Feature: [cron] Create a cron manager 2022-12-12 14:02:19 +01:00
333e524136 Merge branch 'calendar/finalization' into testing 2022-12-12 13:50:58 +01:00
3c85b5ca92 Fixed: a bug for range generatoion during week-end
The range generator failed during week-end, because no range is selected (lastStart and endDate is null).

with this commit, the rangeGenerator may return null instead of an array, which means no sms will be send.
2022-12-12 13:09:31 +01:00
ff7f5a5dd3 Fixed: [vue][accompanyingCourse] typeError in toaster when removing referrer
https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/667
2022-12-09 12:39:29 +01:00
fb8f74119f Merge branch '670-private-comments-markdown' into VSR-issues 2022-12-08 16:26:20 +01:00
34602d0a56 Fixed: markdown resolution for private comments
note: j'ai une branche locale wip ou j'essaie d'implémenter un renderbox pour les private comments
2022-12-08 16:24:48 +01:00
43a4576ed4 Merge branch '668-select2-aside-activity' into testing 2022-12-08 15:01:12 +01:00
a32d20e320 Fixed: [form] improve Aside Activity category form selector 2022-12-08 15:00:45 +01:00
7e6ef3dafe fix some errors in twig templates 2022-12-08 14:22:06 +01:00
7e06d7beed Merge branch '677-order-social-actions' into testing 2022-12-08 14:03:51 +01:00
8e65b3851a FIXED: [api] sort socialactions by ordering
https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/677
2022-12-08 14:03:09 +01:00
aca81122d5 Merge branch 'calendar/finalization' into testing 2022-12-08 13:42:25 +01:00
5a93e21758 Merge branch '681-order-users-api' into testing 2022-12-08 10:42:22 +01:00
368846e09b FIXED: [api] sort users list by label
https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/681
2022-12-08 10:39:58 +01:00
efe494d61f handle package version from within chill bundles 2022-12-07 15:42:39 +01:00
c050c42a27 Fixed: [My Calendar Ranges] fix use of legacy mode in vue createI18n 2022-12-07 14:15:52 +01:00
6309877a14 Fixed: [relationship graph] fix layout of button to add a link (upgrade bootstrap) 2022-12-07 12:18:35 +01:00
8d19e8d7af Fixed: Fix padding inside top right menus 2022-12-07 12:00:31 +01:00
34c97769a6 Fixed: Fix modal layout with bootstrap upgrade 2022-12-07 12:00:14 +01:00
a10aae2100 Deploy: update webpack config for postcss loader and ckeditor 2022-12-06 22:27:27 +01:00
516e4e5f47 Fixed: fix the loading of bootstrap
See https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/690
2022-12-06 21:25:35 +01:00
531b49a536 Merge branch '111_exports_suite' into calendar/finalization 2022-12-06 21:21:01 +01:00
5328bee262 Fixed: [SocialAction] Fix the loading of evaluations associated to a SocialActions 2022-12-06 10:17:49 +01:00
060d5d5ca3 Merge remote-tracking branch 'origin/master' into 111_exports_suite 2022-12-05 20:52:33 +01:00
368136ea57 Feature: [activity][list] Fix list for activities and refactor list with an helper 2022-12-05 18:26:01 +01:00
d080dfda9a DX: Fix CS 2022-12-05 18:26:01 +01:00
88fb48e2be Fixed: let the aggregator "Activity by type" be shown again 2022-12-05 18:26:01 +01:00
feb760a97b Merge branch 'calendar/finalization' into testing 2022-11-29 16:08:05 +01:00
e97a04ab54 Feature: [Calendar doc] Pick document to generate inside the edit/new form 2022-11-29 15:27:36 +01:00
c16454214d Merge branch 'calendar/finalization' into testing 2022-11-28 21:38:35 +01:00
be5f87348b Feature: [CalendarDoc] pick template for generating calendar directly in list 2022-11-28 21:37:17 +01:00
e71bb5d77b Merge branch 'calendar/finalization' into testing 2022-11-28 14:54:26 +01:00
6cac298724 Feature: [Calendar doc] show an alert when document is linked to a previous datetime version of the calendar 2022-11-28 14:40:33 +01:00
39f410dc8f Feature: [Calendar doc] complete CRUD for associating documents within Calendar 2022-11-28 14:33:06 +01:00
fc15b85d11 DX: [accompanying period] refactor the getCenters method
Use more portable spl_object_hash for listing different centers
2022-11-28 12:24:10 +01:00
74673380aa Fixed: [calendar] refactor ACL on calendar 2022-11-28 12:22:58 +01:00
72ae6fb2cd merge calendar/finalization into testing: fix conflicts 2022-11-28 09:33:24 +01:00
a73dca5efe Feature: [calendar] show the number of calendars ignored by the date filter, in the list 2022-11-25 17:27:42 +01:00
8cbfe16c24 DX: Fix cs 2022-11-25 17:02:57 +01:00
9b32ce53c8 Fixed: [calendar] add a return path to calendar doc
See https://gitlab.com/Chill-Projet/chill-bundles/-/issues/23
2022-11-25 17:02:12 +01:00
788b1e9eeb Fixed: [calendar] Fix picking calendar document templating, when adding document in person context 2022-11-25 16:51:41 +01:00
57e1786b99 Fixed: [calendar] Always show filter of calendars in list 2022-11-25 16:50:56 +01:00
6eb23c6073 Feature: [calendar] add proper location on short message text for next rendez-vous 2022-11-25 16:28:00 +01:00
b6e3baa5dc DX: fix cs 2022-11-25 16:04:40 +01:00
02a7074218 Fixed: [calendar] Do not require scope when adding calendar roles 2022-11-25 15:57:50 +01:00
593caec851 Merge remote-tracking branch 'origin/111_exports_suite' into calendar/finalization 2022-11-25 15:29:17 +01:00
9913938c1b show x instead of 1 or 0 for boolean field in export 2022-11-25 14:19:22 +01:00
7c8ac8cfcb Merge branch '111_exports_suite' into testing 2022-11-25 14:17:16 +01:00
3ebf3ae148 fix activity list export for linked with person 2022-11-25 14:16:44 +01:00
24833be681 take into account null value in formatter 2022-11-25 14:15:56 +01:00
6777cf7225 household can be null in budget abstractElement 2022-11-24 13:01:55 +01:00
3b9e6d2742 fix z-index of dropdown menus 2022-11-24 11:12:01 +01:00
390da7c641 Merge branch 'testing' of gitlab.com:Chill-Projet/chill-bundles into testing 2022-11-21 11:11:57 +01:00
d3e784de15 DX: fix cs 2022-11-20 21:28:07 +01:00
d35dacf562 Fixed: [budget] Fix voter on household's budget 2022-11-20 21:27:19 +01:00
cd54fdd13f Feature: [activity] automatically add a person to an activity, if
created in the person context

See https://gitlab.com/Chill-Projet/chill-bundles/-/issues/28
2022-11-18 16:12:49 +01:00
448d93cd02 Fixed: [address] Add missing window.addaddress in person create page, and third party create and update page 2022-11-18 16:11:03 +01:00
8894491dac #16 fix error with vue_activity component in person context (when accompanyingPeriod is null) 2022-11-17 21:43:03 +01:00
999e9e8553 Feature: [workflow] do not subscribe user on notification for each step
automatically
2022-11-17 19:17:30 +01:00
3ca46efd2c #16 pass default variables to add-address component when it is called from another vue component 2022-11-17 19:02:07 +01:00
e90782500b #16 add default value for config variables 2022-11-16 23:10:11 +01:00
0f159281ba Merge branch '111_exports_suite' into testing 2022-11-16 22:53:38 +01:00
15c304b1d1 Feature: [rolling date] do not show the fixed date input, unless the fixed date value is picked 2022-11-16 22:52:30 +01:00
53980dd757 #16 replace hardcoded country and map_center in vue add-address by symfony config yaml variables 2022-11-16 22:30:05 +01:00
c1261f63e7 Merge branch 'testing' of gitlab.com:Chill-Projet/chill-bundles into testing 2022-11-16 18:41:42 +01:00
80f6b7d330 cs fix 2022-11-16 18:41:26 +01:00
56a7833858 #16 Fix html5 widget for ChillDateTimeType 2022-11-16 17:44:48 +01:00
318d6b6d4e Fixed: remaining options not linked with PickRollingDateType 2022-11-16 14:58:08 +01:00
d0e1f31ec7 Fixed: [saved exports] Fix a test in list when no export ungrouped 2022-11-16 14:58:08 +01:00
15871db7fd Fixed: [saved exports] Transform null strings into blank strings, and add validation 2022-11-16 14:58:08 +01:00
00bf7bf299 DX: fix construct of ReferrerScopeAggregator in test 2022-11-16 14:58:07 +01:00
dafd715efd Merge branch '111_exports_suite' into testing 2022-11-16 14:32:54 +01:00
928869666c #16 fix errors and some design regressions in eventBundle 2022-11-16 13:09:59 +01:00
9623a35e6f #16 EventBundle participation (fix errors and improve ux) 2022-11-16 10:57:06 +01:00
d58aad4624 improve savedExport translation 2022-11-15 22:08:15 +01:00
a39f547907 fix flex-bloc look in exports list and saved exports 2022-11-15 22:01:35 +01:00
0e661784b0 DX: fix construct of ReferrerScopeAggregator in test 2022-11-15 18:17:58 +01:00
fc607d6a0e DX: improve import command + help for address-ref-from-best-addresses 2022-11-15 16:16:52 +01:00
2f765a3aa5 Merge branch 'testing' of gitlab.com:Chill-Projet/chill-bundles into testing 2022-11-15 13:44:14 +01:00
9ad3bbc1b4 Fixed: fix typo in workflows 2022-11-15 11:58:26 +00:00
f144663877 Fixed: Fix typo in message for activity 2022-11-15 11:46:32 +00:00
434ef075da Feature: Add geographical unit name and ref ids in list, associated to address 2022-11-14 17:06:39 +01:00
2db778c4a4 fix chill-bundles#25 RollingDate bad expression 2022-11-14 16:18:04 +01:00
2178485e5e Merge branch '111_exports_suite' of gitlab.com:Chill-Projet/chill-bundles into 111_exports_suite 2022-11-14 16:12:30 +01:00
e767557216 csfixer 2022-11-14 16:03:04 +01:00
68bfb082fc chill-bundles#25: replace ChillDateType by PickRollingDateType
batch/serial replacing
untested
2022-11-14 15:43:02 +01:00
1f3dd00d81 improve flex positionning for list exports cards 2022-11-14 15:43:02 +01:00
f633fabf79 Merge branch '111_exports_suite' into testing 2022-11-14 14:23:49 +01:00
cf6430ae9b Feature: Adapt geographical unit filters and aggregator to use the materialized view, instead of geographical computation (improve performance) 2022-11-14 14:22:48 +01:00
d3ba11f521 Feature: Store location of each address contained in geographical units in a materialized view 2022-11-14 14:21:03 +01:00
f3401faea1 Merge branch '111_exports_suite' into testing 2022-11-14 11:29:26 +01:00
ec9555ec84 Merge branch 'exports/apply-person-modifier-on-course' into '111_exports_suite'
Apply persons filters and aggregators on accompanying course

See merge request Chill-Projet/chill-bundles!466
2022-11-14 10:22:48 +00:00
a68422e0e8 Features: [export] Apply person filters and aggreators on Count Household 2022-11-14 11:21:16 +01:00
400770123a Features: [export] Apply person filters and aggreators on Count Evaluation 2022-11-14 10:46:13 +01:00
91e3588e76 Features: [export] Show also SocialIssue in the By Social Action aggregator 2022-11-10 21:17:48 +01:00
61f44396c5 Features: [export] Apply person filters and aggreators on Count Social Works export 2022-11-10 15:51:46 +01:00
8e44f20535 Features: [export] Remove old unnecessary filters for person with accompanying period
Those filters applyed on persons and allowed to select person which has a new, closing, or active accompanying period. But this is deprecated: there are now a dedicated Export for that ( CountPersonWithAccompanyingCourse)
2022-11-10 15:21:56 +01:00
a7c44830d2 Features: [export] Filter "persons who do not have a household composition" 2022-11-10 15:11:45 +01:00
a942a24596 Fixes: [export] fixes filters by household composition, and apply them on persons directly 2022-11-09 20:46:15 +01:00
826a975fbe Features: apply all the filters and aggregators concerning person on accompanying courses 2022-11-09 16:20:24 +01:00
c1df8084a6 DX: Add DQL function LEAST and GREATEST 2022-11-09 15:48:20 +01:00
c22135f101 Feature: [export] apply all filters valid for person on accompanying course 2022-11-09 14:50:22 +01:00
a2e1228c09 Merge branch 'testing' of gitlab.com:Chill-Projet/chill-bundles into testing 2022-11-09 11:39:28 +01:00
11f0cac86e Merge branch '111_exports_suite' into testing 2022-11-09 10:47:07 +01:00
9dba5965f6 Merge branch '21-save-exports' into '111_exports_suite'
Allow to save exports

See merge request Chill-Projet/chill-bundles!465
2022-11-09 09:44:07 +00:00
be38251a13 Feature: [saved export] Switch between list of export and saved export thanks to nav at the list's top 2022-11-08 19:59:43 +01:00
43791badd5 Feature: [saved export] Edit and delete saved exports 2022-11-08 19:24:22 +01:00
79e9906a05 Feature: [saved export] Générate a report from a saved export 2022-11-08 18:02:26 +01:00
aec4c52567 Feature: [saved export] First list of saved exports 2022-11-08 16:57:49 +01:00
ccb2cd0295 Feature: [saved export] Create a "saved export" 2022-11-08 10:20:38 +01:00
8aeeab9e6b Feature: Apply rolling "open between dates filters" (accompanying period) 2022-11-07 21:18:56 +01:00
48da6d0a92 Feature: Apply rolling date on StepAggregator 2022-11-07 21:11:20 +01:00
50db96ffbc Fix validation of fixed date 2022-11-07 18:20:34 +01:00
86be95ac43 Feature: [export] Add a rolling date on Acp "by step" filter 2022-11-07 18:20:22 +01:00
8159f91e25 DX: create interface for RollingDateConverterInterface 2022-11-07 18:19:35 +01:00
0756bec580 DX: fix cs 2022-11-07 18:07:26 +01:00
4e3c93cdd3 DX: Add validation to PickRolingDateType
It is not possible to pick a fixed date when not setting a fixed date
2022-11-07 17:56:30 +01:00
c7f740d5d7 DX: Add rolling date converter + unit test 2022-11-07 17:42:00 +01:00
5489178e4b DX: Create a RollingDate data transfer object and Form type 2022-11-07 14:06:47 +01:00
3b96ac3ef3 DX: fixed double declaration of AsideActivity 2022-11-07 11:43:21 +01:00
df4f5e7cf8 Fixed: [export] improve memory footprint for filter by Geographical Unit 2022-11-07 11:31:23 +01:00
82d9ab8ca6 DX: [export] review on CreatorFilter, CreatorJobAggregator, CreatorJobFilter 2022-11-07 11:31:23 +01:00
c05637bc72 evaluations aggregators 2022-11-07 11:31:23 +01:00
d450f06286 filters and aggregator aside activity 2022-11-07 11:31:23 +01:00
3b68997c69 Feature: [export][evaluation] Group evaluation by start date 2022-11-07 11:31:23 +01:00
17e8e1964d Feature: [export][evaluation] Adding group by evaluation having end date 2022-11-07 11:31:23 +01:00
bf5ecd25de Feature: [export][evaluation] filter by current evaluation (without any end date) 2022-11-07 11:31:23 +01:00
9fa3a72cb4 Feature: [export][evaluation] add by end date filter 2022-11-07 11:31:23 +01:00
f10a448ae9 DX: prevent collision in parameter name in evaluation / by start date filter 2022-11-07 11:31:23 +01:00
9bfc184f70 Feature: [export][work] Group by current action 2022-11-07 11:31:23 +01:00
2e60b6735a DX: more cs 2022-11-07 11:31:23 +01:00
2ee362bfd5 Feature: [export][action] Filter 'active' action: which does not have an end date 2022-11-07 11:31:23 +01:00
b42e1a9a05 Feature: [export][activity] Add an aggregator to group by sent / received 2022-11-07 11:31:21 +01:00
055acbf43c DX: more code style fixes 2022-11-07 11:30:51 +01:00
5655f953d7 Feature: [export] group accompanying period by number of actions 2022-11-07 11:30:51 +01:00
e6553e71ee Feature: [export] filter accompanying period which has no action - work 2022-11-07 11:30:51 +01:00
7f9e8c5a7b Feature: [export] add aggregator by "number of activity" for acp 2022-11-07 11:30:51 +01:00
f3a3cab801 DX: review for hasNoActivityFilter 2022-11-07 11:30:51 +01:00
d6b358cfa1 Fixed: fix date's type in DateType input, and prevent collision on
parameter name
2022-11-07 11:30:51 +01:00
abd79df8cd count aside activity 2022-11-07 11:30:51 +01:00
dc38e5927c voter aside activity created 2022-11-07 11:30:51 +01:00
18406e83a1 creator job aggregator 2022-11-07 11:30:51 +01:00
6687742e23 DX: simplify creatorJobFilter 2022-11-07 11:30:51 +01:00
2767075be7 Feature: [export] Finalize HasTemporaryLocation filter on accompanying
course
2022-11-07 11:30:51 +01:00
371a7dc05c Fixed: handle null value in SentReceivedAggregator 2022-11-07 11:30:51 +01:00
63129a3b8c setup aside activity export 2022-11-07 11:30:14 +01:00
8ea29e8ec4 add translations creator filters 2022-11-07 11:30:14 +01:00
2bdc06397e creator job filter 2022-11-07 11:30:14 +01:00
edd9aaa475 comment out builder method 2022-11-07 11:30:14 +01:00
5695564723 fix code style 2022-11-07 11:30:13 +01:00
fc9689e881 DX: repairs code style, and psalm types 2022-11-07 11:29:09 +01:00
75f69859e6 fix psalm errors 2022-11-07 11:29:09 +01:00
b5a9dac62e Feature: [export] Add a list of accompanying periods 2022-11-07 11:29:09 +01:00
bf58c5d59c Feature: [export] add a list of people having an accompanying period 2022-11-07 11:29:09 +01:00
8a395bf108 DX: ensure that the return type is correct in ListPersonHelper 2022-11-07 11:29:09 +01:00
1ed367e079 Fixed: [export][acl][Social issue filter] fix type for retrieving data from form 2022-11-07 11:29:09 +01:00
e3801d54b4 DX: Refactor ListPerson to extract methods linked to label and select 2022-11-07 11:29:09 +01:00
4c9cdb7b8c Fixed: [list person] fix list person and add new fields 2022-11-07 11:29:09 +01:00
2096e175d4 Fixed: [export][list person] use address from household for person list 2022-11-07 11:29:09 +01:00
781253a854 Fixed: correctly show datetime in spreadsheet list 2022-11-07 11:29:09 +01:00
c396635163 acp creator filter 2022-11-07 11:29:09 +01:00
eeb84d5cfb php csfixes 2022-11-07 11:29:09 +01:00
fc2f8d33e1 correct namespace and use statements 2022-11-07 11:29:09 +01:00
a69965345f correct config file 2022-11-07 11:29:09 +01:00
226f172970 SentReceivedAggregator (in activity) 2022-11-07 11:29:09 +01:00
6d0622aa38 HasNoActivityFilter (in activity) 2022-11-07 11:29:09 +01:00
0e553594a0 CurrentEvaluationsFilter 2022-11-07 11:29:09 +01:00
f714c7206c ByEndDateFilter evaluation 2022-11-07 11:29:09 +01:00
42012dbad2 ByStartDateFilter evaluation 2022-11-07 11:29:09 +01:00
bc41910a39 HasNoReferrer filter 2022-11-07 11:29:09 +01:00
a18870c91e Evaluation HavingEndDate Aggregator 2022-11-07 11:29:09 +01:00
68ebf8303c remove ByMaxDateFilter (evaluation) 2022-11-07 11:29:09 +01:00
9e89302aa4 SocialWork: Current actions filter + aggregator 2022-11-07 11:29:09 +01:00
2e52729806 acp HasNoAction Filter (UNTESTED) 2022-11-07 11:29:09 +01:00
afb5ebc077 define queryKey in 11 aggregators 2022-11-07 11:29:09 +01:00
f751d2e9ab create 13 new export/filters/aggregators in Person and AsideActivity Bundles
* minor corrections on last commit
* modify related files (declaration, messages.fr, repository)
* yaml service declaration
2022-11-07 11:29:09 +01:00
13d6e4587a Create 16 new filters/aggregators in Bundles: Vendée, Person, Activity
Basic file creation, with methods, namespace, and title translation
2022-11-07 11:29:09 +01:00
6fd75a175f Fixed: [export] improve memory footprint for filter by Geographical Unit 2022-11-03 13:59:16 +01:00
03e765f811 DX: [export] review on CreatorFilter, CreatorJobAggregator, CreatorJobFilter 2022-11-03 12:39:19 +01:00
d3f03fb27c evaluations aggregators 2022-11-02 20:06:03 +01:00
481be32997 filters and aggregator aside activity 2022-11-02 20:02:46 +01:00
4524240ad8 Merge branch '111_exports_suite' of gitlab.com:Chill-Projet/chill-bundles into 111_exports_suite 2022-11-02 18:39:11 +01:00
0255f12fa9 Feature: [export][evaluation] Group evaluation by start date 2022-11-02 16:42:23 +01:00
4ca10ce38d Feature: [export][evaluation] Adding group by evaluation having end date 2022-11-02 16:26:56 +01:00
f0b2ec1348 Feature: [export][evaluation] filter by current evaluation (without any end date) 2022-11-02 16:17:10 +01:00
2d40c38c88 Feature: [export][evaluation] add by end date filter 2022-11-02 15:56:48 +01:00
d8104c4443 DX: prevent collision in parameter name in evaluation / by start date filter 2022-11-02 15:08:04 +01:00
63d38e35f7 Feature: [export][work] Group by current action 2022-11-02 14:55:12 +01:00
9c3533d106 count aside activity 2022-11-02 14:42:44 +01:00
e07d2ab467 voter aside activity created 2022-11-02 14:41:59 +01:00
cda25d3459 DX: more cs 2022-11-02 14:40:17 +01:00
1bf7f9945c Feature: [export][action] Filter 'active' action: which does not have an end date 2022-11-02 14:39:36 +01:00
9cf06c147f Feature: [export][activity] Add an aggregator to group by sent / received 2022-11-02 14:25:52 +01:00
60f93f7f12 DX: more code style fixes 2022-11-02 14:06:10 +01:00
c872ca7204 Feature: [export] group accompanying period by number of actions 2022-11-02 14:05:16 +01:00
51ac4e0938 Feature: [export] filter accompanying period which has no action - work 2022-11-02 13:44:04 +01:00
24873f0cc2 Feature: [export] add aggregator by "number of activity" for acp 2022-11-02 13:33:33 +01:00
84e5be6a60 DX: review for hasNoActivityFilter 2022-11-02 13:21:26 +01:00
5acf2a1986 creator job aggregator 2022-11-02 13:17:03 +01:00
094a912e42 Fixed: fix date's type in DateType input, and prevent collision on
parameter name
2022-11-02 13:15:40 +01:00
f40aa89d08 Merge branch '111_exports_suite' of gitlab.com:Chill-Projet/chill-bundles into 111_exports_suite 2022-11-02 13:14:50 +01:00
50e2f4a147 setup aside activity export 2022-11-02 13:14:38 +01:00
be215bd135 DX: simplify creatorJobFilter 2022-11-02 13:05:12 +01:00
be75cdce55 Feature: [export] Finalize HasTemporaryLocation filter on accompanying
course
2022-11-02 12:56:13 +01:00
e46b285d3e Fixed: handle null value in SentReceivedAggregator 2022-11-02 12:56:13 +01:00
17a7b053cf DX: remove unused variable 2022-11-02 12:56:13 +01:00
32cdf56fbd add translations creator filters 2022-11-02 12:00:29 +01:00
749facb9b0 creator job filter 2022-11-02 11:55:36 +01:00
edd1557f35 comment out builder method 2022-11-02 11:32:55 +01:00
3059935305 merge conflict fixed 2022-11-02 11:20:11 +01:00
355436aa82 acp creator filter 2022-11-02 11:15:54 +01:00
8d4ec5d675 fix code style 2022-11-02 11:12:55 +01:00
c20b561de5 Merge branch 'exports/listes_2022' into '111_exports_suite'
Repairs and add new lists in exports

See merge request Chill-Projet/chill-bundles!464
2022-11-02 09:54:13 +00:00
acc9523ff5 DX: repairs code style, and psalm types 2022-11-02 10:52:49 +01:00
afa6dfd77c fix psalm errors 2022-11-02 10:52:49 +01:00
c331f94201 fix cs 2022-11-02 10:52:49 +01:00
6ffe99a2be Feature: [export] Add a list of accompanying periods 2022-11-02 10:52:49 +01:00
d75ec92417 Feature: [export] add a list of people having an accompanying period 2022-11-02 10:52:49 +01:00
4e55f1ede7 DX: ensure that the return type is correct in ListPersonHelper 2022-11-02 10:52:49 +01:00
cf7d0c1bdb Fixed: [export][acl][Social issue filter] fix type for retrieving data from form 2022-11-02 10:52:49 +01:00
f4c3997e55 DX: Refactor ListPerson to extract methods linked to label and select 2022-11-02 10:52:49 +01:00
f434cc5c02 Fixed: [list person] fix list person and add new fields 2022-11-02 10:52:49 +01:00
333c305eef Fixed: [export][list person] use address from household for person list 2022-11-02 10:52:49 +01:00
4af261a366 Fixed: correctly show datetime in spreadsheet list 2022-11-02 10:52:49 +01:00
1228a0323c php csfixes 2022-11-02 10:28:52 +01:00
dc149c7fd5 correct namespace and use statements 2022-11-02 10:26:44 +01:00
7dc34cb357 correct config file 2022-11-02 10:15:08 +01:00
ed04c276c2 SentReceivedAggregator (in activity) 2022-10-31 16:18:10 +01:00
f8b5078997 HasNoActivityFilter (in activity) 2022-10-31 16:10:24 +01:00
68b9c171a6 CurrentEvaluationsFilter 2022-10-31 15:54:41 +01:00
791ea25e4f ByEndDateFilter evaluation 2022-10-31 15:51:35 +01:00
e3846829e1 ByStartDateFilter evaluation 2022-10-31 15:46:29 +01:00
d48474bbc9 HasNoReferrer filter 2022-10-31 15:32:34 +01:00
05f9a83bed Evaluation HavingEndDate Aggregator 2022-10-31 15:15:35 +01:00
441c5c8da7 remove ByMaxDateFilter (evaluation) 2022-10-31 14:58:25 +01:00
a0fc9d4de5 SocialWork: Current actions filter + aggregator 2022-10-31 11:43:41 +01:00
8527c19073 acp HasNoAction Filter (UNTESTED) 2022-10-31 11:19:21 +01:00
fe120086c7 define queryKey in 11 aggregators 2022-10-28 16:59:11 +02:00
f1fb77187f create 13 new export/filters/aggregators in Person and AsideActivity Bundles
* minor corrections on last commit
* modify related files (declaration, messages.fr, repository)
* yaml service declaration
2022-10-28 16:48:09 +02:00
43d9ba1ba5 Create 16 new filters/aggregators in Bundles: Vendée, Person, Activity
Basic file creation, with methods, namespace, and title translation
2022-10-28 13:07:24 +02:00
77a6e92f69 fix if condition in CalendarController + phpStan error 2022-10-26 11:08:37 +02:00
e1b6fb2db1 Merge branch 'master' into testing 2022-10-25 10:17:25 +02:00
2a4a4a80b1 change name of échange to activité 2022-10-25 10:11:42 +02:00
2e44689549 Merge branch 'calendar/finalization' into testing 2022-10-24 11:12:49 +02:00
eb404404f9 Merge remote-tracking branch 'origin/111_exports_suite' into testing 2022-10-17 09:16:39 +02:00
a26029999f Merge branch '111_exports_suite' into testing 2022-10-12 11:30:52 +02:00
dbf3780593 Merge branch '111_exports_suite' into testing 2022-10-05 15:47:25 +02:00
b20a75c2ee Merge branch '111_exports_suite' into testing 2022-10-05 15:28:51 +02:00
71db287ded Merge branch '111_exports_suite' into testing 2022-10-05 14:57:55 +02:00
5f0a6f37b0 Merge branch '111_exports_suite' into testing 2022-10-05 10:43:35 +02:00
fa1b5c4a02 Merge branch 'workflow-show-link' into testing 2022-10-05 10:23:08 +02:00
4388331b2f Merge branch '111_exports_suite' into testing 2022-10-05 10:21:42 +02:00
9d1c38e978 Merge remote-tracking branch 'origin/testing' into testing 2022-10-03 09:31:44 +02:00
a95f0c538d Merge remote-tracking branch 'origin/master' into testing 2022-10-03 09:31:15 +02:00
ffd1145cd0 [apimethods] Fixed: prevent makeFetch to add a null body on GET and HEAD
requests
2022-09-30 17:35:43 +02:00
d1b9400257 [person][relations] Fixed: GET request had a body, this prevented to
load files
2022-09-30 17:31:30 +02:00
fdd537b18e Merge branch 'master' into testing 2022-09-29 10:53:48 +02:00
1786fa838f Merge branch '111_exports_suite' into testing 2022-09-28 09:49:33 +02:00
7fe8d0837f [export][person] fix alias name for person in CountPersonWithAccompanyingCourse export 2022-09-23 21:55:00 +02:00
753d6ea481 [export][person] Fixed: filter per person's age: use calculatio non year interval 2022-09-23 21:51:26 +02:00
8cf25415ab Merge branch '111_exports_suite' into testing 2022-09-22 18:16:15 +02:00
743e0b9403 Merge branch '111_exports_suite' into testing 2022-09-22 16:58:47 +02:00
97d6f35605 Merge branch '111_exports_suite' into testing 2022-09-21 17:31:13 +02:00
5af492b2db Merge remote-tracking branch 'origin/111_exports_suite' into testing 2022-09-20 12:18:00 +02:00
70c631b612 Merge remote-tracking branch 'origin/master' into testing 2022-09-20 12:15:29 +02:00
e550d64fd4 change class reference 2022-09-08 10:17:22 +02:00
4aaf75a1a4 merge 111_exports_suite into testing branch 2022-09-08 10:03:21 +02:00
9db43f1de3 remove trailing dumps 2022-09-07 10:37:22 +02:00
674629e2bf comment out exports that are not yet ready 2022-09-07 10:37:01 +02:00
e42d6c2d77 Merge branch 'master' into testing 2022-09-06 15:33:27 +02:00
3782cf35ff Merge branch 'master' into testing 2022-07-11 20:03:37 +02:00
68c1833584 fixed: CS 2022-07-11 12:56:48 +02:00
191b8ecf81 fixed: query for index in PersonDocumentACLAwareRepository 2022-07-11 12:56:34 +02:00
e7ba42de1f fixed: voter and permissions in accompanying course document 2022-07-11 12:55:02 +02:00
8b145ebc11 fixed: migration of databse with address on same day fails 2022-07-11 03:32:15 +02:00
661 changed files with 20620 additions and 4035 deletions

4
.gitignore vendored
View File

@@ -3,7 +3,9 @@ composer
composer.phar
composer.lock
docs/build/
node_modules/*
.php_cs.cache
.cache/*
###> symfony/framework-bundle ###
/.env.local
@@ -24,3 +26,5 @@ docs/build/
/.php-cs-fixer.cache
/.idea/
/.psalm/
node_modules/*

View File

@@ -9,18 +9,22 @@
],
"require": {
"php": "^7.4",
"ext-json": "*",
"ext-openssl": "*",
"ext-redis": "*",
"champs-libres/async-uploader-bundle": "dev-sf4#d57134aee8e504a83c902ff0cf9f8d36ac418290",
"champs-libres/wopi-bundle": "dev-master#6dd8e0a14e00131eb4b889ecc30270ee4a0e5224",
"champs-libres/wopi-lib": "dev-master#8615f4a45a39fc2b6a98765ea835fcfd39618787",
"champs-libres/wopi-bundle": "dev-master@dev",
"champs-libres/wopi-lib": "dev-master@dev",
"doctrine/doctrine-bundle": "^2.1",
"doctrine/doctrine-migrations-bundle": "^3.0",
"doctrine/orm": "^2.7",
"doctrine/orm": "^2.13.0",
"erusev/parsedown": "^1.7",
"graylog2/gelf-php": "^1.5",
"knplabs/knp-menu-bundle": "^3.0",
"knplabs/knp-time-bundle": "^1.12",
"knpuniversity/oauth2-client-bundle": "^2.10",
"league/csv": "^9.7.1",
"lexik/jwt-authentication-bundle": "^2.16",
"nyholm/psr7": "^1.4",
"ocramius/package-versions": "^1.10 || ^2",
"odolbeau/phone-number-bundle": "^3.6",
@@ -29,12 +33,12 @@
"ramsey/uuid-doctrine": "^1.7",
"sensio/framework-extra-bundle": "^5.5",
"spomky-labs/base64url": "^2.0",
"symfony/asset": "^4.4",
"symfony/browser-kit": "^4.4",
"symfony/css-selector": "^4.4",
"symfony/expression-language": "^4.4",
"symfony/form": "^4.4",
"symfony/framework-bundle": "^4.4",
"symfony/http-client": "^4.4 || ^5",
"symfony/http-foundation": "^4.4",
"symfony/intl": "^4.4",
"symfony/mailer": "^5.4",
@@ -48,7 +52,6 @@
"symfony/translation": "^4.4",
"symfony/twig-bundle": "^4.4",
"symfony/validator": "^4.4",
"symfony/web-link": "*",
"symfony/webpack-encore-bundle": "^1.11",
"symfony/workflow": "^4.4",
"symfony/yaml": "^4.4",
@@ -72,8 +75,7 @@
"symfony/maker-bundle": "^1.20",
"symfony/phpunit-bridge": "^4.4",
"symfony/stopwatch": "^4.4",
"symfony/var-dumper": "^4.4",
"symfony/web-profiler-bundle": "^4.4"
"symfony/var-dumper": "^4.4"
},
"conflict": {
"symfony/symfony": "*"

View File

@@ -0,0 +1,93 @@
.. Copyright (C) 2014-2023 Champs Libres Cooperative SCRLFS
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the section entitled "GNU
Free Documentation License".
.. _cronjob:
Cron jobs
*********
Some tasks must be executed regularly: refresh some materialized views, remove old data, ...
For this purpose, one can programmatically implements a "cron job", which will be scheduled by a specific command.
The command :code:`chill:cron-job:execute`
==========================================
The command :code:`chill:cron-job:execute` will schedule a task, one by one. In a classical implementation, it should
be executed every 15 minutes (more or less), to ensure that every task can be executed.
.. warning::
This command should not be executed in parallel. The installer should ensure that two job are executed concurrently.
How to implements a cron job ?
==============================
Implements a :code:`Chill\MainBundle\Cron\CronJobInterface`. Here is an example:
.. code-block:: php
namespace Chill\MainBundle\Service\Something;
use Chill\MainBundle\Cron\CronJobInterface;
use Chill\MainBundle\Entity\CronJobExecution;
use DateInterval;
use DateTimeImmutable;
class MyCronJob implements CronJobInterface
{
public function canRun(?CronJobExecution $cronJobExecution): bool
{
// the parameter $cronJobExecution contains data about the last execution of the cronjob
// if it is null, it should be executed immediatly
if (null === $cronJobExecution) {
return true;
}
if ($cronJobExecution->getKey() !== $this->getKey()) {
throw new UnexpectedValueException();
}
// this cron job should be executed if the last execution is greater than one day, but only during the night
$now = new DateTimeImmutable('now');
return $cronJobExecution->getLastStart() < $now->sub(new DateInterval('P1D'))
&& in_array($now->format('H'), self::ACCEPTED_HOURS, true)
// introduce a random component to ensure a roll of task execution when multiple instances are hosted on same machines
&& mt_rand(0, 5) === 0;
}
public function getKey(): string
{
return 'arbitrary-and-unique-key';
}
public function run(): void
{
// here, we execute the command
}
}
How are cron job scheduled ?
============================
If the command :code:`chill:cron-job:execute` is run with one or more :code:`job` argument, those jobs are run, **without checking that the job can run** (the method :code:`canRun` is not executed).
If any :code:`job` argument is given, the :code:`CronManager` schedule job with those steps:
* the tasks are ordered, with:
* a priority is given for tasks that weren't never executed;
* then, the tasks are ordered, the last executed are the first in the list
* then, for each tasks, and in the given order, the first task where :code:`canRun` return :code:`TRUE` will be executed.
The command :code:`chill:cron-job:execute` execute **only one** task.

View File

@@ -34,6 +34,7 @@ As Chill rely on the `symfony <http://symfony.com>`_ framework, reading the fram
Useful snippets <useful-snippets.rst>
manual/index.rst
Assets <assets.rst>
Cron Jobs <cronjob.rst>
Layout and UI
**************

View File

@@ -18,6 +18,7 @@ Installation & Usage
:maxdepth: 2
prod.rst
load-addresses.rst
prod-calendar-sms-sending.rst
msgraph-configure.rst
@@ -170,7 +171,7 @@ There are several users available:
The password is always ``password``.
Now, read `Operations` below.
Now, read `Operations` below. For running in production, read `prod_`.
Operations

View File

@@ -0,0 +1,50 @@
.. _addresses:
Addresses
*********
Chill can store a list of geolocated address references, which are used to suggest address and ensure that the data is correctly stored.
Those addresses may be load from a dedicated source.
In France
=========
The address are loaded from the `BANO <https://bano.openstreetmap.fr/>`_. The postal codes are loaded from `the official list of
postal codes <https://datanova.laposte.fr/explore/dataset/laposte_hexasmal/information/>`_
.. code-block:: bash
# first, load postal codes
bin/console chill:main:postal-code:load:FR
# then, load all addresses, by departement (multiple departement can be loaded by repeating the departement code
bin/console chill:main:address-ref-from-bano 57 54 51
In Belgium
==========
Addresses are prepared from the `BeST Address data <https://www.geo.be/catalog/details/ca0fd5c0-8146-11e9-9012-482ae30f98d9>`_.
Postal code are loaded from this database. There is no need to load postal codes from another source (actually, this is strongly discouraged).
The data are prepared for Chill (`See this repository <https://gitea.champs-libres.be/Chill-project/belgian-bestaddresses-transform/releases>`_).
One can select postal code by his first number (:code:`1xxx` for postal codes from 1000 to 1999), or a limited list for development purpose.
.. code-block:: bash
# load postal code from 1000 to 3999:
bin/console chill:main:address-ref-from-best-addresse 1xxx 2xxx 3xxx
# load only an extract (for dev purposes)
bin/console chill:main:address-ref-from-best-addresse extract
# load full addresses (discouraged)
bin/console chill:main:address-ref-from-best-addresse full
.. note::
There is a possibility to load the full list of addresses is discouraged: the loading is optimized with smaller extracts.
Once you load the full list, it is not possible to load smaller extract: each extract loaded **after** will not
delete the addresses loaded with the full extract (and some addresses will be present twice).

View File

@@ -1,10 +1,12 @@
.. Copyright (C) 2014-2019 Champs Libres Cooperative SCRLFS
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the section entitled "GNU
Free Documentation License".
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the section entitled "GNU
Free Documentation License".
.. _prod:
Installation for production
###########################
@@ -36,6 +38,19 @@ This should be adapted to your needs:
* Think about how you will backup your database. Some adminsys find easier to store database outside of docker, which might be easier to administrate or replicate.
Cron jobs
=========
The command :code:`chill:cron-job:execute` should be executed every 15 minutes (more or less).
This command should never be executed concurrently. It should be not have more than one process for a single instance.
Post-install tasks
==================
- import addresses. See :ref:`addresses`.
Tweak symfony messenger
=======================

View File

@@ -5,69 +5,70 @@ Add condition with distinct alias on each export join clauses (Indicators + Filt
These are alias conventions :
| Entity | Join | Attribute | Alias |
|:----------------------------------------|:----------------------------------------|:-------------------------------------------|:----------------------------------|
| AccompanyingPeriod::class | | | acp |
| | AccompanyingPeriodWork::class | acp.works | acpw |
| | AccompanyingPeriodParticipation::class | acp.participations | acppart |
| | Location::class | acp.administrativeLocation | acploc |
| | ClosingMotive::class | acp.closingMotive | acpmotive |
| | UserJob::class | acp.job | acpjob |
| | Origin::class | acp.origin | acporigin |
| | Scope::class | acp.scopes | acpscope |
| | SocialIssue::class | acp.socialIssues | acpsocialissue |
| | User::class | acp.user | acpuser |
| | AccompanyingPeriopStepHistory::class | acp.stepHistories | acpstephistories |
| AccompanyingPeriodWork::class | | | acpw |
| | AccompanyingPeriodWorkEvaluation::class | acpw.accompanyingPeriodWorkEvaluations | workeval |
| | User::class | acpw.referrers | acpwuser |
| | SocialAction::class | acpw.socialAction | acpwsocialaction |
| | Goal::class | acpw.goals | goal |
| | Result::class | acpw.results | result |
| AccompanyingPeriodParticipation::class | | | acppart |
| | Person::class | acppart.person | partperson |
| AccompanyingPeriodWorkEvaluation::class | | | workeval |
| | Evaluation::class | workeval.evaluation | eval |
| Goal::class | | | goal |
| | Result::class | goal.results | goalresult |
| Person::class | | | person |
| | Center::class | person.center | center |
| | HouseholdMember::class | partperson.householdParticipations | householdmember |
| | MaritalStatus::class | person.maritalStatus | personmarital |
| | VendeePerson::class | | vp |
| | VendeePersonMineur::class | | vpm |
| ResidentialAddress::class | | | resaddr |
| | ThirdParty::class | resaddr.hostThirdParty | tparty |
| ThirdParty::class | | | tparty |
| | ThirdPartyCategory::class | tparty.categories | tpartycat |
| HouseholdMember::class | | | householdmember |
| | Household::class | householdmember.household | household |
| | Person::class | householdmember.person | memberperson |
| | | memberperson.center | membercenter |
| Household::class | | | household |
| | HouseholdComposition::class | household.compositions | composition |
| Activity::class | | | activity |
| | Person::class | activity.person | actperson |
| | AccompanyingPeriod::class | activity.accompanyingPeriod | acp |
| | Person::class | activity\_person\_having\_activity.person | person\_person\_having\_activity |
| | ActivityReason::class | activity\_person\_having\_activity.reasons | reasons\_person\_having\_activity |
| | ActivityType::class | activity.activityType | acttype |
| | Location::class | activity.location | actloc |
| | SocialAction::class | activity.socialActions | actsocialaction |
| | SocialIssue::class | activity.socialIssues | actsocialssue |
| | ThirdParty::class | activity.thirdParties | acttparty |
| | User::class | activity.user | actuser |
| | User::class | activity.users | actusers |
| | ActivityReason::class | activity.reasons | actreasons |
| | Center::class | actperson.center | actcenter |
| | Person::class | activity.createdBy | actcreator |
| ActivityReason::class | | | actreasons |
| | ActivityReasonCategory::class | actreason.category | actreasoncat |
| Calendar::class | | | cal |
| | CancelReason::class | cal.cancelReason | calcancel |
| | Location::class | cal.location | calloc |
| | User::class | cal.user | caluser |
| VendeePerson::class | | | vp |
| | SituationProfessionelle::class | vp.situationProfessionelle | vpprof |
| | StatutLogement::class | vp.statutLogement | vplog |
| | TempsDeTravail::class | vp.tempsDeTravail | vptt |
| Entity | Join | Attribute | Alias |
|:----------------------------------------|:----------------------------------------|:-------------------------------------------|:---------------------------------------|
| AccompanyingPeriod::class | | | acp |
| | AccompanyingPeriodWork::class | acp.works | acpw |
| | AccompanyingPeriodParticipation::class | acp.participations | acppart |
| | Location::class | acp.administrativeLocation | acploc |
| | ClosingMotive::class | acp.closingMotive | acpmotive |
| | UserJob::class | acp.job | acpjob |
| | Origin::class | acp.origin | acporigin |
| | Scope::class | acp.scopes | acpscope |
| | SocialIssue::class | acp.socialIssues | acpsocialissue |
| | User::class | acp.user | acpuser |
| | AccompanyingPeriopStepHistory::class | acp.stepHistories | acpstephistories |
| AccompanyingPeriodWork::class | | | acpw |
| | AccompanyingPeriodWorkEvaluation::class | acpw.accompanyingPeriodWorkEvaluations | workeval |
| | User::class | acpw.referrers | acpwuser |
| | SocialAction::class | acpw.socialAction | acpwsocialaction |
| | Goal::class | acpw.goals | goal |
| | Result::class | acpw.results | result |
| AccompanyingPeriodParticipation::class | | | acppart |
| | Person::class | acppart.person | partperson |
| AccompanyingPeriodWorkEvaluation::class | | | workeval |
| | Evaluation::class | workeval.evaluation | eval |
| Goal::class | | | goal |
| | Result::class | goal.results | goalresult |
| Person::class | | | person |
| | Center::class | person.center | center |
| | HouseholdMember::class | partperson.householdParticipations | householdmember |
| | MaritalStatus::class | person.maritalStatus | personmarital |
| | VendeePerson::class | | vp |
| | VendeePersonMineur::class | | vpm |
| | CurrentPersonAddress::class | person.currentPersonAddress | currentPersonAddress (on a given date) |
| ResidentialAddress::class | | | resaddr |
| | ThirdParty::class | resaddr.hostThirdParty | tparty |
| ThirdParty::class | | | tparty |
| | ThirdPartyCategory::class | tparty.categories | tpartycat |
| HouseholdMember::class | | | householdmember |
| | Household::class | householdmember.household | household |
| | Person::class | householdmember.person | memberperson |
| | | memberperson.center | membercenter |
| Household::class | | | household |
| | HouseholdComposition::class | household.compositions | composition |
| Activity::class | | | activity |
| | Person::class | activity.person | actperson |
| | AccompanyingPeriod::class | activity.accompanyingPeriod | acp |
| | Person::class | activity\_person\_having\_activity.person | person\_person\_having\_activity |
| | ActivityReason::class | activity\_person\_having\_activity.reasons | reasons\_person\_having\_activity |
| | ActivityType::class | activity.activityType | acttype |
| | Location::class | activity.location | actloc |
| | SocialAction::class | activity.socialActions | actsocialaction |
| | SocialIssue::class | activity.socialIssues | actsocialssue |
| | ThirdParty::class | activity.thirdParties | acttparty |
| | User::class | activity.user | actuser |
| | User::class | activity.users | actusers |
| | ActivityReason::class | activity.reasons | actreasons |
| | Center::class | actperson.center | actcenter |
| | Person::class | activity.createdBy | actcreator |
| ActivityReason::class | | | actreasons |
| | ActivityReasonCategory::class | actreason.category | actreasoncat |
| Calendar::class | | | cal |
| | CancelReason::class | cal.cancelReason | calcancel |
| | Location::class | cal.location | calloc |
| | User::class | cal.user | caluser |
| VendeePerson::class | | | vp |
| | SituationProfessionelle::class | vp.situationProfessionelle | vpprof |
| | StatutLogement::class | vp.statutLogement | vplog |
| | TempsDeTravail::class | vp.tempsDeTravail | vptt |

67
package.json Normal file
View File

@@ -0,0 +1,67 @@
{
"name": "chill",
"version": "2.0.0",
"devDependencies": {
"@alexlafroscia/yaml-merge": "^4.0.0",
"@apidevtools/swagger-cli": "^4.0.4",
"@babel/core": "^7.20.5",
"@babel/preset-env": "^7.20.2",
"@ckeditor/ckeditor5-build-classic": "^35.3.2",
"@ckeditor/ckeditor5-dev-utils": "^31.1.13",
"@ckeditor/ckeditor5-dev-webpack-plugin": "^31.1.13",
"@ckeditor/ckeditor5-markdown-gfm": "^35.3.2",
"@ckeditor/ckeditor5-theme-lark": "^35.3.2",
"@ckeditor/ckeditor5-vue": "^4.0.1",
"@symfony/webpack-encore": "^4.1.0",
"@tsconfig/node14": "^1.0.1",
"bindings": "^1.5.0",
"bootstrap": "^5.0.1",
"chokidar": "^3.5.1",
"fork-awesome": "^1.1.7",
"jquery": "^3.6.0",
"node-sass": "^8.0.0",
"popper.js": "^1.16.1",
"postcss-loader": "^7.0.2",
"raw-loader": "^4.0.2",
"sass-loader": "^13.0.0",
"select2": "^4.0.13",
"select2-bootstrap-theme": "0.1.0-beta.10",
"style-loader": "^3.3.1",
"ts-loader": "^9.3.1",
"typescript": "^4.7.2",
"vue-loader": "^17.0.0",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1"
},
"dependencies": {
"@fullcalendar/core": "^5.11.0",
"@fullcalendar/daygrid": "^5.11.0",
"@fullcalendar/interaction": "^5.11.0",
"@fullcalendar/list": "^5.11.0",
"@fullcalendar/timegrid": "^5.11.0",
"@fullcalendar/vue3": "^5.11.1",
"@popperjs/core": "^2.9.2",
"dropzone": "^5.7.6",
"es6-promise": "^4.2.8",
"leaflet": "^1.7.1",
"masonry-layout": "^4.2.2",
"mime": "^3.0.0",
"swagger-ui": "^4.15.5",
"vis-network": "^9.1.0",
"vue": "^3.2.37",
"vue-i18n": "^9.1.6",
"vue-multiselect": "3.0.0-alpha.2",
"vue-toast-notification": "^2.0",
"vuex": "^4.0.0"
},
"browserslist": [
"Firefox ESR"
],
"scripts": {
"dev-server": "encore dev-server",
"dev": "encore dev",
"watch": "encore dev --watch",
"build": "encore production --progress"
},
"private": true
}

View File

@@ -5,11 +5,6 @@ parameters:
count: 1
path: src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php
-
message: "#^Access to an undefined property Chill\\\\PersonBundle\\\\Entity\\\\Household\\\\PersonHouseholdAddress\\:\\:\\$relation\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Entity/Household/PersonHouseholdAddress.php
-
message: "#^Access to an undefined property Chill\\\\PersonBundle\\\\Entity\\\\AccompanyingPeriod\\:\\:\\$work\\.$#"
count: 1
@@ -30,11 +25,6 @@ parameters:
count: 1
path: src/Bundle/ChillPersonBundle/Serializer/Normalizer/MembersEditorNormalizer.php
-
message: "#^Undefined variable\\: \\$choiceSlug$#"
count: 1
path: src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php
-
message: "#^Undefined variable\\: \\$choiceSlug$#"
count: 1

View File

@@ -10,16 +10,6 @@ parameters:
count: 1
path: src/Bundle/ChillActivityBundle/Entity/ActivityReasonCategory.php
-
message: "#^Method Chill\\\\ActivityBundle\\\\Export\\\\Export\\\\StatActivityDuration\\:\\:getDescription\\(\\) should return string but return statement is missing\\.$#"
count: 1
path: src/Bundle/ChillActivityBundle/Export/Export/StatActivityDuration.php
-
message: "#^Method Chill\\\\ActivityBundle\\\\Export\\\\Export\\\\StatActivityDuration\\:\\:getTitle\\(\\) should return string but return statement is missing\\.$#"
count: 1
path: src/Bundle/ChillActivityBundle/Export/Export/StatActivityDuration.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
@@ -330,21 +320,6 @@ parameters:
count: 6
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Export/Aggregator/CountryOfBirthAggregator.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
path: src/Bundle/ChillPersonBundle/Export/Aggregator/NationalityAggregator.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 2
path: src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
@@ -365,11 +340,6 @@ parameters:
count: 1
path: src/Bundle/ChillPersonBundle/Form/Type/PersonPhoneType.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 3
path: src/Bundle/ChillPersonBundle/Search/PersonSearch.php
-
message: "#^Method Chill\\\\PersonBundle\\\\Search\\\\PersonSearch\\:\\:renderResult\\(\\) should return string but return statement is missing\\.$#"
count: 1

View File

@@ -43,6 +43,7 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use function array_key_exists;
final class ActivityController extends AbstractController
@@ -73,6 +74,8 @@ final class ActivityController extends AbstractController
private ThirdPartyRepository $thirdPartyRepository;
private TranslatorInterface $translator;
private UserRepositoryInterface $userRepository;
public function __construct(
@@ -89,7 +92,8 @@ final class ActivityController extends AbstractController
LoggerInterface $logger,
SerializerInterface $serializer,
UserRepositoryInterface $userRepository,
CenterResolverManagerInterface $centerResolver
CenterResolverManagerInterface $centerResolver,
TranslatorInterface $translator
) {
$this->activityACLAwareRepository = $activityACLAwareRepository;
$this->activityTypeRepository = $activityTypeRepository;
@@ -105,6 +109,7 @@ final class ActivityController extends AbstractController
$this->serializer = $serializer;
$this->userRepository = $userRepository;
$this->centerResolver = $centerResolver;
$this->translator = $translator;
}
/**
@@ -160,7 +165,7 @@ final class ActivityController extends AbstractController
$this->entityManager->remove($activity);
$this->entityManager->flush();
$this->addFlash('success', $this->get('translator')
$this->addFlash('success', $this->translator
->trans('The activity has been successfully removed.'));
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
@@ -245,7 +250,7 @@ final class ActivityController extends AbstractController
);
}
$this->addFlash('success', $this->get('translator')->trans('Success : activity updated!'));
$this->addFlash('success', $this->translator->trans('Success : activity updated!'));
return $this->redirectToRoute('chill_activity_activity_show', $params);
}
@@ -363,6 +368,7 @@ final class ActivityController extends AbstractController
if ($person instanceof Person) {
$entity->setPerson($person);
$entity->getPersons()->add($person);
}
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
@@ -472,7 +478,7 @@ final class ActivityController extends AbstractController
);
}
$this->addFlash('success', $this->get('translator')->trans('Success : activity created!'));
$this->addFlash('success', $this->translator->trans('Success : activity created!'));
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);

View File

@@ -13,15 +13,24 @@ namespace Chill\ActivityBundle\Controller;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Form\ActivityReasonType;
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* ActivityReason controller.
*/
class ActivityReasonController extends AbstractController
{
private ActivityReasonRepository $activityReasonRepository;
public function __construct(ActivityReasonRepository $activityReasonRepository)
{
$this->activityReasonRepository = $activityReasonRepository;
}
/**
* Creates a new ActivityReason entity.
*/
@@ -56,8 +65,8 @@ class ActivityReasonController extends AbstractController
$entity = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityReason::class)->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find ActivityReason entity.');
if (null === $entity) {
throw new NotFoundHttpException('Unable to find ActivityReason entity.');
}
$editForm = $this->createEditForm($entity);
@@ -75,7 +84,7 @@ class ActivityReasonController extends AbstractController
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityReason::class)->findAll();
$entities = $this->activityReasonRepository->findAll();
return $this->render('ChillActivityBundle:ActivityReason:index.html.twig', [
'entities' => $entities,

View File

@@ -63,10 +63,8 @@ class ActivityReason
/**
* Get category.
*
* @return ActivityReasonCategory
*/
public function getCategory()
public function getCategory(): ?ActivityReasonCategory
{
return $this->category;
}
@@ -107,6 +105,11 @@ class ActivityReason
return $this->name;
}
public function isActiveAndParentActive(): bool
{
return $this->active && null !== $this->getCategory() && $this->getCategory()->getActive();
}
/**
* Set active.
*

View File

@@ -0,0 +1,68 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Export\Aggregator\ACPAggregators;
use Chill\ActivityBundle\Entity\Activity;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\PersonBundle\Export\Declarations;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
class ByActivityNumberAggregator implements AggregatorInterface
{
public function addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data): void
{
$qb
->addSelect('(SELECT COUNT(activity.id) FROM ' . Activity::class . ' activity WHERE activity.accompanyingPeriod = acp) AS activity_by_number_aggregator')
->addGroupBy('activity_by_number_aggregator');
}
public function applyOn(): string
{
return Declarations::ACP_TYPE;
}
public function buildForm(FormBuilderInterface $builder): void
{
// No form needed
}
public function getLabels($key, array $values, $data)
{
return static function ($value) {
if ('_header' === $value) {
return '';
}
if (null === $value) {
return '';
}
return $value;
};
}
public function getQueryKeys($data): array
{
return ['activity_by_number_aggregator'];
}
public function getTitle(): string
{
return 'Group acp by activity number';
}
}

View File

@@ -60,7 +60,7 @@ class ByCreatorAggregator implements AggregatorInterface
return 'Created by';
}
if (null === $value) {
if (null === $value || '' === $value) {
return '';
}

View File

@@ -65,7 +65,7 @@ class BySocialActionAggregator implements AggregatorInterface
return 'Social action';
}
if (null === $value) {
if (null === $value || '' === $value) {
return '';
}

View File

@@ -65,7 +65,7 @@ class BySocialIssueAggregator implements AggregatorInterface
return 'Social issues';
}
if (null === $value) {
if (null === $value || '' === $value) {
return '';
}

View File

@@ -65,7 +65,7 @@ class ByThirdpartyAggregator implements AggregatorInterface
return 'Accepted thirdparty';
}
if (null === $value) {
if (null === $value || '' === $value) {
return '';
}

View File

@@ -65,7 +65,7 @@ class CreatorScopeAggregator implements AggregatorInterface
return 'Scope';
}
if (null === $value) {
if (null === $value || '' === $value) {
return '';
}

View File

@@ -65,11 +65,13 @@ class LocationTypeAggregator implements AggregatorInterface
return 'Accepted locationtype';
}
if (null === $value) {
if (null === $value || '' === $value) {
return '';
}
$lt = $this->locationTypeRepository->find($value);
if (null === $lt = $this->locationTypeRepository->find($value)) {
return '';
}
return $this->translatableStringHelper->localize(
$lt->getTitle()

View File

@@ -44,7 +44,7 @@ class ActivityTypeAggregator implements AggregatorInterface
public function alterQuery(QueryBuilder $qb, $data)
{
if (!in_array('acttype', $qb->getAllAliases(), true)) {
$qb->join('activity.activityType', 'acttype');
$qb->leftJoin('activity.activityType', 'acttype');
}
$qb->addSelect(sprintf('IDENTITY(activity.activityType) AS %s', self::KEY));
@@ -71,7 +71,7 @@ class ActivityTypeAggregator implements AggregatorInterface
return 'Activity type';
}
if (null === $value) {
if (null === $value || '' === $value) {
return '';
}

View File

@@ -66,7 +66,7 @@ class ActivityUserAggregator implements AggregatorInterface
return 'Activity user';
}
if (null === $value) {
if (null === $value || '' === $value) {
return '';
}

View File

@@ -64,7 +64,7 @@ class ActivityUsersAggregator implements AggregatorInterface
return 'Activity users';
}
if (null === $value) {
if (null === $value || '' === $value) {
return '';
}

View File

@@ -63,7 +63,7 @@ class ActivityUsersJobAggregator implements \Chill\MainBundle\Export\AggregatorI
return 'Users \'s job';
}
if (null === $value) {
if (null === $value || '' === $value) {
return '';
}

View File

@@ -63,7 +63,7 @@ class ActivityUsersScopeAggregator implements \Chill\MainBundle\Export\Aggregato
return 'Users \'s scope';
}
if (null === $value) {
if (null === $value || '' === $value) {
return '';
}

View File

@@ -134,6 +134,10 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
return 'reasons' === $data['level'] ? 'Group by reasons' : 'Group by categories of reason';
}
if (null === $value || '' === $value) {
return '';
}
switch ($data['level']) {
case 'reasons':
$r = $this->activityReasonRepository->find($value);

View File

@@ -0,0 +1,84 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Export\Aggregator;
use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\AggregatorInterface;
use Doctrine\ORM\QueryBuilder;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
class SentReceivedAggregator implements AggregatorInterface
{
private TranslatorInterface $translator;
public function __construct(TranslatorInterface $translator)
{
$this->translator = $translator;
}
public function addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data): void
{
$qb->addSelect('activity.sentReceived AS activity_sentreceived_aggregator')
->addGroupBy('activity_sentreceived_aggregator');
}
public function applyOn(): string
{
return Declarations::ACTIVITY;
}
public function buildForm(FormBuilderInterface $builder): void
{
// No form needed
}
public function getLabels($key, array $values, $data): callable
{
return function (?string $value): string {
if ('_header' === $value) {
return 'export.aggregator.activity.by_sent_received.Sent or received';
}
switch ($value) {
case null:
case '':
return '';
case 'sent':
return $this->translator->trans('export.aggregator.activity.by_sent_received.is sent');
case 'received':
return $this->translator->trans('export.aggregator.activity.by_sent_received.is received');
default:
throw new LogicException(sprintf('The value %s is not valid', $value));
}
};
}
public function getQueryKeys($data): array
{
return ['activity_sentreceived_aggregator'];
}
public function getTitle(): string
{
return 'export.aggregator.activity.by_sent_received.Group activity by sentreceived';
}
}

View File

@@ -0,0 +1,165 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Export\Export\ListActivityHelper;
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Export\GroupedExportInterface;
use Chill\MainBundle\Export\Helper\TranslatableStringExportLabelHelper;
use Chill\MainBundle\Export\ListInterface;
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\FormBuilderInterface;
class ListActivity implements ListInterface, GroupedExportInterface
{
private EntityManagerInterface $entityManager;
private ListActivityHelper $helper;
private TranslatableStringExportLabelHelper $translatableStringExportLabelHelper;
public function __construct(
ListActivityHelper $helper,
EntityManagerInterface $entityManager,
TranslatableStringExportLabelHelper $translatableStringExportLabelHelper
) {
$this->helper = $helper;
$this->entityManager = $entityManager;
$this->translatableStringExportLabelHelper = $translatableStringExportLabelHelper;
}
public function buildForm(FormBuilderInterface $builder)
{
$this->helper->buildForm($builder);
}
public function getAllowedFormattersTypes()
{
return $this->helper->getAllowedFormattersTypes();
}
public function getDescription()
{
return ListActivityHelper::MSG_KEY . 'List activities linked to an accompanying course';
}
public function getGroup(): string
{
return 'Exports of activities linked to an accompanying period';
}
public function getLabels($key, array $values, $data)
{
switch ($key) {
case 'acpId':
return static function ($value) {
if ('_header' === $value) {
return ListActivityHelper::MSG_KEY . 'accompanying course id';
}
return $value ?? '';
};
case 'scopesNames':
return $this->translatableStringExportLabelHelper->getLabelMulti($key, $values, ListActivityHelper::MSG_KEY . 'course circles');
default:
return $this->helper->getLabels($key, $values, $data);
}
}
public function getQueryKeys($data)
{
return
array_merge(
$this->helper->getQueryKeys($data),
[
'acpId',
'scopesNames',
]
);
}
public function getResult($query, $data)
{
return $this->helper->getResult($query, $data);
}
public function getTitle()
{
return ListActivityHelper::MSG_KEY . 'List activity linked to a course';
}
public function getType()
{
return $this->helper->getType();
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$centers = array_map(static function ($el) {
return $el['center'];
}, $acl);
$qb = $this->entityManager->createQueryBuilder();
$qb
->distinct()
->from(Activity::class, 'activity')
->join('activity.accompanyingPeriod', 'acp')
->leftJoin('acp.participations', 'acppart')
->leftJoin('acppart.person', 'person')
->andWhere('acppart.startDate != acppart.endDate OR acppart.endDate IS NULL')
->andWhere(
$qb->expr()->exists(
'SELECT 1
FROM ' . PersonCenterHistory::class . ' acl_count_person_history
WHERE acl_count_person_history.person = person
AND acl_count_person_history.center IN (:authorized_centers)
'
)
)
// some grouping are necessary
->addGroupBy('acp.id')
->addOrderBy('activity.date')
->addOrderBy('activity.id')
->setParameter('authorized_centers', $centers);
$this->helper->addSelect($qb);
// add select for this step
$qb
->addSelect('acp.id AS acpId')
->addSelect('(SELECT AGGREGATE(acpScope.name) FROM ' . Scope::class . ' acpScope WHERE acpScope MEMBER OF acp.scopes) AS scopesNames')
->addGroupBy('scopesNames');
return $qb;
}
public function requiredRole(): string
{
return ActivityStatsVoter::LISTS;
}
public function supportsModifiers()
{
return array_merge(
$this->helper->supportsModifiers(),
[
\Chill\PersonBundle\Export\Declarations::ACP_TYPE,
]
);
}
}

View File

@@ -124,7 +124,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
return 'attendee';
}
return $value ? 1 : 0;
return $value ? 'X' : '';
};
case 'list_reasons':
@@ -210,10 +210,20 @@ class ListActivity implements ListInterface, GroupedExportInterface
$qb
->from('ChillActivityBundle:Activity', 'activity')
->join('activity.person', 'person')
->join('actperson.center', 'actcenter')
->andWhere('actcenter IN (:authorized_centers)')
->setParameter('authorized_centers', $centers);
->join('activity.person', 'actperson')
->join('actperson.centerHistory', 'centerHistory');
$qb->where(
$qb->expr()->andX(
$qb->expr()->lte('centerHistory.startDate', 'activity.date'),
$qb->expr()->orX(
$qb->expr()->isNull('centerHistory.endDate'),
$qb->expr()->gt('centerHistory.endDate', 'activity.date')
)
)
)
->andWhere($qb->expr()->in('centerHistory.center', ':centers'))
->setParameter('centers', $centers);
foreach ($this->fields as $f) {
if (in_array($f, $data['fields'], true)) {
@@ -224,17 +234,17 @@ class ListActivity implements ListInterface, GroupedExportInterface
break;
case 'person_firstname':
$qb->addSelect('person.firstName AS person_firstname');
$qb->addSelect('actperson.firstName AS person_firstname');
break;
case 'person_lastname':
$qb->addSelect('person.lastName AS person_lastname');
$qb->addSelect('actperson.lastName AS person_lastname');
break;
case 'person_id':
$qb->addSelect('person.id AS person_id');
$qb->addSelect('actperson.id AS person_id');
break;
@@ -251,7 +261,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
break;
case 'type_name':
$qb->join('activity.type', 'type');
$qb->join('activity.activityType', 'type');
$qb->addSelect('type.name AS type_name');
break;
@@ -263,6 +273,11 @@ class ListActivity implements ListInterface, GroupedExportInterface
break;
case 'attendee':
$qb->addSelect('IDENTITY(activity.attendee) AS attendee');
break;
default:
$qb->addSelect(sprintf('activity.%s as %s', $f, $f));

View File

@@ -0,0 +1,269 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Export\Export;
use Chill\ActivityBundle\Export\Declarations;
use Chill\ActivityBundle\Repository\ActivityPresenceRepositoryInterface;
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\Helper\DateTimeHelper;
use Chill\MainBundle\Export\Helper\TranslatableStringExportLabelHelper;
use Chill\MainBundle\Export\Helper\UserHelper;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Export\Helper\LabelPersonHelper;
use Chill\ThirdPartyBundle\Export\Helper\LabelThirdPartyHelper;
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\QueryBuilder;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use const SORT_NUMERIC;
class ListActivityHelper
{
public const MSG_KEY = 'export.list.activity.';
private ActivityPresenceRepositoryInterface $activityPresenceRepository;
private ActivityTypeRepositoryInterface $activityTypeRepository;
private DateTimeHelper $dateTimeHelper;
private LabelPersonHelper $labelPersonHelper;
private LabelThirdPartyHelper $labelThirdPartyHelper;
private TranslatableStringHelperInterface $translatableStringHelper;
private TranslatableStringExportLabelHelper $translatableStringLabelHelper;
private TranslatorInterface $translator;
private UserHelper $userHelper;
public function __construct(
ActivityPresenceRepositoryInterface $activityPresenceRepository,
ActivityTypeRepositoryInterface $activityTypeRepository,
DateTimeHelper $dateTimeHelper,
LabelPersonHelper $labelPersonHelper,
LabelThirdPartyHelper $labelThirdPartyHelper,
TranslatorInterface $translator,
TranslatableStringHelperInterface $translatableStringHelper,
TranslatableStringExportLabelHelper $translatableStringLabelHelper,
UserHelper $userHelper
) {
$this->activityPresenceRepository = $activityPresenceRepository;
$this->activityTypeRepository = $activityTypeRepository;
$this->dateTimeHelper = $dateTimeHelper;
$this->labelPersonHelper = $labelPersonHelper;
$this->labelThirdPartyHelper = $labelThirdPartyHelper;
$this->translator = $translator;
$this->translatableStringHelper = $translatableStringHelper;
$this->translatableStringLabelHelper = $translatableStringLabelHelper;
$this->userHelper = $userHelper;
}
public function addSelect(QueryBuilder $qb): void
{
$qb
->addSelect('activity.id AS id')
->addSelect('activity.date')
->addSelect('IDENTITY(activity.activityType) AS typeName')
->leftJoin('activity.reasons', 'reasons')
->addSelect('AGGREGATE(reasons.name) AS listReasons')
->leftJoin('activity.persons', 'actPerson')
->addSelect('AGGREGATE(actPerson.id) AS personsIds')
->addSelect('AGGREGATE(actPerson.id) AS personsNames')
->leftJoin('activity.users', 'users_u')
->addSelect('AGGREGATE(users_u.id) AS usersIds')
->addSelect('AGGREGATE(users_u.id) AS usersNames')
->leftJoin('activity.thirdParties', 'thirdparty')
->addSelect('AGGREGATE(thirdparty.id) AS thirdPartiesIds')
->addSelect('AGGREGATE(thirdparty.id) AS thirdPartiesNames')
->addSelect('IDENTITY(activity.attendee) AS attendeeName')
->addSelect('activity.durationTime')
->addSelect('activity.travelTime')
->addSelect('activity.emergency')
->leftJoin('activity.location', 'location')
->addSelect('location.name AS locationName')
->addSelect('activity.sentReceived')
->addSelect('IDENTITY(activity.createdBy) AS createdBy')
->addSelect('activity.createdAt')
->addSelect('IDENTITY(activity.updatedBy) AS updatedBy')
->addSelect('activity.updatedAt')
->addGroupBy('activity.id')
->addGroupBy('location.id');
}
public function buildForm(FormBuilderInterface $builder)
{
}
public function getAllowedFormattersTypes()
{
return [FormatterInterface::TYPE_LIST];
}
public function getLabels($key, array $values, $data)
{
switch ($key) {
case 'createdAt':
case 'updatedAt':
return $this->dateTimeHelper->getLabel($key);
case 'createdBy':
case 'updatedBy':
return $this->userHelper->getLabel($key, $values, $key);
case 'date':
return $this->dateTimeHelper->getLabel(self::MSG_KEY . $key);
case 'attendeeName':
return function ($value) {
if ('_header' === $value) {
return 'Attendee';
}
if (null === $value || null === $presence = $this->activityPresenceRepository->find($value)) {
return '';
}
return $this->translatableStringHelper->localize($presence->getName());
};
case 'listReasons':
return $this->translatableStringLabelHelper->getLabelMulti($key, $values, 'Activity Reasons');
case 'typeName':
return function ($value) {
if ('_header' === $value) {
return 'Activity type';
}
if (null === $value || null === $type = $this->activityTypeRepository->find($value)) {
return '';
}
return $this->translatableStringHelper->localize($type->getName());
};
case 'usersNames':
return $this->userHelper->getLabelMulti($key, $values, self::MSG_KEY . 'users name');
case 'usersIds':
case 'thirdPartiesIds':
case 'personsIds':
return static function ($value) use ($key) {
if ('_header' === $value) {
switch ($key) {
case 'usersIds':
return self::MSG_KEY . 'users ids';
case 'thirdPartiesIds':
return self::MSG_KEY . 'third parties ids';
case 'personsIds':
return self::MSG_KEY . 'persons ids';
default:
throw new LogicException('key not supported');
}
}
$decoded = json_decode($value);
return implode(
'|',
array_unique(
array_filter($decoded, static fn (?int $id) => null !== $id),
SORT_NUMERIC
)
);
};
case 'personsNames':
return $this->labelPersonHelper->getLabelMulti($key, $values, self::MSG_KEY . 'persons name');
case 'thirdPartiesNames':
return $this->labelThirdPartyHelper->getLabelMulti($key, $values, self::MSG_KEY . 'thirds parties');
case 'sentReceived':
return function ($value) {
if ('_header' === $value) {
return self::MSG_KEY . 'sent received';
}
if (null === $value) {
return '';
}
return $this->translator->trans($value);
};
default:
return function ($value) use ($key) {
if ('_header' === $value) {
return self::MSG_KEY . $key;
}
if (null === $value) {
return '';
}
return $this->translator->trans($value);
};
}
}
public function getQueryKeys($data)
{
return [
'id',
'date',
'typeName',
'listReasons',
'attendeeName',
'durationTime',
'travelTime',
'emergency',
'locationName',
'sentReceived',
'personsIds',
'personsNames',
'usersIds',
'usersNames',
'thirdPartiesIds',
'thirdPartiesNames',
'createdBy',
'createdAt',
'updatedBy',
'updatedAt',
];
}
public function getResult($query, $data)
{
return $query->getQuery()->getResult(AbstractQuery::HYDRATE_SCALAR);
}
public function getType(): string
{
return Declarations::ACTIVITY;
}
public function supportsModifiers()
{
return [
Declarations::ACTIVITY,
];
}
}

View File

@@ -17,11 +17,9 @@ use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Export\Declarations;
use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
use function in_array;
class ActivityTypeFilter implements FilterInterface
{
@@ -44,14 +42,13 @@ class ActivityTypeFilter implements FilterInterface
public function alterQuery(QueryBuilder $qb, $data)
{
if (!in_array('activity', $qb->getAllAliases(), true)) {
$qb->join(Activity::class, 'activity', Expr\Join::WITH, 'activity.accompanyingPeriod = acp');
}
$clause = $qb->expr()->in('activity.activityType', ':selected_activity_types');
$qb->andWhere($clause);
$qb->setParameter('selected_activity_types', $data['types']);
$qb->andWhere(
$qb->expr()->exists(
'SELECT 1 FROM ' . Activity::class . ' act_type_filter_activity
WHERE act_type_filter_activity.activityType IN (:act_type_filter_activity_types) AND act_type_filter_activity.accompanyingPeriod = acp'
)
);
$qb->setParameter('act_type_filter_activity_types', $data['accepted_activitytypes']);
}
public function applyOn()

View File

@@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Export\Filter\ACPFilters;
use Chill\ActivityBundle\Entity\Activity;
use Chill\MainBundle\Export\FilterInterface;
use Chill\PersonBundle\Export\Declarations;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
class HasNoActivityFilter implements FilterInterface
{
public function addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
$qb
->andWhere('
NOT EXISTS (
SELECT 1 FROM ' . Activity::class . ' activity
WHERE activity.accompanyingPeriod = acp
)
');
}
public function applyOn(): string
{
return Declarations::ACP_TYPE;
}
public function buildForm(FormBuilderInterface $builder)
{
//no form needed
}
public function describeAction($data, $format = 'string'): array
{
return ['Filtered acp which has no activities', []];
}
public function getTitle(): string
{
return 'Filter acp which has no activity';
}
}

View File

@@ -0,0 +1,74 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Export\Filter\ACPFilters;
use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Form\Type\PickUserLocationType;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
class LocationFilter implements FilterInterface
{
private TranslatableStringHelper $translatableStringHelper;
public function __construct(TranslatableStringHelper $translatableStringHelper)
{
$this->translatableStringHelper = $translatableStringHelper;
}
public function addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
$qb->andWhere(
$qb->expr()->in('activity.location', ':location')
);
$qb->setParameter('location', $data['accepted_location']);
}
public function applyOn(): string
{
return Declarations::ACTIVITY_ACP;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('accepted_location', PickUserLocationType::class, [
'multiple' => true,
'label' => 'pick location',
]);
}
public function describeAction($data, $format = 'string'): array
{
$locations = [];
foreach ($data['accepted_location'] as $location) {
$locations[] = $location->getName();
}
return ['Filtered activity by location: only %locations%', [
'%locations%' => implode(', ', $locations),
]];
}
public function getTitle(): string
{
return 'Filter activity by location';
}
}

View File

@@ -13,9 +13,10 @@ namespace Chill\ActivityBundle\Export\Filter;
use Chill\ActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Form\Type\ChillDateType;
use Chill\MainBundle\Form\Type\Export\FilterType;
use DateTime;
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;
@@ -28,9 +29,14 @@ class ActivityDateFilter implements FilterInterface
{
protected TranslatorInterface $translator;
public function __construct(TranslatorInterface $translator)
{
private RollingDateConverterInterface $rollingDateConverter;
public function __construct(
TranslatorInterface $translator,
RollingDateConverterInterface $rollingDateConverter
) {
$this->translator = $translator;
$this->rollingDateConverter = $rollingDateConverter;
}
public function addRole(): ?string
@@ -54,8 +60,14 @@ class ActivityDateFilter implements FilterInterface
}
$qb->add('where', $where);
$qb->setParameter('date_from', $data['date_from']);
$qb->setParameter('date_to', $data['date_to']);
$qb->setParameter(
'date_from',
$this->rollingDateConverter->convert($data['date_from'])
);
$qb->setParameter(
'date_to',
$this->rollingDateConverter->convert($data['date_to'])
);
}
public function applyOn(): string
@@ -66,13 +78,13 @@ class ActivityDateFilter implements FilterInterface
public function buildForm(FormBuilderInterface $builder)
{
$builder
->add('date_from', ChillDateType::class, [
->add('date_from', PickRollingDateType::class, [
'label' => 'Activities after this date',
'data' => new DateTime(),
'data' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START),
])
->add('date_to', ChillDateType::class, [
->add('date_to', PickRollingDateType::class, [
'label' => 'Activities before this date',
'data' => new DateTime(),
'data' => new RollingDate(RollingDate::T_TODAY),
]);
$builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
@@ -121,8 +133,8 @@ class ActivityDateFilter implements FilterInterface
return [
'Filtered by date of activity: only between %date_from% and %date_to%',
[
'%date_from%' => $data['date_from']->format('d-m-Y'),
'%date_to%' => $data['date_to']->format('d-m-Y'),
'%date_from%' => $this->rollingDateConverter->convert($data['date_from'])->format('d-m-Y'),
'%date_to%' => $this->rollingDateConverter->convert($data['date_to'])->format('d-m-Y'),
],
];
}

View File

@@ -50,7 +50,7 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
{
$where = $qb->getDQLPart('where');
$join = $qb->getDQLPart('join');
$clause = $qb->expr()->in('reasons', ':selected_activity_reasons');
$clause = $qb->expr()->in('actreasons', ':selected_activity_reasons');
if (!in_array('actreasons', $qb->getAllAliases(), true)) {
$qb->join('activity.reasons', 'actreasons');
@@ -77,6 +77,7 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
'class' => ActivityReason::class,
'choice_label' => fn (ActivityReason $reason) => $this->translatableStringHelper->localize($reason->getName()),
'group_by' => fn (ActivityReason $reason) => $this->translatableStringHelper->localize($reason->getCategory()->getName()),
'attr' => ['class' => 'select2 '],
'multiple' => true,
'expanded' => false,
]);

View File

@@ -39,9 +39,9 @@ class UsersJobFilter implements FilterInterface
$qb
->andWhere(
$qb->expr()->exists(
'SELECT 1 FROM ' . Activity::class . ' activity_users_job_filter_act
'SELECT 1 FROM ' . Activity::class . ' activity_users_job_filter_act
JOIN activity_users_job_filter_act.users users WHERE users.userJob IN (:activity_users_job_filter_jobs) AND activity_users_job_filter_act = activity '
)
)
)
->setParameter('activity_users_job_filter_jobs', $data['jobs']);
}

View File

@@ -11,7 +11,8 @@ declare(strict_types=1);
namespace Chill\ActivityBundle\Form;
use Chill\ActivityBundle\Form\Type\TranslatableActivityReasonCategory;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Form\Type\TranslatableActivityReasonCategoryType;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
@@ -25,13 +26,13 @@ class ActivityReasonType extends AbstractType
$builder
->add('name', TranslatableStringFormType::class)
->add('active', CheckboxType::class, ['required' => false])
->add('category', TranslatableActivityReasonCategory::class);
->add('category', TranslatableActivityReasonCategoryType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'Chill\ActivityBundle\Entity\ActivityReason',
'data_class' => ActivityReason::class,
]);
}

View File

@@ -13,7 +13,7 @@ namespace Chill\ActivityBundle\Form;
use Chill\ActivityBundle\Entity\Activity;
use Chill\ActivityBundle\Entity\ActivityPresence;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Form\Type\PickActivityReasonType;
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
use Chill\DocStoreBundle\Form\StoredObjectType;
use Chill\MainBundle\Entity\Center;
@@ -229,19 +229,10 @@ class ActivityType extends AbstractType
}
if ($activityType->isVisible('reasons')) {
$builder->add('reasons', EntityType::class, [
$builder->add('reasons', PickActivityReasonType::class, [
'label' => $activityType->getLabel('reasons'),
'required' => $activityType->isRequired('reasons'),
'class' => ActivityReason::class,
'multiple' => true,
'choice_label' => function (ActivityReason $activityReason) {
return $this->translatableStringHelper->localize($activityReason->getName());
},
'attr' => ['class' => 'select2 '],
'query_builder' => static function (EntityRepository $er) {
return $er->createQueryBuilder('a')
->where('a.active = true');
},
]);
}

View File

@@ -12,9 +12,9 @@ declare(strict_types=1);
namespace Chill\ActivityBundle\Form\Type;
use Chill\ActivityBundle\Entity\ActivityReason;
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
use Chill\ActivityBundle\Templating\Entity\ActivityReasonRender;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\EntityRepository;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
@@ -22,31 +22,29 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* FormType to choose amongst activity reasons.
*/
class TranslatableActivityReason extends AbstractType
class PickActivityReasonType extends AbstractType
{
/**
* @var ActivityReasonRender
*/
protected $reasonRender;
private ActivityReasonRepository $activityReasonRepository;
/**
* @var TranslatableStringHelper
*/
protected $translatableStringHelper;
private ActivityReasonRender $reasonRender;
private TranslatableStringHelperInterface $translatableStringHelper;
public function __construct(
TranslatableStringHelper $translatableStringHelper,
ActivityReasonRender $reasonRender
ActivityReasonRepository $activityReasonRepository,
ActivityReasonRender $reasonRender,
TranslatableStringHelperInterface $translatableStringHelper
) {
$this->translatableStringHelper = $translatableStringHelper;
$this->activityReasonRepository = $activityReasonRepository;
$this->reasonRender = $reasonRender;
$this->translatableStringHelper = $translatableStringHelper;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
[
'class' => 'ChillActivityBundle:ActivityReason',
'class' => ActivityReason::class,
'choice_label' => function (ActivityReason $choice) {
return $this->reasonRender->renderString($choice, []);
},
@@ -57,10 +55,7 @@ class TranslatableActivityReason extends AbstractType
return null;
},
'query_builder' => static function (EntityRepository $er) {
return $er->createQueryBuilder('r')
->where('r.active = true');
},
'choices' => $this->activityReasonRepository->findAll(),
'attr' => ['class' => ' select2 '],
]
);

View File

@@ -1,59 +0,0 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Form\Type;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* Description of TranslatableActivityReasonCategory.
*/
class TranslatableActivityReasonCategory extends AbstractType
{
/**
* @var RequestStack
*/
private $requestStack;
public function __construct(RequestStack $requestStack)
{
$this->requestStack = $requestStack;
}
public function configureOptions(OptionsResolver $resolver)
{
$locale = $this->requestStack->getCurrentRequest()->getLocale();
$resolver->setDefaults(
[
'class' => 'ChillActivityBundle:ActivityReasonCategory',
'choice_label' => 'name[' . $locale . ']',
'query_builder' => static function (EntityRepository $er) {
return $er->createQueryBuilder('c')
->where('c.active = true');
},
]
);
}
public function getBlockPrefix()
{
return 'translatable_activity_reason_category';
}
public function getParent()
{
return EntityType::class;
}
}

View File

@@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Form\Type;
use Chill\ActivityBundle\Entity\ActivityReasonCategory;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* Description of TranslatableActivityReasonCategory.
*/
class TranslatableActivityReasonCategoryType extends AbstractType
{
private TranslatableStringHelperInterface $translatableStringHelper;
private TranslatorInterface $translator;
public function __construct(TranslatableStringHelperInterface $translatableStringHelper, TranslatorInterface $translator)
{
$this->translatableStringHelper = $translatableStringHelper;
$this->translator = $translator;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
[
'class' => ActivityReasonCategory::class,
'choice_label' => function (ActivityReasonCategory $category) {
return $this->translatableStringHelper->localize($category->getName())
. (!$category->getActive() ? ' (' . $this->translator->trans('inactive') . ')' : '');
},
]
);
}
public function getBlockPrefix()
{
return 'translatable_activity_reason_category';
}
public function getParent()
{
return EntityType::class;
}
}

View File

@@ -36,7 +36,6 @@ final class AdminMenuBuilder implements LocalMenuBuilderInterface
->setAttribute('class', 'list-group-item-header')
->setExtras([
'order' => 5000,
'icons' => ['exchange'],
]);
$menu->addChild('Activity Reasons', [

View File

@@ -0,0 +1,51 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Repository;
use Chill\ActivityBundle\Entity\ActivityPresence;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
class ActivityPresenceRepository implements ActivityPresenceRepositoryInterface
{
private EntityRepository $repository;
public function __construct(EntityManagerInterface $entityManager)
{
$this->repository = $entityManager->getRepository($this->getClassName());
}
public function find($id): ?ActivityPresence
{
return $this->repository->find($id);
}
public function findAll(): array
{
return $this->repository->findAll();
}
public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array
{
return $this->findBy($criteria, $orderBy, $limit, $offset);
}
public function findOneBy(array $criteria): ?ActivityPresence
{
return $this->findOneBy($criteria);
}
public function getClassName(): string
{
return ActivityPresence::class;
}
}

View File

@@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ActivityBundle\Repository;
use Chill\ActivityBundle\Entity\ActivityPresence;
interface ActivityPresenceRepositoryInterface
{
public function find($id): ?ActivityPresence;
/**
* @return array|ActivityPresence[]
*/
public function findAll(): array;
/**
* @return array|ActivityPresence[]
*/
public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array;
public function findOneBy(array $criteria): ?ActivityPresence;
public function getClassName(): string;
}

View File

@@ -14,17 +14,38 @@ namespace Chill\ActivityBundle\Repository;
use Chill\ActivityBundle\Entity\ActivityReason;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* @method ActivityReason|null find($id, $lockMode = null, $lockVersion = null)
* @method ActivityReason|null findOneBy(array $criteria, array $orderBy = null)
* @method ActivityReason[] findAll()
* @method ActivityReason[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class ActivityReasonRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
private RequestStack $requestStack;
public function __construct(
ManagerRegistry $registry,
RequestStack $requestStack
) {
parent::__construct($registry, ActivityReason::class);
$this->requestStack = $requestStack;
}
/**
* @return ActivityReason[]
*/
public function findAll(): array
{
$qb = $this->createQueryBuilder('ar');
$qb->select(['ar'])
->leftJoin('ar.category', 'category')
->addOrderBy('JSON_EXTRACT(category.name, :lang)')
->addOrderBy('JSON_EXTRACT(ar.name, :lang)')
->setParameter('lang', $this->requestStack->getCurrentRequest()->getLocale() ?? 'fr');
return $qb->getQuery()->getResult();
}
}

View File

@@ -88,3 +88,11 @@ div.flex-bloc.concerned-groups {
font-size: 120%;
}
}
/// DOCUMENT LIST IN ACTIVITY ITEM
li.document-list-item {
display: flex;
width: 100%;
justify-content: space-between;
margin-bottom: 0.3rem;
}

View File

@@ -117,7 +117,8 @@ export default {
target: { //name, id
},
edit: false,
addressId: null
addressId: null,
defaults: window.addaddress
}
}
}

View File

@@ -30,7 +30,7 @@ const store = createStore({
},
getters: {
suggestedEntities(state) {
if (typeof state.activity.accompanyingPeriod === "undefined") {
if (typeof state.activity.accompanyingPeriod === "undefined" || state.activity.accompanyingPeriod === null) {
return [];
}
const allEntities = [

View File

@@ -39,6 +39,9 @@ const makeConcernedThirdPartiesLocation = (locationType, store) => {
return locations;
};
const makeAccompanyingPeriodLocation = (locationType, store) => {
if (store.state.activity.accompanyingPeriod === null) {
return {};
}
const accPeriodLocation = store.state.activity.accompanyingPeriod.location;
return {
type: 'location',

View File

@@ -68,7 +68,7 @@
<div class="wl-col title"><h3>{{ 'Referrer'|trans }}</h3></div>
<div class="wl-col list">
<p class="wl-item">
{{ activity.user|chill_entity_render_box }}
<span class="badge-user">{{ activity.user|chill_entity_render_box }}</span>
</p>
</div>
</div>
@@ -137,19 +137,42 @@
{{ activity.comment|chill_entity_render_box({
'disable_markdown': false,
'limit_lines': 3,
'metadata': false
'metadata': false,
}) }}
</div>
</div>
{% endif %}
{# Only if ACL SEE_DETAILS AND/OR only on template SHOW ??
durationTime
travelTime
comment
documents
attendee
#}
{% if is_granted('CHILL_ACTIVITY_SEE_DETAILS', activity) and activity.privateComment.hasCommentForUser(app.user) %}
<div class="wl-row">
<div class="wl-col title">
<h3>{{ 'Private comment'|trans }}</h3>
</div>
<div class="wl-col list">
<section class="chill-entity entity-comment-embeddable">
<blockquote class="chill-user-quote private-quote">
{{ activity.privateComment.comments[app.user.id]|chill_markdown_to_html }}
</blockquote>
</section>
</div>
</div>
{% endif %}
{% if is_granted('CHILL_ACTIVITY_SEE_DETAILS', activity) and activity.documents|length > 0 %}
<div class="wl-row">
<div class="wl-col title">
<h3>{{ 'Documents'|trans }}</h3>
</div>
<div class="wl-col list">
<ul>
{% for d in activity.documents %}
<li class="document-list-item">{{ d.title|chill_print_or_message('document.Any title') }} {{ d|chill_document_button_group(d.title, is_granted('CHILL_ACTIVITY_UPDATE', activity), {small: true}) }}</li>
{% endfor %}
</ul>
</div>
</div>
{% endif %}
</div>
</div>

View File

@@ -8,11 +8,13 @@
{% block js %}
{{ parent() }}
{{ encore_entry_script_tags('mod_notification_toggle_read_status') }}
{{ encore_entry_script_tags('mod_document_action_buttons_group') }}
{% endblock %}
{% block css %}
{{ parent() }}
{{ encore_entry_link_tags('mod_notification_toggle_read_status') }}
{{ encore_entry_link_tags('mod_document_action_buttons_group') }}
{% endblock %}
{% block content %}

View File

@@ -23,11 +23,13 @@
{% block js %}
{{ parent() }}
{{ encore_entry_script_tags('mod_notification_toggle_read_status') }}
{{ encore_entry_script_tags('mod_document_action_buttons_group') }}
{% endblock %}
{% block css %}
{{ parent() }}
{{ encore_entry_link_tags('mod_notification_toggle_read_status') }}
{{ encore_entry_link_tags('mod_document_action_buttons_group') }}
{% endblock %}
{% block content %}

View File

@@ -41,7 +41,7 @@
{% if activity.user and t.userVisible %}
<li>
<span class="item-key">{{ 'Referrer'|trans ~ ': ' }}</span>
<b>{{ activity.user|chill_entity_render_box}}</b>
<span class="badge-user">{{ activity.user|chill_entity_render_box }}</span>
</li>
{% endif %}

View File

@@ -35,7 +35,9 @@
<div class="item-row separator">
<dl class="chill_view_data">
<dt class="inline">{{ 'Referrer'|trans|capitalize }}</dt>
<dd>{{ entity.user|chill_entity_render_box }}</dd>
<dd>
<span class="badge-user">{{ entity.user|chill_entity_render_box }}</span>
</dd>
{%- if entity.scope -%}
<dt class="inline">{{ 'Scope'|trans }}</dt>
@@ -156,7 +158,7 @@
<dd>
<section class="chill-entity entity-comment-embeddable">
<blockquote class="chill-user-quote private-quote">
{{ entity.privateComment.comments[userId] }}
{{ entity.privateComment.comments[userId]|chill_markdown_to_html }}
</blockquote>
</section>
</dd>
@@ -168,11 +170,11 @@
{% if entity.documents|length > 0 %}
<ul>
{% for d in entity.documents %}
<li>{{ d.title }}{{ m.download_button(d) }}</li>
<li class="document-list-item">{{ d.title|chill_print_or_message('document.Any title') }} {{ d|chill_document_button_group(d.title, is_granted('CHILL_ACTIVITY_UPDATE', entity), {small: true}) }}</li>
{% endfor %}
</ul>
{% else %}
<span class="chill-no-data-statement">{{ 'Any document found'|trans }}</span>
<span class="chill-no-data-statement">{{ 'No document found'|trans }}</span>
{% endif %}
</dd>
{% endif %}

View File

@@ -8,12 +8,14 @@
{{ parent() }}
{{ encore_entry_script_tags('mod_notification_toggle_read_status') }}
{{ encore_entry_script_tags('mod_async_upload') }}
{{ encore_entry_script_tags('mod_document_action_buttons_group') }}
{% endblock %}
{% block css %}
{{ parent() }}
{{ encore_entry_link_tags('mod_notification_toggle_read_status') }}
{{ encore_entry_link_tags('mod_async_upload') }}
{{ encore_entry_link_tags('mod_document_action_buttons_group') }}
{% endblock %}
{% import 'ChillActivityBundle:ActivityReason:macro.html.twig' as m %}

View File

@@ -7,13 +7,13 @@
{% block js %}
{{ parent() }}
{{ encore_entry_script_tags('mod_notification_toggle_read_status') }}
{{ encore_entry_link_tags('mod_async_upload') }}
{{ encore_entry_script_tags('mod_document_action_buttons_group') }}
{% endblock %}
{% block css %}
{{ parent() }}
{{ encore_entry_link_tags('mod_notification_toggle_read_status') }}
{{ encore_entry_link_tags('mod_async_upload') }}
{{ encore_entry_link_tags('mod_document_action_buttons_group') }}
{% endblock %}
{% import 'ChillActivityBundle:ActivityReason:macro.html.twig' as m %}

View File

@@ -7,22 +7,34 @@
<thead>
<tr>
<th>{{ 'Name'|trans }}</th>
<th>{{ 'Active'|trans }}</th>
<th>{{ 'Actions'|trans }}</th>
</tr>
</thead>
<tbody>
{% for entity in entities %}
<tr class="{% if entity.active %}active{% else %}inactive{% endif %}">
<td><a href="{{ path('chill_activity_activityreason_show', { 'id': entity.id }) }}">{{ entity.name|localize_translatable_string }}</a></td>
<td>
<ul class="record_actions">
<li>
<a href="{{ path('chill_activity_activityreason_show', { 'id': entity.id }) }}" class="btn btn-show" title="{{ 'show'|trans }}"></a>
</li>
<li>
<a href="{{ path('chill_activity_activityreason_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a>
</li>
</ul>
{% if entity.category is not null -%}
{{ entity.category.name|localize_translatable_string }} >
{% endif -%}
{{ entity.name|localize_translatable_string }}
</td>
<td>
<i class="fa {% if entity.active %}fa-check-square-o{% else %}fa-square-o{% endif %}"></i>
{% if entity.active and not entity.isActiveAndParentActive %}
<span class="badge text-bg-danger text-white">{{ 'Associated activity reason category is inactive'|trans }}</span>
{% endif %}
</td>
<td>
<ul class="record_actions">
<li>
<a href="{{ path('chill_activity_activityreason_show', { 'id': entity.id }) }}" class="btn btn-show" title="{{ 'show'|trans }}"></a>
</li>
<li>
<a href="{{ path('chill_activity_activityreason_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a>
</li>
</ul>
</td>
</tr>
{% endfor %}

View File

@@ -7,6 +7,7 @@
<thead>
<tr>
<th>{{ 'Name'|trans }}</th>
<th>{{ 'Active'|trans }}</th>
<th>{{ 'Actions'|trans }}</th>
</tr>
</thead>
@@ -14,7 +15,11 @@
{% for entity in entities %}
<tr>
<td>
<a href="{{ path('chill_activity_activityreasoncategory_show', { 'id': entity.id }) }}">{{ entity.name|localize_translatable_string }}</a></td>
{{ entity.name|localize_translatable_string }}
</td>
<td>
<i class="fa {% if entity.active %}fa-check-square-o{% else %}fa-square-o{% endif %}"></i>
</td>
<td>
<ul class="record_actions">
<li>

View File

@@ -22,6 +22,7 @@ use Chill\DocStoreBundle\Repository\DocumentCategoryRepository;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Repository\PersonRepository;
use Chill\PersonBundle\Templating\Entity\PersonRenderInterface;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
@@ -45,6 +46,8 @@ class ActivityContext implements
private PersonRenderInterface $personRender;
private PersonRepository $personRepository;
private TranslatableStringHelperInterface $translatableStringHelper;
private TranslatorInterface $translator;
@@ -55,6 +58,7 @@ class ActivityContext implements
TranslatableStringHelperInterface $translatableStringHelper,
EntityManagerInterface $em,
PersonRenderInterface $personRender,
PersonRepository $personRepository,
TranslatorInterface $translator,
BaseContextData $baseContextData
) {
@@ -63,6 +67,7 @@ class ActivityContext implements
$this->translatableStringHelper = $translatableStringHelper;
$this->em = $em;
$this->personRender = $personRender;
$this->personRepository = $personRepository;
$this->translator = $translator;
$this->baseContextData = $baseContextData;
}
@@ -147,7 +152,7 @@ class ActivityContext implements
$options = $template->getOptions();
$data = [];
$data = array_merge($data, $this->baseContextData->getData());
$data = array_merge($data, $this->baseContextData->getData($contextGenerationData['creator'] ?? null));
$data['activity'] = $this->normalizer->normalize($entity, 'docgen', ['docgen:expects' => Activity::class, 'groups' => 'docgen:read']);
$data['course'] = $this->normalizer->normalize($entity->getAccompanyingPeriod(), 'docgen', ['docgen:expects' => AccompanyingPeriod::class, 'groups' => 'docgen:read']);
@@ -206,6 +211,32 @@ class ActivityContext implements
return $options['mainPerson'] || $options['person1'] || $options['person2'];
}
public function contextGenerationDataNormalize(DocGeneratorTemplate $template, $entity, array $data): array
{
$normalized = [];
foreach (['mainPerson', 'person1', 'person2'] as $k) {
$normalized[$k] = null === $data[$k] ? null : $data[$k]->getId();
}
return $normalized;
}
public function contextGenerationDataDenormalize(DocGeneratorTemplate $template, $entity, array $data): array
{
$denormalized = [];
foreach (['mainPerson', 'person1', 'person2'] as $k) {
if (null !== ($id = ($data[$k] ?? null))) {
$denormalized[$k] = $this->personRepository->find($id);
} else {
$denormalized[$k] = null;
}
}
return $denormalized;
}
/**
* @param Activity $entity
*/

View File

@@ -146,6 +146,16 @@ class ListActivitiesByAccompanyingPeriodContext implements
return $this->accompanyingPeriodContext->hasPublicForm($template, $entity);
}
public function contextGenerationDataNormalize(DocGeneratorTemplate $template, $entity, array $data): array
{
return $this->accompanyingPeriodContext->contextGenerationDataNormalize($template, $entity, $data);
}
public function contextGenerationDataDenormalize(DocGeneratorTemplate $template, $entity, array $data): array
{
return $this->accompanyingPeriodContext->contextGenerationDataDenormalize($template, $entity, $data);
}
public function storeGenerated(DocGeneratorTemplate $template, StoredObject $storedObject, object $entity, array $contextGenerationData): void
{
$this->accompanyingPeriodContext->storeGenerated($template, $storedObject, $entity, $contextGenerationData);

View File

@@ -369,8 +369,12 @@ final class ActivityControllerTest extends WebTestCase
$center
);
$reachableScopesId = array_intersect(
array_map(static function ($s) { return $s->getId(); }, $reachableScopesDelete),
array_map(static function ($s) { return $s->getId(); }, $reachableScopesUpdate)
array_map(static function ($s) {
return $s->getId();
}, $reachableScopesDelete),
array_map(static function ($s) {
return $s->getId();
}, $reachableScopesUpdate)
);
if (count($reachableScopesId) === 0) {

View File

@@ -188,7 +188,9 @@ final class ActivityTypeTest extends KernelTestCase
// map all the values in an array
$values = array_map(
static function ($choice) { return $choice->value; },
static function ($choice) {
return $choice->value;
},
$view['activity']['durationTime']->vars['choices']
);

View File

@@ -11,7 +11,7 @@ declare(strict_types=1);
namespace Chill\ActivityBundle\Tests\Form\Type;
use Chill\ActivityBundle\Form\Type\TranslatableActivityReason;
use Chill\ActivityBundle\Form\Type\PickActivityReasonType;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Symfony\Component\Form\PreloadedExtension;
use Symfony\Component\Form\Test\TypeTestCase;
@@ -36,7 +36,7 @@ final class TranslatableActivityReasonTest extends TypeTestCase
public function testSimple()
{
$translatableActivityReasonType = new TranslatableActivityReason(
$translatableActivityReasonType = new PickActivityReasonType(
$this->getTranslatableStringHelper()
);

View File

@@ -1,4 +1,11 @@
services:
Chill\ActivityBundle\Controller\ActivityController:
_defaults:
autowire: true
autoconfigure: true
Chill\ActivityBundle\Controller\:
resource: '../../Controller/'
tags: ['controller.service_arguments']
Chill\ActivityBundle\Controller\ActivityController:
tags: ['controller.service_arguments']

View File

@@ -41,6 +41,12 @@ services:
tags:
- { name: chill.export, alias: 'avg_activity_visit_duration_linked_to_acp' }
Chill\ActivityBundle\Export\Export\LinkedToACP\ListActivity:
tags:
- { name: chill.export, alias: 'list_activity_acp'}
Chill\ActivityBundle\Export\Export\ListActivityHelper: ~
## Filters
chill.activity.export.type_filter:
class: Chill\ActivityBundle\Export\Filter\ActivityTypeFilter
@@ -73,6 +79,11 @@ services:
tags:
- { name: chill.export_filter, alias: 'accompanyingcourse_activitytype_filter' }
chill.activity.export.location_filter:
class: Chill\ActivityBundle\Export\Filter\ACPFilters\LocationFilter
tags:
- { name: chill.export_filter, alias: 'activity_location_filter' }
chill.activity.export.locationtype_filter:
class: Chill\ActivityBundle\Export\Filter\ACPFilters\LocationTypeFilter
tags:
@@ -120,15 +131,18 @@ services:
tags:
- { name: chill.export_filter, alias: 'activity_usersscope_filter' }
Chill\ActivityBundle\Export\Filter\ACPFilters\HasNoActivityFilter:
tags:
- { name: chill.export_filter, alias: 'accompanyingcourse_has_no_activity_filter' }
## Aggregators
Chill\ActivityBundle\Export\Aggregator\PersonAggregators\ActivityReasonAggregator:
tags:
- { name: chill.export_aggregator, alias: activity_reason_aggregator }
chill.activity.export.type_aggregator:
class: Chill\ActivityBundle\Export\Aggregator\ActivityTypeAggregator
Chill\ActivityBundle\Export\Aggregator\ActivityTypeAggregator:
tags:
- { name: chill.export_aggregator, alias: activity_type_aggregator }
- { name: chill.export_aggregator, alias: activity_common_type_aggregator }
chill.activity.export.user_aggregator:
class: Chill\ActivityBundle\Export\Aggregator\ActivityUserAggregator
@@ -179,3 +193,11 @@ services:
Chill\ActivityBundle\Export\Aggregator\ActivityUsersJobAggregator:
tags:
- { name: chill.export_aggregator, alias: activity_users_job_aggregator }
Chill\ActivityBundle\Export\Aggregator\ACPAggregators\ByActivityNumberAggregator:
tags:
- { name: chill.export_aggregator, alias: accompanyingcourse_by_activity_number_aggregator }
Chill\ActivityBundle\Export\Aggregator\SentReceivedAggregator:
tags:
- { name: chill.export_aggregator, alias: activity_sentreceived_aggregator }

View File

@@ -1,19 +1,12 @@
---
services:
chill.activity.form.type.translatableactivityreasoncategory:
class: Chill\ActivityBundle\Form\Type\TranslatableActivityReasonCategory
arguments:
- "@request_stack"
tags:
- { name: form.type, alias: translatable_activity_reason_category }
Chill\ActivityBundle\Form\Type\TranslatableActivityReasonCategoryType:
autowire: true
autoconfigure: true
chill.activity.form.type.translatableactivityreason:
class: Chill\ActivityBundle\Form\Type\TranslatableActivityReason
arguments:
$translatableStringHelper: "@chill.main.helper.translatable_string"
$reasonRender: '@Chill\ActivityBundle\Templating\Entity\ActivityReasonRender'
tags:
- { name: form.type, alias: translatable_activity_reason }
Chill\ActivityBundle\Form\Type\PickActivityReasonType:
autowire: true
autoconfigure: true
chill.activity.form.type.translatableactivitytype:
class: Chill\ActivityBundle\Form\Type\TranslatableActivityType

View File

@@ -1,5 +1,8 @@
---
services:
Chill\ActivityBundle\Repository\ActivityReasonRepository:
autowire: true
chill_activity.repository.activity_type: '@Chill\ActivityBundle\Repository\ActivityTypeRepository'
chill_activity.repository.reason: '@Chill\ActivityBundle\Repository\ActivityReasonRepository'
chill_activity.repository.reason_category: '@Chill\ActivityBundle\Repository\ActivityReasonCategoryRepository'

View File

@@ -45,6 +45,8 @@ by: 'Par '
location: Lieu
Reasons: Sujets
Private comment: Commentaire privé
sent: Envoyé
received: Reçu
#forms
@@ -75,7 +77,7 @@ Choose a type: Choisir un type
4 hours: 4 heures
4 hours 30: 4 heures 30
5 hours: 5 heures
Concerned groups: Parties concernées
Concerned groups: Parties concernées par l'échange
Persons in accompanying course: Usagers du parcours
Third persons: Tiers non-pro.
Others persons: Usagers
@@ -115,6 +117,7 @@ Activity Reasons: Sujets d'une activité
Activity Reasons Category: Catégories de sujet d'activités
Activity Types Categories: Catégories des types d'activité
Activity Presences: Presences aux activités
Associated activity reason category is inactive: La catégorie de sujet attachée est inactive
# Crud
@@ -249,6 +252,8 @@ Activity reasons for those activities: Sujets de ces activités
Filter by activity type: Filtrer les activités par type
Filter activity by location: Filtrer les activités par localisation
'Filtered activity by location: only %locations%': "Filtré par localisation: uniquement %locations%"
Filter activity by locationtype: Filtrer les activités par type de localisation
'Filtered activity by locationtype: only %types%': "Filtré par type de localisation: uniquement %types%"
Accepted locationtype: Types de localisation
@@ -260,8 +265,6 @@ activity is not emergency: l'activité n'est pas urgente
Filter activity by sentreceived: Filtrer les activités par envoyé/reçu
'Filtered activity by sentreceived: only %sentreceived%': "Filtré par envoyé/reçu: uniquement %sentreceived%"
Accepted sentreceived: ''
is sent: envoyé
is received: reçu
Filter activity by linked socialaction: Filtrer les activités par action liée
'Filtered activity by linked socialaction: only %actions%': "Filtré par action liée: uniquement %actions%"
Filter activity by linked socialissue: Filtrer les activités par problématique liée
@@ -277,6 +280,10 @@ Filter activity by userscope: Filtrer les activités par service du créateur
'Filtered activity by userscope: only %scopes%': "Filtré par service du créateur: uniquement %scopes%"
Accepted userscope: Services
Filter acp which has no activity: Filtrer les parcours qui nont pas dactivité
Filtered acp which has no activities: Filtrer les parcours sans activité associée
Group acp by activity number: Grouper les parcours par nombre dactivité
#aggregators
Activity type: Type d'activité
Activity user: Utilisateur lié à l'activité
@@ -319,11 +326,32 @@ This is the minimal activity data: Activité n°
docgen:
Activity basic: Echange
A basic context for activity: Contexte pour les échanges
Accompanying period with a list of activities: Parcours d'accompagnement avec liste des échanges
Accompanying period with a list of activities description: Ce contexte reprend les informations du parcours, et tous les échanges pour un parcours. Les échanges ne sont pas filtrés.
A basic context for activity: Contexte pour les activités
Accompanying period with a list of activities: Parcours d'accompagnement avec liste des activités
Accompanying period with a list of activities description: Ce contexte reprend les informations du parcours, et tous les activités pour un parcours. Les activités ne sont pas filtrés.
export:
list:
activity:
users name: Nom des utilisateurs
users ids: Identifiant des utilisateurs
third parties ids: Identifiant des tiers
persons ids: Identifiant des personnes
persons name: Nom des personnes
thirds parties: Tiers
date: Date de l'activité
locationName: Localisation
sent received: Envoyé ou reçu
emergency: Urgence
accompanying course id: Identifiant du parcours
course circles: Cercles du parcours
travelTime: Durée de déplacement
durationTime: Durée
id: Identifiant
List activities linked to an accompanying course: Liste les activités liées à un parcours en fonction de différents filtres.
List activity linked to a course: Liste des activités liées à un parcours
filter:
activity:
by_usersjob:
@@ -332,3 +360,10 @@ export:
by_usersscope:
Filter by users scope: Filtrer les activités par services d'au moins un utilisateur participant
'Filtered activity by users scope: only %scopes%': 'Filtré par service d''au moins un utilisateur participant: seulement %scopes%'
aggregator:
activity:
by_sent_received:
Sent or received: Envoyé ou reçu
is sent: envoyé
is received: reçu
Group activity by sentreceived: Grouper les activités par envoyé / reçu

View File

@@ -231,4 +231,4 @@ This is the minimal activity data: Activité n°
docgen:
Activity basic: Echange
A basic context for activity: Contexte pour les échanges
A basic context for activity: Contexte pour les activités

View File

@@ -16,7 +16,7 @@ For this type of activity, document is required: Pour ce type d'activité, un do
For this type of activity, emergency is required: Pour ce type d'activité, le champ "Urgent" est requis
For this type of activity, accompanying period is required: Pour ce type d'activité, le parcours d'accompagnement est requis
For this type of activity, you must add at least one social issue: Pour ce type d'activité, vous devez ajouter au moins une problématique sociale
For this type of activity, you must add at least one social action: Pour ce type d'activité, vous devez indiquez au moins une action sociale
For this type of activity, you must add at least one social action: Pour ce type d'activité, vous devez indiquer au moins une action sociale
# admin
This parameter must be equal to social issue parameter: Ce paramètre doit être égal au paramètre "Visibilité du champs Problématiques sociales"

View File

@@ -30,6 +30,8 @@ final class ChillAsideActivityExtension extends Extension implements PrependExte
$loader->load('services.yaml');
$loader->load('services/form.yaml');
$loader->load('services/menu.yaml');
$loader->load('services/security.yaml');
$loader->load('services/export.yaml');
}
public function prepend(ContainerBuilder $container)

View File

@@ -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\AsideActivityBundle\Export\Aggregator;
use Chill\AsideActivityBundle\Export\Declarations;
use Chill\AsideActivityBundle\Repository\AsideActivityCategoryRepository;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
class ByActivityTypeAggregator implements AggregatorInterface
{
private AsideActivityCategoryRepository $asideActivityCategoryRepository;
private TranslatableStringHelper $translatableStringHelper;
public function __construct(AsideActivityCategoryRepository $asideActivityCategoryRepository, TranslatableStringHelper $translatableStringHelper)
{
$this->asideActivityCategoryRepository = $asideActivityCategoryRepository;
$this->translatableStringHelper = $translatableStringHelper;
}
public function addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
$qb->addSelect('IDENTITY(aside.type) AS by_aside_activity_type_aggregator')
->addGroupBy('by_aside_activity_type_aggregator');
}
public function applyOn(): string
{
return Declarations::ASIDE_ACTIVITY_TYPE;
}
public function buildForm(FormBuilderInterface $builder)
{
// No form needed
}
public function getLabels($key, array $values, $data)
{
return function ($value): string {
if ('_header' === $value) {
return 'export.aggregator.Aside activity type';
}
if (null === $value || null === $t = $this->asideActivityCategoryRepository->find($value)) {
return '';
}
return $this->translatableStringHelper->localize($t->getTitle());
};
}
public function getQueryKeys($data): array
{
return ['by_aside_activity_type_aggregator'];
}
public function getTitle(): string
{
return 'export.aggregator.Group by aside activity type';
}
}

View File

@@ -0,0 +1,89 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\AsideActivityBundle\Export\Aggregator;
use Chill\AsideActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Repository\UserJobRepositoryInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use function in_array;
class ByUserJobAggregator implements AggregatorInterface
{
private TranslatableStringHelperInterface $translatableStringHelper;
private UserJobRepositoryInterface $userJobRepository;
public function __construct(UserJobRepositoryInterface $userJobRepository, TranslatableStringHelperInterface $translatableStringHelper)
{
$this->userJobRepository = $userJobRepository;
$this->translatableStringHelper = $translatableStringHelper;
}
public function addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
if (!in_array('aside_user', $qb->getAllAliases(), true)) {
$qb->leftJoin('aside.agent', 'aside_user');
}
$qb
->addSelect('IDENTITY(aside_user.userJob) AS aside_activity_user_job_aggregator')
->addGroupBy('aside_activity_user_job_aggregator');
}
public function applyOn()
{
return Declarations::ASIDE_ACTIVITY_TYPE;
}
public function buildForm(FormBuilderInterface $builder)
{
// nothing to add in the form
}
public function getLabels($key, array $values, $data)
{
return function ($value): string {
if ('_header' === $value) {
return 'Users \'s job';
}
if (null === $value || '' === $value) {
return '';
}
$j = $this->userJobRepository->find($value);
return $this->translatableStringHelper->localize(
$j->getLabel()
);
};
}
public function getQueryKeys($data): array
{
return ['aside_activity_user_job_aggregator'];
}
public function getTitle()
{
return 'export.aggregator.Aggregate by user job';
}
}

View File

@@ -0,0 +1,89 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\AsideActivityBundle\Export\Aggregator;
use Chill\AsideActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\AggregatorInterface;
use Chill\MainBundle\Repository\ScopeRepositoryInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use function in_array;
class ByUserScopeAggregator implements AggregatorInterface
{
private ScopeRepositoryInterface $scopeRepository;
private TranslatableStringHelperInterface $translatableStringHelper;
public function __construct(ScopeRepositoryInterface $scopeRepository, TranslatableStringHelperInterface $translatableStringHelper)
{
$this->scopeRepository = $scopeRepository;
$this->translatableStringHelper = $translatableStringHelper;
}
public function addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
if (!in_array('aside_user', $qb->getAllAliases(), true)) {
$qb->leftJoin('aside.agent', 'aside_user');
}
$qb
->addSelect('IDENTITY(aside_user.mainScope) AS aside_activity_user_scope_aggregator')
->addGroupBy('aside_activity_user_scope_aggregator');
}
public function applyOn()
{
return Declarations::ASIDE_ACTIVITY_TYPE;
}
public function buildForm(FormBuilderInterface $builder)
{
// nothing to add in the form
}
public function getLabels($key, array $values, $data)
{
return function ($value): string {
if ('_header' === $value) {
return 'Users \'s scope';
}
if (null === $value || '' === $value) {
return '';
}
$s = $this->scopeRepository->find($value);
return $this->translatableStringHelper->localize(
$s->getName()
);
};
}
public function getQueryKeys($data): array
{
return ['aside_activity_user_scope_aggregator'];
}
public function getTitle()
{
return 'export.aggregator.Aggregate by user scope';
}
}

View File

@@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\AsideActivityBundle\Export;
/**
* This class declare constants used for the export framework.
*/
abstract class Declarations
{
public const ASIDE_ACTIVITY_TYPE = 'aside_activity';
}

View File

@@ -0,0 +1,102 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\AsideActivityBundle\Export\Export;
use Chill\AsideActivityBundle\Export\Declarations;
use Chill\AsideActivityBundle\Repository\AsideActivityRepository;
use Chill\AsideActivityBundle\Security\AsideActivityVoter;
use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface;
use Doctrine\ORM\Query;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface;
class AvgAsideActivityDuration implements ExportInterface, GroupedExportInterface
{
private AsideActivityRepository $repository;
public function __construct(
AsideActivityRepository $repository
) {
$this->repository = $repository;
}
public function buildForm(FormBuilderInterface $builder)
{
}
public function getAllowedFormattersTypes(): array
{
return [FormatterInterface::TYPE_TABULAR];
}
public function getDescription(): string
{
return 'export.Average aside activities duration';
}
public function getGroup(): string
{
return 'export.Exports of aside activities';
}
public function getLabels($key, array $values, $data)
{
if ('export_avg_aside_activity_duration' !== $key) {
throw new LogicException("the key {$key} is not used by this export");
}
return static fn ($value) => '_header' === $value ? 'Average duration aside activities' : $value;
}
public function getQueryKeys($data): array
{
return ['export_avg_aside_activity_duration'];
}
public function getResult($query, $data)
{
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
public function getTitle(): string
{
return 'export.Average aside activities duration';
}
public function getType(): string
{
return Declarations::ASIDE_ACTIVITY_TYPE;
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$qb = $this->repository->createQueryBuilder('aside');
$qb
->select('AVG(aside.duration) as export_avg_aside_activity_duration')
->andWhere($qb->expr()->isNotNull('aside.duration'));
return $qb;
}
public function requiredRole(): string
{
return AsideActivityVoter::STATS;
}
public function supportsModifiers(): array
{
return [Declarations::ASIDE_ACTIVITY_TYPE];
}
}

View File

@@ -0,0 +1,107 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\AsideActivityBundle\Export\Export;
use Chill\AsideActivityBundle\Export\Declarations;
use Chill\AsideActivityBundle\Repository\AsideActivityRepository;
use Chill\AsideActivityBundle\Security\AsideActivityVoter;
use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface;
use Doctrine\ORM\Query;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface;
class CountAsideActivity implements ExportInterface, GroupedExportInterface
{
private AsideActivityRepository $repository;
public function __construct(
AsideActivityRepository $repository
) {
$this->repository = $repository;
}
public function buildForm(FormBuilderInterface $builder)
{
}
public function getAllowedFormattersTypes(): array
{
return [FormatterInterface::TYPE_TABULAR];
}
public function getDescription(): string
{
return 'export.Count aside activities by various parameters.';
}
public function getGroup(): string
{
return 'export.Exports of aside activities';
}
public function getLabels($key, array $values, $data)
{
if ('export_result' !== $key) {
throw new LogicException("the key {$key} is not used by this export");
}
$labels = array_combine($values, $values);
$labels['_header'] = $this->getTitle();
return static function ($value) use ($labels) {
return $labels[$value];
};
}
public function getQueryKeys($data): array
{
return ['export_result'];
}
public function getResult($query, $data)
{
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
public function getTitle(): string
{
return 'export.Count aside activities';
}
public function getType(): string
{
return Declarations::ASIDE_ACTIVITY_TYPE;
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$qb = $this->repository->createQueryBuilder('aside');
$qb->select('COUNT(DISTINCT aside.id) AS export_result');
return $qb;
}
public function requiredRole(): string
{
return AsideActivityVoter::STATS;
}
public function supportsModifiers(): array
{
return [
Declarations::ASIDE_ACTIVITY_TYPE,
];
}
}

View File

@@ -0,0 +1,243 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\AsideActivityBundle\Export\Export;
use Chill\AsideActivityBundle\Entity\AsideActivity;
use Chill\AsideActivityBundle\Export\Declarations;
use Chill\AsideActivityBundle\Repository\AsideActivityCategoryRepository;
use Chill\AsideActivityBundle\Security\AsideActivityVoter;
use Chill\AsideActivityBundle\Templating\Entity\CategoryRender;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface;
use Chill\MainBundle\Export\Helper\DateTimeHelper;
use Chill\MainBundle\Export\Helper\UserHelper;
use Chill\MainBundle\Export\ListInterface;
use Chill\MainBundle\Repository\CenterRepositoryInterface;
use Chill\MainBundle\Repository\ScopeRepositoryInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use DateTimeInterface;
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface;
final class ListAsideActivity implements ListInterface, GroupedExportInterface
{
private AsideActivityCategoryRepository $asideActivityCategoryRepository;
private CategoryRender $categoryRender;
private CenterRepositoryInterface $centerRepository;
private DateTimeHelper $dateTimeHelper;
private EntityManagerInterface $em;
private ScopeRepositoryInterface $scopeRepository;
private TranslatableStringHelperInterface $translatableStringHelper;
private UserHelper $userHelper;
public function __construct(
EntityManagerInterface $em,
DateTimeHelper $dateTimeHelper,
UserHelper $userHelper,
ScopeRepositoryInterface $scopeRepository,
CenterRepositoryInterface $centerRepository,
AsideActivityCategoryRepository $asideActivityCategoryRepository,
CategoryRender $categoryRender,
TranslatableStringHelperInterface $translatableStringHelper
) {
$this->em = $em;
$this->dateTimeHelper = $dateTimeHelper;
$this->userHelper = $userHelper;
$this->scopeRepository = $scopeRepository;
$this->centerRepository = $centerRepository;
$this->asideActivityCategoryRepository = $asideActivityCategoryRepository;
$this->categoryRender = $categoryRender;
$this->translatableStringHelper = $translatableStringHelper;
}
public function buildForm(FormBuilderInterface $builder)
{
}
public function getAllowedFormattersTypes()
{
return [FormatterInterface::TYPE_LIST];
}
public function getDescription()
{
return 'export.aside_activity.List of aside activities';
}
public function getGroup(): string
{
return 'export.Exports of aside activities';
}
public function getLabels($key, array $values, $data)
{
switch ($key) {
case 'id':
case 'note':
return static function ($value) use ($key) {
if ('_header' === $value) {
return 'export.aside_activity.' . $key;
}
return $value ?? '';
};
case 'duration':
return static function ($value) use ($key) {
if ('_header' === $value) {
return 'export.aside_activity.' . $key;
}
if (null === $value) {
return '';
}
if ($value instanceof DateTimeInterface) {
return $value->format('H:i:s');
}
return $value;
};
case 'createdAt':
case 'updatedAt':
case 'date':
return $this->dateTimeHelper->getLabel('export.aside_activity.' . $key);
case 'agent_id':
case 'creator_id':
return $this->userHelper->getLabel($key, $values, 'export.aside_activity.' . $key);
case 'aside_activity_type':
return function ($value) {
if ('_header' === $value) {
return 'export.aside_activity.aside_activity_type';
}
if (null === $value || '' === $value || null === $c = $this->asideActivityCategoryRepository->find($value)) {
return '';
}
return $this->categoryRender->renderString($c, []);
};
case 'main_scope':
return function ($value) {
if ('_header' === $value) {
return 'export.aside_activity.main_scope';
}
if (null === $value || '' === $value || null === $c = $this->scopeRepository->find($value)) {
return '';
}
return $this->translatableStringHelper->localize($c->getName());
};
case 'main_center':
return function ($value) {
if ('_header' === $value) {
return 'export.aside_activity.main_center';
}
/** @var Center $c */
if (null === $value || '' === $value || null === $c = $this->centerRepository->find($value)) {
return '';
}
return $c->getName();
};
default:
throw new LogicException('this key is not supported : ' . $key);
}
}
public function getQueryKeys($data)
{
return [
'id',
'createdAt',
'updatedAt',
'agent_id',
'creator_id',
'main_scope',
'main_center',
'aside_activity_type',
'date',
'duration',
'note',
];
}
/**
* @param QueryBuilder $query
* @param array $data
*/
public function getResult($query, $data): array
{
return $query->getQuery()->getResult(AbstractQuery::HYDRATE_ARRAY);
}
public function getTitle()
{
return 'export.aside_activity.List of aside activities';
}
public function getType(): string
{
return Declarations::ASIDE_ACTIVITY_TYPE;
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$qb = $this->em->createQueryBuilder()
->from(AsideActivity::class, 'aside')
->leftJoin('aside.agent', 'agent');
$qb
->addSelect('aside.id AS id')
->addSelect('aside.createdAt AS createdAt')
->addSelect('aside.updatedAt AS updatedAt')
->addSelect('IDENTITY(aside.agent) AS agent_id')
->addSelect('IDENTITY(aside.createdBy) AS creator_id')
->addSelect('IDENTITY(agent.mainScope) AS main_scope')
->addSelect('IDENTITY(agent.mainCenter) AS main_center')
->addSelect('IDENTITY(aside.type) AS aside_activity_type')
->addSelect('aside.date')
->addSelect('aside.duration')
->addSelect('aside.note');
return $qb;
}
public function requiredRole(): string
{
return AsideActivityVoter::STATS;
}
public function supportsModifiers()
{
return [Declarations::ASIDE_ACTIVITY_TYPE];
}
}

View File

@@ -0,0 +1,102 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\AsideActivityBundle\Export\Export;
use Chill\AsideActivityBundle\Export\Declarations;
use Chill\AsideActivityBundle\Repository\AsideActivityRepository;
use Chill\AsideActivityBundle\Security\AsideActivityVoter;
use Chill\MainBundle\Export\ExportInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\GroupedExportInterface;
use Doctrine\ORM\Query;
use LogicException;
use Symfony\Component\Form\FormBuilderInterface;
class SumAsideActivityDuration implements ExportInterface, GroupedExportInterface
{
private AsideActivityRepository $repository;
public function __construct(
AsideActivityRepository $repository
) {
$this->repository = $repository;
}
public function buildForm(FormBuilderInterface $builder)
{
}
public function getAllowedFormattersTypes(): array
{
return [FormatterInterface::TYPE_TABULAR];
}
public function getDescription(): string
{
return 'export.Sum aside activities duration';
}
public function getGroup(): string
{
return 'export.Exports of aside activities';
}
public function getLabels($key, array $values, $data)
{
if ('export_sum_aside_activity_duration' !== $key) {
throw new LogicException("the key {$key} is not used by this export");
}
return static fn ($value) => '_header' === $value ? 'Sum duration aside activities' : $value;
}
public function getQueryKeys($data): array
{
return ['export_sum_aside_activity_duration'];
}
public function getResult($query, $data)
{
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
}
public function getTitle(): string
{
return 'export.Sum aside activities duration';
}
public function getType(): string
{
return Declarations::ASIDE_ACTIVITY_TYPE;
}
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$qb = $this->repository
->createQueryBuilder('aside');
$qb->select('SUM(aside.duration) as export_sum_aside_activity_duration')
->andWhere($qb->expr()->isNotNull('aside.duration'));
return $qb;
}
public function requiredRole(): string
{
return AsideActivityVoter::STATS;
}
public function supportsModifiers(): array
{
return [Declarations::ASIDE_ACTIVITY_TYPE];
}
}

View File

@@ -0,0 +1,96 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\AsideActivityBundle\Export\Filter;
use Chill\AsideActivityBundle\Entity\AsideActivityCategory;
use Chill\AsideActivityBundle\Export\Declarations;
use Chill\AsideActivityBundle\Repository\AsideActivityCategoryRepository;
use Chill\AsideActivityBundle\Templating\Entity\CategoryRender;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
class ByActivityTypeFilter implements FilterInterface
{
private AsideActivityCategoryRepository $asideActivityTypeRepository;
private CategoryRender $categoryRender;
private TranslatableStringHelperInterface $translatableStringHelper;
public function __construct(
CategoryRender $categoryRender,
TranslatableStringHelperInterface $translatableStringHelper,
AsideActivityCategoryRepository $asideActivityTypeRepository
) {
$this->categoryRender = $categoryRender;
$this->asideActivityTypeRepository = $asideActivityTypeRepository;
$this->translatableStringHelper = $translatableStringHelper;
}
public function addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
$clause = $qb->expr()->in('aside.type', ':types');
$qb->andWhere($clause);
$qb->setParameter('types', $data['types']);
}
public function applyOn(): string
{
return Declarations::ASIDE_ACTIVITY_TYPE;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder
->add('types', EntityType::class, [
'class' => AsideActivityCategory::class,
'choices' => $this->asideActivityTypeRepository->findAllActive(),
'required' => false,
'multiple' => true,
'expanded' => false,
'attr' => [
'class' => 'select2',
],
'choice_label' => function (AsideActivityCategory $category) {
$options = [];
return $this->categoryRender->renderString($category, $options);
},
]);
}
public function describeAction($data, $format = 'string'): array
{
$types = array_map(
fn (AsideActivityCategory $t): string => $this->translatableStringHelper->localize($t->getTitle()),
$data['types']->toArray()
);
return ['export.filter.Filtered by aside activity type: only %type%', [
'%type%' => implode(', ', $types),
]];
}
public function getTitle(): string
{
return 'export.filter.Filter by aside activity type';
}
}

View File

@@ -0,0 +1,135 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\AsideActivityBundle\Export\Filter;
use Chill\AsideActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Form\Type\Export\FilterType;
use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Contracts\Translation\TranslatorInterface;
class ByDateFilter implements FilterInterface
{
protected TranslatorInterface $translator;
private RollingDateConverterInterface $rollingDateConverter;
public function __construct(
RollingDateConverterInterface $rollingDateConverter,
TranslatorInterface $translator
) {
$this->translator = $translator;
$this->rollingDateConverter = $rollingDateConverter;
}
public function addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
$clause = $qb->expr()->between(
'aside.date',
':date_from',
':date_to'
);
$qb->andWhere($clause);
$qb->setParameter(
'date_from',
$this->rollingDateConverter->convert($data['date_from'])
)->setParameter(
'date_to',
$this->rollingDateConverter->convert($data['date_to'])
);
}
public function applyOn(): string
{
return Declarations::ASIDE_ACTIVITY_TYPE;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder
->add('date_from', PickRollingDateType::class, [
'label' => 'export.filter.Aside activities after this date',
'data' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START),
])
->add('date_to', PickRollingDateType::class, [
'label' => 'export.filter.Aside activities before this date',
'data' => new RollingDate(RollingDate::T_TODAY),
]);
$builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
/** @var \Symfony\Component\Form\FormInterface $filterForm */
$filterForm = $event->getForm()->getParent();
$enabled = $filterForm->get(FilterType::ENABLED_FIELD)->getData();
if (true === $enabled) {
// if the filter is enabled, add some validation
$form = $event->getForm();
$date_from = $form->get('date_from')->getData();
$date_to = $form->get('date_to')->getData();
// check that fields are not empty
if (null === $date_from) {
$form->get('date_from')->addError(new FormError(
$this->translator->trans('This field '
. 'should not be empty')
));
}
if (null === $date_to) {
$form->get('date_to')->addError(new FormError(
$this->translator->trans('This field '
. 'should not be empty')
));
}
// check that date_from is before date_to
if (
(null !== $date_from && null !== $date_to)
&& $date_from >= $date_to
) {
$form->get('date_to')->addError(new FormError(
$this->translator->trans('export.filter.This date should be after '
. 'the date given in "Implied in an aside activity after '
. 'this date" field')
));
}
}
});
}
public function describeAction($data, $format = 'string'): array
{
return ['export.filter.Filtered by aside activities between %dateFrom% and %dateTo%', [
'%dateFrom%' => $this->rollingDateConverter->convert($data['date_from'])->format('d-m-Y'),
'%dateTo%' => $this->rollingDateConverter->convert($data['date_to'])->format('d-m-Y'),
]];
}
public function getTitle(): string
{
return 'export.filter.Filter by aside activity date';
}
}

View File

@@ -0,0 +1,74 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\AsideActivityBundle\Export\Filter;
use Chill\AsideActivityBundle\Export\Declarations;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Form\Type\PickUserDynamicType;
use Chill\MainBundle\Templating\Entity\UserRender;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\FormBuilderInterface;
class ByUserFilter implements FilterInterface
{
private UserRender $userRender;
public function __construct(UserRender $userRender)
{
$this->userRender = $userRender;
}
public function addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
$clause = $qb->expr()->in('aside.agent', ':users');
$qb
->andWhere($clause)
->setParameter('users', $data['accepted_users']);
}
public function applyOn(): string
{
return Declarations::ASIDE_ACTIVITY_TYPE;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('accepted_users', PickUserDynamicType::class, [
'multiple' => true,
'label' => 'Creators',
]);
}
public function describeAction($data, $format = 'string'): array
{
$users = [];
foreach ($data['accepted_users'] as $u) {
$users[] = $this->userRender->renderString($u, []);
}
return ['export.filter.Filtered aside activity by user: only %users%', [
'%users%' => implode(', ', $users),
]];
}
public function getTitle(): string
{
return 'export.filter.Filter aside activity by user';
}
}

View File

@@ -0,0 +1,81 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\AsideActivityBundle\Export\Filter;
use Chill\AsideActivityBundle\Entity\AsideActivity;
use Chill\AsideActivityBundle\Export\Declarations;
use Chill\MainBundle\Entity\UserJob;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
class ByUserJobFilter implements FilterInterface
{
private TranslatableStringHelperInterface $translatableStringHelper;
public function __construct(TranslatableStringHelperInterface $translatableStringHelper)
{
$this->translatableStringHelper = $translatableStringHelper;
}
public function addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
$qb
->andWhere(
$qb->expr()->exists(
'SELECT 1 FROM ' . AsideActivity::class . ' aside_activity_user_job_filter_act
JOIN aside_activity_user_job_filter_act.agent aside_activity_user_job_filter_user WHERE aside_activity_user_job_filter_user.userJob IN (:aside_activity_user_job_filter_jobs) AND aside_activity_user_job_filter_act = aside'
)
)
->setParameter('aside_activity_user_job_filter_jobs', $data['jobs']);
}
public function applyOn()
{
return Declarations::ASIDE_ACTIVITY_TYPE;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('jobs', EntityType::class, [
'class' => UserJob::class,
'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize($j->getLabel()),
'multiple' => true,
'expanded' => true,
]);
}
public function describeAction($data, $format = 'string')
{
return ['export.filter.Filtered aside activities by user jobs: only %jobs%', [
'%jobs%' => implode(
', ',
array_map(
fn (UserJob $job) => $this->translatableStringHelper->localize($job->getLabel()),
$data['jobs']->toArray()
)
),
]];
}
public function getTitle()
{
return 'export.filter.Filter by user jobs';
}
}

View File

@@ -0,0 +1,88 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\AsideActivityBundle\Export\Filter;
use Chill\AsideActivityBundle\Entity\AsideActivity;
use Chill\AsideActivityBundle\Export\Declarations;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Repository\ScopeRepositoryInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
class ByUserScopeFilter implements FilterInterface
{
private ScopeRepositoryInterface $scopeRepository;
private TranslatableStringHelperInterface $translatableStringHelper;
public function __construct(
ScopeRepositoryInterface $scopeRepository,
TranslatableStringHelperInterface $translatableStringHelper
) {
$this->scopeRepository = $scopeRepository;
$this->translatableStringHelper = $translatableStringHelper;
}
public function addRole(): ?string
{
return null;
}
public function alterQuery(QueryBuilder $qb, $data)
{
$qb
->andWhere(
$qb->expr()->exists(
'SELECT 1 FROM ' . AsideActivity::class . ' aside_activity_user_scope_filter_act
JOIN aside_activity_user_scope_filter_act.agent aside_activity_user_scope_filter_user WHERE aside_activity_user_scope_filter_user.mainScope IN (:aside_activity_user_scope_filter_scopes) AND aside_activity_user_scope_filter_act = aside '
)
)
->setParameter('aside_activity_user_scope_filter_scopes', $data['scopes']);
}
public function applyOn()
{
return Declarations::ASIDE_ACTIVITY_TYPE;
}
public function buildForm(FormBuilderInterface $builder)
{
$builder->add('scopes', EntityType::class, [
'class' => Scope::class,
'choices' => $this->scopeRepository->findAllActive(),
'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()),
'multiple' => true,
'expanded' => true,
]);
}
public function describeAction($data, $format = 'string')
{
return ['export.filter.Filtered aside activities by user scope: only %scopes%', [
'%scopes%' => implode(
', ',
array_map(
fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()),
$data['scopes']->toArray()
)
),
]];
}
public function getTitle()
{
return 'export.filter.Filter by user scope';
}
}

View File

@@ -12,8 +12,7 @@ declare(strict_types=1);
namespace Chill\AsideActivityBundle\Form;
use Chill\AsideActivityBundle\Entity\AsideActivity;
use Chill\AsideActivityBundle\Entity\AsideActivityCategory;
use Chill\AsideActivityBundle\Templating\Entity\CategoryRender;
use Chill\AsideActivityBundle\Form\Type\PickAsideActivityCategoryType;
use Chill\MainBundle\Form\Type\ChillDateType;
use Chill\MainBundle\Form\Type\ChillTextareaType;
use Chill\MainBundle\Form\Type\PickUserDynamicType;
@@ -21,8 +20,6 @@ use DateInterval;
use DateTime;
use DateTimeImmutable;
use DateTimeZone;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer;
@@ -37,20 +34,16 @@ use function in_array;
final class AsideActivityFormType extends AbstractType
{
private CategoryRender $categoryRender;
private TokenStorageInterface $storage;
private array $timeChoices;
public function __construct(
ParameterBagInterface $parameterBag,
TokenStorageInterface $storage,
CategoryRender $categoryRender
TokenStorageInterface $storage
) {
$this->timeChoices = $parameterBag->get('chill_aside_activity.form.time_duration');
$this->storage = $storage;
$this->categoryRender = $categoryRender;
}
public function buildForm(FormBuilderInterface $builder, array $options)
@@ -81,28 +74,10 @@ final class AsideActivityFormType extends AbstractType
'required' => true,
]
)
->add(
'type',
EntityType::class,
[
'label' => 'Type',
'required' => true,
'class' => AsideActivityCategory::class,
'placeholder' => 'Choose the activity category',
'query_builder' => static function (EntityRepository $er) {
$qb = $er->createQueryBuilder('ac');
$qb->where($qb->expr()->eq('ac.isActive', 'TRUE'))
->addOrderBy('ac.ordering', 'ASC');
return $qb;
},
'choice_label' => function (AsideActivityCategory $asideActivityCategory) {
$options = [];
return $this->categoryRender->renderString($asideActivityCategory, $options);
},
]
)
->add('type', PickAsideActivityCategoryType::class, [
'label' => 'Type',
'required' => true,
])
->add('duration', ChoiceType::class, $durationTimeOptions)
->add('note', ChillTextareaType::class, [
'label' => 'Note',

View File

@@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\AsideActivityBundle\Form\Type;
use Chill\AsideActivityBundle\Entity\AsideActivityCategory;
use Chill\AsideActivityBundle\Templating\Entity\CategoryRender;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
final class PickAsideActivityCategoryType extends AbstractType
{
private CategoryRender $categoryRender;
public function __construct(
CategoryRender $categoryRender
) {
$this->categoryRender = $categoryRender;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver
->setDefaults([
'class' => AsideActivityCategory::class,
'placeholder' => 'Choose the activity category',
'query_builder' => static function (EntityRepository $er) {
$qb = $er->createQueryBuilder('ac');
$qb->where($qb->expr()->eq('ac.isActive', 'TRUE'))
->addOrderBy('ac.ordering', 'ASC');
return $qb;
},
'choice_label' => function (AsideActivityCategory $asideActivityCategory) {
$options = [];
return $this->categoryRender->renderString($asideActivityCategory, $options);
},
'attr' => ['class' => 'select2'],
]);
}
public function getParent(): string
{
return EntityType::class;
}
}

View File

@@ -38,6 +38,11 @@ class AsideActivityCategoryRepository implements ObjectRepository
return $this->repository->findAll();
}
public function findAllActive(): array
{
return $this->repository->findBy(['isActive' => true]);
}
/**
* @param mixed|null $limit
* @param mixed|null $offset

View File

@@ -12,46 +12,20 @@ declare(strict_types=1);
namespace Chill\AsideActivityBundle\Repository;
use Chill\AsideActivityBundle\Entity\AsideActivity;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ObjectRepository;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
final class AsideActivityRepository implements ObjectRepository
/**
* @method AsideActivity|null find($id, $lockMode = null, $lockVersion = null)
* @method AsideActivity|null findOneBy(array $criteria, array $orderBy = null)
* @method AsideActivity[] findAll()
* @method AsideActivity[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
final class AsideActivityRepository extends ServiceEntityRepository
{
private EntityRepository $repository;
public function __construct(EntityManagerInterface $entityManager)
public function __construct(ManagerRegistry $registry)
{
$this->repository = $entityManager->getRepository(AsideActivity::class);
}
public function find($id): ?AsideActivity
{
return $this->repository->find($id);
}
/**
* @return AsideActivity[]
*/
public function findAll(): array
{
return $this->repository->findAll();
}
/**
* @param mixed|null $limit
* @param mixed|null $offset
*
* @return AsideActivity[]
*/
public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array
{
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
}
public function findOneBy(array $criteria): ?AsideActivity
{
return $this->repository->findOneBy($criteria);
parent::__construct($registry, AsideActivity::class);
}
public function getClassName(): string

View File

@@ -1,4 +1,4 @@
<div class="{% block crud_content_main_div_class %}col-10 centered{% endblock %}">
{% block crud_content_header %}
<h1>{{ ('crud.'~crud_name~'.title_delete')|trans({ '%as_string%': 'Aside Activity' }) }}</h1>
{% endblock crud_content_header %}
@@ -27,4 +27,4 @@
</ul>
{{ form_end(form) }}
</div>

View File

@@ -87,5 +87,5 @@
</li>
</ul>
{% endif %}
</div>
{% endblock %}

View File

@@ -1,4 +1,4 @@
{% extends '@ChillMain/Admin/layout.html.twig' %}
{% extends '@ChillMain/layout.html.twig' %}
{% block js %}
{{ parent() }}
@@ -14,7 +14,7 @@
{% include('@ChillMain/CRUD/_new_title.html.twig') %}
{% endblock %}
{% block admin_content %}
{% block content %}
{% embed '@ChillMain/CRUD/_new_content.html.twig' %}
{% block content_form_actions_save_and_show %}{% endblock %}
{% endembed %}

View File

@@ -0,0 +1,79 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\AsideActivityBundle\Security;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
use Chill\MainBundle\Security\Authorization\VoterHelperFactoryInterface;
use Chill\MainBundle\Security\Authorization\VoterHelperInterface;
use Chill\MainBundle\Security\ProvideRoleHierarchyInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
class AsideActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
{
public const STATS = 'CHILL_ASIDE_ACTIVITY_STATS';
private VoterHelperInterface $voterHelper;
public function __construct(
VoterHelperFactoryInterface $voterHelperFactory
) {
$this->voterHelper = $voterHelperFactory
->generate(self::class)
->addCheckFor(Center::class, [self::STATS])
->build();
}
/**
* @return string[]
*/
public function getRoles(): array
{
return $this->getAttributes();
}
/**
* @return string[][]
*/
public function getRolesWithHierarchy(): array
{
return ['Aside activity' => $this->getRoles()];
}
/**
* @return string[]
*/
public function getRolesWithoutScope(): array
{
return $this->getAttributes();
}
protected function supports($attribute, $subject)
{
return $this->voterHelper->supports($attribute, $subject);
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
{
if (!$token->getUser() instanceof User) {
return false;
}
return $this->voterHelper->voteOnAttribute($attribute, $subject, $token);
}
private function getAttributes(): array
{
return [self::STATS];
}
}

View File

@@ -0,0 +1,64 @@
services:
_defaults:
autowire: true
autoconfigure: true
Chill\AsideActivityBundle\Export\Export\ListAsideActivity:
tags:
- { name: chill.export, alias: 'list_aside_activity' }
## Indicators
Chill\AsideActivityBundle\Export\Export\CountAsideActivity:
tags:
- { name: chill.export, alias: 'count_aside_activity' }
Chill\AsideActivityBundle\Export\Export\SumAsideActivityDuration:
tags:
- { name: chill.export, alias: 'sum_aside_activity_duration' }
Chill\AsideActivityBundle\Export\Export\AvgAsideActivityDuration:
tags:
- { name: chill.export, alias: 'avg_aside_activity_duration' }
## Filters
chill.aside_activity.export.date_filter:
class: Chill\AsideActivityBundle\Export\Filter\ByDateFilter
tags:
- { name: chill.export_filter, alias: 'aside_activity_date_filter' }
chill.aside_activity.export.type_filter:
class: Chill\AsideActivityBundle\Export\Filter\ByActivityTypeFilter
tags:
- { name: chill.export_filter, alias: 'aside_activity_type_filter' }
chill.aside_activity.export.user_job_filter:
class: Chill\AsideActivityBundle\Export\Filter\ByUserJobFilter
tags:
- { name: chill.export_filter, alias: 'aside_activity_user_job_filter' }
chill.aside_activity.export.user_scope_filter:
class: Chill\AsideActivityBundle\Export\Filter\ByUserScopeFilter
tags:
- { name: chill.export_filter, alias: 'aside_activity_user_scope_filter' }
chill.aside_activity.export.user_filter:
class: Chill\AsideActivityBundle\Export\Filter\ByUserFilter
tags:
- { name: chill.export_filter, alias: 'aside_activity_user_filter' }
## Aggregators
chill.aside_activity.export.type_aggregator:
class: Chill\AsideActivityBundle\Export\Aggregator\ByActivityTypeAggregator
tags:
- { name: chill.export_aggregator, alias: activity_type_aggregator }
chill.aside_activity.export.user_job_aggregator:
class: Chill\AsideActivityBundle\Export\Aggregator\ByUserJobAggregator
tags:
- { name: chill.export_aggregator, alias: aside_activity_user_job_aggregator }
chill.aside_activity.export.user_scope_aggregator:
class: Chill\AsideActivityBundle\Export\Aggregator\ByUserScopeAggregator
tags:
- { name: chill.export_aggregator, alias: aside_activity_user_scope_aggregator }

View File

@@ -0,0 +1,7 @@
services:
Chill\AsideActivityBundle\Security\AsideActivityVoter:
autowire: true
autoconfigure: true
tags:
- { name: security.voter }
- { name: chill.role }

View File

@@ -29,16 +29,16 @@ location: Lieu
# Crud
crud:
aside_activity:
title_view: Détail de l'activité annexe
title_new: Nouvelle activité annexe
title_edit: Édition d'une activité annexe
title_delete: Supprimer une activité annexe
button_delete: Supprimer
confirm_message_delete: Êtes-vous sûr de vouloir supprimer cette activité annexe?
aside_activity_category:
title_new: Nouvelle catégorie d'activité annexe
title_edit: Édition d'une catégorie de type d'activité
aside_activity:
title_view: Détail de l'activité annexe
title_new: Nouvelle activité annexe
title_edit: Édition d'une activité annexe
title_delete: Supprimer une activité annexe
button_delete: Supprimer
confirm_message_delete: Êtes-vous sûr de vouloir supprimer cette activité annexe?
aside_activity_category:
title_new: Nouvelle catégorie d'activité annexe
title_edit: Édition d'une catégorie de type d'activité
#forms
Create a new aside activity type: Nouvelle categorie d'activité annexe
@@ -166,3 +166,46 @@ Aside activities: Activités annexes
Aside activity types: Types d'activités annexes
Aside activity type configuration: Configuration des categories d'activités annexes
Aside activity configuration: Configuration des activités annexes
# exports
export:
aside_activity:
List of aside activities: Liste des activités annexes
createdAt: Création
updatedAt: Dernière mise à jour
agent_id: Utilisateur
creator_id: Créateur
main_scope: Service principal de l'utilisateur
main_center: Centre principal de l'utilisteur
aside_activity_type: Catégorie d'activité annexe
date: Date
duration: Durée
note: Note
Exports of aside activities: Exports des activités annexes
Count aside activities: Nombre d'activités annexes
Count aside activities by various parameters.: Compte le nombre d'activités annexes selon divers critères
Average aside activities duration: Durée moyenne des activités annexes
Sum aside activities duration: Durée des activités annexes
filter:
Filter by aside activity date: Filtrer les activités annexes par date
Filter by aside activity type: Filtrer les activités annexes par type d'activité
'Filtered by aside activity type: only %type%': "Filtré par type d'activité annexe: uniquement %type%"
Filtered by aside activities between %dateFrom% and %dateTo%: Filtré par date d'activité annexe, entre %dateFrom% et %dateTo%
This date should be after the date given in "Implied in an aside activity after this date" field: Cette date devrait être postérieure à la date donnée dans le champ "activités annexes après cette date"
Aside activities after this date: Actvitités annexes après cette date
Aside activities before this date: Actvitités annexes avant cette date
'Filtered aside activity by user: only %users%': "Filtré par utilisateur: uniquement %users%"
Filter aside activity by user: Filtrer par utilisateur
'Filtered aside activities by user jobs: only %jobs%': "Filtré par métier des utilisateurs: uniquement %jobs%"
Filter by user jobs: Filtrer les activités annexes par métier des utilisateurs
'Filtered aside activities by user scope: only %scopes%': "Filtré par service des utilisateur: uniquement %scopes%"
Filter by user scope: Filtrer les activités annexes par service d'utilisateur
aggregator:
Group by aside activity type: Grouper les activités annexes par type d'activité
Aside activity type: Type d'activité annexe
Aggregate by user job: Grouper les activités annexes par métier des utilisateurs
Aggregate by user scope: Grouper les activités annexes par service des utilisateurs
# ROLES
CHILL_ASIDE_ACTIVITY_STATS: Statistiques pour les activités annexes

View File

@@ -29,10 +29,10 @@ class CalculatorManager
public function addCalculator(CalculatorInterface $calculator, bool $default)
{
$this->calculators[$calculator::getAlias()] = $calculator;
$this->calculators[$calculator->getAlias()] = $calculator;
if ($default) {
$this->defaultCalculator[] = $calculator::getAlias();
$this->defaultCalculator[] = $calculator->getAlias();
}
}
@@ -50,7 +50,7 @@ class CalculatorManager
$result = $calculator->calculate($elements);
if (null !== $result) {
$results[$calculator::getAlias()] = $result;
$results[$calculator->getAlias()] = $result;
}
}

View File

@@ -1,94 +0,0 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\BudgetBundle\Config;
class ConfigRepository
{
/**
* @var array
*/
protected $charges;
/**
* @var array
*/
protected $resources;
public function __construct($resources, $charges)
{
$this->resources = $resources;
$this->charges = $charges;
}
public function getChargesKeys(bool $onlyActive = false): array
{
return array_map(static function ($element) { return $element['key']; }, $this->getCharges($onlyActive));
}
/**
* @return array where keys are the resource'key and label the ressource label
*/
public function getChargesLabels(bool $onlyActive = false)
{
$charges = [];
foreach ($this->getCharges($onlyActive) as $definition) {
$charges[$definition['key']] = $this->normalizeLabel($definition['labels']);
}
return $charges;
}
public function getResourcesKeys(bool $onlyActive = false): array
{
return array_map(static function ($element) { return $element['key']; }, $this->getResources($onlyActive));
}
/**
* @return array where keys are the resource'key and label the ressource label
*/
public function getResourcesLabels(bool $onlyActive = false)
{
$resources = [];
foreach ($this->getResources($onlyActive) as $definition) {
$resources[$definition['key']] = $this->normalizeLabel($definition['labels']);
}
return $resources;
}
private function getCharges(bool $onlyActive = false): array
{
return $onlyActive ?
array_filter($this->charges, static function ($el) { return $el['active']; })
: $this->charges;
}
private function getResources(bool $onlyActive = false): array
{
return $onlyActive ?
array_filter($this->resources, static function ($el) { return $el['active']; })
: $this->resources;
}
private function normalizeLabel($labels)
{
$normalizedLabels = [];
foreach ($labels as $labelDefinition) {
$normalizedLabels[$labelDefinition['lang']] = $labelDefinition['label'];
}
return $normalizedLabels;
}
}

View File

@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\BudgetBundle\Controller\Admin;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
class AdminController extends AbstractController
{
/**
* @Route("/{_locale}/admin/budget", name="chill_admin_budget")
*/
public function indexAdminAction()
{
return $this->render('@ChillBudget/Admin/index.html.twig');
}
}

View File

@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\BudgetBundle\Controller\Admin;
use Chill\MainBundle\CRUD\Controller\CRUDController;
use Chill\MainBundle\Pagination\PaginatorInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\HttpFoundation\Request;
class ChargeKindController extends CRUDController
{
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
{
/** @var QueryBuilder $query */
$query->addOrderBy('e.ordering', 'ASC');
return $query;
}
}

Some files were not shown because too many files have changed in this diff Show More