mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-10-04 20:39:40 +00:00
Compare commits
158 Commits
testing-20
...
288-signat
Author | SHA1 | Date | |
---|---|---|---|
d33dcacc46 | |||
8d97df9f96 | |||
2822800c76 | |||
8973b7c20b | |||
7f144da1a7 | |||
ab4193938d | |||
e2426ba1d8 | |||
8209990437 | |||
b1885de3e2 | |||
218280304c | |||
8a7b48b201 | |||
52a9aab73f | |||
8f358112b1 | |||
57a07af3db | |||
fd216ff66e | |||
689c2c574a | |||
a8de18beac | |||
babca5fc0f | |||
f2c5663b05 | |||
ba95687f46 | |||
a309cc0774
|
|||
3db4fff80d
|
|||
c9d54a5fea
|
|||
86c862e69d
|
|||
d88b5a0098
|
|||
9bc6fe6aff
|
|||
18a03fd740
|
|||
4c3bfc90b5 | |||
610239930b
|
|||
b65e2c62c4 | |||
89f5231649
|
|||
bd41308bbd
|
|||
f8fa96d836
|
|||
d28cec3786
|
|||
7cd36cd483
|
|||
d3d98cdec2
|
|||
49dd7f94fa
|
|||
916724c0c5
|
|||
|
102d0dad94 | ||
|
8d225dd68c | ||
|
61d0005be8 | ||
99818c211d
|
|||
a9f0059743
|
|||
5bc542a567
|
|||
c8ccce83fd
|
|||
47f4cfddbb
|
|||
e95f9e9846 | |||
1f4bef754d
|
|||
19e34d5dc0
|
|||
fab00f679c
|
|||
791b3776c5
|
|||
6bd38f1a58
|
|||
68d21c9267
|
|||
e7ca89e0c1
|
|||
fc8bc33ba9
|
|||
cbd9489810
|
|||
4a229ebf6b | |||
90b615c5b2
|
|||
5ca222b501 | |||
3e4495dd6e
|
|||
bca0d04201
|
|||
f66ac50571 | |||
b454774836
|
|||
008f344e49
|
|||
90bfd87ec6
|
|||
cc0030c1cd
|
|||
d60ba3ecb2
|
|||
cd5001ac74 | |||
98f47ac512
|
|||
31b541d12f
|
|||
72045ce082
|
|||
0bfb3de465
|
|||
9ec4c77fb7
|
|||
77c53972c8
|
|||
350d991a85
|
|||
0ce9cdd07a
|
|||
1993fac1c4
|
|||
83883567a2
|
|||
29d57934a1
|
|||
f43d79c940
|
|||
be730679c8
|
|||
f62f1891d8
|
|||
ebb856fe85
|
|||
61877e0157
|
|||
4c3f082163
|
|||
35109133f6
|
|||
a220dad83b
|
|||
9eb571549b
|
|||
db8257d230 | |||
bce93efe83 | |||
06401af801 | |||
ea1d4c48f2
|
|||
|
33cba27dd4 | ||
a7ec7c9f37 | |||
c9e13be736 | |||
b9b342fe44 | |||
31f29f0bc5 | |||
0bc9fff825 | |||
25f93e8a89 | |||
4e0d8e4def | |||
1ecc825945 | |||
addc623add | |||
1b96deb4ee | |||
f510acd170 | |||
835409cb94 | |||
2121b3ef28 | |||
6c9101c167 | |||
b46883fe36 | |||
8d58805abd | |||
c3a799cb7d | |||
bc683b28d6 | |||
d91b1a70bf | |||
853014d8d2 | |||
ad6154a1e4 | |||
50c04382ef | |||
d62e9ce269 | |||
2149ef1cb4 | |||
d15fbadd27 | |||
fbbf421d8b | |||
fe695f1a14 | |||
d0ec6f9819 | |||
0b739fda34 | |||
9b8e143855 | |||
a533ab77ed | |||
087032881b | |||
82667a1c0f | |||
db6408926b | |||
f5c7ab6ef0 | |||
a13ada2937 | |||
3be8a39a1a | |||
d7eb1e01da | |||
bd62202d22 | |||
0e3de2ec8a | |||
aa2a398f9e | |||
33187448a0 | |||
a4482ad28b | |||
8ed5a023e8 | |||
653ac1d62b | |||
499009ac43 | |||
192b161e78 | |||
1b1f355123 | |||
39a863448c | |||
0c1a4a5f59 | |||
6f358ee1a9 | |||
0f36b9349b | |||
d18cc29acf | |||
4220d1a2d3 | |||
1ae27152c2 | |||
b946f8c10a | |||
62d6106801 | |||
89fb87f71f | |||
1337360690 | |||
9324c33caf | |||
c2dd9ef676 | |||
a42d7231d9 | |||
38deaf6f36 | |||
04fc5b6614 | |||
384b2be577 |
@@ -1,5 +0,0 @@
|
||||
kind: Feature
|
||||
body: Add job bundle (module emploi)
|
||||
time: 2024-05-22T16:49:33.730465146+02:00
|
||||
custom:
|
||||
Issue: ""
|
8
.changes/unreleased/Feature-20240614-153236.yaml
Normal file
8
.changes/unreleased/Feature-20240614-153236.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
kind: Feature
|
||||
body: |-
|
||||
Electronic signature
|
||||
|
||||
Implementation of the electronic signature for documents within chill.
|
||||
time: 2024-06-14T15:32:36.875891692+02:00
|
||||
custom:
|
||||
Issue: ""
|
5
.changes/unreleased/Feature-20240718-151233.yaml
Normal file
5
.changes/unreleased/Feature-20240718-151233.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
kind: Feature
|
||||
body: Metadata form added for person signatures
|
||||
time: 2024-07-18T15:12:33.8134266+02:00
|
||||
custom:
|
||||
Issue: "288"
|
21
.changes/v2.20.0.md
Normal file
21
.changes/v2.20.0.md
Normal file
@@ -0,0 +1,21 @@
|
||||
## v2.20.0 - 2024-06-05
|
||||
### Fixed
|
||||
* ([#170](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/170)) Display agents traitants instead of accompanying period referrer in export list social actions.
|
||||
* Added translations for choices of durations (> 5 hours)
|
||||
### Feature
|
||||
* ([#145](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/145)) Allow to open documents in LibreOffice locally (need configuration within security);
|
||||
|
||||
This endpoint should be added to make the endpoint works properly:
|
||||
|
||||
```yaml
|
||||
security:
|
||||
firewalls:
|
||||
dav:
|
||||
pattern: ^/dav
|
||||
provider: chain_provider
|
||||
stateless: true
|
||||
guard:
|
||||
authenticators:
|
||||
- Chill\DocStoreBundle\Security\Guard\JWTOnDavUrlAuthenticator
|
||||
|
||||
```
|
3
.changes/v2.20.1.md
Normal file
3
.changes/v2.20.1.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## v2.20.1 - 2024-06-05
|
||||
### Fixed
|
||||
* Do not allow StoredObjectCreated for edit and convert buttons
|
31
.changes/v2.21.0.md
Normal file
31
.changes/v2.21.0.md
Normal file
@@ -0,0 +1,31 @@
|
||||
## v2.21.0 - 2024-06-18
|
||||
### Feature
|
||||
* Add flash menu buttons in search results, to open directly a new calendar, or a new activity in an accompanying period
|
||||
* ([#122](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/122)) Improve the list of calendar in the search results: make all calendar clicable, and display a list of calendars
|
||||
* ([#282](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/282)) [export] add start date and end date on filters "filter course by referrer job" and "filter course by referrer scope"
|
||||
* ([#282](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/282)) [export] the aggregator "Group by referrer" now accept a date range.
|
||||
* ([#282](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/282)) [export] add date range on "group course by referrer's scope"
|
||||
* ([#282](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/282)) [export] add date range on "group course by referrer's jobs"
|
||||
* ([#168](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/168) In the UX, display user job and service at the time when he performs an action:
|
||||
now, the job and service is shown:
|
||||
* at the activity's date,
|
||||
* at the appointment's date,
|
||||
* when the user is marked as referrer for an accompanying period work,
|
||||
* when the user apply a transition in a workflow,
|
||||
* when the user updates or creates "something" ("created/updated by ... at ..."),
|
||||
* or when he wrote a comment,
|
||||
* …
|
||||
|
||||
### Traduction francophone
|
||||
* Ajout d'un menu "flash" dans les résultats de recherche, pour créer un rendez-vous ou un échange dans un parcours depuis les résultats de recherche;
|
||||
* Améliore la liste des rendez-vous dans les résultats de recherche: les rendez-vous sont cliquables;
|
||||
* [exports] Ajout d'intervalles de dates pour des filtres et regroupements des parcours par référent, métier du référent, service du référent;
|
||||
* Affiche le métier et le service des utilisateurs à la date à laquelle il a exécuté une action. Le métier et le service est affiché:
|
||||
* à la date d'un échange,
|
||||
* au jour d'un rendez-vous,
|
||||
* quand l'utilisateur est devenu référent d'un parcours d'accompagnement,
|
||||
* quand il a appliqué une transition sur un workflow,
|
||||
* quand il a mise à jour ou créé une fiche, dans les mentions "créé / mise à jour par ..., le ...",
|
||||
* quand il a mis à jour un commentaire,
|
||||
* …
|
||||
|
58
CHANGELOG.md
58
CHANGELOG.md
@@ -6,6 +6,64 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
|
||||
and is generated by [Changie](https://github.com/miniscruff/changie).
|
||||
|
||||
|
||||
## v2.21.0 - 2024-06-18
|
||||
### Feature
|
||||
* Add flash menu buttons in search results, to open directly a new calendar, or a new activity in an accompanying period
|
||||
* ([#122](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/122)) Improve the list of calendar in the search results: make all calendar clicable, and display a list of calendars
|
||||
* ([#282](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/282)) [export] add start date and end date on filters "filter course by referrer job" and "filter course by referrer scope"
|
||||
* ([#282](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/282)) [export] the aggregator "Group by referrer" now accept a date range.
|
||||
* ([#282](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/282)) [export] add date range on "group course by referrer's scope"
|
||||
* ([#282](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/282)) [export] add date range on "group course by referrer's jobs"
|
||||
* ([#168](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/168) In the UX, display user job and service at the time when he performs an action:
|
||||
now, the job and service is shown:
|
||||
* at the activity's date,
|
||||
* at the appointment's date,
|
||||
* when the user is marked as referrer for an accompanying period work,
|
||||
* when the user apply a transition in a workflow,
|
||||
* when the user updates or creates "something" ("created/updated by ... at ..."),
|
||||
* or when he wrote a comment,
|
||||
* …
|
||||
|
||||
### Traduction francophone
|
||||
* Ajout d'un menu "flash" dans les résultats de recherche, pour créer un rendez-vous ou un échange dans un parcours depuis les résultats de recherche;
|
||||
* Améliore la liste des rendez-vous dans les résultats de recherche: les rendez-vous sont cliquables;
|
||||
* [exports] Ajout d'intervalles de dates pour des filtres et regroupements des parcours par référent, métier du référent, service du référent;
|
||||
* Affiche le métier et le service des utilisateurs à la date à laquelle il a exécuté une action. Le métier et le service est affiché:
|
||||
* à la date d'un échange,
|
||||
* au jour d'un rendez-vous,
|
||||
* quand l'utilisateur est devenu référent d'un parcours d'accompagnement,
|
||||
* quand il a appliqué une transition sur un workflow,
|
||||
* quand il a mise à jour ou créé une fiche, dans les mentions "créé / mise à jour par ..., le ...",
|
||||
* quand il a mis à jour un commentaire,
|
||||
* …
|
||||
|
||||
|
||||
## v2.20.1 - 2024-06-05
|
||||
### Fixed
|
||||
* Do not allow StoredObjectCreated for edit and convert buttons
|
||||
|
||||
## v2.20.0 - 2024-06-05
|
||||
### Fixed
|
||||
* ([#170](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/170)) Display agents traitants instead of accompanying period referrer in export list social actions.
|
||||
* Added translations for choices of durations (> 5 hours)
|
||||
### Feature
|
||||
* ([#145](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/145)) Allow to open documents in LibreOffice locally (need configuration within security);
|
||||
|
||||
This endpoint should be added to make the endpoint works properly:
|
||||
|
||||
```yaml
|
||||
security:
|
||||
firewalls:
|
||||
dav:
|
||||
pattern: ^/dav
|
||||
provider: chain_provider
|
||||
stateless: true
|
||||
guard:
|
||||
authenticators:
|
||||
- Chill\DocStoreBundle\Security\Guard\JWTOnDavUrlAuthenticator
|
||||
|
||||
```
|
||||
|
||||
## v2.19.0 - 2024-05-14
|
||||
### Feature
|
||||
* ([#197](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/197)) Make the script which subscribe to microsoft calendars changes more tolerant to errors or missing configuration on the microsoft side
|
||||
|
@@ -19,7 +19,6 @@
|
||||
"doctrine/doctrine-migrations-bundle": "^3.0",
|
||||
"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",
|
||||
@@ -32,6 +31,7 @@
|
||||
"phpoffice/phpspreadsheet": "^1.16",
|
||||
"ramsey/uuid-doctrine": "^1.7",
|
||||
"sensio/framework-extra-bundle": "^5.5",
|
||||
"smalot/pdfparser": "^2.10",
|
||||
"spomky-labs/base64url": "^2.0",
|
||||
"symfony/asset": "^5.4",
|
||||
"symfony/browser-kit": "^5.4",
|
||||
@@ -92,12 +92,12 @@
|
||||
"phpstan/phpstan": "^1.9",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.1",
|
||||
"phpstan/phpstan-strict-rules": "^1.0",
|
||||
"phpunit/phpunit": ">= 7.5",
|
||||
"phpunit/phpunit": "^10.5.24",
|
||||
"rector/rector": "^1.1.0",
|
||||
"symfony/debug-bundle": "^5.4",
|
||||
"symfony/dotenv": "^5.4",
|
||||
"symfony/maker-bundle": "^1.20",
|
||||
"symfony/phpunit-bridge": "^5.4",
|
||||
"symfony/phpunit-bridge": "^7.1",
|
||||
"symfony/runtime": "^5.4",
|
||||
"symfony/stopwatch": "^5.4",
|
||||
"symfony/var-dumper": "^5.4"
|
||||
@@ -115,8 +115,6 @@
|
||||
"Chill\\DocGeneratorBundle\\": "src/Bundle/ChillDocGeneratorBundle",
|
||||
"Chill\\DocStoreBundle\\": "src/Bundle/ChillDocStoreBundle",
|
||||
"Chill\\EventBundle\\": "src/Bundle/ChillEventBundle",
|
||||
"Chill\\FranceTravailApiBundle\\": "src/Bundle/ChillFranceTravailApiBundle/src",
|
||||
"Chill\\JobBundle\\": "src/Bundle/ChillJobBundle/src",
|
||||
"Chill\\MainBundle\\": "src/Bundle/ChillMainBundle",
|
||||
"Chill\\PersonBundle\\": "src/Bundle/ChillPersonBundle",
|
||||
"Chill\\ReportBundle\\": "src/Bundle/ChillReportBundle",
|
||||
|
@@ -21,7 +21,7 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
class BirthdateFilter implements ExportElementValidatedInterface, FilterInterface
|
||||
{
|
||||
// add specific role for this filter
|
||||
public function addRole(): ?string
|
||||
public function addRole()
|
||||
{
|
||||
// we do not need any new role for this filter, so we return null
|
||||
return null;
|
||||
|
@@ -95,7 +95,7 @@ custom developments. But most of the time, this should be fine.
|
||||
|
||||
You have to configure some local variables, which are described in the :code:`.env` file. The secrets should not be stored
|
||||
in this :code:`.env` file, but instead using the `secrets management tool <https://symfony.com/doc/current/configuration/secrets.html>`_
|
||||
or in the :code:`.env.local` file, which should not be commited to the git repository.
|
||||
or in the :code:`.env.local` file, which should not be committed to the git repository.
|
||||
|
||||
You do not need to set variables for the smtp server, redis server and relatorio server, as they are generated automatically
|
||||
by the symfony server, from the docker compose services.
|
||||
@@ -114,6 +114,12 @@ you can either:
|
||||
- add the generated password to the secrets manager (**note**: you must add the generated hashed password to the secrets env,
|
||||
not the password in clear text).
|
||||
|
||||
- set up the jwt authentication bundle
|
||||
|
||||
Some environment variables are available for the JWT authentication bundle in the :code:`.env` file. You must also run the command
|
||||
:code:`symfony console lexik:jwt:generate-keypair` to generate some keys that will be stored in the paths set up in the :code:`JWT_SECRET_KEY`
|
||||
and the :code:`JWT_PUBLIC_KEY` env variables. This is only required for using the stored documents in Chill.
|
||||
|
||||
Prepare migrations and other tools
|
||||
**********************************
|
||||
|
||||
@@ -164,7 +170,7 @@ can rely on the whole chill framework, meaning there is no need to add them to t
|
||||
You will require some bundles to have the following development tools:
|
||||
|
||||
- add fixtures
|
||||
- add profiler and var-dumper to debug
|
||||
- add profiler and debug bundle
|
||||
|
||||
Install fixtures
|
||||
****************
|
||||
@@ -179,7 +185,7 @@ Install fixtures
|
||||
This will generate user accounts, centers, and some basic configuration.
|
||||
|
||||
The accounts created are: :code:`center a_social`, :code:`center b_social`, :code:`center a_direction`, ... The full list is
|
||||
visibile in the "users" table: :code:`docker compose exec database psql -U app -c "SELECT username FROM users"`.
|
||||
visible in the "users" table: :code:`docker compose exec database psql -U app -c "SELECT username FROM users"`.
|
||||
|
||||
The password is always :code:`password`.
|
||||
|
||||
@@ -192,7 +198,7 @@ Add web profiler and debugger
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
symfony composer require --dev symfony/web-profiler-bundle symfony/var-dumper
|
||||
symfony composer require --dev symfony/web-profiler-bundle symfony/debug-bundle
|
||||
|
||||
Working on chill bundles
|
||||
************************
|
||||
|
@@ -27,7 +27,7 @@
|
||||
"popper.js": "^1.16.1",
|
||||
"postcss-loader": "^7.0.2",
|
||||
"raw-loader": "^4.0.2",
|
||||
"sass-loader": "^14.0.0",
|
||||
"sass-loader": "^13.0.0",
|
||||
"select2": "^4.0.13",
|
||||
"select2-bootstrap-theme": "0.1.0-beta.10",
|
||||
"style-loader": "^3.3.1",
|
||||
@@ -46,9 +46,11 @@
|
||||
"@fullcalendar/vue3": "^6.1.4",
|
||||
"@popperjs/core": "^2.9.2",
|
||||
"@types/leaflet": "^1.9.3",
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"dropzone": "^5.7.6",
|
||||
"es6-promise": "^4.2.8",
|
||||
"leaflet": "^1.7.1",
|
||||
"marked": "^12.0.2",
|
||||
"masonry-layout": "^4.2.2",
|
||||
"mime": "^4.0.0",
|
||||
"swagger-ui": "^4.15.5",
|
||||
@@ -56,7 +58,7 @@
|
||||
"vue": "^3.2.37",
|
||||
"vue-i18n": "^9.1.6",
|
||||
"vue-multiselect": "3.0.0-alpha.2",
|
||||
"vue-toast-notification": "^3.1.2",
|
||||
"vue-toast-notification": "^2.0",
|
||||
"vuex": "^4.0.0"
|
||||
},
|
||||
"browserslist": [
|
||||
|
@@ -1,29 +1,34 @@
|
||||
parameters:
|
||||
ignoreErrors:
|
||||
-
|
||||
message: "#^Foreach overwrites \\$key with its key variable\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCustomFieldsBundle/Controller/CustomFieldsGroupController.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCustomFieldsBundle/Entity/CustomField.php
|
||||
|
||||
-
|
||||
message: "#^Property Chill\\\\CustomFieldsBundle\\\\Entity\\\\CustomField\\:\\:\\$required \\(false\\) does not accept bool\\.$#"
|
||||
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCustomFieldsBundle/Entity/CustomField.php
|
||||
path: src/Bundle/ChillPersonBundle/Form/PersonType.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$user of method Chill\\\\DocStoreBundle\\\\Entity\\\\Document\\:\\:setUser\\(\\) expects Chill\\\\MainBundle\\\\Entity\\\\User\\|null, Symfony\\\\Component\\\\Security\\\\Core\\\\User\\\\UserInterface\\|null given\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillDocStoreBundle/Controller/DocumentAccompanyingCourseController.php
|
||||
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Templating/ChillTwigRoutingHelper.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$user of method Chill\\\\DocStoreBundle\\\\Entity\\\\Document\\:\\:setUser\\(\\) expects Chill\\\\MainBundle\\\\Entity\\\\User\\|null, Symfony\\\\Component\\\\Security\\\\Core\\\\User\\\\UserInterface\\|null given\\.$#"
|
||||
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCustomFieldsBundle/Entity/CustomFieldsGroup.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php
|
||||
path: src/Bundle/ChillMainBundle/Repository/NotificationRepository.php
|
||||
|
||||
-
|
||||
message: "#^Foreach overwrites \\$key with its key variable\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillCustomFieldsBundle/Controller/CustomFieldsGroupController.php
|
||||
|
||||
-
|
||||
message: "#^Variable \\$participation might not be defined\\.$#"
|
||||
@@ -35,106 +40,6 @@ parameters:
|
||||
count: 1
|
||||
path: src/Bundle/ChillEventBundle/Form/ChoiceLoader/EventChoiceLoader.php
|
||||
|
||||
-
|
||||
message: "#^Comparison operation \"\\>\" between \\(bool\\|int\\|Redis\\) and 0 results in an error\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillFranceTravailApiBundle/src/ApiHelper/ApiWrapper.php
|
||||
|
||||
-
|
||||
message: "#^Variable \\$response might not be defined\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillFranceTravailApiBundle/src/ApiHelper/ApiWrapper.php
|
||||
|
||||
-
|
||||
message: "#^Function GuzzleHttp\\\\Psr7\\\\get not found\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillFranceTravailApiBundle/src/ApiHelper/PartenaireRomeAppellation.php
|
||||
|
||||
-
|
||||
message: "#^Function GuzzleHttp\\\\Psr7\\\\str not found\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillFranceTravailApiBundle/src/ApiHelper/PartenaireRomeAppellation.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$seconds of function sleep expects int, string given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillFranceTravailApiBundle/src/ApiHelper/PartenaireRomeAppellation.php
|
||||
|
||||
-
|
||||
message: "#^Unreachable statement \\- code above always terminates\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillJobBundle/src/Controller/CSPersonController.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$interval of method DateTimeImmutable\\:\\:add\\(\\) expects DateInterval, string\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillJobBundle/src/Entity/Immersion.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$object of static method DateTimeImmutable\\:\\:createFromMutable\\(\\) expects DateTime, DateTimeInterface given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillJobBundle/src/Entity/Immersion.php
|
||||
|
||||
-
|
||||
message: "#^Property Chill\\\\JobBundle\\\\Entity\\\\Rome\\\\Metier\\:\\:\\$appellations is never read, only written\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillJobBundle/src/Entity/Rome/Metier.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\JobBundle\\\\Export\\\\ListCSPerson\\:\\:splitArrayToColumns\\(\\) never returns Closure so it can be removed from the return type\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillJobBundle/src/Export/ListCSPerson.php
|
||||
|
||||
-
|
||||
message: "#^Variable \\$f might not be defined\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillJobBundle/src/Export/ListCSPerson.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\JobBundle\\\\Export\\\\ListFrein\\:\\:splitArrayToColumns\\(\\) never returns Closure so it can be removed from the return type\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillJobBundle/src/Export/ListFrein.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\JobBundle\\\\Export\\\\ListProjetProfessionnel\\:\\:splitArrayToColumns\\(\\) never returns Closure so it can be removed from the return type\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillJobBundle/src/Export/ListProjetProfessionnel.php
|
||||
|
||||
-
|
||||
message: "#^Property Chill\\\\JobBundle\\\\Form\\\\ChoiceLoader\\\\RomeAppellationChoiceLoader\\:\\:\\$appellationRepository \\(Chill\\\\JobBundle\\\\Repository\\\\Rome\\\\AppellationRepository\\) does not accept Doctrine\\\\ORM\\\\EntityRepository\\<Chill\\\\JobBundle\\\\Entity\\\\Rome\\\\Appellation\\>\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillJobBundle/src/Form/ChoiceLoader/RomeAppellationChoiceLoader.php
|
||||
|
||||
-
|
||||
message: "#^Result of && is always false\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillJobBundle/src/Form/ChoiceLoader/RomeAppellationChoiceLoader.php
|
||||
|
||||
-
|
||||
message: "#^Strict comparison using \\=\\=\\= between array\\{\\} and Symfony\\\\Component\\\\Validator\\\\ConstraintViolationListInterface will always evaluate to false\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillJobBundle/src/Form/ChoiceLoader/RomeAppellationChoiceLoader.php
|
||||
|
||||
-
|
||||
message: "#^Strict comparison using \\=\\=\\= between null and string will always evaluate to false\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillJobBundle/src/Form/ChoiceLoader/RomeAppellationChoiceLoader.php
|
||||
|
||||
-
|
||||
message: "#^Variable \\$metier might not be defined\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillJobBundle/src/Form/ChoiceLoader/RomeAppellationChoiceLoader.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$interval of method DateTimeImmutable\\:\\:add\\(\\) expects DateInterval, string\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillJobBundle/src/Security/Authorization/CSConnectesVoter.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$object of static method DateTimeImmutable\\:\\:createFromMutable\\(\\) expects DateTime, DateTimeInterface given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillJobBundle/src/Security/Authorization/CSConnectesVoter.php
|
||||
|
||||
-
|
||||
message: "#^Cannot unset offset '_token' on array\\{formatter\\: mixed, export\\: mixed, centers\\: mixed, alias\\: string\\}\\.$#"
|
||||
count: 1
|
||||
@@ -160,31 +65,11 @@ parameters:
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Form/ChoiceLoader/PostalCodeChoiceLoader.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillMainBundle/Repository/NotificationRepository.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$user of method Chill\\\\MainBundle\\\\Security\\\\Authorization\\\\AuthorizationHelper\\:\\:userHasAccessForCenter\\(\\) expects Chill\\\\MainBundle\\\\Entity\\\\User, Symfony\\\\Component\\\\Security\\\\Core\\\\User\\\\UserInterface given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Security/Authorization/AuthorizationHelper.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Templating/ChillTwigRoutingHelper.php
|
||||
|
||||
-
|
||||
message: "#^Foreach overwrites \\$value with its value variable\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Form/ChoiceLoader/PersonChoiceLoader.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Form/PersonType.php
|
||||
|
||||
-
|
||||
message: "#^Foreach overwrites \\$value with its value variable\\.$#"
|
||||
count: 1
|
||||
|
11
rector.php
11
rector.php
@@ -28,9 +28,6 @@ return static function (RectorConfig $rectorConfig): void {
|
||||
|
||||
// register a single rule
|
||||
$rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class);
|
||||
$rectorConfig->rule(Rector\TypeDeclaration\Rector\ClassMethod\AddParamTypeFromPropertyTypeRector::class);
|
||||
$rectorConfig->rule(Rector\TypeDeclaration\Rector\Class_\MergeDateTimePropertyTypeDeclarationRector::class);
|
||||
$rectorConfig->rule(Rector\TypeDeclaration\Rector\ClassMethod\AddReturnTypeDeclarationBasedOnParentClassMethodRector::class);
|
||||
|
||||
// part of the symfony 54 rules
|
||||
$rectorConfig->rule(\Rector\Symfony\Symfony53\Rector\StaticPropertyFetch\KernelTestCaseContainerPropertyDeprecationRector::class);
|
||||
@@ -39,8 +36,12 @@ return static function (RectorConfig $rectorConfig): void {
|
||||
|
||||
//define sets of rules
|
||||
$rectorConfig->sets([
|
||||
\Rector\Set\ValueObject\LevelSetList::UP_TO_PHP_82,
|
||||
\Rector\Symfony\Set\SymfonyLevelSetList::UP_TO_SYMFONY_54,
|
||||
\Rector\Symfony\Set\SymfonySetList::SYMFONY_50,
|
||||
\Rector\Symfony\Set\SymfonySetList::SYMFONY_50_TYPES,
|
||||
\Rector\Symfony\Set\SymfonySetList::SYMFONY_51,
|
||||
\Rector\Symfony\Set\SymfonySetList::SYMFONY_52,
|
||||
\Rector\Symfony\Set\SymfonySetList::SYMFONY_53,
|
||||
\Rector\Symfony\Set\SymfonySetList::SYMFONY_54,
|
||||
\Rector\Doctrine\Set\DoctrineSetList::DOCTRINE_CODE_QUALITY,
|
||||
\Rector\Doctrine\Set\DoctrineSetList::ANNOTATIONS_TO_ATTRIBUTES,
|
||||
]);
|
||||
|
@@ -79,9 +79,11 @@ class ActivityReason
|
||||
/**
|
||||
* Set active.
|
||||
*
|
||||
* @param bool $active
|
||||
*
|
||||
* @return ActivityReason
|
||||
*/
|
||||
public function setActive(bool $active)
|
||||
public function setActive($active)
|
||||
{
|
||||
$this->active = $active;
|
||||
|
||||
@@ -108,9 +110,11 @@ class ActivityReason
|
||||
/**
|
||||
* Set name.
|
||||
*
|
||||
* @param array $name
|
||||
*
|
||||
* @return ActivityReason
|
||||
*/
|
||||
public function setName(array $name)
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
|
@@ -0,0 +1,49 @@
|
||||
<?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\Menu;
|
||||
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
|
||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
||||
use Knp\Menu\MenuItem;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
final readonly class AccompanyingCourseQuickMenuBuilder implements LocalMenuBuilderInterface
|
||||
{
|
||||
public function __construct(private Security $security) {}
|
||||
|
||||
public static function getMenuIds(): array
|
||||
{
|
||||
return ['accompanying_course_quick_menu'];
|
||||
}
|
||||
|
||||
public function buildMenu($menuId, MenuItem $menu, array $parameters)
|
||||
{
|
||||
/** @var \Chill\PersonBundle\Entity\AccompanyingPeriod $accompanyingCourse */
|
||||
$accompanyingCourse = $parameters['accompanying-course'];
|
||||
|
||||
if ($this->security->isGranted(ActivityVoter::CREATE, $accompanyingCourse)) {
|
||||
$menu
|
||||
->addChild('Create a new activity in accompanying course', [
|
||||
'route' => 'chill_activity_activity_new',
|
||||
'routeParameters' => [
|
||||
// 'activityType_id' => '',
|
||||
'accompanying_period_id' => $accompanyingCourse->getId(),
|
||||
],
|
||||
])
|
||||
->setExtras([
|
||||
'order' => 10,
|
||||
'icon' => 'plus',
|
||||
])
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
@@ -68,7 +68,7 @@
|
||||
<div class="wl-col title"><h3>{{ 'Referrer'|trans }}</h3></div>
|
||||
<div class="wl-col list">
|
||||
<p class="wl-item">
|
||||
<span class="badge-user">{{ activity.user|chill_entity_render_box }}</span>
|
||||
<span class="badge-user">{{ activity.user|chill_entity_render_box({'at_date': activity.date}) }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -87,7 +87,8 @@
|
||||
<li>
|
||||
{% if bloc.type == 'user' %}
|
||||
<span class="badge-user">
|
||||
{{ item|chill_entity_render_box({'render': 'raw', 'addAltNames': false }) }}
|
||||
hello
|
||||
{{ item|chill_entity_render_box({'render': 'raw', 'addAltNames': false, 'at_date': entity.date }) }}
|
||||
</span>
|
||||
{% else %}
|
||||
{{ _self.insert_onthefly(bloc.type, item) }}
|
||||
@@ -114,7 +115,7 @@
|
||||
<li>
|
||||
{% if bloc.type == 'user' %}
|
||||
<span class="badge-user">
|
||||
{{ item|chill_entity_render_box({'render': 'raw', 'addAltNames': false }) }}
|
||||
{{ item|chill_entity_render_box({'render': 'raw', 'addAltNames': false, 'at_date': entity.date }) }}
|
||||
</span>
|
||||
{% else %}
|
||||
{{ _self.insert_onthefly(bloc.type, item) }}
|
||||
@@ -142,7 +143,7 @@
|
||||
<span class="wl-item">
|
||||
{% if bloc.type == 'user' %}
|
||||
<span class="badge-user">
|
||||
{{ item|chill_entity_render_box({'render': 'raw', 'addAltNames': false }) }}
|
||||
{{ item|chill_entity_render_box({'render': 'raw', 'addAltNames': false, 'at_date': entity.date }) }}
|
||||
{%- if context == 'calendar_accompanyingCourse' or context == 'calendar_person' %}
|
||||
{% set invite = entity.inviteForUser(item) %}
|
||||
{% if invite is not null %}
|
||||
|
@@ -41,7 +41,7 @@
|
||||
{% if activity.user and t.userVisible %}
|
||||
<li>
|
||||
<span class="item-key">{{ 'Referrer'|trans ~ ': ' }}</span>
|
||||
<span class="badge-user">{{ activity.user|chill_entity_render_box }}</span>
|
||||
<span class="badge-user">{{ activity.user|chill_entity_render_box({'at_date': activity.date}) }}</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
|
@@ -37,7 +37,7 @@
|
||||
{%- if entity.user is not null %}
|
||||
<dt class="inline">{{ 'Referrer'|trans|capitalize }}</dt>
|
||||
<dd>
|
||||
<span class="badge-user">{{ entity.user|chill_entity_render_box }}</span>
|
||||
<span class="badge-user">{{ entity.user|chill_entity_render_box({'at_date': entity.date}) }}</span>
|
||||
</dd>
|
||||
{% endif %}
|
||||
|
||||
|
@@ -145,7 +145,7 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
|
||||
throw new \RuntimeException('Could not determine context of activity.');
|
||||
}
|
||||
} elseif ($subject instanceof AccompanyingPeriod) {
|
||||
if (AccompanyingPeriod::STEP_CLOSED === $subject->getStep()) {
|
||||
if (AccompanyingPeriod::STEP_CLOSED === $subject->getStep() || AccompanyingPeriod::STEP_DRAFT === $subject->getStep()) {
|
||||
if (\in_array($attribute, [self::UPDATE, self::CREATE, self::DELETE], true)) {
|
||||
return false;
|
||||
}
|
||||
|
@@ -60,7 +60,7 @@ final class TranslatableActivityTypeTest extends KernelTestCase
|
||||
$this->assertInstanceOf(
|
||||
ActivityType::class,
|
||||
$form->getData()['type'],
|
||||
'The data is an instance of Chill\\ActivityBundle\\Entity\\ActivityType'
|
||||
'The data is an instance of Chill\ActivityBundle\Entity\ActivityType'
|
||||
);
|
||||
$this->assertEquals($type->getId(), $form->getData()['type']->getId());
|
||||
|
||||
|
@@ -77,6 +77,18 @@ Choose a type: Choisir un type
|
||||
4 hours: 4 heures
|
||||
4 hours 30: 4 heures 30
|
||||
5 hours: 5 heures
|
||||
5 hours 30: 5 heure 30
|
||||
6 hours: 6 heures
|
||||
6 hours 30: 6 heure 30
|
||||
7 hours: 7 heures
|
||||
7 hours 30: 7 heure 30
|
||||
8 hours: 8 heures
|
||||
8 hours 30: 8 heure 30
|
||||
9 hours: 9 heures
|
||||
9 hours 30: 9 heure 30
|
||||
10 hours: 10 heures
|
||||
11 hours: 11 heures
|
||||
12 hours: 12 heures
|
||||
Concerned groups: Parties concernées par l'échange
|
||||
Persons in accompanying course: Usagers du parcours
|
||||
Third persons: Tiers non-pro.
|
||||
@@ -210,6 +222,7 @@ Documents label: Libellé du champ Documents
|
||||
# activity type category admin
|
||||
ActivityTypeCategory list: Liste des catégories des types d'échange
|
||||
Create a new activity type category: Créer une nouvelle catégorie de type d'échange
|
||||
Create a new activity in accompanying course: Créer un échange dans le parcours
|
||||
|
||||
# activity delete
|
||||
Remove activity: Supprimer un échange
|
||||
|
@@ -49,13 +49,13 @@
|
||||
<li>
|
||||
<span>
|
||||
<abbr class="referrer" title={{ 'Created by'|trans }}>{{ 'By'|trans }}:</abbr>
|
||||
<b>{{ entity.createdBy|chill_entity_render_box }}</b>
|
||||
<b>{{ entity.createdBy|chill_entity_render_box({'at_date': entity.date}) }}</b>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>
|
||||
<abbr class="referrer" title={{ 'Created for'|trans }}>{{ 'For'|trans }}:</abbr>
|
||||
<b>{{ entity.agent|chill_entity_render_box }}</b>
|
||||
<b>{{ entity.agent|chill_entity_render_box({'at_date': entity.date}) }}</b>
|
||||
|
||||
</span>
|
||||
</li>
|
||||
|
@@ -18,10 +18,10 @@
|
||||
<dd>{{ entity.type|chill_entity_render_box }}</dd>
|
||||
|
||||
<dt class="inline">{{ 'Created by'|trans }}</dt>
|
||||
<dd>{{ entity.createdBy }}</dd>
|
||||
<dd>{{ entity.createdBy|chill_entity_render_box({'at_date': entity.date}) }}</dd>
|
||||
|
||||
<dt class="inline">{{ 'Created for'|trans }}</dt>
|
||||
<dd>{{ entity.agent }}</dd>
|
||||
<dd>{{ entity.agent|chill_entity_render_box({'at_date': entity.date}) }}</dd>
|
||||
|
||||
<dt class="inline">{{ 'Asideactivity location'|trans }}</dt>
|
||||
{%- if entity.location.name is defined -%}
|
||||
|
@@ -72,21 +72,21 @@ days: jours
|
||||
1 hour 30: 1 heure 30
|
||||
1 hour 45: 1 heure 45
|
||||
2 hours: 2 heures
|
||||
2 hours 30: 2 heure 30
|
||||
2 hours 30: 2 heures 30
|
||||
3 hours: 3 heures
|
||||
3 hours 30: 3 heure 30
|
||||
3 hours 30: 3 heures 30
|
||||
4 hours: 4 heures
|
||||
4 hours 30: 4 heure 30
|
||||
4 hours 30: 4 heures 30
|
||||
5 hours: 5 heures
|
||||
5 hours 30: 5 heure 30
|
||||
5 hours 30: 5 heures 30
|
||||
6 hours: 6 heures
|
||||
6 hours 30: 6 heure 30
|
||||
6 hours 30: 6 heures 30
|
||||
7 hours: 7 heures
|
||||
7 hours 30: 7 heure 30
|
||||
7 hours 30: 7 heures 30
|
||||
8 hours: 8 heures
|
||||
8 hours 30: 8 heure 30
|
||||
8 hours 30: 8 heures 30
|
||||
9 hours: 9 heures
|
||||
9 hours 30: 9 heure 30
|
||||
9 hours 30: 9 heures 30
|
||||
10 hours: 10 heures
|
||||
1/2 day: 1/2 jour
|
||||
1 day: 1 jour
|
||||
|
@@ -100,7 +100,7 @@ class Charge extends AbstractElement implements HasCentersInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setHelp(?string $help)
|
||||
public function setHelp($help)
|
||||
{
|
||||
$this->help = $help;
|
||||
|
||||
|
@@ -440,6 +440,16 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface, HasCente
|
||||
return $this->startDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the date of the calendar.
|
||||
*
|
||||
* Useful for showing the date of the calendar event, required by twig in some places.
|
||||
*/
|
||||
public function getDate(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->getStartDate();
|
||||
}
|
||||
|
||||
public function getStatus(): ?string
|
||||
{
|
||||
return $this->status;
|
||||
|
@@ -0,0 +1,48 @@
|
||||
<?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\CalendarBundle\Menu;
|
||||
|
||||
use Chill\CalendarBundle\Security\Voter\CalendarVoter;
|
||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
||||
use Knp\Menu\MenuItem;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
final readonly class AccompanyingCourseQuickMenuBuilder implements LocalMenuBuilderInterface
|
||||
{
|
||||
public function __construct(private Security $security) {}
|
||||
|
||||
public static function getMenuIds(): array
|
||||
{
|
||||
return ['accompanying_course_quick_menu'];
|
||||
}
|
||||
|
||||
public function buildMenu($menuId, MenuItem $menu, array $parameters)
|
||||
{
|
||||
/** @var \Chill\PersonBundle\Entity\AccompanyingPeriod $accompanyingCourse */
|
||||
$accompanyingCourse = $parameters['accompanying-course'];
|
||||
|
||||
if ($this->security->isGranted(CalendarVoter::CREATE, $accompanyingCourse)) {
|
||||
$menu
|
||||
->addChild('Create a new calendar in accompanying course', [
|
||||
'route' => 'chill_calendar_calendar_new',
|
||||
'routeParameters' => [
|
||||
'accompanying_period_id' => $accompanyingCourse->getId(),
|
||||
],
|
||||
])
|
||||
->setExtras([
|
||||
'order' => 20,
|
||||
'icon' => 'plus',
|
||||
])
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
@@ -37,12 +37,12 @@ class RemoteEventConverter
|
||||
* valid when the remote string contains also a timezone, like in
|
||||
* lastModifiedDate.
|
||||
*/
|
||||
final public const REMOTE_DATETIMEZONE_FORMAT = 'Y-m-d\\TH:i:s.u?P';
|
||||
final public const REMOTE_DATETIMEZONE_FORMAT = 'Y-m-d\TH:i:s.u?P';
|
||||
|
||||
/**
|
||||
* Same as above, but sometimes the date is expressed with only 6 milliseconds.
|
||||
*/
|
||||
final public const REMOTE_DATETIMEZONE_FORMAT_ALT = 'Y-m-d\\TH:i:s.uP';
|
||||
final public const REMOTE_DATETIMEZONE_FORMAT_ALT = 'Y-m-d\TH:i:s.uP';
|
||||
|
||||
private const REMOTE_DATE_FORMAT = 'Y-m-d\TH:i:s.u0';
|
||||
|
||||
|
@@ -1 +1,2 @@
|
||||
import './scss/badge.scss';
|
||||
import './scss/calendar-list.scss';
|
||||
|
@@ -0,0 +1,26 @@
|
||||
ul.calendar-list {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
& > li {
|
||||
display: inline-block;
|
||||
}
|
||||
& > li:nth-child(n+2) {
|
||||
margin-left: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
div.calendar-list {
|
||||
|
||||
ul.calendar-list {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
& > a.calendar-list__global {
|
||||
display: inline-block;;
|
||||
padding: 0.2rem;
|
||||
min-width: 2rem;
|
||||
border: 1px solid var(--bs-chill-blue);
|
||||
border-radius: 0.25rem;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
@@ -55,7 +55,7 @@
|
||||
<div class="item-col">
|
||||
<ul class="list-content">
|
||||
{% if calendar.mainUser is not empty %}
|
||||
<span class="badge-user">{{ calendar.mainUser|chill_entity_render_box }}</span>
|
||||
<span class="badge-user">{{ calendar.mainUser|chill_entity_render_box({'at_date': calendar.startDate}) }}</span>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
@@ -132,7 +132,7 @@
|
||||
<li class="cancel">
|
||||
<span class="createdBy">
|
||||
{{ 'Created by'|trans }}
|
||||
<b>{{ calendar.activity.createdBy|chill_entity_render_string }}</b>, {{ 'on'|trans }} {{ calendar.activity.createdAt|format_datetime('short', 'short') }}
|
||||
<b>{{ calendar.activity.createdBy|chill_entity_render_string({'at_date': calendar.activity.createdAt}) }}</b>, {{ 'on'|trans }} {{ calendar.activity.createdAt|format_datetime('short', 'short') }}
|
||||
</span>
|
||||
</li>
|
||||
{% if is_granted('CHILL_ACTIVITY_SEE', calendar.activity) %}
|
||||
|
@@ -89,7 +89,7 @@ class CalendarVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
|
||||
switch ($attribute) {
|
||||
case self::SEE:
|
||||
case self::CREATE:
|
||||
if (AccompanyingPeriod::STEP_DRAFT === $subject->getStep()) {
|
||||
if (AccompanyingPeriod::STEP_DRAFT === $subject->getStep() || AccompanyingPeriod::STEP_CLOSED === $subject->getStep()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -26,6 +26,7 @@ The calendar item has been successfully removed.: Le rendez-vous a été supprim
|
||||
From the day: Du
|
||||
to the day: au
|
||||
Transform to activity: Transformer en échange
|
||||
Create a new calendar in accompanying course: Créer un rendez-vous dans le parcours
|
||||
Will send SMS: Un SMS de rappel sera envoyé
|
||||
Will not send SMS: Aucun SMS de rappel ne sera envoyé
|
||||
SMS already sent: Un SMS a été envoyé
|
||||
|
@@ -172,9 +172,11 @@ class CustomField
|
||||
/**
|
||||
* Set active.
|
||||
*
|
||||
* @param bool $active
|
||||
*
|
||||
* @return CustomField
|
||||
*/
|
||||
public function setActive(bool $active)
|
||||
public function setActive($active)
|
||||
{
|
||||
$this->active = $active;
|
||||
|
||||
@@ -222,16 +224,18 @@ class CustomField
|
||||
/**
|
||||
* Set order.
|
||||
*
|
||||
* @param float $order
|
||||
*
|
||||
* @return CustomField
|
||||
*/
|
||||
public function setOrdering(?float $order)
|
||||
public function setOrdering($order)
|
||||
{
|
||||
$this->ordering = $order;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setRequired(bool $required)
|
||||
public function setRequired($required)
|
||||
{
|
||||
$this->required = $required;
|
||||
|
||||
@@ -241,7 +245,7 @@ class CustomField
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setSlug(?string $slug)
|
||||
public function setSlug($slug)
|
||||
{
|
||||
$this->slug = $slug;
|
||||
|
||||
@@ -251,9 +255,11 @@ class CustomField
|
||||
/**
|
||||
* Set type.
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return CustomField
|
||||
*/
|
||||
public function setType(?string $type)
|
||||
public function setType($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
|
@@ -129,7 +129,7 @@ class Option
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setActive(bool $active)
|
||||
public function setActive($active)
|
||||
{
|
||||
$this->active = $active;
|
||||
|
||||
@@ -139,7 +139,7 @@ class Option
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setInternalKey(string $internal_key)
|
||||
public function setInternalKey($internal_key)
|
||||
{
|
||||
$this->internalKey = $internal_key;
|
||||
|
||||
@@ -149,7 +149,7 @@ class Option
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setKey(?string $key)
|
||||
public function setKey($key)
|
||||
{
|
||||
$this->key = $key;
|
||||
|
||||
|
@@ -69,7 +69,7 @@ class CustomFieldsDefaultGroup
|
||||
*
|
||||
* @return CustomFieldsDefaultGroup
|
||||
*/
|
||||
public function setCustomFieldsGroup(?CustomFieldsGroup $customFieldsGroup)
|
||||
public function setCustomFieldsGroup($customFieldsGroup)
|
||||
{
|
||||
$this->customFieldsGroup = $customFieldsGroup;
|
||||
|
||||
@@ -79,9 +79,11 @@ class CustomFieldsDefaultGroup
|
||||
/**
|
||||
* Set entity.
|
||||
*
|
||||
* @param string $entity
|
||||
*
|
||||
* @return CustomFieldsDefaultGroup
|
||||
*/
|
||||
public function setEntity(?string $entity)
|
||||
public function setEntity($entity)
|
||||
{
|
||||
$this->entity = $entity;
|
||||
|
||||
|
@@ -165,9 +165,11 @@ class CustomFieldsGroup
|
||||
/**
|
||||
* Set entity.
|
||||
*
|
||||
* @param string $entity
|
||||
*
|
||||
* @return CustomFieldsGroup
|
||||
*/
|
||||
public function setEntity(?string $entity)
|
||||
public function setEntity($entity)
|
||||
{
|
||||
$this->entity = $entity;
|
||||
|
||||
|
@@ -0,0 +1,65 @@
|
||||
<?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\DocGeneratorBundle\Test;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
/**
|
||||
* @template T of object
|
||||
*/
|
||||
abstract class DocGenNormalizerTestAbstract extends KernelTestCase
|
||||
{
|
||||
public function testNullValueHasSameKeysAsNull(): void
|
||||
{
|
||||
$normalizedObject = $this->getNormalizer()->normalize($this->provideNotNullObject(), 'docgen', [
|
||||
AbstractNormalizer::GROUPS => ['docgen:read'], 'docgen:expects' => $this->provideDocGenExpectClass(),
|
||||
]);
|
||||
$nullNormalizedObject = $this->getNormalizer()->normalize(null, 'docgen', [
|
||||
AbstractNormalizer::GROUPS => ['docgen:read'], 'docgen:expects' => $this->provideDocGenExpectClass(),
|
||||
]);
|
||||
|
||||
self::assertEqualsCanonicalizing(array_keys($normalizedObject), array_keys($nullNormalizedObject));
|
||||
self::assertArrayHasKey('isNull', $nullNormalizedObject, 'each object must have an "isNull" key');
|
||||
self::assertTrue($nullNormalizedObject['isNull'], 'isNull key must be true for null objects');
|
||||
self::assertFalse($normalizedObject['isNull'], 'isNull key must be false for null objects');
|
||||
|
||||
foreach ($normalizedObject as $key => $value) {
|
||||
if (in_array($key, ['isNull', 'type'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
if (array_is_list($value)) {
|
||||
self::assertEquals([], $nullNormalizedObject[$key], "list must be serialized as an empty array, in {$key}");
|
||||
} else {
|
||||
self::assertEqualsCanonicalizing(array_keys($value), array_keys($nullNormalizedObject[$key]), "sub-object must have the same keys, in {$key}");
|
||||
}
|
||||
} elseif (is_string($value)) {
|
||||
self::assertEquals('', $nullNormalizedObject[$key], 'strings must be ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return T
|
||||
*/
|
||||
abstract public function provideNotNullObject(): object;
|
||||
|
||||
/**
|
||||
* @return class-string<T>
|
||||
*/
|
||||
abstract public function provideDocGenExpectClass(): string;
|
||||
|
||||
abstract public function getNormalizer(): NormalizerInterface;
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
<?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\DocStoreBundle\Controller;
|
||||
|
||||
use Chill\DocStoreBundle\Entity\StoredObject;
|
||||
use Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner\RequestPdfSignMessage;
|
||||
use Chill\DocStoreBundle\Service\Signature\PDFPage;
|
||||
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZone;
|
||||
use Chill\DocStoreBundle\Service\StoredObjectManagerInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Messenger\MessageBusInterface;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class SignatureRequestController
|
||||
{
|
||||
public function __construct(
|
||||
private MessageBusInterface $messageBus,
|
||||
private StoredObjectManagerInterface $storedObjectManager,
|
||||
) {}
|
||||
|
||||
#[Route('/api/1.0/document/workflow/{id}/signature-request', name: 'chill_docstore_signature_request')]
|
||||
public function processSignature(StoredObject $storedObject): Response
|
||||
{
|
||||
$content = $this->storedObjectManager->read($storedObject);
|
||||
|
||||
$this->messageBus->dispatch(new RequestPdfSignMessage(
|
||||
0,
|
||||
new PDFSignatureZone(10.0, 10.0, 180.0, 180.0, new PDFPage(0, 500.0, 800.0)),
|
||||
0,
|
||||
'test signature',
|
||||
'Mme Caroline Diallo',
|
||||
$content
|
||||
));
|
||||
|
||||
return new Response('<html><head><title>test</title></head><body><p>ok</p></body></html>');
|
||||
}
|
||||
}
|
@@ -129,7 +129,7 @@ class Document implements TrackCreationInterface, TrackUpdateInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setUser(?\Chill\MainBundle\Entity\User $user): self
|
||||
public function setUser($user): self
|
||||
{
|
||||
$this->user = $user;
|
||||
|
||||
|
@@ -86,7 +86,7 @@ class DocumentCategory
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDocumentClass(?string $documentClass): self
|
||||
public function setDocumentClass($documentClass): self
|
||||
{
|
||||
$this->documentClass = $documentClass;
|
||||
|
||||
|
@@ -55,14 +55,14 @@ class PersonDocument extends Document implements HasCenterInterface, HasScopeInt
|
||||
return $this->scope;
|
||||
}
|
||||
|
||||
public function setPerson(Person $person): self
|
||||
public function setPerson($person): self
|
||||
{
|
||||
$this->person = $person;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setScope(?Scope $scope): self
|
||||
public function setScope($scope): self
|
||||
{
|
||||
$this->scope = $scope;
|
||||
|
||||
|
@@ -313,4 +313,19 @@ class StoredObject implements Document, TrackCreationInterface
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function saveHistory(): void
|
||||
{
|
||||
if ('' === $this->getFilename()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->datas['history'][] = [
|
||||
'filename' => $this->getFilename(),
|
||||
'iv' => $this->getIv(),
|
||||
'key_infos' => $this->getKeyInfos(),
|
||||
'type' => $this->getType(),
|
||||
'before' => (new \DateTimeImmutable('now'))->getTimestamp(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -57,8 +57,8 @@ class StoredObjectDataMapper implements DataMapperInterface
|
||||
|
||||
/** @var StoredObject $viewData */
|
||||
if ($viewData->getFilename() !== $forms['stored_object']->getData()['filename']) {
|
||||
// we do not want to erase the previous object
|
||||
$viewData = new StoredObject();
|
||||
// we want to keep the previous history
|
||||
$viewData->saveHistory();
|
||||
}
|
||||
|
||||
$viewData->setFilename($forms['stored_object']->getData()['filename']);
|
||||
|
@@ -4,13 +4,13 @@
|
||||
Actions
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li v-if="props.canEdit && is_extension_editable(props.storedObject.type)">
|
||||
<li v-if="props.canEdit && is_extension_editable(props.storedObject.type) && props.storedObject.status !== 'stored_object_created'">
|
||||
<wopi-edit-button :stored-object="props.storedObject" :classes="{'dropdown-item': true}" :execute-before-leave="props.executeBeforeLeave"></wopi-edit-button>
|
||||
</li>
|
||||
<li v-if="props.canEdit && is_extension_editable(props.storedObject.type) && props.davLink !== undefined && props.davLinkExpiration !== undefined">
|
||||
<desktop-edit-button :classes="{'dropdown-item': true}" :edit-link="props.davLink" :expiration-link="props.davLinkExpiration"></desktop-edit-button>
|
||||
</li>
|
||||
<li v-if="props.storedObject.type != 'application/pdf' && is_extension_viewable(props.storedObject.type) && props.canConvertPdf">
|
||||
<li v-if="props.storedObject.type != 'application/pdf' && is_extension_viewable(props.storedObject.type) && props.canConvertPdf && props.storedObject.status !== 'stored_object_created'">
|
||||
<convert-button :stored-object="props.storedObject" :filename="filename" :classes="{'dropdown-item': true}"></convert-button>
|
||||
</li>
|
||||
<li v-if="props.canDownload">
|
||||
|
@@ -13,7 +13,7 @@ import {reactive} from "vue";
|
||||
import {StoredObject, StoredObjectCreated} from "../../types";
|
||||
|
||||
interface ConvertButtonConfig {
|
||||
storedObject: StoredObject|StoredObjectCreated,
|
||||
storedObject: StoredObject,
|
||||
classes: { [key: string]: boolean},
|
||||
filename?: string,
|
||||
};
|
||||
|
@@ -11,7 +11,7 @@ import {build_wopi_editor_link} from "./helpers";
|
||||
import {StoredObject, StoredObjectCreated, WopiEditButtonExecutableBeforeLeaveFunction} from "../../types";
|
||||
|
||||
interface WopiEditButtonConfig {
|
||||
storedObject: StoredObject|StoredObjectCreated,
|
||||
storedObject: StoredObject,
|
||||
returnPath?: string,
|
||||
classes: {[k: string] : boolean},
|
||||
executeBeforeLeave?: WopiEditButtonExecutableBeforeLeaveFunction,
|
||||
|
@@ -0,0 +1,23 @@
|
||||
<?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\DocStoreBundle\Service\Signature\Driver\BaseSigner;
|
||||
|
||||
/**
|
||||
* Message which is received when a pdf is signed.
|
||||
*/
|
||||
final readonly class PdfSignedMessage
|
||||
{
|
||||
public function __construct(
|
||||
public readonly int $signatureId,
|
||||
public readonly string $content
|
||||
) {}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
<?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\DocStoreBundle\Service\Signature\Driver\BaseSigner;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
|
||||
|
||||
final readonly class PdfSignedMessageHandler implements MessageHandlerInterface
|
||||
{
|
||||
/**
|
||||
* log prefix.
|
||||
*/
|
||||
private const P = '[pdf signed message] ';
|
||||
|
||||
public function __construct(
|
||||
private LoggerInterface $logger,
|
||||
) {}
|
||||
|
||||
public function __invoke(PdfSignedMessage $message): void
|
||||
{
|
||||
$this->logger->info(self::P.'a message is received', ['signaturedId' => $message->signatureId]);
|
||||
}
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
<?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\DocStoreBundle\Service\Signature\Driver\BaseSigner;
|
||||
|
||||
use Symfony\Component\Messenger\Envelope;
|
||||
use Symfony\Component\Messenger\Exception\MessageDecodingFailedException;
|
||||
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
|
||||
|
||||
/**
|
||||
* Decode (and requeue) @see{PdfSignedMessage}, which comes from an external producer.
|
||||
*/
|
||||
final readonly class PdfSignedMessageSerializer implements SerializerInterface
|
||||
{
|
||||
public function decode(array $encodedEnvelope): Envelope
|
||||
{
|
||||
$body = $encodedEnvelope['body'];
|
||||
|
||||
try {
|
||||
$decoded = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
|
||||
} catch (\JsonException $e) {
|
||||
throw new MessageDecodingFailedException('Could not deserialize message', previous: $e);
|
||||
}
|
||||
|
||||
if (!array_key_exists('signatureId', $decoded) || !array_key_exists('content', $decoded)) {
|
||||
throw new MessageDecodingFailedException('Could not find expected keys: signatureId or content');
|
||||
}
|
||||
|
||||
$content = base64_decode($decoded['content'], true);
|
||||
|
||||
if (false === $content) {
|
||||
throw new MessageDecodingFailedException('Invalid character found in the base64 encoded content');
|
||||
}
|
||||
|
||||
$message = new PdfSignedMessage($decoded['signatureId'], $content);
|
||||
|
||||
return new Envelope($message);
|
||||
}
|
||||
|
||||
public function encode(Envelope $envelope): array
|
||||
{
|
||||
$message = $envelope->getMessage();
|
||||
|
||||
if (!$message instanceof PdfSignedMessage) {
|
||||
throw new MessageDecodingFailedException('Expected a PdfSignedMessage');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'signatureId' => $message->signatureId,
|
||||
'content' => base64_encode($message->content),
|
||||
];
|
||||
|
||||
return [
|
||||
'body' => json_encode($data, JSON_THROW_ON_ERROR),
|
||||
'headers' => [],
|
||||
];
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
<?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\DocStoreBundle\Service\Signature\Driver\BaseSigner;
|
||||
|
||||
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZone;
|
||||
|
||||
/**
|
||||
* Message which is sent when we request a signature on a pdf.
|
||||
*/
|
||||
final readonly class RequestPdfSignMessage
|
||||
{
|
||||
public function __construct(
|
||||
public int $signatureId,
|
||||
public PDFSignatureZone $PDFSignatureZone,
|
||||
public int $signatureZoneIndex,
|
||||
public string $reason,
|
||||
public string $signerText,
|
||||
public string $content,
|
||||
) {}
|
||||
}
|
@@ -0,0 +1,105 @@
|
||||
<?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\DocStoreBundle\Service\Signature\Driver\BaseSigner;
|
||||
|
||||
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZone;
|
||||
use Symfony\Component\Messenger\Envelope;
|
||||
use Symfony\Component\Messenger\Exception\MessageDecodingFailedException;
|
||||
use Symfony\Component\Messenger\Stamp\NonSendableStampInterface;
|
||||
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
/**
|
||||
* Serialize a RequestPdfSignMessage, for external consumer.
|
||||
*/
|
||||
final readonly class RequestPdfSignMessageSerializer implements SerializerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private NormalizerInterface $normalizer,
|
||||
private DenormalizerInterface $denormalizer,
|
||||
) {}
|
||||
|
||||
public function decode(array $encodedEnvelope): Envelope
|
||||
{
|
||||
$body = $encodedEnvelope['body'];
|
||||
$headers = $encodedEnvelope['headers'];
|
||||
|
||||
if (RequestPdfSignMessage::class !== ($headers['Message'] ?? null)) {
|
||||
throw new MessageDecodingFailedException('serializer does not support this message');
|
||||
}
|
||||
|
||||
$data = json_decode($body, true);
|
||||
|
||||
$zoneSignature = $this->denormalizer->denormalize($data['signatureZone'], PDFSignatureZone::class, 'json', [
|
||||
AbstractNormalizer::GROUPS => ['write'],
|
||||
]);
|
||||
|
||||
$content = base64_decode($data['content'], true);
|
||||
|
||||
if (false === $content) {
|
||||
throw new MessageDecodingFailedException('the content could not be converted from base64 encoding');
|
||||
}
|
||||
|
||||
$message = new RequestPdfSignMessage(
|
||||
$data['signatureId'],
|
||||
$zoneSignature,
|
||||
$data['signatureZoneIndex'],
|
||||
$data['reason'],
|
||||
$data['signerText'],
|
||||
$content,
|
||||
);
|
||||
|
||||
// in case of redelivery, unserialize any stamps
|
||||
$stamps = [];
|
||||
if (isset($headers['stamps'])) {
|
||||
$stamps = unserialize($headers['stamps']);
|
||||
}
|
||||
|
||||
return new Envelope($message, $stamps);
|
||||
}
|
||||
|
||||
public function encode(Envelope $envelope): array
|
||||
{
|
||||
$message = $envelope->getMessage();
|
||||
|
||||
if (!$message instanceof RequestPdfSignMessage) {
|
||||
throw new MessageDecodingFailedException('Message is not a RequestPdfSignMessage');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'signatureId' => $message->signatureId,
|
||||
'signatureZoneIndex' => $message->signatureZoneIndex,
|
||||
'signatureZone' => $this->normalizer->normalize($message->PDFSignatureZone, 'json', [AbstractNormalizer::GROUPS => ['read']]),
|
||||
'reason' => $message->reason,
|
||||
'signerText' => $message->signerText,
|
||||
'content' => base64_encode($message->content),
|
||||
];
|
||||
|
||||
$allStamps = [];
|
||||
foreach ($envelope->all() as $stamp) {
|
||||
if ($stamp instanceof NonSendableStampInterface) {
|
||||
continue;
|
||||
}
|
||||
$allStamps = [...$allStamps, ...$stamp];
|
||||
}
|
||||
|
||||
return [
|
||||
'body' => json_encode($data, JSON_THROW_ON_ERROR, 512),
|
||||
'headers' => [
|
||||
'stamps' => serialize($allStamps),
|
||||
'Message' => RequestPdfSignMessage::class,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
33
src/Bundle/ChillDocStoreBundle/Service/Signature/PDFPage.php
Normal file
33
src/Bundle/ChillDocStoreBundle/Service/Signature/PDFPage.php
Normal 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\DocStoreBundle\Service\Signature;
|
||||
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
|
||||
final readonly class PDFPage
|
||||
{
|
||||
public function __construct(
|
||||
#[Groups(['read'])]
|
||||
public int $index,
|
||||
#[Groups(['read'])]
|
||||
public float $width,
|
||||
#[Groups(['read'])]
|
||||
public float $height,
|
||||
) {}
|
||||
|
||||
public function equals(self $page): bool
|
||||
{
|
||||
return $page->index === $this->index
|
||||
&& round($page->width, 2) === round($this->width, 2)
|
||||
&& round($page->height, 2) === round($this->height, 2);
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
<?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\DocStoreBundle\Service\Signature;
|
||||
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
|
||||
final readonly class PDFSignatureZone
|
||||
{
|
||||
public function __construct(
|
||||
#[Groups(['read'])]
|
||||
public float $x,
|
||||
#[Groups(['read'])]
|
||||
public float $y,
|
||||
#[Groups(['read'])]
|
||||
public float $height,
|
||||
#[Groups(['read'])]
|
||||
public float $width,
|
||||
#[Groups(['read'])]
|
||||
public PDFPage $PDFPage,
|
||||
) {}
|
||||
|
||||
public function equals(self $other): bool
|
||||
{
|
||||
return
|
||||
$this->x == $other->x
|
||||
&& $this->y == $other->y
|
||||
&& $this->height == $other->height
|
||||
&& $this->width == $other->width
|
||||
&& $this->PDFPage->equals($other->PDFPage);
|
||||
}
|
||||
}
|
@@ -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\DocStoreBundle\Service\Signature;
|
||||
|
||||
use Smalot\PdfParser\Parser;
|
||||
|
||||
class PDFSignatureZoneParser
|
||||
{
|
||||
public const ZONE_SIGNATURE_START = 'signature_zone';
|
||||
|
||||
private Parser $parser;
|
||||
|
||||
public function __construct(
|
||||
public float $defaultHeight = 180.0,
|
||||
public float $defaultWidth = 180.0,
|
||||
) {
|
||||
$this->parser = new Parser();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<PDFSignatureZone>
|
||||
*/
|
||||
public function findSignatureZones(string $fileContent): array
|
||||
{
|
||||
$pdf = $this->parser->parseContent($fileContent);
|
||||
$zones = [];
|
||||
|
||||
$defaults = $pdf->getObjectsByType('Pages');
|
||||
$defaultPage = reset($defaults);
|
||||
$defaultPageDetails = $defaultPage->getDetails();
|
||||
|
||||
foreach ($pdf->getPages() as $index => $page) {
|
||||
$details = $page->getDetails();
|
||||
$pdfPage = new PDFPage(
|
||||
$index,
|
||||
(float) ($details['MediaBox'][2] ?? $defaultPageDetails['MediaBox'][2]),
|
||||
(float) ($details['MediaBox'][3] ?? $defaultPageDetails['MediaBox'][3]),
|
||||
);
|
||||
|
||||
foreach ($page->getDataTm() as $dataTm) {
|
||||
if (str_starts_with($dataTm[1], self::ZONE_SIGNATURE_START)) {
|
||||
$zones[] = new PDFSignatureZone((float) $dataTm[0][4], (float) $dataTm[0][5], $this->defaultHeight, $this->defaultWidth, $pdfPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $zones;
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\DocStoreBundle\Tests\Entity;
|
||||
|
||||
use Chill\DocStoreBundle\Entity\StoredObject;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
class StoredObjectTest extends KernelTestCase
|
||||
{
|
||||
public function testSaveHistory(): void
|
||||
{
|
||||
$storedObject = new StoredObject();
|
||||
$storedObject
|
||||
->setFilename('test_0')
|
||||
->setIv([2, 4, 6, 8])
|
||||
->setKeyInfos(['key' => ['data0' => 'data0']])
|
||||
->setType('text/html');
|
||||
|
||||
$storedObject->saveHistory();
|
||||
|
||||
$storedObject
|
||||
->setFilename('test_1')
|
||||
->setIv([8, 10, 12])
|
||||
->setKeyInfos(['key' => ['data1' => 'data1']])
|
||||
->setType('text/text');
|
||||
|
||||
$storedObject->saveHistory();
|
||||
|
||||
self::assertEquals('test_0', $storedObject->getDatas()['history'][0]['filename']);
|
||||
self::assertEquals([2, 4, 6, 8], $storedObject->getDatas()['history'][0]['iv']);
|
||||
self::assertEquals(['key' => ['data0' => 'data0']], $storedObject->getDatas()['history'][0]['key_infos']);
|
||||
self::assertEquals('text/html', $storedObject->getDatas()['history'][0]['type']);
|
||||
|
||||
self::assertEquals('test_1', $storedObject->getDatas()['history'][1]['filename']);
|
||||
self::assertEquals([8, 10, 12], $storedObject->getDatas()['history'][1]['iv']);
|
||||
self::assertEquals(['key' => ['data1' => 'data1']], $storedObject->getDatas()['history'][1]['key_infos']);
|
||||
self::assertEquals('text/text', $storedObject->getDatas()['history'][1]['type']);
|
||||
}
|
||||
}
|
@@ -56,14 +56,14 @@ class StoredObjectTypeTest extends TypeTestCase
|
||||
{"filename":"abcdef","iv":[10, 15, 20, 30],"keyInfos":[],"type":"text/html","status":"object_store_created"}
|
||||
JSON];
|
||||
$model = new StoredObject();
|
||||
$originalObjectId = spl_object_id($model);
|
||||
$originalObjectId = spl_object_hash($model);
|
||||
$form = $this->factory->create(StoredObjectType::class, $model, ['has_title' => true]);
|
||||
|
||||
$form->submit($formData);
|
||||
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
$model = $form->getData();
|
||||
$this->assertNotEquals($originalObjectId, spl_object_hash($model));
|
||||
$this->assertEquals($originalObjectId, spl_object_hash($model));
|
||||
$this->assertEquals('abcdef', $model->getFilename());
|
||||
$this->assertEquals([10, 15, 20, 30], $model->getIv());
|
||||
$this->assertEquals('text/html', $model->getType());
|
||||
|
@@ -0,0 +1,63 @@
|
||||
<?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\DocStoreBundle\Tests\Service\Signature\Driver\BaseSigner;
|
||||
|
||||
use Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner\PdfSignedMessage;
|
||||
use Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner\PdfSignedMessageSerializer;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Messenger\Envelope;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
class PdfSignedMessageSerializerTest extends TestCase
|
||||
{
|
||||
public function testDecode(): void
|
||||
{
|
||||
$asString = <<<'JSON'
|
||||
{"signatureId": 0, "content": "dGVzdAo="}
|
||||
JSON;
|
||||
|
||||
$actual = $this->buildSerializer()->decode(['body' => $asString]);
|
||||
|
||||
self::assertInstanceOf(Envelope::class, $actual);
|
||||
$message = $actual->getMessage();
|
||||
self::assertInstanceOf(PdfSignedMessage::class, $message);
|
||||
self::assertEquals("test\n", $message->content);
|
||||
self::assertEquals(0, $message->signatureId);
|
||||
}
|
||||
|
||||
public function testEncode(): void
|
||||
{
|
||||
$envelope = new Envelope(
|
||||
new PdfSignedMessage(0, "test\n")
|
||||
);
|
||||
|
||||
$actual = $this->buildSerializer()->encode($envelope);
|
||||
|
||||
self::assertIsArray($actual);
|
||||
self::assertArrayHasKey('body', $actual);
|
||||
self::assertArrayHasKey('headers', $actual);
|
||||
self::assertEquals([], $actual['headers']);
|
||||
|
||||
self::assertEquals(<<<'JSON'
|
||||
{"signatureId":0,"content":"dGVzdAo="}
|
||||
JSON, $actual['body']);
|
||||
}
|
||||
|
||||
private function buildSerializer(): PdfSignedMessageSerializer
|
||||
{
|
||||
return new PdfSignedMessageSerializer();
|
||||
}
|
||||
}
|
@@ -0,0 +1,137 @@
|
||||
<?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\DocStoreBundle\Tests\Service\Signature\Driver\BaseSigner;
|
||||
|
||||
use Chill\DocStoreBundle\Service\Signature\PDFPage;
|
||||
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZone;
|
||||
use Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner\RequestPdfSignMessage;
|
||||
use Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner\RequestPdfSignMessageSerializer;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Messenger\Envelope;
|
||||
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
class RequestPdfSignMessageSerializerTest extends TestCase
|
||||
{
|
||||
public function testEncode(): void
|
||||
{
|
||||
$serializer = $this->buildSerializer();
|
||||
|
||||
$envelope = new Envelope(
|
||||
$request = new RequestPdfSignMessage(
|
||||
0,
|
||||
new PDFSignatureZone(10.0, 10.0, 180.0, 180.0, new PDFPage(0, 500.0, 800.0)),
|
||||
0,
|
||||
'metadata to add to the signature',
|
||||
'Mme Caroline Diallo',
|
||||
'abc'
|
||||
),
|
||||
);
|
||||
|
||||
$actual = $serializer->encode($envelope);
|
||||
$expectedBody = json_encode([
|
||||
'signatureId' => $request->signatureId,
|
||||
'signatureZoneIndex' => $request->signatureZoneIndex,
|
||||
'signatureZone' => ['x' => 10.0],
|
||||
'reason' => $request->reason,
|
||||
'signerText' => $request->signerText,
|
||||
'content' => base64_encode($request->content),
|
||||
]);
|
||||
|
||||
self::assertIsArray($actual);
|
||||
self::assertArrayHasKey('body', $actual);
|
||||
self::assertArrayHasKey('headers', $actual);
|
||||
self::assertEquals($expectedBody, $actual['body']);
|
||||
}
|
||||
|
||||
public function testDecode(): void
|
||||
{
|
||||
$serializer = $this->buildSerializer();
|
||||
|
||||
$request = new RequestPdfSignMessage(
|
||||
0,
|
||||
new PDFSignatureZone(10.0, 10.0, 180.0, 180.0, new PDFPage(0, 500.0, 800.0)),
|
||||
0,
|
||||
'metadata to add to the signature',
|
||||
'Mme Caroline Diallo',
|
||||
'abc'
|
||||
);
|
||||
|
||||
$bodyAsString = json_encode([
|
||||
'signatureId' => $request->signatureId,
|
||||
'signatureZoneIndex' => $request->signatureZoneIndex,
|
||||
'signatureZone' => ['x' => 10.0],
|
||||
'reason' => $request->reason,
|
||||
'signerText' => $request->signerText,
|
||||
'content' => base64_encode($request->content),
|
||||
], JSON_THROW_ON_ERROR);
|
||||
|
||||
$actual = $serializer->decode([
|
||||
'body' => $bodyAsString,
|
||||
'headers' => [
|
||||
'Message' => RequestPdfSignMessage::class,
|
||||
],
|
||||
]);
|
||||
|
||||
self::assertInstanceOf(RequestPdfSignMessage::class, $actual->getMessage());
|
||||
self::assertEquals($request->signatureId, $actual->getMessage()->signatureId);
|
||||
self::assertEquals($request->signatureZoneIndex, $actual->getMessage()->signatureZoneIndex);
|
||||
self::assertEquals($request->reason, $actual->getMessage()->reason);
|
||||
self::assertEquals($request->signerText, $actual->getMessage()->signerText);
|
||||
self::assertEquals($request->content, $actual->getMessage()->content);
|
||||
self::assertNotNull($actual->getMessage()->PDFSignatureZone);
|
||||
}
|
||||
|
||||
private function buildSerializer(): RequestPdfSignMessageSerializer
|
||||
{
|
||||
$normalizer =
|
||||
new class () implements NormalizerInterface {
|
||||
public function normalize($object, ?string $format = null, array $context = []): array
|
||||
{
|
||||
if (!$object instanceof PDFSignatureZone) {
|
||||
throw new UnexpectedValueException('expected RequestPdfSignMessage');
|
||||
}
|
||||
|
||||
return [
|
||||
'x' => $object->x,
|
||||
];
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, ?string $format = null): bool
|
||||
{
|
||||
return $data instanceof PDFSignatureZone;
|
||||
}
|
||||
};
|
||||
$denormalizer = new class () implements DenormalizerInterface {
|
||||
public function denormalize($data, string $type, ?string $format = null, array $context = [])
|
||||
{
|
||||
return new PDFSignatureZone(10.0, 10.0, 180.0, 180.0, new PDFPage(0, 500.0, 800.0));
|
||||
}
|
||||
|
||||
public function supportsDenormalization($data, string $type, ?string $format = null)
|
||||
{
|
||||
return PDFSignatureZone::class === $type;
|
||||
}
|
||||
};
|
||||
|
||||
$serializer = new Serializer([$normalizer, $denormalizer]);
|
||||
|
||||
return new RequestPdfSignMessageSerializer($serializer, $serializer);
|
||||
}
|
||||
}
|
@@ -0,0 +1,77 @@
|
||||
<?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 Tests\Service\Signature;
|
||||
|
||||
use Chill\DocStoreBundle\Service\Signature\PDFPage;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZone;
|
||||
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZoneParser;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
class PDFSignatureZoneParserTest extends TestCase
|
||||
{
|
||||
private static PDFSignatureZoneParser $parser;
|
||||
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
self::$parser = new PDFSignatureZoneParser();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideFiles
|
||||
*
|
||||
* @param list<PDFSignatureZone> $expected
|
||||
*/
|
||||
public function testFindSignatureZones(string $filePath, array $expected): void
|
||||
{
|
||||
$content = file_get_contents($filePath);
|
||||
|
||||
if (false === $content) {
|
||||
throw new \LogicException("Unable to read file {$filePath}");
|
||||
}
|
||||
|
||||
$actual = self::$parser->findSignatureZones($content);
|
||||
|
||||
self::assertEquals(count($expected), count($actual));
|
||||
|
||||
foreach ($actual as $index => $signatureZone) {
|
||||
self::assertObjectEquals($expected[$index], $signatureZone);
|
||||
}
|
||||
}
|
||||
|
||||
public static function provideFiles(): iterable
|
||||
{
|
||||
yield [
|
||||
__DIR__.'/data/signature_2_signature_page_1.pdf',
|
||||
[
|
||||
new PDFSignatureZone(
|
||||
127.7,
|
||||
95.289,
|
||||
180.0,
|
||||
180.0,
|
||||
$page = new PDFPage(0, 595.30393, 841.8897)
|
||||
),
|
||||
new PDFSignatureZone(
|
||||
269.5,
|
||||
95.289,
|
||||
180.0,
|
||||
180.0,
|
||||
$page,
|
||||
),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
Binary file not shown.
@@ -121,9 +121,4 @@ class AccompanyingCourseDocumentWorkflowHandler implements EntityWorkflowHandler
|
||||
{
|
||||
return AccompanyingCourseDocument::class === $entityWorkflow->getRelatedEntityClass();
|
||||
}
|
||||
|
||||
public function supportsFreeze(EntityWorkflow $entityWorkflow, array $options = []): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -418,6 +418,7 @@ final class EventController extends AbstractController
|
||||
$builder->add('event_id', HiddenType::class, [
|
||||
'data' => $event->getId(),
|
||||
]);
|
||||
dump($event->getId());
|
||||
|
||||
return $builder->getForm();
|
||||
}
|
||||
|
@@ -47,7 +47,7 @@ class Event implements HasCenterInterface, HasScopeInterface, TrackCreationInter
|
||||
private ?Scope $circle = null;
|
||||
|
||||
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE)]
|
||||
private ?\DateTime $date = null;
|
||||
private ?\DateTime $date;
|
||||
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)]
|
||||
@@ -265,9 +265,11 @@ class Event implements HasCenterInterface, HasScopeInterface, TrackCreationInter
|
||||
/**
|
||||
* Set label.
|
||||
*
|
||||
* @param string $label
|
||||
*
|
||||
* @return Event
|
||||
*/
|
||||
public function setName(?string $label)
|
||||
public function setName($label)
|
||||
{
|
||||
$this->name = $label;
|
||||
|
||||
|
@@ -146,9 +146,11 @@ class EventType
|
||||
/**
|
||||
* Set active.
|
||||
*
|
||||
* @param bool $active
|
||||
*
|
||||
* @return EventType
|
||||
*/
|
||||
public function setActive(bool $active)
|
||||
public function setActive($active)
|
||||
{
|
||||
$this->active = $active;
|
||||
|
||||
|
@@ -81,9 +81,11 @@ class Role
|
||||
/**
|
||||
* Set active.
|
||||
*
|
||||
* @param bool $active
|
||||
*
|
||||
* @return Role
|
||||
*/
|
||||
public function setActive(bool $active)
|
||||
public function setActive($active)
|
||||
{
|
||||
$this->active = $active;
|
||||
|
||||
|
@@ -81,9 +81,11 @@ class Status
|
||||
/**
|
||||
* Set active.
|
||||
*
|
||||
* @param bool $active
|
||||
*
|
||||
* @return Status
|
||||
*/
|
||||
public function setActive(bool $active)
|
||||
public function setActive($active)
|
||||
{
|
||||
$this->active = $active;
|
||||
|
||||
|
@@ -1,84 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\FranceTravailApiBundle\ApiHelper;
|
||||
|
||||
use Chill\MainBundle\Redis\ChillRedis;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
|
||||
/**
|
||||
* Wraps the pole emploi api.
|
||||
*/
|
||||
class ApiWrapper
|
||||
{
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
private $client;
|
||||
|
||||
/**
|
||||
* key for the bearer for the api pole emploi.
|
||||
*
|
||||
* This bearer is shared across users
|
||||
*/
|
||||
public const UNPERSONAL_BEARER = 'api_pemploi_bear_';
|
||||
|
||||
public function __construct(private $clientId, private $clientSecret, private readonly ChillRedis $redis)
|
||||
{
|
||||
$this->client = new Client([
|
||||
'base_uri' => 'https://entreprise.francetravail.fr/connexion/oauth2/access_token',
|
||||
]);
|
||||
}
|
||||
|
||||
public function getPublicBearer($scopes): string
|
||||
{
|
||||
$cacheKey = $this->getCacheKey($scopes);
|
||||
|
||||
if ($this->redis->exists($cacheKey) > 0) {
|
||||
$data = \unserialize($this->redis->get($cacheKey));
|
||||
|
||||
return $data->access_token;
|
||||
}
|
||||
|
||||
try {
|
||||
$response = $this->client->post('', [
|
||||
'query' => ['realm' => '/partenaire'],
|
||||
'headers' => [
|
||||
'Content-Type' => 'application/x-www-form-urlencoded',
|
||||
],
|
||||
'form_params' => [
|
||||
'grant_type' => 'client_credentials',
|
||||
'client_id' => $this->clientId,
|
||||
'client_secret' => $this->clientSecret,
|
||||
'scope' => \implode(' ', \array_merge($scopes, ['application_'.$this->clientId])),
|
||||
],
|
||||
]);
|
||||
} catch (ClientException $e) {
|
||||
dump($e->getResponse());
|
||||
}
|
||||
$data = \json_decode((string) $response->getBody());
|
||||
|
||||
// set the key with an expiry time
|
||||
$this->redis->setex(
|
||||
$cacheKey,
|
||||
$data->expires_in - 2,
|
||||
\serialize($data)
|
||||
);
|
||||
|
||||
return $data->access_token;
|
||||
}
|
||||
|
||||
protected function getCacheKey($scopes)
|
||||
{
|
||||
return self::UNPERSONAL_BEARER.implode('', $scopes);
|
||||
}
|
||||
}
|
@@ -1,106 +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\FranceTravailApiBundle\ApiHelper;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
|
||||
|
||||
/**
|
||||
* Queries for ROME partenaires api.
|
||||
*/
|
||||
class PartenaireRomeAppellation
|
||||
{
|
||||
use ProcessRequestTrait;
|
||||
/**
|
||||
* @var ApiWrapper
|
||||
*/
|
||||
protected $wrapper;
|
||||
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
private const BASE = 'https://api.pole-emploi.io/partenaire/rome-metiers/v1/metiers/';
|
||||
|
||||
public function __construct(
|
||||
ApiWrapper $wrapper,
|
||||
LoggerInterface $logger,
|
||||
private \Symfony\Contracts\HttpClient\HttpClientInterface $httpClient,
|
||||
) {
|
||||
$this->wrapper = $wrapper;
|
||||
$this->logger = $logger;
|
||||
$this->client = new Client([
|
||||
'base_uri' => 'https://api.pole-emploi.io/partenaire/rome-metiers/v1/metiers/',
|
||||
]);
|
||||
}
|
||||
|
||||
private function getBearer()
|
||||
{
|
||||
return $this->wrapper->getPublicBearer([
|
||||
'api_rome-metiersv1',
|
||||
'nomenclatureRome',
|
||||
]);
|
||||
}
|
||||
|
||||
public function getListeAppellation(string $search): array
|
||||
{
|
||||
$bearer = $this->getBearer();
|
||||
|
||||
try {
|
||||
$response = $this->httpClient->request(
|
||||
'GET',
|
||||
self::BASE.'appellation/requete',
|
||||
[
|
||||
'headers' => [
|
||||
'Authorization' => 'Bearer '.$bearer,
|
||||
'Accept' => 'application/json',
|
||||
],
|
||||
'query' => [
|
||||
'q' => $search,
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
return $response->toArray()['resultats'];
|
||||
} catch (HttpExceptionInterface $exception) {
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
||||
public function getAppellation(string $code): array
|
||||
{
|
||||
$bearer = $this->getBearer();
|
||||
|
||||
try {
|
||||
$response = $this->httpClient->request('GET', sprintf(self::BASE.'appellation/%s', $code), [
|
||||
'headers' => [
|
||||
'Authorization' => 'Bearer '.$bearer,
|
||||
'Accept' => 'application/json',
|
||||
],
|
||||
'query' => [
|
||||
'champs' => 'code,libelle,metier(code,libelle)',
|
||||
],
|
||||
]);
|
||||
|
||||
return $response->toArray();
|
||||
} catch (HttpExceptionInterface $exception) {
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,100 +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\FranceTravailApiBundle\ApiHelper;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Psr7\Request;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use GuzzleHttp\Exception\BadResponseException;
|
||||
use GuzzleHttp\Psr7;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Methods to process request against the api, and handle the
|
||||
* Exceptions.
|
||||
*/
|
||||
trait ProcessRequestTrait
|
||||
{
|
||||
/**
|
||||
* Handle a request and 429 errors.
|
||||
*
|
||||
* @param Request $request the request
|
||||
* @param array $parameters the requests parameters
|
||||
*/
|
||||
protected function handleRequest(
|
||||
Request $request,
|
||||
array $parameters,
|
||||
Client $client,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
return $this->handleRequestRecursive(
|
||||
$request,
|
||||
$parameters,
|
||||
$client,
|
||||
$logger
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* internal method to handle recursive requests.
|
||||
*
|
||||
* @throws BadResponseException
|
||||
*/
|
||||
private function handleRequestRecursive(
|
||||
Request $request,
|
||||
array $parameters,
|
||||
Client $client,
|
||||
LoggerInterface $logger,
|
||||
$counter = 0
|
||||
) {
|
||||
try {
|
||||
return $client->send($request, $parameters);
|
||||
} catch (BadResponseException $e) {
|
||||
if (
|
||||
// get 429 exceptions
|
||||
$e instanceof ClientException
|
||||
&& 429 === $e->getResponse()->getStatusCode()
|
||||
&& count($e->getResponse()->getHeader('Retry-After')) > 0) {
|
||||
if ($counter > 5) {
|
||||
$logger->error('too much 429 response', [
|
||||
'request' => Psr7\get($e->getRequest()),
|
||||
]);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$delays = $e->getResponse()->getHeader('Retry-After');
|
||||
$delay = \end($delays);
|
||||
|
||||
sleep($delay);
|
||||
|
||||
return $this->handleRequestRecursive(
|
||||
$request,
|
||||
$parameters,
|
||||
$client,
|
||||
$logger,
|
||||
$counter + 1
|
||||
);
|
||||
}
|
||||
|
||||
// handling other errors
|
||||
$logger->error('Error while querying ROME api', [
|
||||
'status_code' => $e->getResponse()->getStatusCode(),
|
||||
'part' => 'appellation',
|
||||
'request' => $e->getRequest()->getBody()->getContents(),
|
||||
'response' => $e->getResponse()->getBody()->getContents(),
|
||||
]);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,16 +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\FranceTravailApiBundle;
|
||||
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
|
||||
class ChillFranceTravailApiBundle extends Bundle {}
|
@@ -1,56 +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\FranceTravailApiBundle\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Chill\FranceTravailApiBundle\ApiHelper\PartenaireRomeAppellation;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class RomeController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* @var PartenaireRomeAppellation
|
||||
*/
|
||||
protected $apiAppellation;
|
||||
|
||||
public function __construct(PartenaireRomeAppellation $apiAppellation)
|
||||
{
|
||||
$this->apiAppellation = $apiAppellation;
|
||||
}
|
||||
|
||||
#[Route(path: '/{_locale}/france-travail/appellation/search.{_format}', name: 'chill_france_travail_api_appellation_search')]
|
||||
public function appellationSearchAction(Request $request)
|
||||
{
|
||||
if (false === $request->query->has('q')) {
|
||||
return new JsonResponse([]);
|
||||
}
|
||||
|
||||
$appellations = $this->apiAppellation
|
||||
->getListeAppellation($request->query->get('q'));
|
||||
$results = [];
|
||||
|
||||
foreach ($appellations as $appellation) {
|
||||
$appellation['id'] = 'original-'.$appellation['code'];
|
||||
$appellation['text'] = $appellation['libelle'];
|
||||
$results[] = $appellation;
|
||||
}
|
||||
|
||||
$computed = new \stdClass();
|
||||
$computed->pagination = (new \stdClass());
|
||||
$computed->pagination->more = false;
|
||||
$computed->results = $results;
|
||||
|
||||
return new JsonResponse($computed);
|
||||
}
|
||||
}
|
@@ -1,52 +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\FranceTravailApiBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\Config\FileLocator;
|
||||
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
|
||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||
use Symfony\Component\DependencyInjection\Loader;
|
||||
|
||||
/**
|
||||
* This is the class that loads and manages your bundle configuration.
|
||||
*
|
||||
* @see http://symfony.com/doc/current/cookbook/bundles/extension.html
|
||||
*/
|
||||
class ChillFranceTravailApiExtension extends Extension implements PrependExtensionInterface
|
||||
{
|
||||
public function load(array $configs, ContainerBuilder $container)
|
||||
{
|
||||
$configuration = new Configuration();
|
||||
$config = $this->processConfiguration($configuration, $configs);
|
||||
|
||||
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
|
||||
$loader->load('services.yml');
|
||||
}
|
||||
|
||||
public function prepend(ContainerBuilder $container): void
|
||||
{
|
||||
$this->prependRoute($container);
|
||||
}
|
||||
|
||||
protected function prependRoute(ContainerBuilder $container): void
|
||||
{
|
||||
// declare routes for france travail api bundle
|
||||
$container->prependExtensionConfig('chill_main', [
|
||||
'routing' => [
|
||||
'resources' => [
|
||||
'@ChillFranceTravailApiBundle/Resources/config/routing.yml',
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
@@ -1,34 +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\FranceTravailApiBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||
|
||||
/**
|
||||
* This is the class that validates and merges configuration from your app/config files.
|
||||
*
|
||||
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/configuration.html}
|
||||
*/
|
||||
class Configuration implements ConfigurationInterface
|
||||
{
|
||||
public function getConfigTreeBuilder()
|
||||
{
|
||||
$treeBuilder = new TreeBuilder('chill_france_travail_api');
|
||||
$rootNode = $treeBuilder->getRootNode();
|
||||
// Here you should define the parameters that are allowed to
|
||||
// configure your bundle. See the documentation linked above for
|
||||
// more information on that topic.
|
||||
|
||||
return $treeBuilder;
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
chill_france_travail_api_controllers:
|
||||
resource: "@ChillFranceTravailApiBundle/Controller"
|
||||
type: annotation
|
@@ -1,16 +0,0 @@
|
||||
services:
|
||||
_defaults:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
Chill\FranceTravailApiBundle\ApiHelper\ApiWrapper:
|
||||
$clientId: '%env(FRANCE_TRAVAIL_CLIENT_ID)%'
|
||||
$clientSecret: '%env(FRANCE_TRAVAIL_CLIENT_SECRET)%'
|
||||
$redis: '@Chill\MainBundle\Redis\ChillRedis'
|
||||
|
||||
Chill\FranceTravailApiBundle\ApiHelper\PartenaireRomeAppellation: ~
|
||||
|
||||
Chill\FranceTravailApiBundle\Controller\RomeController:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
tags: ['controller.service_arguments']
|
@@ -1,93 +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\FranceTravailApiBundle\Tests\ApiHelper;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Chill\FranceTravailApiBundle\ApiHelper\PartenaireRomeAppellation;
|
||||
|
||||
/**
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
class PartenaireRomeAppellationTest extends KernelTestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
self::bootKernel();
|
||||
}
|
||||
|
||||
public function testGetListeMetiersSimple()
|
||||
{
|
||||
/** @var PartenaireRomeAppellation $appellations */
|
||||
$appellations = self::$kernel
|
||||
->getContainer()
|
||||
->get(PartenaireRomeAppellation::class)
|
||||
;
|
||||
|
||||
$data = $appellations->getListeAppellation('arb');
|
||||
|
||||
$this->assertTrue(\is_array($data));
|
||||
$this->assertNotNull($data[0]->libelle);
|
||||
$this->assertNotNull($data[0]->code);
|
||||
}
|
||||
|
||||
public function testGetListeMetiersTooMuchRequests()
|
||||
{
|
||||
/** @var PartenaireRomeMetier $appellations */
|
||||
$appellations = self::$kernel
|
||||
->getContainer()
|
||||
->get(PartenaireRomeAppellation::class)
|
||||
;
|
||||
|
||||
$appellations->getListeAppellation('arb');
|
||||
$appellations->getListeAppellation('ing');
|
||||
$appellations->getListeAppellation('rob');
|
||||
$appellations->getListeAppellation('chori');
|
||||
$data = $appellations->getListeAppellation('camion');
|
||||
|
||||
$this->assertTrue(
|
||||
$data[0] instanceof \stdClass,
|
||||
'assert that first index of data is an instance of stdClass'
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetAppellation()
|
||||
{
|
||||
/** @var PartenaireRomeMetier $appellations */
|
||||
$appellations = self::$kernel
|
||||
->getContainer()
|
||||
->get(PartenaireRomeAppellation::class)
|
||||
;
|
||||
|
||||
$a = $appellations->getListeAppellation('arb');
|
||||
|
||||
$full = $appellations->getAppellation($a[0]->code);
|
||||
|
||||
$this->assertNotNull(
|
||||
$full->libelle,
|
||||
'assert that libelle is not null'
|
||||
);
|
||||
$this->assertTrue(
|
||||
$full->metier instanceof \stdClass,
|
||||
'assert that metier is returned'
|
||||
);
|
||||
$this->assertNotNull(
|
||||
$full->metier->libelle,
|
||||
'assert that metier->libelle is not null'
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,29 +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\FranceTravailApiBundle\Tests\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
class RomeControllerTest extends WebTestCase
|
||||
{
|
||||
public function testAppellationsearch()
|
||||
{
|
||||
$client = static::createClient();
|
||||
|
||||
$crawler = $client->request('GET', '/{_locale}/pole-emploi/appellation/search');
|
||||
}
|
||||
}
|
@@ -1,16 +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\JobBundle;
|
||||
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
|
||||
class ChillJobBundle extends Bundle {}
|
@@ -1,123 +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\JobBundle\Controller;
|
||||
|
||||
use Chill\PersonBundle\CRUD\Controller\EntityPersonCRUDController;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Chill\JobBundle\Entity\Immersion;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* CRUD Controller for reports (Frein, ...).
|
||||
*/
|
||||
class CSCrudReportController extends EntityPersonCRUDController
|
||||
{
|
||||
protected function onBeforeRedirectAfterSubmission(string $action, $entity, FormInterface $form, Request $request): ?Response
|
||||
{
|
||||
$next = $request->request->get('submit', 'save-and-close');
|
||||
|
||||
return match ($next) {
|
||||
'save-and-close', 'delete-and-close' => $this->redirectToRoute('chill_job_report_index', [
|
||||
'person' => $entity->getPerson()->getId(),
|
||||
]),
|
||||
default => parent::onBeforeRedirectAfterSubmission($action, $entity, $form, $request),
|
||||
};
|
||||
}
|
||||
|
||||
protected function duplicateEntity(string $action, Request $request)
|
||||
{
|
||||
if ('cscv' === $this->getCrudName()) {
|
||||
$id = $request->query->get('duplicate_id', 0);
|
||||
/** @var \Chill\JobBundle\Entity\CV $cv */
|
||||
$cv = $this->getEntity($action, $id, $request);
|
||||
$em = $this->managerRegistry->getManager();
|
||||
|
||||
$em->detach($cv);
|
||||
|
||||
foreach ($cv->getExperiences() as $experience) {
|
||||
$cv->removeExperience($experience);
|
||||
$em->detach($experience);
|
||||
$cv->addExperience($experience);
|
||||
}
|
||||
foreach ($cv->getFormations() as $formation) {
|
||||
$cv->removeFormation($formation);
|
||||
$em->detach($formation);
|
||||
$cv->addFormation($formation);
|
||||
}
|
||||
|
||||
return $cv;
|
||||
}
|
||||
if ('projet_prof' === $this->getCrudName()) {
|
||||
$id = $request->query->get('duplicate_id', 0);
|
||||
/** @var \Chill\JobBundle\Entity\ProjetProfessionnel $original */
|
||||
$original = $this->getEntity($action, $id, $request);
|
||||
|
||||
$new = parent::duplicateEntity($action, $request);
|
||||
|
||||
foreach ($original->getSouhait() as $s) {
|
||||
$new->addSouhait($s);
|
||||
}
|
||||
foreach ($original->getValide() as $s) {
|
||||
$new->addValide($s);
|
||||
}
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
return parent::duplicateEntity($action, $request);
|
||||
}
|
||||
|
||||
protected function createFormFor(string $action, $entity, ?string $formClass = null, array $formOptions = []): FormInterface
|
||||
{
|
||||
if ($entity instanceof Immersion) {
|
||||
if ('edit' === $action || 'new' === $action) {
|
||||
return parent::createFormFor($action, $entity, $formClass, [
|
||||
'center' => $entity->getPerson()->getCenter(),
|
||||
]);
|
||||
}
|
||||
if ('bilan' === $action) {
|
||||
return parent::createFormFor($action, $entity, $formClass, [
|
||||
'center' => $entity->getPerson()->getCenter(),
|
||||
'step' => 'bilan',
|
||||
]);
|
||||
}
|
||||
if ('delete' === $action) {
|
||||
return parent::createFormFor($action, $entity, $formClass, $formOptions);
|
||||
}
|
||||
throw new \LogicException("this step {$action} is not supported");
|
||||
}
|
||||
|
||||
return parent::createFormFor($action, $entity, $formClass, $formOptions);
|
||||
}
|
||||
|
||||
protected function onPreFlush(string $action, $entity, FormInterface $form, Request $request)
|
||||
{
|
||||
// for immersion / edit-bilan action
|
||||
if ('bilan' === $action) {
|
||||
/* @var $entity Immersion */
|
||||
$entity->setIsBilanFullfilled(true);
|
||||
}
|
||||
|
||||
parent::onPreFlush($action, $entity, $form, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit immersion bilan.
|
||||
*
|
||||
* @param int $id
|
||||
*/
|
||||
public function editBilan(Request $request, $id): Response
|
||||
{
|
||||
return $this->formEditAction('bilan', $request, $id);
|
||||
}
|
||||
}
|
@@ -1,150 +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\JobBundle\Controller;
|
||||
|
||||
use Chill\PersonBundle\CRUD\Controller\OneToOneEntityPersonCRUDController;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Chill\JobBundle\Form\CSPersonPersonalSituationType;
|
||||
use Chill\JobBundle\Form\CSPersonDispositifsType;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class CSPersonController extends OneToOneEntityPersonCRUDController
|
||||
{
|
||||
#[Route(path: '{_locale}/person/job/personal_situation/{id}/edit', name: 'chill_crud_job_personal_situation_edit')]
|
||||
public function personalSituationEdit(Request $request, $id): Response
|
||||
{
|
||||
return $this->formEditAction(
|
||||
'ps_situation_edit',
|
||||
$request,
|
||||
$id,
|
||||
CSPersonPersonalSituationType::class
|
||||
);
|
||||
}
|
||||
|
||||
#[Route(path: '{_locale}/person/job/dispositifs/{id}/edit', name: 'chill_crud_job_dispositifs_edit')]
|
||||
public function dispositifsEdit(Request $request, $id)
|
||||
{
|
||||
return $this->formEditAction(
|
||||
'dispositifs_edit',
|
||||
$request,
|
||||
$id,
|
||||
CSPersonDispositifsType::class
|
||||
);
|
||||
}
|
||||
|
||||
#[Route(path: '{_locale}/person/job/{person}/personal_situation', name: 'chill_crud_job_personal_situation_view')]
|
||||
public function personalSituationView(Request $request, $person): Response
|
||||
{
|
||||
return $this->viewAction('ps_situation_view', $request, $person);
|
||||
}
|
||||
|
||||
#[Route(path: '{_locale}/person/job/{person}/dispositifs', name: 'chill_crud_job_dispositifs_view')]
|
||||
public function dispositifsView(Request $request, $person): Response
|
||||
{
|
||||
return $this->viewAction('dispositifs_view', $request, $person);
|
||||
}
|
||||
|
||||
protected function generateRedirectOnCreateRoute($action, Request $request, $entity): string
|
||||
{
|
||||
$route = '';
|
||||
|
||||
switch ($action) {
|
||||
case 'ps_situation_view':
|
||||
$route = 'chill_crud_job_personal_situation_edit';
|
||||
break;
|
||||
case 'dispositifs_view':
|
||||
$route = 'chill_crud_job_dispositifs_edit';
|
||||
break;
|
||||
default:
|
||||
parent::generateRedirectOnCreateRoute($action, $request, $entity);
|
||||
}
|
||||
|
||||
return $this->generateUrl($route, ['id' => $entity->getPerson()->getId()]);
|
||||
}
|
||||
|
||||
protected function checkACL($action, $entity): void
|
||||
{
|
||||
match ($action) {
|
||||
'ps_situation_edit', 'dispositifs_edit' => $this->denyAccessUnlessGranted(
|
||||
PersonVoter::UPDATE,
|
||||
$entity->getPerson()
|
||||
),
|
||||
'ps_situation_view', 'dispositifs_view' => $this->denyAccessUnlessGranted(
|
||||
PersonVoter::SEE,
|
||||
$entity->getPerson()
|
||||
),
|
||||
default => parent::checkACL($action, $entity),
|
||||
};
|
||||
}
|
||||
|
||||
protected function onBeforeRedirectAfterSubmission(string $action, $entity, FormInterface $form, Request $request): ?Response
|
||||
{
|
||||
return match ($action) {
|
||||
'ps_situation_edit' => $this->redirectToRoute(
|
||||
'chill_crud_'.$this->getCrudName().'_personal_situation_view',
|
||||
['person' => $entity->getId()]
|
||||
),
|
||||
'dispositifs_edit' => $this->redirectToRoute(
|
||||
'chill_crud_'.$this->getCrudName().'_dispositifs_view',
|
||||
['person' => $entity->getId()]
|
||||
),
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
|
||||
protected function getTemplateFor($action, $entity, Request $request): string
|
||||
{
|
||||
return match ($action) {
|
||||
'ps_situation_edit' => '@ChillJob/CSPerson/personal_situation_edit.html.twig',
|
||||
'dispositifs_edit' => '@ChillJob/CSPerson/dispositifs_edit.html.twig',
|
||||
'ps_situation_view' => '@ChillJob/CSPerson/personal_situation_view.html.twig',
|
||||
'dispositifs_view' => '@ChillJob/CSPerson/dispositifs_view.html.twig',
|
||||
default => parent::getTemplateFor($action, $entity, $request),
|
||||
};
|
||||
}
|
||||
|
||||
protected function createFormFor(string $action, $entity, ?string $formClass = null, array $formOptions = []): FormInterface
|
||||
{
|
||||
switch ($action) {
|
||||
case 'ps_situation_edit':
|
||||
case 'dispositifs_edit':
|
||||
$form = $this->createForm($formClass, $entity, \array_merge(
|
||||
$formOptions,
|
||||
['center' => $entity->getPerson()->getCenter()]
|
||||
));
|
||||
$this->customizeForm($action, $form);
|
||||
|
||||
return $form;
|
||||
|
||||
default:
|
||||
return parent::createFormFor($action, $entity, $formClass, $formOptions);
|
||||
}
|
||||
}
|
||||
|
||||
protected function generateLabelForButton($action, $formName, $form): string
|
||||
{
|
||||
switch ($action) {
|
||||
case 'ps_situation_edit':
|
||||
case 'dispositifs_edit':
|
||||
if ('submit' === $formName) {
|
||||
return 'Enregistrer';
|
||||
}
|
||||
throw new \LogicException("this formName is not supported: {$formName}");
|
||||
break;
|
||||
default:
|
||||
return 'Enregistrer';
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,73 +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\JobBundle\Controller;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Chill\JobBundle\Entity\Frein;
|
||||
use Chill\JobBundle\Entity\CV;
|
||||
use Chill\JobBundle\Entity\Immersion;
|
||||
use Chill\JobBundle\Entity\ProjetProfessionnel;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Chill\JobBundle\Security\Authorization\JobVoter;
|
||||
|
||||
class CSReportController extends AbstractController
|
||||
{
|
||||
public function __construct(private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry) {}
|
||||
|
||||
#[Route(path: '{_locale}/person/job/{person}/report', name: 'chill_job_report_index')]
|
||||
public function index(Person $person): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted(PersonVoter::SEE, $person, 'The access to '
|
||||
.'person is denied');
|
||||
|
||||
$reports = $this->getReports($person);
|
||||
|
||||
return $this->render('@ChillJob/Report/index.html.twig', \array_merge([
|
||||
'person' => $person,
|
||||
], $reports));
|
||||
}
|
||||
|
||||
protected function getReports(Person $person): array
|
||||
{
|
||||
$results = [];
|
||||
|
||||
$kinds = [];
|
||||
|
||||
if ($this->isGranted(JobVoter::REPORT_CV, $person)) {
|
||||
$kinds['cvs'] = CV::class;
|
||||
}
|
||||
|
||||
if ($this->isGranted(JobVoter::REPORT_NEW, $person)) {
|
||||
$kinds = \array_merge($kinds, [
|
||||
'cvs' => CV::class,
|
||||
'freins' => Frein::class,
|
||||
'immersions' => Immersion::class,
|
||||
'projet_professionnels' => ProjetProfessionnel::class,
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ($kinds as $key => $className) {
|
||||
$ordering = match ($key) {
|
||||
'immersions' => ['debutDate' => 'DESC'],
|
||||
default => ['reportDate' => 'DESC'],
|
||||
};
|
||||
$results[$key] = $this->managerRegistry->getManager()
|
||||
->getRepository($className)
|
||||
->findBy(['person' => $person], $ordering);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
@@ -1,62 +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\JobBundle\Controller;
|
||||
|
||||
use Chill\PersonBundle\CRUD\Controller\EntityPersonCRUDController;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* CRUD Controller for reports (Frein, ...).
|
||||
*/
|
||||
class CVCrudController extends EntityPersonCRUDController
|
||||
{
|
||||
protected function onBeforeRedirectAfterSubmission(string $action, $entity, FormInterface $form, Request $request): ?Response
|
||||
{
|
||||
$next = $request->request->get('submit', 'save-and-close');
|
||||
|
||||
return match ($next) {
|
||||
'save-and-close', 'delete-and-close' => $this->redirectToRoute('chill_job_report_index', [
|
||||
'person' => $entity->getPerson()->getId(),
|
||||
]),
|
||||
default => parent::onBeforeRedirectAfterSubmission($action, $entity, $form, $request),
|
||||
};
|
||||
}
|
||||
|
||||
protected function duplicateEntity(string $action, Request $request)
|
||||
{
|
||||
if ('cv' === $this->getCrudName()) {
|
||||
$id = $request->query->get('duplicate_id', 0);
|
||||
/** @var \Chill\JobBundle\Entity\CV $cv */
|
||||
$cv = $this->getEntity($action, $id, $request);
|
||||
$em = $this->managerRegistry->getManager();
|
||||
|
||||
$em->detach($cv);
|
||||
|
||||
foreach ($cv->getExperiences() as $experience) {
|
||||
$cv->removeExperience($experience);
|
||||
$em->detach($experience);
|
||||
$cv->addExperience($experience);
|
||||
}
|
||||
foreach ($cv->getFormations() as $formation) {
|
||||
$cv->removeFormation($formation);
|
||||
$em->detach($formation);
|
||||
$cv->addFormation($formation);
|
||||
}
|
||||
|
||||
return $cv;
|
||||
}
|
||||
|
||||
return parent::duplicateEntity($action, $request);
|
||||
}
|
||||
}
|
@@ -1,35 +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\JobBundle\Controller;
|
||||
|
||||
use Chill\PersonBundle\CRUD\Controller\EntityPersonCRUDController;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* CRUD Controller for reports (Frein, ...).
|
||||
*/
|
||||
class FreinCrudController extends EntityPersonCRUDController
|
||||
{
|
||||
protected function onBeforeRedirectAfterSubmission(string $action, $entity, FormInterface $form, Request $request): ?Response
|
||||
{
|
||||
$next = $request->request->get('submit', 'save-and-close');
|
||||
|
||||
return match ($next) {
|
||||
'save-and-close', 'delete-and-close' => $this->redirectToRoute('chill_job_report_index', [
|
||||
'person' => $entity->getPerson()->getId(),
|
||||
]),
|
||||
default => parent::onBeforeRedirectAfterSubmission($action, $entity, $form, $request),
|
||||
};
|
||||
}
|
||||
}
|
@@ -1,80 +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\JobBundle\Controller;
|
||||
|
||||
use Chill\PersonBundle\CRUD\Controller\EntityPersonCRUDController;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Chill\JobBundle\Entity\Immersion;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* CRUD Controller for reports (Frein, ...).
|
||||
*/
|
||||
class ImmersionCrudController extends EntityPersonCRUDController
|
||||
{
|
||||
protected function onBeforeRedirectAfterSubmission(string $action, $entity, FormInterface $form, Request $request): ?Response
|
||||
{
|
||||
$next = $request->request->get('submit', 'save-and-close');
|
||||
|
||||
return match ($next) {
|
||||
'save-and-close', 'delete-and-close' => $this->redirectToRoute('chill_job_report_index', [
|
||||
'person' => $entity->getPerson()->getId(),
|
||||
]),
|
||||
default => parent::onBeforeRedirectAfterSubmission($action, $entity, $form, $request),
|
||||
};
|
||||
}
|
||||
|
||||
protected function createFormFor(string $action, $entity, ?string $formClass = null, array $formOptions = []): FormInterface
|
||||
{
|
||||
if ($entity instanceof Immersion) {
|
||||
if ('edit' === $action || 'new' === $action) {
|
||||
return parent::createFormFor($action, $entity, $formClass, [
|
||||
'center' => $entity->getPerson()->getCenter(),
|
||||
]);
|
||||
}
|
||||
if ('bilan' === $action) {
|
||||
return parent::createFormFor($action, $entity, $formClass, [
|
||||
'center' => $entity->getPerson()->getCenter(),
|
||||
'step' => 'bilan',
|
||||
]);
|
||||
}
|
||||
if ('delete' === $action) {
|
||||
return parent::createFormFor($action, $entity, $formClass, $formOptions);
|
||||
}
|
||||
throw new \LogicException("this step {$action} is not supported");
|
||||
}
|
||||
|
||||
return parent::createFormFor($action, $entity, $formClass, $formOptions);
|
||||
}
|
||||
|
||||
protected function onPreFlush(string $action, $entity, FormInterface $form, Request $request)
|
||||
{
|
||||
// for immersion / edit-bilan action
|
||||
if ('bilan' === $action) {
|
||||
/* @var $entity Immersion */
|
||||
$entity->setIsBilanFullfilled(true);
|
||||
}
|
||||
|
||||
parent::onPreFlush($action, $entity, $form, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit immersion bilan.
|
||||
*
|
||||
* @param int $id
|
||||
*/
|
||||
public function bilan(Request $request, $id): Response
|
||||
{
|
||||
return $this->formEditAction('bilan', $request, $id);
|
||||
}
|
||||
}
|
@@ -1,57 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\JobBundle\Controller;
|
||||
|
||||
use Chill\PersonBundle\CRUD\Controller\EntityPersonCRUDController;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* CRUD Controller for reports (Frein, ...).
|
||||
*/
|
||||
class ProjetProfessionnelCrudController extends EntityPersonCRUDController
|
||||
{
|
||||
protected function onBeforeRedirectAfterSubmission(string $action, $entity, FormInterface $form, Request $request): ?Response
|
||||
{
|
||||
$next = $request->request->get('submit', 'save-and-close');
|
||||
|
||||
return match ($next) {
|
||||
'save-and-close', 'delete-and-close' => $this->redirectToRoute('chill_job_report_index', [
|
||||
'person' => $entity->getPerson()->getId(),
|
||||
]),
|
||||
default => parent::onBeforeRedirectAfterSubmission($action, $entity, $form, $request),
|
||||
};
|
||||
}
|
||||
|
||||
protected function duplicateEntity(string $action, Request $request)
|
||||
{
|
||||
if ('projet_prof' === $this->getCrudName()) {
|
||||
$id = $request->query->get('duplicate_id', 0);
|
||||
/** @var \Chill\JobBundle\Entity\ProjetProfessionnel $original */
|
||||
$original = $this->getEntity($action, $id, $request);
|
||||
|
||||
$new = parent::duplicateEntity($action, $request);
|
||||
|
||||
foreach ($original->getSouhait() as $s) {
|
||||
$new->addSouhait($s);
|
||||
}
|
||||
foreach ($original->getValide() as $s) {
|
||||
$new->addValide($s);
|
||||
}
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
return parent::duplicateEntity($action, $request);
|
||||
}
|
||||
}
|
@@ -1,196 +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\JobBundle\DependencyInjection;
|
||||
|
||||
use Chill\JobBundle\Controller\CSPersonController;
|
||||
use Chill\JobBundle\Controller\CVCrudController;
|
||||
use Chill\JobBundle\Controller\FreinCrudController;
|
||||
use Chill\JobBundle\Controller\ImmersionCrudController;
|
||||
use Chill\JobBundle\Controller\ProjetProfessionnelCrudController;
|
||||
use Chill\JobBundle\Entity\CSPerson;
|
||||
use Chill\JobBundle\Entity\CV;
|
||||
use Chill\JobBundle\Entity\Frein;
|
||||
use Chill\JobBundle\Entity\Immersion;
|
||||
use Chill\JobBundle\Entity\ProjetProfessionnel;
|
||||
use Chill\JobBundle\Form\CVType;
|
||||
use Chill\JobBundle\Form\FreinType;
|
||||
use Chill\JobBundle\Form\ImmersionType;
|
||||
use Chill\JobBundle\Form\ProjetProfessionnelType;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\Config\FileLocator;
|
||||
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
|
||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||
use Symfony\Component\DependencyInjection\Loader;
|
||||
|
||||
/**
|
||||
* This is the class that loads and manages your bundle configuration.
|
||||
*
|
||||
* @see http://symfony.com/doc/current/cookbook/bundles/extension.html
|
||||
*/
|
||||
class ChillJobExtension extends Extension implements PrependExtensionInterface
|
||||
{
|
||||
public function load(array $configs, ContainerBuilder $container): void
|
||||
{
|
||||
$configuration = new Configuration();
|
||||
$config = $this->processConfiguration($configuration, $configs);
|
||||
|
||||
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
|
||||
$loader->load('services.yml');
|
||||
$loader->load('services/3party_type.yml');
|
||||
$loader->load('services/controller.yml');
|
||||
$loader->load('services/form.yml');
|
||||
$loader->load('services/export.yml');
|
||||
$loader->load('services/menu.yml');
|
||||
$loader->load('services/security.yml');
|
||||
}
|
||||
|
||||
public function prepend(ContainerBuilder $container): void
|
||||
{
|
||||
$this->prependRoute($container);
|
||||
$this->prependCruds($container);
|
||||
}
|
||||
|
||||
protected function prependCruds(ContainerBuilder $container)
|
||||
{
|
||||
$container->prependExtensionConfig('chill_main', [
|
||||
'cruds' => [
|
||||
[
|
||||
'class' => CSPerson::class,
|
||||
'controller' => CSPersonController::class,
|
||||
'name' => 'job',
|
||||
'base_role' => 'ROLE_USER',
|
||||
'base_path' => '/person/job/',
|
||||
],
|
||||
[
|
||||
'class' => CV::class,
|
||||
'controller' => CVCrudController::class,
|
||||
'name' => 'cscv',
|
||||
'base_role' => 'ROLE_USER',
|
||||
'base_path' => '/person/report/cv',
|
||||
'form_class' => CVType::class,
|
||||
'actions' => [
|
||||
'view' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillJob/CV/view.html.twig',
|
||||
],
|
||||
'new' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillJob/CV/new.html.twig',
|
||||
],
|
||||
'edit' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillJob/CV/edit.html.twig',
|
||||
],
|
||||
'delete' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillJob/Report/delete.html.twig',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'class' => ProjetProfessionnel::class,
|
||||
'controller' => ProjetProfessionnelCrudController::class,
|
||||
'name' => 'projet_prof',
|
||||
'base_role' => 'ROLE_USER',
|
||||
'base_path' => '/person/report/projet-professionnel',
|
||||
'form_class' => ProjetProfessionnelType::class,
|
||||
'actions' => [
|
||||
'view' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillJob/ProjetProfessionnel/view.html.twig',
|
||||
],
|
||||
'new' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillJob/ProjetProfessionnel/new.html.twig',
|
||||
],
|
||||
'edit' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillJob/ProjetProfessionnel/edit.html.twig',
|
||||
],
|
||||
'delete' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillJob/Report/delete.html.twig',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'class' => Frein::class,
|
||||
'controller' => FreinCrudController::class,
|
||||
'name' => 'csfrein',
|
||||
'base_role' => 'ROLE_USER',
|
||||
'base_path' => '/person/report/frein',
|
||||
'form_class' => FreinType::class,
|
||||
'actions' => [
|
||||
'view' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillJob/Frein/view.html.twig',
|
||||
],
|
||||
'new' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillJob/Frein/new.html.twig',
|
||||
],
|
||||
'edit' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillJob/Frein/edit.html.twig',
|
||||
],
|
||||
'delete' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillJob/Report/delete.html.twig',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'class' => Immersion::class,
|
||||
'controller' => ImmersionCrudController::class,
|
||||
'name' => 'immersion',
|
||||
'base_role' => 'ROLE_USER',
|
||||
'base_path' => '/person/report/immersion',
|
||||
'form_class' => ImmersionType::class,
|
||||
'actions' => [
|
||||
'view' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillJob/Immersion/view.html.twig',
|
||||
],
|
||||
'new' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillJob/Immersion/new.html.twig',
|
||||
],
|
||||
'bilan' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillJob/Immersion/edit-bilan.html.twig',
|
||||
],
|
||||
'edit' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillJob/Immersion/edit.html.twig',
|
||||
],
|
||||
'delete' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillJob/Report/delete.html.twig',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
protected function prependRoute(ContainerBuilder $container): void
|
||||
{
|
||||
// declare routes for job bundle
|
||||
$container->prependExtensionConfig('chill_main', [
|
||||
'routing' => [
|
||||
'resources' => [
|
||||
'@ChillJobBundle/Resources/config/routing.yml',
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
@@ -1,35 +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\JobBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||
|
||||
/**
|
||||
* This is the class that validates and merges configuration from your app/config files.
|
||||
*
|
||||
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/configuration.html}
|
||||
*/
|
||||
class Configuration implements ConfigurationInterface
|
||||
{
|
||||
public function getConfigTreeBuilder()
|
||||
{
|
||||
$treeBuilder = new TreeBuilder('chill_job');
|
||||
$rootNode = $treeBuilder->getRootNode();
|
||||
|
||||
// Here you should define the parameters that are allowed to
|
||||
// configure your bundle. See the documentation linked above for
|
||||
// more information on that topic.
|
||||
|
||||
return $treeBuilder;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,303 +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\JobBundle\Entity;
|
||||
|
||||
use Doctrine\Common\Collections\Order;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* CV.
|
||||
*/
|
||||
#[ORM\Table(name: 'chill_job.cv')]
|
||||
#[ORM\Entity(repositoryClass: \Chill\JobBundle\Repository\CVRepository::class)]
|
||||
class CV implements \Stringable
|
||||
{
|
||||
#[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)]
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue(strategy: 'AUTO')]
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
#[ORM\Column(name: 'reportDate', type: \Doctrine\DBAL\Types\Types::DATE_MUTABLE)]
|
||||
private ?\DateTimeInterface $reportDate = null;
|
||||
|
||||
public const FORMATION_LEVEL = [
|
||||
'sans_diplome',
|
||||
'BEP_CAP',
|
||||
'BAC',
|
||||
'BAC+2',
|
||||
'BAC+3',
|
||||
'BAC+4',
|
||||
'BAC+5',
|
||||
'BAC+8',
|
||||
];
|
||||
|
||||
/**
|
||||
* @Assert\NotBlank()
|
||||
*/
|
||||
#[ORM\Column(name: 'formationLevel', type: \Doctrine\DBAL\Types\Types::STRING, length: 255, nullable: true)]
|
||||
private ?string $formationLevel = null;
|
||||
|
||||
public const FORMATION_TYPE = [
|
||||
'formation_initiale',
|
||||
'formation_continue',
|
||||
];
|
||||
|
||||
#[ORM\Column(name: 'formationType', type: \Doctrine\DBAL\Types\Types::STRING, length: 255, nullable: true)]
|
||||
private ?string $formationType = null;
|
||||
|
||||
/**
|
||||
* @var string[]|null
|
||||
*/
|
||||
#[ORM\Column(name: 'spokenLanguages', type: \Doctrine\DBAL\Types\Types::JSON, nullable: true)]
|
||||
private $spokenLanguages;
|
||||
|
||||
#[ORM\Column(name: 'notes', type: \Doctrine\DBAL\Types\Types::TEXT, nullable: true)]
|
||||
private ?string $notes = null;
|
||||
|
||||
/**
|
||||
* @Assert\Valid(traverse=true)
|
||||
*
|
||||
* @var \Doctrine\Common\Collections\Collection<int, \Chill\JobBundle\Entity\CV\Formation>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: CV\Formation::class, mappedBy: 'CV', cascade: ['persist', 'remove', 'detach'], orphanRemoval: true)]
|
||||
// #[ORM\OrderBy(['startDate' => Order::Descending, 'endDate' => 'DESC'])]
|
||||
private Collection $formations;
|
||||
|
||||
/**
|
||||
* @Assert\Valid(traverse=true)
|
||||
*
|
||||
* @var \Doctrine\Common\Collections\Collection<int, \Chill\JobBundle\Entity\CV\Experience>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: CV\Experience::class, mappedBy: 'CV', cascade: ['persist', 'remove', 'detach'], orphanRemoval: true)]
|
||||
// #[ORM\OrderBy(['startDate' => Order::Descending, 'endDate' => 'DESC'])]
|
||||
private Collection $experiences;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Person::class)]
|
||||
private ?Person $person = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->formations = new ArrayCollection();
|
||||
$this->experiences = new ArrayCollection();
|
||||
$this->reportDate = new \DateTime('now');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set reportDate.
|
||||
*/
|
||||
public function setReportDate(\DateTime $reportDate): self
|
||||
{
|
||||
$this->reportDate = $reportDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get reportDate.
|
||||
*/
|
||||
public function getReportDate(): ?\DateTimeInterface
|
||||
{
|
||||
return $this->reportDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set formationLevel.
|
||||
*/
|
||||
public function setFormationLevel(?string $formationLevel = null): self
|
||||
{
|
||||
$this->formationLevel = $formationLevel;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get formationLevel.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getFormationLevel()
|
||||
{
|
||||
return $this->formationLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set formationType.
|
||||
*/
|
||||
public function setFormationType(string $formationType): self
|
||||
{
|
||||
$this->formationType = $formationType;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get formationType.
|
||||
*/
|
||||
public function getFormationType(): ?string
|
||||
{
|
||||
return $this->formationType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set spokenLanguages.
|
||||
*
|
||||
* @param mixed|null $spokenLanguages
|
||||
*/
|
||||
public function setSpokenLanguages($spokenLanguages = null): self
|
||||
{
|
||||
$this->spokenLanguages = $spokenLanguages;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get spokenLanguages.
|
||||
*/
|
||||
public function getSpokenLanguages(): array
|
||||
{
|
||||
return $this->spokenLanguages ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set notes.
|
||||
*/
|
||||
public function setNotes(?string $notes = null): self
|
||||
{
|
||||
$this->notes = $notes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get notes.
|
||||
*/
|
||||
public function getNotes(): ?string
|
||||
{
|
||||
return $this->notes;
|
||||
}
|
||||
|
||||
public function getFormations(): Collection
|
||||
{
|
||||
return $this->formations;
|
||||
}
|
||||
|
||||
public function getExperiences(): Collection
|
||||
{
|
||||
return $this->experiences;
|
||||
}
|
||||
|
||||
public function setFormations(Collection $formations): self
|
||||
{
|
||||
foreach ($formations as $formation) {
|
||||
/* @var CV\Formation $formation */
|
||||
$formation->setCV($this);
|
||||
}
|
||||
$this->formations = $formations;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addFormation(CV\Formation $formation): self
|
||||
{
|
||||
if ($this->formations->contains($formation)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->formations->add($formation);
|
||||
$formation->setCV($this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeFormation(CV\Formation $formation): self
|
||||
{
|
||||
if (false === $this->formations->contains($formation)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$formation->setCV(null);
|
||||
$this->formations->removeElement($formation);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setExperiences(Collection $experiences): self
|
||||
{
|
||||
foreach ($experiences as $experience) {
|
||||
/* @var CV\Experience $experience */
|
||||
$experience->setCV($this);
|
||||
}
|
||||
|
||||
$this->experiences = $experiences;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addExperience(CV\Experience $experience): self
|
||||
{
|
||||
if ($this->experiences->contains($experience)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$experience->setCV($this);
|
||||
$this->experiences->add($experience);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeExperience(CV\Experience $experience): self
|
||||
{
|
||||
if (false === $this->experiences->contains($experience)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->experiences->removeElement($experience);
|
||||
$experience->setCV(null);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPerson(): Person
|
||||
{
|
||||
return $this->person;
|
||||
}
|
||||
|
||||
public function setPerson(Person $person)
|
||||
{
|
||||
$this->person = $person;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return 'CV de '.$this->getPerson().' daté du '.
|
||||
$this->getReportDate()->format('d-m-Y');
|
||||
}
|
||||
}
|
@@ -1,205 +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\JobBundle\Entity\CV;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Chill\JobBundle\Entity\CV;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* Experience.
|
||||
*/
|
||||
#[ORM\Table(name: 'chill_job.cv_experience')]
|
||||
#[ORM\Entity(repositoryClass: \Chill\JobBundle\Repository\CV\ExperienceRepository::class)]
|
||||
class Experience
|
||||
{
|
||||
#[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)]
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue(strategy: 'AUTO')]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(name: 'poste', type: \Doctrine\DBAL\Types\Types::TEXT, nullable: true)]
|
||||
private ?string $poste = null;
|
||||
|
||||
#[ORM\Column(name: 'structure', type: \Doctrine\DBAL\Types\Types::TEXT, nullable: true)]
|
||||
private ?string $structure = null;
|
||||
|
||||
#[ORM\Column(name: 'startDate', type: \Doctrine\DBAL\Types\Types::DATE_MUTABLE, nullable: true)]
|
||||
private ?\DateTimeInterface $startDate = null;
|
||||
|
||||
/**
|
||||
* @Assert\GreaterThan(propertyPath="startDate", message="La date de fin doit être postérieure à la date de début")
|
||||
*/
|
||||
#[ORM\Column(name: 'endDate', type: \Doctrine\DBAL\Types\Types::DATE_MUTABLE, nullable: true)]
|
||||
private ?\DateTimeInterface $endDate = null;
|
||||
|
||||
public const CONTRAT_TYPE = [
|
||||
'cddi',
|
||||
'cdd-6mois',
|
||||
'cdd+6mois',
|
||||
'interim',
|
||||
'apprentissage',
|
||||
'contrat_prof',
|
||||
'cui',
|
||||
'cae',
|
||||
'cdi',
|
||||
'stage',
|
||||
'volontariat',
|
||||
'benevolat',
|
||||
'autres',
|
||||
];
|
||||
|
||||
#[ORM\Column(name: 'contratType', type: \Doctrine\DBAL\Types\Types::STRING, length: 100)]
|
||||
private ?string $contratType = null;
|
||||
|
||||
#[ORM\Column(name: 'notes', type: \Doctrine\DBAL\Types\Types::TEXT, nullable: true)]
|
||||
private ?string $notes = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: CV::class, inversedBy: 'experiences')]
|
||||
private ?CV $CV = null;
|
||||
|
||||
/**
|
||||
* Get id.
|
||||
*/
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set poste.
|
||||
*/
|
||||
public function setPoste(?string $poste = null): self
|
||||
{
|
||||
$this->poste = $poste;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get poste.
|
||||
*/
|
||||
public function getPoste(): ?string
|
||||
{
|
||||
return $this->poste;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set structure.
|
||||
*/
|
||||
public function setStructure(?string $structure = null): self
|
||||
{
|
||||
$this->structure = $structure;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get structure.
|
||||
*/
|
||||
public function getStructure(): ?string
|
||||
{
|
||||
return $this->structure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set startDate.
|
||||
*
|
||||
* @param \DateTime|null $startDate
|
||||
*/
|
||||
public function setStartDate(?\DateTimeInterface $startDate = null): self
|
||||
{
|
||||
$this->startDate = $startDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get startDate.
|
||||
*
|
||||
* @return \DateTimeInterface
|
||||
*/
|
||||
public function getStartDate()
|
||||
{
|
||||
return $this->startDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set endDate.
|
||||
*
|
||||
* @param \DateTime|null $endDate
|
||||
*/
|
||||
public function setEndDate(?\DateTimeInterface $endDate = null): self
|
||||
{
|
||||
$this->endDate = $endDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get endDate.
|
||||
*
|
||||
* @return \DateTimeInterface
|
||||
*/
|
||||
public function getEndDate()
|
||||
{
|
||||
return $this->endDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set contratType.
|
||||
*/
|
||||
public function setContratType(?string $contratType): self
|
||||
{
|
||||
$this->contratType = $contratType;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get contratType.
|
||||
*/
|
||||
public function getContratType(): ?string
|
||||
{
|
||||
return $this->contratType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set notes.
|
||||
*/
|
||||
public function setNotes(?string $notes): self
|
||||
{
|
||||
$this->notes = $notes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get notes.
|
||||
*/
|
||||
public function getNotes(): ?string
|
||||
{
|
||||
return $this->notes;
|
||||
}
|
||||
|
||||
public function getCV(): CV
|
||||
{
|
||||
return $this->CV;
|
||||
}
|
||||
|
||||
public function setCV(?CV $CV = null): self
|
||||
{
|
||||
$this->CV = $CV;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@@ -1,214 +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\JobBundle\Entity\CV;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Chill\JobBundle\Entity\CV;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* Formation.
|
||||
*/
|
||||
#[ORM\Table(name: 'chill_job.cv_formation')]
|
||||
#[ORM\Entity(repositoryClass: \Chill\JobBundle\Repository\CV\FormationRepository::class)]
|
||||
class Formation
|
||||
{
|
||||
#[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)]
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue(strategy: 'AUTO')]
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @Assert\Length(min=3)
|
||||
*
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
#[ORM\Column(name: 'title', type: \Doctrine\DBAL\Types\Types::TEXT)]
|
||||
private ?string $title = null;
|
||||
|
||||
#[ORM\Column(name: 'startDate', type: \Doctrine\DBAL\Types\Types::DATE_MUTABLE, nullable: true)]
|
||||
private ?\DateTimeInterface $startDate = null;
|
||||
|
||||
/**
|
||||
* @Assert\GreaterThan(propertyPath="startDate", message="La date de fin doit être postérieure à la date de début")
|
||||
*/
|
||||
#[ORM\Column(name: 'endDate', type: \Doctrine\DBAL\Types\Types::DATE_MUTABLE, nullable: true)]
|
||||
private ?\DateTimeInterface $endDate = null;
|
||||
|
||||
public const DIPLOMA_OBTAINED = [
|
||||
'fr', 'non-fr', 'aucun',
|
||||
];
|
||||
|
||||
#[ORM\Column(name: 'diplomaObtained', type: \Doctrine\DBAL\Types\Types::STRING, nullable: true)]
|
||||
private ?string $diplomaObtained = null;
|
||||
|
||||
public const DIPLOMA_RECONNU = [
|
||||
'oui', 'non', 'nsp',
|
||||
];
|
||||
|
||||
#[ORM\Column(name: 'diplomaReconnue', type: \Doctrine\DBAL\Types\Types::STRING, length: 50, nullable: true)]
|
||||
private ?string $diplomaReconnue = null;
|
||||
|
||||
#[ORM\Column(name: 'organisme', type: \Doctrine\DBAL\Types\Types::TEXT, nullable: true)]
|
||||
private ?string $organisme = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: CV::class, inversedBy: 'formations')]
|
||||
private ?CV $CV = null;
|
||||
|
||||
/**
|
||||
* Get id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set title.
|
||||
*
|
||||
* @return Formation
|
||||
*/
|
||||
public function setTitle(?string $title)
|
||||
{
|
||||
$this->title = $title;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get title.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set startDate.
|
||||
*
|
||||
* @param \DateTime|null $startDate
|
||||
*
|
||||
* @return Formation
|
||||
*/
|
||||
public function setStartDate(?\DateTimeInterface $startDate = null)
|
||||
{
|
||||
$this->startDate = $startDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get startDate.
|
||||
*
|
||||
* @return \DateTimeInterface
|
||||
*/
|
||||
public function getStartDate()
|
||||
{
|
||||
return $this->startDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set endDate.
|
||||
*
|
||||
* @param \DateTime|null $endDate
|
||||
*
|
||||
* @return Formation
|
||||
*/
|
||||
public function setEndDate(?\DateTimeInterface $endDate = null)
|
||||
{
|
||||
$this->endDate = $endDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get endDate.
|
||||
*
|
||||
* @return \DateTimeInterface
|
||||
*/
|
||||
public function getEndDate()
|
||||
{
|
||||
return $this->endDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set diplomaObtained.
|
||||
*
|
||||
* @return Formation
|
||||
*/
|
||||
public function setDiplomaObtained(?string $diplomaObtained = null)
|
||||
{
|
||||
$this->diplomaObtained = $diplomaObtained;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get diplomaObtained.
|
||||
*/
|
||||
public function getDiplomaObtained()
|
||||
{
|
||||
return $this->diplomaObtained;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set diplomaReconnue.
|
||||
*/
|
||||
public function setDiplomaReconnue(?string $diplomaReconnue = null): self
|
||||
{
|
||||
$this->diplomaReconnue = $diplomaReconnue;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get diplomaReconnue.
|
||||
*/
|
||||
public function getDiplomaReconnue(): ?string
|
||||
{
|
||||
return $this->diplomaReconnue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set organisme.
|
||||
*/
|
||||
public function setOrganisme(?string $organisme): self
|
||||
{
|
||||
$this->organisme = $organisme;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get organisme.
|
||||
*/
|
||||
public function getOrganisme(): ?string
|
||||
{
|
||||
return $this->organisme;
|
||||
}
|
||||
|
||||
public function getCV(): ?CV
|
||||
{
|
||||
return $this->CV;
|
||||
}
|
||||
|
||||
public function setCV(?CV $CV = null): self
|
||||
{
|
||||
$this->CV = $CV;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@@ -1,192 +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\JobBundle\Entity;
|
||||
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Chill\PersonBundle\Entity\HasPerson;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
/**
|
||||
* Frein.
|
||||
*/
|
||||
#[ORM\Table(name: 'chill_job.frein')]
|
||||
#[ORM\Entity(repositoryClass: \Chill\JobBundle\Repository\FreinRepository::class)]
|
||||
class Frein implements HasPerson, \Stringable
|
||||
{
|
||||
#[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)]
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue(strategy: 'AUTO')]
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @Assert\NotNull()
|
||||
*
|
||||
* @Assert\GreaterThan("5 years ago",
|
||||
* message="La date du rapport ne peut pas être plus de cinq ans dans le passé"
|
||||
* )
|
||||
*/
|
||||
#[ORM\Column(name: 'reportDate', type: \Doctrine\DBAL\Types\Types::DATE_MUTABLE)]
|
||||
private ?\DateTimeInterface $reportDate = null;
|
||||
|
||||
public const FREINS_PERSO = [
|
||||
'situation_administrative',
|
||||
'situation_personnelle_et_familiale',
|
||||
'comportement',
|
||||
'etat_de_sante',
|
||||
'precarite_situation_materielle',
|
||||
'condition_ou_absence_logement',
|
||||
'autres',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
#[ORM\Column(name: 'freinsPerso', type: \Doctrine\DBAL\Types\Types::JSON)]
|
||||
private $freinsPerso = [];
|
||||
|
||||
#[ORM\Column(name: 'notesPerso', type: \Doctrine\DBAL\Types\Types::TEXT)]
|
||||
private ?string $notesPerso = '';
|
||||
|
||||
public const FREINS_EMPLOI = [
|
||||
'garde_d_enfants',
|
||||
'sante',
|
||||
'famille',
|
||||
'finances',
|
||||
'maitrise_de_la_langue',
|
||||
'autres',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
#[ORM\Column(name: 'freinsEmploi', type: \Doctrine\DBAL\Types\Types::JSON)]
|
||||
private $freinsEmploi = [];
|
||||
|
||||
#[ORM\Column(name: 'notesEmploi', type: \Doctrine\DBAL\Types\Types::TEXT)]
|
||||
private ?string $notesEmploi = '';
|
||||
|
||||
/**
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
#[ORM\ManyToOne(targetEntity: Person::class)]
|
||||
private Person $person;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->reportDate = new \DateTime('today');
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setReportDate(?\DateTimeInterface $reportDate): self
|
||||
{
|
||||
$this->reportDate = $reportDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getReportDate(): ?\DateTimeInterface
|
||||
{
|
||||
return $this->reportDate;
|
||||
}
|
||||
|
||||
public function setFreinsPerso(array $freinsPerso = []): self
|
||||
{
|
||||
$this->freinsPerso = $freinsPerso;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFreinsPerso(): array
|
||||
{
|
||||
return $this->freinsPerso;
|
||||
}
|
||||
|
||||
public function setNotesPerso(?string $notesPerso = null): self
|
||||
{
|
||||
$this->notesPerso = (string) $notesPerso;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNotesPerso(): ?string
|
||||
{
|
||||
return $this->notesPerso;
|
||||
}
|
||||
|
||||
public function setFreinsEmploi(array $freinsEmploi = []): self
|
||||
{
|
||||
$this->freinsEmploi = $freinsEmploi;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFreinsEmploi(): array
|
||||
{
|
||||
return $this->freinsEmploi;
|
||||
}
|
||||
|
||||
public function setNotesEmploi(?string $notesEmploi = null): self
|
||||
{
|
||||
$this->notesEmploi = (string) $notesEmploi;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNotesEmploi(): ?string
|
||||
{
|
||||
return $this->notesEmploi;
|
||||
}
|
||||
|
||||
public function getPerson(): ?Person
|
||||
{
|
||||
return $this->person;
|
||||
}
|
||||
|
||||
public function setPerson(?Person $person = null): HasPerson
|
||||
{
|
||||
$this->person = $person;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Assert\Callback()
|
||||
*/
|
||||
public function validateFreinsCount(ExecutionContextInterface $context, $payload): void
|
||||
{
|
||||
$nb = count($this->getFreinsEmploi()) + count($this->getFreinsPerso());
|
||||
|
||||
if (0 === $nb) {
|
||||
$msg = 'Indiquez au moins un frein parmi les freins '
|
||||
."liés à l'emploi et les freins liés à la situation personnelle.";
|
||||
$context->buildViolation($msg)
|
||||
->atPath('freinsEmploi')
|
||||
->addViolation();
|
||||
|
||||
$context->buildViolation($msg)
|
||||
->atPath('freinsPerso')
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return 'Rapport "frein" de '.$this->getPerson().' daté du '.
|
||||
$this->getReportDate()->format('d-m-Y');
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,407 +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\JobBundle\Entity;
|
||||
|
||||
use Chill\JobBundle\Repository\ProjetProfessionnelRepository;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\JobBundle\Entity\Rome\Appellation;
|
||||
|
||||
/**
|
||||
* ProjetProfessionnel.
|
||||
*/
|
||||
#[ORM\Table(name: 'chill_job.projet_professionnel')]
|
||||
#[ORM\Entity(repositoryClass: ProjetProfessionnelRepository::class)]
|
||||
class ProjetProfessionnel implements \Stringable
|
||||
{
|
||||
#[ORM\Column(name: 'id', type: Types::INTEGER)]
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue(strategy: 'AUTO')]
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
#[ORM\ManyToOne(targetEntity: Person::class)]
|
||||
private ?Person $person = null;
|
||||
|
||||
/**
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
#[ORM\Column(name: 'reportDate', type: Types::DATE_MUTABLE)]
|
||||
private ?\DateTimeInterface $reportDate = null;
|
||||
|
||||
/**
|
||||
* @var \Doctrine\Common\Collections\Collection<int, \Chill\JobBundle\Entity\Rome\Appellation>
|
||||
*/
|
||||
#[ORM\JoinTable(name: 'chill_job.projetprofessionnel_souhait')]
|
||||
#[ORM\ManyToMany(targetEntity: Appellation::class, cascade: ['persist'])]
|
||||
private Collection $souhait;
|
||||
|
||||
#[ORM\Column(name: 'domaineActiviteSouhait', type: Types::TEXT, nullable: true)]
|
||||
private ?string $domaineActiviteSouhait = null;
|
||||
|
||||
public const TYPE_CONTRAT = [
|
||||
'cdd', 'cdi', 'contrat_insertion',
|
||||
'interim', 'indifferent', 'apprentissage',
|
||||
'personnalisation', 'creation_entreprise',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array|null
|
||||
*
|
||||
* @Assert\Count(min=1, minMessage="Indiquez au moins un type de contrat")
|
||||
*/
|
||||
#[ORM\Column(name: 'typeContrat', type: Types::JSON, nullable: true)]
|
||||
private $typeContrat;
|
||||
|
||||
#[ORM\Column(name: 'typeContratNotes', type: Types::TEXT, nullable: true)]
|
||||
private ?string $typeContratNotes = null;
|
||||
|
||||
public const VOLUME_HORAIRES = [
|
||||
'temps_plein',
|
||||
'temps_partiel',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array|null
|
||||
*
|
||||
* @Assert\Count(min=1, minMessage="Indiquez un volume horaire souhaité")
|
||||
*/
|
||||
#[ORM\Column(name: 'volumeHoraire', type: Types::JSON, nullable: true)]
|
||||
private $volumeHoraire;
|
||||
|
||||
#[ORM\Column(name: 'volumeHoraireNotes', type: Types::TEXT, nullable: true)]
|
||||
private ?string $volumeHoraireNotes = null;
|
||||
|
||||
#[ORM\Column(name: 'idee', type: Types::TEXT, nullable: true)]
|
||||
private ?string $idee = null;
|
||||
|
||||
#[ORM\Column(name: 'enCoursConstruction', type: Types::TEXT, nullable: true)]
|
||||
private ?string $enCoursConstruction = null;
|
||||
|
||||
/**
|
||||
* @var \Doctrine\Common\Collections\Collection<int, \Chill\JobBundle\Entity\Rome\Appellation>
|
||||
*/
|
||||
#[ORM\JoinTable(name: 'chill_job.projetprofessionnel_valide')]
|
||||
#[ORM\ManyToMany(targetEntity: Appellation::class)]
|
||||
private Collection $valide;
|
||||
|
||||
#[ORM\Column(name: 'domaineActiviteValide', type: Types::TEXT, nullable: true)]
|
||||
private ?string $domaineActiviteValide = null;
|
||||
|
||||
#[ORM\Column(name: 'valideNotes', type: Types::TEXT, nullable: true)]
|
||||
private ?string $valideNotes = null;
|
||||
|
||||
#[ORM\Column(name: 'projetProfessionnelNote', type: Types::TEXT, nullable: true)]
|
||||
private ?string $projetProfessionnelNote = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->valide = new ArrayCollection();
|
||||
$this->souhait = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set reportDate.
|
||||
*
|
||||
* @param \DateTime $reportDate
|
||||
*
|
||||
* @return ProjetProfessionnel
|
||||
*/
|
||||
public function setReportDate(?\DateTimeInterface $reportDate)
|
||||
{
|
||||
$this->reportDate = $reportDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get reportDate.
|
||||
*
|
||||
* @return \DateTimeInterface
|
||||
*/
|
||||
public function getReportDate()
|
||||
{
|
||||
return $this->reportDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set typeContrat.
|
||||
*
|
||||
* @param mixed|null $typeContrat
|
||||
*
|
||||
* @return ProjetProfessionnel
|
||||
*/
|
||||
public function setTypeContrat($typeContrat = null)
|
||||
{
|
||||
$this->typeContrat = $typeContrat;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get typeContrat.
|
||||
*/
|
||||
public function getTypeContrat()
|
||||
{
|
||||
return $this->typeContrat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set typeContratNotes.
|
||||
*
|
||||
* @return ProjetProfessionnel
|
||||
*/
|
||||
public function setTypeContratNotes(?string $typeContratNotes = null)
|
||||
{
|
||||
$this->typeContratNotes = $typeContratNotes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get typeContratNotes.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getTypeContratNotes()
|
||||
{
|
||||
return $this->typeContratNotes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set volumeHoraire.
|
||||
*
|
||||
* @param mixed|null $volumeHoraire
|
||||
*
|
||||
* @return ProjetProfessionnel
|
||||
*/
|
||||
public function setVolumeHoraire($volumeHoraire = null)
|
||||
{
|
||||
$this->volumeHoraire = $volumeHoraire;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get volumeHoraire.
|
||||
*/
|
||||
public function getVolumeHoraire()
|
||||
{
|
||||
return $this->volumeHoraire;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set volumeHoraireNotes.
|
||||
*
|
||||
* @return ProjetProfessionnel
|
||||
*/
|
||||
public function setVolumeHoraireNotes(?string $volumeHoraireNotes = null)
|
||||
{
|
||||
$this->volumeHoraireNotes = $volumeHoraireNotes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get volumeHoraireNotes.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getVolumeHoraireNotes()
|
||||
{
|
||||
return $this->volumeHoraireNotes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set idee.
|
||||
*
|
||||
* @return ProjetProfessionnel
|
||||
*/
|
||||
public function setIdee(?string $idee = null)
|
||||
{
|
||||
$this->idee = $idee;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get idee.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getIdee()
|
||||
{
|
||||
return $this->idee;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set enCoursConstruction.
|
||||
*
|
||||
* @return ProjetProfessionnel
|
||||
*/
|
||||
public function setEnCoursConstruction(?string $enCoursConstruction = null)
|
||||
{
|
||||
$this->enCoursConstruction = $enCoursConstruction;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get enCoursConstruction.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getEnCoursConstruction()
|
||||
{
|
||||
return $this->enCoursConstruction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set valideNotes.
|
||||
*
|
||||
* @return ProjetProfessionnel
|
||||
*/
|
||||
public function setValideNotes(?string $valideNotes = null)
|
||||
{
|
||||
$this->valideNotes = $valideNotes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get valideNotes.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getValideNotes()
|
||||
{
|
||||
return $this->valideNotes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set projetProfessionnelNote.
|
||||
*
|
||||
* @return ProjetProfessionnel
|
||||
*/
|
||||
public function setProjetProfessionnelNote(?string $projetProfessionnelNote = null)
|
||||
{
|
||||
$this->projetProfessionnelNote = $projetProfessionnelNote;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get projetProfessionnelNote.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getProjetProfessionnelNote()
|
||||
{
|
||||
return $this->projetProfessionnelNote;
|
||||
}
|
||||
|
||||
public function getPerson(): Person
|
||||
{
|
||||
return $this->person;
|
||||
}
|
||||
|
||||
public function getSouhait(): Collection
|
||||
{
|
||||
return $this->souhait;
|
||||
}
|
||||
|
||||
public function getValide(): Collection
|
||||
{
|
||||
return $this->valide;
|
||||
}
|
||||
|
||||
public function setPerson(Person $person)
|
||||
{
|
||||
$this->person = $person;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setSouhait(Collection $souhait)
|
||||
{
|
||||
$this->souhait = $souhait;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addSouhait(Appellation $souhait)
|
||||
{
|
||||
$this->souhait->add($souhait);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setValide(Collection $valide)
|
||||
{
|
||||
$this->valide = $valide;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addValide(Appellation $valide)
|
||||
{
|
||||
$this->valide->add($valide);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDomaineActiviteSouhait(): ?string
|
||||
{
|
||||
return $this->domaineActiviteSouhait;
|
||||
}
|
||||
|
||||
public function getDomaineActiviteValide(): ?string
|
||||
{
|
||||
return $this->domaineActiviteValide;
|
||||
}
|
||||
|
||||
public function setDomaineActiviteSouhait(?string $domaineActiviteSouhait = null)
|
||||
{
|
||||
$this->domaineActiviteSouhait = $domaineActiviteSouhait;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDomaineActiviteValide(?string $domaineActiviteValide = null)
|
||||
{
|
||||
$this->domaineActiviteValide = $domaineActiviteValide;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return 'Rapport "projet professionnel" de '.$this->getPerson().' daté du '.
|
||||
$this->getReportDate()->format('d-m-Y');
|
||||
}
|
||||
}
|
@@ -1,107 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\JobBundle\Entity\Rome;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* Appellation.
|
||||
*/
|
||||
#[ORM\Table(name: 'chill_job.rome_appellation')]
|
||||
#[ORM\Entity(repositoryClass: \Chill\JobBundle\Repository\Rome\AppellationRepository::class)]
|
||||
class Appellation implements \Stringable
|
||||
{
|
||||
#[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)]
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue(strategy: 'AUTO')]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(name: 'code', type: \Doctrine\DBAL\Types\Types::STRING, length: 40, unique: true)]
|
||||
private ?string $code = '';
|
||||
|
||||
#[ORM\Column(name: 'libelle', type: \Doctrine\DBAL\Types\Types::TEXT)]
|
||||
private ?string $libelle = '';
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Metier::class, inversedBy: 'appellations', cascade: ['persist'])]
|
||||
private ?Metier $metier = null;
|
||||
|
||||
/**
|
||||
* Get id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set code.
|
||||
*
|
||||
* @return Appellation
|
||||
*/
|
||||
public function setCode(?string $code)
|
||||
{
|
||||
$this->code = $code;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get code.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCode()
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set libelle.
|
||||
*
|
||||
* @return Appellation
|
||||
*/
|
||||
public function setLibelle(?string $libelle)
|
||||
{
|
||||
$this->libelle = $libelle;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get libelle.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLibelle()
|
||||
{
|
||||
return $this->libelle;
|
||||
}
|
||||
|
||||
public function getMetier(): Metier
|
||||
{
|
||||
return $this->metier;
|
||||
}
|
||||
|
||||
public function setMetier(Metier $metier)
|
||||
{
|
||||
$this->metier = $metier;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return (string) $this->libelle;
|
||||
}
|
||||
}
|
@@ -1,100 +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\JobBundle\Entity\Rome;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
|
||||
/**
|
||||
* Metier.
|
||||
*/
|
||||
#[ORM\Table(name: 'chill_job.rome_metier')]
|
||||
#[ORM\Entity(repositoryClass: \Chill\JobBundle\Repository\Rome\MetierRepository::class)]
|
||||
class Metier
|
||||
{
|
||||
#[ORM\Column(name: 'id', type: \Doctrine\DBAL\Types\Types::INTEGER)]
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue(strategy: 'AUTO')]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(name: 'libelle', type: \Doctrine\DBAL\Types\Types::TEXT)]
|
||||
private ?string $libelle = '';
|
||||
|
||||
#[ORM\Column(name: 'code', type: \Doctrine\DBAL\Types\Types::STRING, length: 20, unique: true)]
|
||||
private ?string $code = '';
|
||||
|
||||
/**
|
||||
* @var \Doctrine\Common\Collections\Collection<int, \Chill\JobBundle\Entity\Rome\Appellation>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: Appellation::class, mappedBy: 'metier')]
|
||||
private \Doctrine\Common\Collections\Collection $appellations;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->appellations = new ArrayCollection();
|
||||
// $this->appellation = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set libelle.
|
||||
*
|
||||
* @return Metier
|
||||
*/
|
||||
public function setLibelle(?string $libelle)
|
||||
{
|
||||
$this->libelle = $libelle;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get libelle.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLibelle()
|
||||
{
|
||||
return $this->libelle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set code.
|
||||
*
|
||||
* @return Metier
|
||||
*/
|
||||
public function setCode(?string $code)
|
||||
{
|
||||
$this->code = $code;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get code.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCode()
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
}
|
@@ -1,188 +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\JobBundle\Export;
|
||||
|
||||
use Chill\JobBundle\Entity\CSPerson;
|
||||
use Chill\PersonBundle\Export\Helper\CustomizeListPersonHelperInterface;
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* Class ListCSPerson.
|
||||
*
|
||||
* @author Mathieu Jaumotte mathieu.jaumotte@champs-libres.coop
|
||||
*/
|
||||
class AddCSPersonToPersonListHelper implements CustomizeListPersonHelperInterface
|
||||
{
|
||||
public function __construct(private readonly TranslatorInterface $translator) {}
|
||||
|
||||
private const CSPERSON_FIELDS = [
|
||||
'dateFinDernierEmploi',
|
||||
/* 'prescripteur__name',
|
||||
'prescripteur__email',
|
||||
'prescripteur__phone',*/
|
||||
'poleEmploiId',
|
||||
'cafId',
|
||||
'cafInscriptionDate',
|
||||
'dateContratIEJ',
|
||||
'cERInscriptionDate',
|
||||
'pPAEInscriptionDate',
|
||||
'pPAESignataire',
|
||||
'cERSignataire',
|
||||
'nEETCommissionDate',
|
||||
'fSEMaDemarcheCode',
|
||||
'enfantACharge',
|
||||
'nEETEligibilite',
|
||||
'situationProfessionnelle',
|
||||
];
|
||||
|
||||
public function alterKeys(array $existing): array
|
||||
{
|
||||
$ressources = array_map(static fn ($key) => 'ressources__'.$key, CSPerson::RESSOURCES);
|
||||
$moyenTransport = array_map(static fn ($key) => 'moyen_transport__'.$key, CSPerson::MOBILITE_MOYEN_TRANSPORT);
|
||||
$accompagnements = array_map(static fn ($key) => 'accompagnements__'.$key, CSPerson::ACCOMPAGNEMENTS);
|
||||
$permisConduire = array_map(static fn ($key) => 'permis_conduire__'.$key, CSPerson::PERMIS_CONDUIRE);
|
||||
$typeContrat = array_map(static fn ($key) => 'type_contrat__'.$key, CSPerson::TYPE_CONTRAT);
|
||||
|
||||
return [
|
||||
...$existing,
|
||||
...self::CSPERSON_FIELDS,
|
||||
...$ressources,
|
||||
...$moyenTransport,
|
||||
...$accompagnements,
|
||||
...$permisConduire,
|
||||
...$typeContrat,
|
||||
];
|
||||
}
|
||||
|
||||
public function alterSelect(QueryBuilder $qb, \DateTimeImmutable $computedDate): void
|
||||
{
|
||||
$qb
|
||||
->leftJoin(CSPerson::class, 'cs_person', Query\Expr\Join::WITH, 'cs_person.person = person');
|
||||
|
||||
foreach (self::CSPERSON_FIELDS as $f) {
|
||||
$qb->addSelect(sprintf('cs_person.%s as %s', $f, $f));
|
||||
}
|
||||
|
||||
/* $qb->addSelect('cs_person.situationProfessionnelle as situation_prof');
|
||||
|
||||
$qb->addSelect('cs_person.nEETEligibilite as nEETEligibilite');*/
|
||||
|
||||
$i = 0;
|
||||
|
||||
foreach (CSPerson::RESSOURCES as $key) {
|
||||
$qb->addSelect("JSONB_EXISTS_IN_ARRAY(cs_person.ressources, :param_{$i}) AS ressources__".$key)
|
||||
->setParameter('param_'.$i, $key);
|
||||
++$i;
|
||||
}
|
||||
|
||||
foreach (CSPerson::MOBILITE_MOYEN_TRANSPORT as $key) {
|
||||
$qb->addSelect("JSONB_EXISTS_IN_ARRAY(cs_person.mobiliteMoyenDeTransport, :param_{$i}) AS moyen_transport__".$key)
|
||||
->setParameter('param_'.$i, $key);
|
||||
++$i;
|
||||
}
|
||||
|
||||
foreach (CSPerson::TYPE_CONTRAT as $key) {
|
||||
$qb->addSelect("JSONB_EXISTS_IN_ARRAY(cs_person.typeContrat, :param_{$i}) AS type_contrat__".$key)
|
||||
->setParameter('param_'.$i, $key);
|
||||
++$i;
|
||||
}
|
||||
|
||||
foreach (CSPerson::ACCOMPAGNEMENTS as $key) {
|
||||
$qb->addSelect("JSONB_EXISTS_IN_ARRAY(cs_person.accompagnement, :param_{$i}) AS accompagnements__".$key)
|
||||
->setParameter('param_'.$i, $key);
|
||||
++$i;
|
||||
}
|
||||
|
||||
foreach (CSPerson::PERMIS_CONDUIRE as $key) {
|
||||
$qb->addSelect("JSONB_EXISTS_IN_ARRAY(cs_person.permisConduire, :param_{$i}) AS permis_conduire__".$key)
|
||||
->setParameter('param_'.$i, $key);
|
||||
++$i;
|
||||
}
|
||||
}
|
||||
|
||||
public function getLabels(string $key, array $values, array $data): ?callable
|
||||
{
|
||||
if (str_contains($key, '__')) {
|
||||
return function (string|bool|null $value) use ($key): string {
|
||||
if ('_header' === $value) {
|
||||
[$domain, $v] = explode('__', $key);
|
||||
|
||||
return 'export.list.cs_person.'.$domain.'.'.$v;
|
||||
}
|
||||
|
||||
if ('1' === $value || true === $value || 't' === $value) {
|
||||
return 'x';
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
}
|
||||
|
||||
return match ($key) {
|
||||
'nEETEligibilite' => function (string|bool|null $value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'export.list.cs_person.neet_eligibility';
|
||||
}
|
||||
|
||||
if ('1' === $value || true === $value || 't' === $value) {
|
||||
return 'x';
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
'situationProfessionnelle' => function ($value) {
|
||||
if ('_header' === $value) {
|
||||
return 'export.list.cs_person.situation_professionelle';
|
||||
}
|
||||
|
||||
return $value;
|
||||
},
|
||||
'cerinscriptiondate', 'ppaeinscriptiondate', 'neetcommissiondate', 'findernieremploidate', 'cafinscriptiondate', 'contratiejdate' => function ($value) use ($key) {
|
||||
if ('_header' === $value) {
|
||||
return $this->translator->trans($key);
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
// warning: won't work with DateTimeImmutable as we reset time a few lines later
|
||||
$date = \DateTime::createFromFormat('Y-m-d', $value);
|
||||
$hasTime = false;
|
||||
|
||||
if (false === $date) {
|
||||
$date = \DateTime::createFromFormat('Y-m-d H:i:s', $value);
|
||||
$hasTime = true;
|
||||
}
|
||||
|
||||
// check that the creation could occur.
|
||||
if (false === $date) {
|
||||
throw new \Exception(sprintf('The value %s could not be converted to %s', $value, \DateTime::class));
|
||||
}
|
||||
|
||||
if (!$hasTime) {
|
||||
$date->setTime(0, 0, 0);
|
||||
}
|
||||
|
||||
return $date;
|
||||
},
|
||||
default => function ($value) use ($key) {
|
||||
if ('_header' === $value) {
|
||||
return $this->translator->trans($key);
|
||||
}
|
||||
|
||||
return $value;
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user