Selaa lähdekoodia

Merge branch 'release/0.2.0'

Olivier Massot 4 vuotta sitten
vanhempi
commit
aa4d04d81e
100 muutettua tiedostoa jossa 4063 lisäystä ja 1732 poistoa
  1. 10 1
      .env
  2. 24 0
      .env.preprod
  3. 24 0
      .env.prod
  4. 6 0
      .gitignore
  5. 30 0
      .gitlab-ci.yml
  6. 4 4
      composer.json
  7. 167 285
      composer.lock
  8. BIN
      composer.phar
  9. 6 6
      config/opentalent/enum.yaml
  10. 11 11
      config/opentalent/modulesbyconditions.yaml
  11. 10 4
      config/opentalent/products.yaml
  12. 29 12
      config/packages/doctrine.yaml
  13. 11 0
      config/packages/framework.yaml
  14. 1 1
      config/packages/nelmio_cors.yaml
  15. 7 9
      config/packages/security.yaml
  16. 29 8
      config/services.yaml
  17. 0 14
      config/services/apiPlatform.yaml
  18. 0 18
      config/services/controlers.yaml
  19. 0 13
      config/services/services.yaml
  20. BIN
      logo.png
  21. 4 0
      readme.md
  22. 7 0
      src/ApiResources/ApiResourcesInterface.php
  23. 68 0
      src/ApiResources/Cotisation/Cotisation.php
  24. 150 0
      src/ApiResources/Dolibarr/DolibarrAccount.php
  25. 137 0
      src/ApiResources/Dolibarr/DolibarrBill.php
  26. 88 0
      src/ApiResources/Dolibarr/DolibarrContract.php
  27. 121 0
      src/ApiResources/Dolibarr/DolibarrContractLine.php
  28. 17 19
      src/ApiResources/Enum/Enum.php
  29. 84 0
      src/ApiResources/Mobyt/MobytUserStatus.php
  30. 201 22
      src/ApiResources/Profile/AccessProfile.php
  31. 67 18
      src/ApiResources/Profile/OrganizationProfile.php
  32. 137 0
      src/ApiResources/Utils/GpsCoordinate.php
  33. 17 17
      src/ApiResources/Utils/Siret.php
  34. 0 49
      src/Controller/EsController.php
  35. 49 0
      src/Controller/EsController.php.ori
  36. 19 0
      src/DQL/DateConditions.php
  37. 15 70
      src/DataProvider/Access/AccessProfileDataProvider.php
  38. 34 0
      src/DataProvider/Cotisation/CotisationDataProvider.php
  39. 32 0
      src/DataProvider/Dolibarr/DolibarrAccountDataProvider.php
  40. 10 24
      src/DataProvider/Enum/EnumDataProvider.php
  41. 31 0
      src/DataProvider/Mobyt/MobytUserStatusDataProvider.php
  42. 62 0
      src/DataProvider/Utils/GpsCoordinateSearchingDataProvider.php
  43. 6 10
      src/DataProvider/Utils/SiretDataProvider.php
  44. 6 9
      src/Doctrine/Access/AccessExtension.php
  45. 11 0
      src/Doctrine/Access/AccessExtensionInterface.php
  46. 21 0
      src/Doctrine/Access/Extensions/AdminExtension.php
  47. 20 0
      src/Doctrine/Access/Extensions/StudentsExtension.php
  48. 19 0
      src/Doctrine/Access/HandleAccessExtension.php
  49. 44 0
      src/Doctrine/Access/PersonalizedListExtension.php
  50. 54 0
      src/Doctrine/Core/NotificationExtension.php
  51. 50 0
      src/Doctrine/Core/NotificationUserExtension.php
  52. 409 100
      src/Entity/Access/Access.php
  53. 71 0
      src/Entity/Access/FunctionType.php
  54. 61 34
      src/Entity/Access/OrganizationFunction.php
  55. 147 0
      src/Entity/Access/PersonalizedList.php
  56. 30 0
      src/Entity/Billing/AbstractBillingIntangible.php
  57. 30 0
      src/Entity/Billing/AbstractBillingPayer.php
  58. 31 0
      src/Entity/Billing/AccessIntangible.php
  59. 49 0
      src/Entity/Billing/AccessPayer.php
  60. 35 60
      src/Entity/Core/AddressPostal.php
  61. 50 79
      src/Entity/Core/BankAccount.php
  62. 60 82
      src/Entity/Core/ContactPoint.php
  63. 10 15
      src/Entity/Core/Country.php
  64. 117 0
      src/Entity/Core/File.php
  65. 174 0
      src/Entity/Core/Notification.php
  66. 82 0
      src/Entity/Core/NotificationUser.php
  67. 15 24
      src/Entity/Network/Network.php
  68. 23 30
      src/Entity/Network/NetworkOrganization.php
  69. 169 275
      src/Entity/Organization/Organization.php
  70. 20 30
      src/Entity/Organization/OrganizationAddressPostal.php
  71. 27 40
      src/Entity/Organization/OrganizationLicence.php
  72. 117 181
      src/Entity/Organization/Parameters.php
  73. 25 39
      src/Entity/Organization/Settings.php
  74. 56 62
      src/Entity/Person/Person.php
  75. 12 50
      src/Entity/Person/PersonActivity.php
  76. 34 0
      src/Entity/Traits/ActivityPeriodTrait.php
  77. 35 0
      src/Entity/Traits/ActivityYearTrait.php
  78. 23 0
      src/Enum/Access/DeparturesCauseEnum.php
  79. 103 0
      src/Enum/Access/FunctionEnum.php
  80. 24 0
      src/Enum/Access/RoleEnum.php
  81. 18 0
      src/Enum/Access/TypeFunctionEnum.php
  82. 2 5
      src/Enum/Core/ContactPointTypeEnum.php
  83. 19 0
      src/Enum/Core/NotificationTypeEnum.php
  84. 2 2
      src/Enum/Core/TimeZoneEnum.php
  85. 17 0
      src/Enum/Cotisation/AlertStateEnum.php
  86. 1 0
      src/Enum/Education/PeriodicityEnum.php
  87. 1 0
      src/Enum/Network/LeadingCauseEnum.php
  88. 1 0
      src/Enum/Network/NetworkEnum.php
  89. 2 0
      src/Enum/Organization/AddressPostalOrganizationTypeEnum.php
  90. 1 0
      src/Enum/Organization/BulletinOutputEnum.php
  91. 1 0
      src/Enum/Organization/BulletinPeriodEnum.php
  92. 1 0
      src/Enum/Organization/CategoryEnum.php
  93. 1 0
      src/Enum/Organization/LegalEnum.php
  94. 1 0
      src/Enum/Organization/OpcaEnum.php
  95. 1 0
      src/Enum/Organization/OrganizationIdsEnum.php
  96. 1 0
      src/Enum/Organization/PrincipalTypeEnum.php
  97. 1 0
      src/Enum/Organization/SchoolCategoryEnum.php
  98. 1 0
      src/Enum/Organization/SendToBulletinEnum.php
  99. 1 0
      src/Enum/Organization/SettingsProductEnum.php
  100. 1 0
      src/Enum/Organization/TypeEstablishmentDetailEnum.php

+ 10 - 1
.env

@@ -41,4 +41,13 @@ JWT_PASSPHRASE=opentalent
 
 ###> opentalent config folder ###
 OPENTALENT_CONFIG=/config/opentalent
-###< opentalent config folder ###
+###< opentalent config folder ###
+
+###> dolibarr client ###
+DOLIBARR_API_BASE_URI='https://prod-erp.2iopenservice.com/api/index.php/'
+DOLIBARR_API_TOKEN='Bocc4zC0J186v8J6QCqu7DnoIw4I7mCJ'
+###< dolibarr client ###
+
+###> mobyt client ###
+MOBYT_API_BASE_URI='https://app.mobyt.fr/API/v1.0/REST/'
+###< mobyt client ###

+ 24 - 0
.env.preprod

@@ -0,0 +1,24 @@
+###> symfony/framework-bundle ###
+APP_ENV=prod
+APP_DEBUG=1
+APP_SECRET=6a76497c8658bb23e2236f97a2627df3
+#TRUSTED_PROXIES=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
+#TRUSTED_HOSTS='^(localhost|example\.com)$'
+###< symfony/framework-bundle ###
+
+###> doctrine/doctrine-bundle ###
+# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
+# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
+DATABASE_URL=mysql://root:mysql2iopenservice369566@preprod.2iopenservice.com:3306/opentalent?serverVersion=5.7
+###< doctrine/doctrine-bundle ###
+
+###> nelmio/cors-bundle ###
+CORS_ALLOW_ORIGIN=^https?://(localhost|127\.0\.0\.1)(:[0-9]+)$
+###< nelmio/cors-bundle ###
+
+###> BlackFire configuration ###
+BLACKFIRE_CLIENT_ID=988fcba8-552d-48df-a9c2-035c76535b69
+BLACKFIRE_CLIENT_TOKEN=8cfbeb263d044da9678dc2612531504da3790c308da7448e35724a5da91c136f
+BLACKFIRE_SERVER_ID=1171e53b-459b-41da-a292-80ff68cee8c2
+BLACKFIRE_SERVER_TOKEN=dbd1cfbea015fe83cccfc189a36ca3c16f3a1b43b94f50032a15e41e53548e8b
+###< BlackFire configuration ###

+ 24 - 0
.env.prod

@@ -0,0 +1,24 @@
+###> symfony/framework-bundle ###
+APP_ENV=prod
+APP_DEBUG=0
+APP_SECRET=6a76497c8658bb23e2236f97a2627df3
+#TRUSTED_PROXIES=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
+#TRUSTED_HOSTS='^(localhost|example\.com)$'
+###< symfony/framework-bundle ###
+
+###> doctrine/doctrine-bundle ###
+# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
+# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
+DATABASE_URL=mysql://root:mysql2iopenservice369566@prod-back:3306/opentalent?serverVersion=5.7
+###< doctrine/doctrine-bundle ###
+
+###> nelmio/cors-bundle ###
+CORS_ALLOW_ORIGIN=^https?://(localhost|127\.0\.0\.1)(:[0-9]+)$
+###< nelmio/cors-bundle ###
+
+###> BlackFire configuration ###
+BLACKFIRE_CLIENT_ID=988fcba8-552d-48df-a9c2-035c76535b69
+BLACKFIRE_CLIENT_TOKEN=8cfbeb263d044da9678dc2612531504da3790c308da7448e35724a5da91c136f
+BLACKFIRE_SERVER_ID=1171e53b-459b-41da-a292-80ff68cee8c2
+BLACKFIRE_SERVER_TOKEN=dbd1cfbea015fe83cccfc189a36ca3c16f3a1b43b94f50032a15e41e53548e8b
+###< BlackFire configuration ###

+ 6 - 0
.gitignore

@@ -24,7 +24,13 @@
 
 ###> phpdocs ###
 src/.phpdoc/
+coverage/*
 ###< phpdocs ###
 /.project
 
 symfony.lock
+
+###> phpunit/phpunit ###
+/phpunit.xml
+.phpunit.result.cache
+###< phpunit/phpunit ###

+ 30 - 0
.gitlab-ci.yml

@@ -0,0 +1,30 @@
+stages:
+  - test
+
+before_script:
+  - curl -sS https://composer.github.io/installer.sig > installer.sig
+  - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
+  - php -r "if (hash_file('SHA384', 'composer-setup.php') === file_get_contents('installer.sig')) { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
+  - php composer-setup.php
+  - php -r "unlink('composer-setup.php'); unlink('installer.sig');"
+
+cache:
+  paths:
+    - ./vendor
+
+unit:otcore:
+  stage: test
+
+  script:
+    - php composer.phar --quiet --no-interaction install
+    - ./bin/phpunit -c ./Tests/Build/UnitTests.xml --coverage-text --colors=never
+
+  artifacts:
+    paths:
+      - ./coverage/
+    when: always
+    reports:
+      junit: ./coverage/junit-report.xml
+
+  coverage: '/^\s*Lines:\s*\d+.\d+\%/'
+

+ 4 - 4
composer.json

@@ -8,16 +8,15 @@
         }
     ],
     "require": {
-        "php": ">=7.2.5",
+        "php": ">=8.0",
         "ext-ctype": "*",
         "ext-iconv": "*",
         "api-platform/core": "^2.6",
         "blackfire/php-sdk": "^1.23",
         "composer/package-versions-deprecated": "^1.11",
-        "doctrine/annotations": "^1.0",
         "doctrine/doctrine-bundle": "^2.1",
         "doctrine/doctrine-migrations-bundle": "^3.0",
-        "doctrine/orm": "^2.7",
+        "doctrine/orm": "^2.9",
         "egulias/email-validator": "^3.0",
         "jbouzekri/phumbor-bundle": "^2.1",
         "lexik/jwt-authentication-bundle": "^2.8",
@@ -40,10 +39,11 @@
         "symfony/twig-bundle": "^5.3",
         "symfony/validator": "5.3.*",
         "symfony/yaml": "5.3.*",
-        "vincent/foselastica": "1.1",
+        "vincent/foselastica": "1.2",
         "webonyx/graphql-php": "^14.3"
     },
     "require-dev": {
+        "cyclonedx/cyclonedx-php-composer": "^3.4",
         "symfony/maker-bundle": "^1.21",
         "symfony/phpunit-bridge": "^5.3",
         "symfony/stopwatch": "^5.3",

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 167 - 285
composer.lock


BIN
composer.phar


+ 6 - 6
config/opentalent/enum.yaml

@@ -52,13 +52,13 @@ opentalent:
 
   #Organization
     organization_category: 'App\Enum\Organization\CategoryEnum'
-    organization_financial: 'App\Enum\Organization\financialEnum'
+    organization_financial: 'App\Enum\Organization\FinancialEnum'
     organization_legal: 'App\Enum\Organization\LegalEnum'
-    organization_opca: 'App\Enum\Organization\opcaEnum'
-    organization_principal_type: 'App\Enum\Organization\principalTypeEnum'
-    organization_school_cat: 'App\Enum\Organization\schoolCategoryEnum'
-    organization_type_establishment_detail: 'App\Enum\Organization\typeEstablishmentDetailEnum'
-    organization_type_establishment: 'App\Enum\Organization\typeEstablishmentEnum'
+    organization_opca: 'App\Enum\Organization\OpcaEnum'
+    organization_principal_type: 'App\Enum\Organization\PrincipalTypeEnum'
+    organization_school_cat: 'App\Enum\Organization\SchoolCategoryEnum'
+    organization_type_establishment_detail: 'App\Enum\Organization\TypeEstablishmentDetailEnum'
+    organization_type_establishment: 'App\Enum\Organization\TypeEstablishmentEnum'
     organization_familly_type: 'App\Enum\Organization\FamillyTypeEnum'
     organization_sub_familly_type: 'App\Enum\Organization\SubFamillyTypeEnum'
     organization_bulletin_period: 'App\Enum\Organization\BulletinPeriodEnum'

+ 11 - 11
config/opentalent/modulesbyconditions.yaml

@@ -5,67 +5,67 @@ opentalent:
                 - ROLE_COTISATION
             conditions:
                 service:
-                    name: opentalent.cotisation.utils
+                    name: App\Service\Cotisation\Utils
                     function: isLastParentAndCMF
         CotisationStructure:
             roles:
                 - ROLE_COTISATION
             conditions:
                 service:
-                    name: opentalent.cotisation.utils
+                    name: App\Service\Cotisation\Utils
                     function: isStructureAndCMF
         CotisationRate:
             roles:
                 - ROLE_COTISATION
             conditions:
                 service:
-                    name: opentalent.cotisation.utils
+                    name: App\Service\Cotisation\Utils
                     function: isManagerAndLastParentAndCMF
         CotisationTransmissionState:
             roles:
                 - ROLE_COTISATION
             conditions:
                 service:
-                    name: opentalent.cotisation.utils
+                    name: App\Service\Cotisation\Utils
                     function: isManagerAndCMF
         CotisationTransmission:
             roles:
                 - ROLE_COTISATION
             conditions:
                 service:
-                    name: opentalent.cotisation.utils
+                    name: App\Service\Cotisation\Utils
                     function: isManagerAndNotLastParentAndCMF
         CotisationCMFAdministration:
             roles:
                 - ROLE_COTISATION
             conditions:
                 service:
-                    name: opentalent.organization.utils
+                    name: App\Service\Organization\Utils
                     function: isOrganizationIsCMF
         Admin2IOS:
             roles:
                 - ROLE_ADMIN2IOS
             conditions:
                 service:
-                    name: opentalent.organization.utils
+                    name: App\Service\Organization\Utils
                     function: isOrganizationIs2ios
         StatisticFederation:
             conditions:
                 service:
-                    name: opentalent.cotisation.utils
+                    name: App\Service\Cotisation\Utils
                     function: isManagerAndNotLastParentAndCMF
         StatisticStructure:
             conditions:
                 service:
-                    name: opentalent.cotisation.utils
+                    name: App\Service\Cotisation\Utils
                     function: isManagerAndCMF
         Network:
             conditions:
                 service:
-                    name: opentalent.network.utils
+                    name: App\Service\Network\Utils
                     function: isCMF
         NetworkOrganization:
             conditions:
                 service:
-                    name: opentalent.network.utils
+                    name: App\Service\Network\Utils
                     function: isCMF

+ 10 - 4
config/opentalent/products.yaml

@@ -103,6 +103,10 @@ opentalent:
         roles:
           - ROLE_MAILS
 
+      TemplateMessages:
+        entities:
+          - TemplateSystem
+
       Tagg:
         entities:
           - Tagg
@@ -206,6 +210,11 @@ opentalent:
           actions:
             - EvaluateStudents
 
+      AdvancedEducationNotation:
+        entities:
+          - EducationNotationConfig
+          - EducationNotationCriteriaConfig
+
       BillingAdministration:
           entities:
             - Intangible
@@ -281,10 +290,6 @@ opentalent:
         roles:
           - ROLE_STATISTIC
 
-      ViewAudit:
-          entities:
-            - ViewAudit
-
       NetworkOrganization:
           entities:
             - NetworkOrganization
@@ -333,6 +338,7 @@ opentalent:
           - Attendances
           - UsersSchool
           - BillingAdministration
+          - TemplateMessages
 
       school_premium:
         extend: school

+ 29 - 12
config/packages/doctrine.yaml

@@ -1,17 +1,34 @@
 doctrine:
     dbal:
-        url: '%env(resolve:DATABASE_URL)%'
+        default_connection: default
+        connections:
+            default:
+                url: '%env(resolve:DATABASE_URL)%'
+
+                # IMPORTANT: You MUST configure your server version,
+                # either here or in the DATABASE_URL env var (see .env file)
+                server_version: '5.7'
+
+            adminassos:
+                url: '%env(resolve:DATABASE_ADMINASSOS_URL)%'
+
+                # IMPORTANT: You MUST configure your server version,
+                # either here or in the DATABASE_URL env var (see .env file)
+                server_version: '5.7'
 
-        # IMPORTANT: You MUST configure your server version,
-        # either here or in the DATABASE_URL env var (see .env file)
-        server_version: '5.7'
     orm:
+        default_entity_manager: default
         auto_generate_proxy_classes: true
-        auto_mapping: true
-        mappings:
-            App:
-                is_bundle: false
-                type: annotation
-                dir: '%kernel.project_dir%/src/Entity'
-                prefix: 'App\Entity'
-                alias: App
+        entity_managers:
+            default:
+                connection: default
+                auto_mapping: true
+                mappings:
+                    App:
+                        is_bundle: false
+                        type: attribute
+                        dir: '%kernel.project_dir%/src/Entity'
+                        prefix: 'App\Entity'
+                        alias: App
+            adminassos:
+                connection: adminassos

+ 11 - 0
config/packages/framework.yaml

@@ -20,3 +20,14 @@ framework:
         scoped_clients:
             siret_checking:
                 base_uri: 'https://entreprise.data.gouv.fr/api/sirene/v3/etablissements/'
+            openstreetmap:
+                base_uri: 'https://nominatim.openstreetmap.org/'
+            dolibarr_client:
+                base_uri: '%env(DOLIBARR_API_BASE_URI)%'
+                headers:
+                    DOLAPIKEY: '%env(DOLIBARR_API_TOKEN)%'
+                    Accept: 'application/json'
+            mobyt_client:
+                base_uri: '%env(MOBYT_API_BASE_URI)%'
+                headers:
+                    Content-Type: 'application/json'

+ 1 - 1
config/packages/nelmio_cors.yaml

@@ -3,7 +3,7 @@ nelmio_cors:
         origin_regex: true
         allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
         allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']
-        allow_headers: ['Content-Type', 'Authorization', 'x-accessid']
+        allow_headers: ['Content-Type', 'Authorization', 'x-accessid', 'x-switch-user']
         expose_headers: ['Link']
         max_age: 3600
     paths:

+ 7 - 9
config/packages/security.yaml

@@ -134,6 +134,8 @@ security:
                 class: App\Entity\Person\Person
                 property: username
 
+    enable_authenticator_manager: true
+
     firewalls:
         dev:
             pattern: ^/(_(profiler|wdt)|css|images|js)/
@@ -142,7 +144,6 @@ security:
         login:
             pattern:  ^/login_check
             stateless: true
-            anonymous: true
             json_login:
                 provider: person_provider
                 check_path: /login_check
@@ -151,21 +152,18 @@ security:
                 success_handler: lexik_jwt_authentication.handler.authentication_success
                 failure_handler: lexik_jwt_authentication.handler.authentication_failure
         api:
+            jwt: ~
             pattern: ^/api/
             stateless: true
-            anonymous: true
             provider: access_provider
-            guard:
-                authenticators:
-                - lexik_jwt_authentication.jwt_token_authenticator
+            switch_user:
+                role: CAN_SWITCH_USER
+                parameter: X-Switch-User
+
         main:
-            anonymous: true
             # activate different ways to authenticate
             # https://symfony.com/doc/current/security.html#firewalls-authentication
 
-            # https://symfony.com/doc/current/security/impersonating_user.html
-            # switch_user: true
-
     # Easy way to control access for large sections of your site
     # Note: Only the *first* access control that matches will be used
     access_control:

+ 29 - 8
config/services.yaml

@@ -1,8 +1,3 @@
-# This file is the entry point to configure your own services.
-# Files in the packages/ subdirectory configure your dependencies.
-imports:
-    - { resource: services/* }
-
 # Put parameters here that don't need to change on each machine where the app is deployed
 # https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
 parameters:
@@ -24,6 +19,32 @@ services:
             - '../src/Entity/'
             - '../src/Kernel.php'
             - '../src/Tests/'
-            - '../src/Controller/'
-            - '../src/DataProvider/'
-            - '../src/Serializer/'
+
+    App\Service\Cotisation\Utils:
+        public: true
+
+    App\Service\Network\Utils:
+        public: true
+
+    App\Service\Organization\Utils:
+        public: true
+
+    #########################################
+    ##  TAG Services ##
+    _instanceof:
+        App\Doctrine\Access\AccessExtensionInterface:
+            tags: ['app.extensions.access']
+        App\Service\Access\OptionalsRolesInterface:
+            tags: ['app.optionalsroles']
+
+    App\Doctrine\Access\HandleAccessExtension:
+        - !tagged_iterator app.extensions.access
+    App\Service\Access\HandleOptionalsRoles:
+        - !tagged_iterator app.optionalsroles
+
+    #########################################
+    ##  SERIALIZER Decorates ##
+    App\Serializer\AccessContextBuilder:
+        decorates: 'api_platform.serializer.context_builder'
+        arguments: [ '@App\Serializer\AccessContextBuilder.inner' ]
+        autoconfigure: false

+ 0 - 14
config/services/apiPlatform.yaml

@@ -1,14 +0,0 @@
-services:
-  # default configuration for services in *this* file
-  _defaults:
-    autowire: true      # Automatically injects dependencies in your services.
-    autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
-    public: false
-    bind:
-      $opentalentConfig: '%kernel.project_dir%%env(OPENTALENT_CONFIG)%'
-
-  App\DataProvider\:
-    resource: '../../src/DataProvider/'
-
-  App\Serializer\OpentalentNormalizer:
-    decorates: 'api_platform.jsonld.normalizer.item'

+ 0 - 18
config/services/controlers.yaml

@@ -1,18 +0,0 @@
-services:
-  # default configuration for services in *this* file
-  _defaults:
-    autowire: true      # Automatically injects dependencies in your services.
-    autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
-
-  # controllers are imported separately to make sure services can be injected
-  # as action arguments even if you don't extend any base controller class
-  App\Controller\:
-    resource: '../../src/Controller/'
-    tags: ['controller.service_arguments']
-
-  App\Controller\EsController:
-    tags: ['controller.service_arguments']
-    public: true
-    arguments:
-      - '@fos_elastica.index_manager'
-      - '@fos_elastica.elastica_to_model_transformer.collection.search'

+ 0 - 13
config/services/services.yaml

@@ -1,13 +0,0 @@
-services:
-  opentalent.cotisation.utils:
-    class: App\Service\Cotisation\Utils
-    public: true
-    autowire: true
-  opentalent.network.utils:
-    class: App\Service\Network\Utils
-    public: true
-    autowire: true
-  opentalent.organization.utils:
-    class: App\Service\Organization\Utils
-    public: true
-    autowire: true

BIN
logo.png


+ 4 - 0
readme.md

@@ -0,0 +1,4 @@
+# AP2I
+
+[![pipeline status](http://gitlab.2iopenservice.com/opentalent/api/badges/master/pipeline.svg)](http://gitlab.2iopenservice.com/opentalent/api/-/commits/master)
+[![coverage report](http://gitlab.2iopenservice.com/opentalent/api/badges/master/coverage.svg)](http://gitlab.2iopenservice.com/opentalent/api/-/commits/master)

+ 7 - 0
src/ApiResources/ApiResourcesInterface.php

@@ -0,0 +1,7 @@
+<?php
+declare(strict_types=1);
+
+namespace App\ApiResources;
+
+interface ApiResourcesInterface{
+}

+ 68 - 0
src/ApiResources/Cotisation/Cotisation.php

@@ -0,0 +1,68 @@
+<?php
+declare(strict_types=1);
+
+namespace App\ApiResources\Cotisation;
+
+use ApiPlatform\Core\Annotation\ApiProperty;
+use ApiPlatform\Core\Annotation\ApiResource;
+use App\ApiResources\ApiResourcesInterface;
+use Symfony\Component\Serializer\Annotation\Groups;
+use Symfony\Component\Validator\Constraints as Assert;
+
+/**
+ * Classe resource qui contient les informations des cotisations de la 5.9
+ */
+#[ApiResource(
+    collectionOperations:[],
+    itemOperations: [
+        'get' => [
+            'method' => 'GET',
+            'path' => '/cotisations/{organizationId}',
+            'security' => 'is_granted("COTISATION_CALL", object)',
+        ]
+    ]
+)]
+class Cotisation implements ApiResourcesInterface
+{
+    #[ApiProperty(identifier: true)]
+    private int $organizationId;
+
+    #[Assert\Choice(callback: ['\App\Enum\Cotisation\AlertStateEnum', 'toArray'], message: 'invalid-alert-state-enum')]
+    private ?string $alertState = null;
+
+    private ?int $cotisationYear = null;
+
+    public function getOrganizationId(): ?int
+    {
+        return $this->organizationId;
+    }
+
+    public function setOrganizationId(?int $organizationId): self
+    {
+        $this->organizationId = $organizationId;
+        return $this;
+    }
+
+    public function getAlertState(): ?string
+    {
+        return $this->alertState;
+    }
+
+    public function setAlertState(?string $alertState): self
+    {
+        $this->alertState = $alertState;
+        return $this;
+    }
+
+    public function getCotisationYear(): ?int
+    {
+        return $this->cotisationYear;
+    }
+
+    public function setCotisationYear(?int $cotisationYear): self
+    {
+        $this->cotisationYear = $cotisationYear;
+
+        return $this;
+    }
+}

+ 150 - 0
src/ApiResources/Dolibarr/DolibarrAccount.php

@@ -0,0 +1,150 @@
+<?php
+declare(strict_types=1);
+
+namespace App\ApiResources\Dolibarr;
+
+use ApiPlatform\Core\Annotation\ApiProperty;
+use ApiPlatform\Core\Annotation\ApiResource;
+use App\ApiResources\ApiResourcesInterface;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
+use JetBrains\PhpStorm\Pure;
+use Symfony\Component\Serializer\Annotation\Groups;
+
+/**
+ * Données de l'organization retournées par l'API Dolibarr
+ * (aussi nommé 'ThirdParty' ou 'Society' dans dolibarr)
+ */
+#[ApiResource(
+    collectionOperations:[],
+    itemOperations: [
+        'get' => [
+            'security' => '(is_granted("ROLE_ADMIN_CORE") or 
+                            is_granted("ROLE_ADMINISTRATIF_MANAGER_CORE") or 
+                            is_granted("ROLE_PEDAGOGICS_MANAGER_CORE") or 
+                            is_granted("ROLE_FINANCIAL_MANAGER_CORE")
+                           ) and object.getOrganizationId() == user.getOrganization().getId()',
+            'method' => 'GET',
+            'path' => '/dolibarr/account/{organizationId}',
+            'requirements' => ['organizationId' => '\d+'],
+            'normalization_context' => [
+                'groups' => ['dolibarr_get']
+            ],
+        ],
+    ],
+    compositeIdentifier: false,
+)]
+class DolibarrAccount implements ApiResourcesInterface
+{
+    #[ApiProperty(identifier: true)]
+    #[Groups('dolibarr_get')]
+    private int $organizationId;
+
+    /**
+     * Dolibarr societies pk
+     */
+    #[Groups('dolibarr_get')]
+    private int $socId;
+
+    /**
+     * Opentalent client ref
+     */
+    #[Groups('dolibarr_get')]
+    private string $clientNumber = "";
+
+    /**
+     * Opentalent product owned
+     */
+    #[Groups('dolibarr_get')]
+    private string $product = "";
+
+    /**
+     * Contract and services currently active
+     */
+    #[Groups('dolibarr_get')]
+    private ?DolibarrContract $contract = null;
+
+    /**
+     * Last bills
+     */
+    #[Groups('dolibarr_get')]
+    private Collection $bills;
+
+    #[Pure]
+    public function __construct()
+    {
+        $this->bills = new ArrayCollection();
+    }
+
+    public function getOrganizationId(): int
+    {
+        return $this->organizationId;
+    }
+
+    public function setOrganizationId(int $organizationId): self
+    {
+        $this->organizationId = $organizationId;
+        return $this;
+    }
+
+    public function getSocId(): int
+    {
+        return $this->socId;
+    }
+
+    public function setSocId(int $socId): self
+    {
+        $this->socId = $socId;
+        return $this;
+    }
+
+    public function getClientNumber(): string
+    {
+        return $this->clientNumber;
+    }
+
+    public function setClientNumber(string $clientNumber): self
+    {
+        $this->clientNumber = $clientNumber;
+        return $this;
+    }
+
+    public function getProduct(): string
+    {
+        return $this->product;
+    }
+
+    public function setProduct(string $product): self
+    {
+        $this->product = $product;
+        return $this;
+    }
+
+    public function getContract(): ?object
+    {
+        return $this->contract;
+    }
+
+    public function setContract(?object $contract): self
+    {
+        $this->contract = $contract;
+        return $this;
+    }
+
+    public function getBills(): Collection
+    {
+        return $this->bills;
+    }
+
+    public function addBill(DolibarrBill $bill): self
+    {
+        $this->bills[] = $bill;
+        return $this;
+    }
+
+    public function removeBill(DolibarrBill $bill): self
+    {
+        $this->bills->removeElement($bill);
+        return $this;
+    }
+}

+ 137 - 0
src/ApiResources/Dolibarr/DolibarrBill.php

@@ -0,0 +1,137 @@
+<?php
+declare(strict_types=1);
+
+namespace App\ApiResources\Dolibarr;
+
+use ApiPlatform\Core\Annotation\ApiProperty;
+use ApiPlatform\Core\Annotation\ApiResource;
+use App\ApiResources\ApiResourcesInterface;
+use Symfony\Component\Serializer\Annotation\Groups;
+
+/**
+ * Bill of a society, retrieved from dolibarr
+ */
+#[ApiResource(
+    collectionOperations:[],
+    itemOperations: [
+        'get'
+    ]
+)]
+class DolibarrBill implements ApiResourcesInterface
+{
+    /**
+     * Id of the dolibarr bill ( = invoice)
+     */
+    #[ApiProperty(identifier: true)]
+    #[Groups('dolibarr_get')]
+    private int $id;
+
+    /**
+     * Bill reference
+     */
+    #[Groups('dolibarr_get')]
+    private string $ref;
+
+    /**
+     * Date of the bill
+     */
+    #[Groups('dolibarr_get')]
+    private \DateTime $date;
+
+    /**
+     * Amount (tax excluded)
+     */
+    #[Groups('dolibarr_get')]
+    private float $taxExcludedAmount;
+
+    /**
+     * Amount (tax included)
+     */
+    #[Groups('dolibarr_get')]
+    private float $taxIncludedAmount;
+
+    /**
+     * Is the bill paid or not
+     */
+    #[Groups('dolibarr_get')]
+    private bool $paid;
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): self
+    {
+        $this->id = $id;
+        return $this;
+    }
+
+    public function getRef(): string
+    {
+        return $this->ref;
+    }
+
+    public function setRef(string $ref): self
+    {
+        $this->ref = $ref;
+        return $this;
+    }
+
+    public function getDate(): \DateTime
+    {
+        return $this->date;
+    }
+
+    public function setDate(\DateTime $date): self
+    {
+        $this->date = $date;
+        return $this;
+    }
+
+    /**
+     * @return float
+     */
+    public function getTaxExcludedAmount(): float
+    {
+        return $this->taxExcludedAmount;
+    }
+
+    /**
+     * @param float $taxExcludedAmount
+     */
+    public function setTaxExcludedAmount(float $taxExcludedAmount): self
+    {
+        $this->taxExcludedAmount = $taxExcludedAmount;
+        return $this;
+    }
+
+    /**
+     * @return float
+     */
+    public function getTaxIncludedAmount(): float
+    {
+        return $this->taxIncludedAmount;
+    }
+
+    /**
+     * @param float $taxIncludedAmount
+     */
+    public function setTaxIncludedAmount(float $taxIncludedAmount): self
+    {
+        $this->taxIncludedAmount = $taxIncludedAmount;
+        return $this;
+    }
+
+    public function getPaid(): bool
+    {
+        return $this->paid;
+    }
+
+    public function setPaid(bool $paid): self
+    {
+        $this->paid = $paid;
+        return $this;
+    }
+
+}

+ 88 - 0
src/ApiResources/Dolibarr/DolibarrContract.php

@@ -0,0 +1,88 @@
+<?php
+declare(strict_types=1);
+
+namespace App\ApiResources\Dolibarr;
+
+use ApiPlatform\Core\Annotation\ApiProperty;
+use ApiPlatform\Core\Annotation\ApiResource;
+use App\ApiResources\ApiResourcesInterface;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
+use JetBrains\PhpStorm\Pure;
+use Symfony\Component\Serializer\Annotation\Groups;
+
+/**
+ * Contract of a society, retrieved from dolibarr
+ */
+#[ApiResource(
+    collectionOperations:[],
+    itemOperations: [
+        'get'
+    ]
+)]
+class DolibarrContract implements ApiResourcesInterface
+{
+    /**
+     * Reference of the dolibarr contract
+     */
+    #[ApiProperty(identifier: true)]
+    #[Groups('dolibarr_get')]
+    private string $ref;
+
+    /**
+     * Id of the society
+     */
+    #[Groups('dolibarr_get')]
+    private int $socId;
+
+    /**
+     * Lines (services) included in the current contract
+     */
+    #[Groups('dolibarr_get')]
+    private Collection $lines;
+
+    #[Pure]
+    public function __construct()
+    {
+        $this->lines = new ArrayCollection();
+    }
+
+    public function getRef(): string
+    {
+        return $this->ref;
+    }
+
+    public function setRef(string $ref): self
+    {
+        $this->ref = $ref;
+        return $this;
+    }
+
+    public function getSocId(): int
+    {
+        return $this->socId;
+    }
+
+    public function setSocId(int $socId): self
+    {
+        $this->socId = $socId;
+        return $this;
+    }
+
+    public function getLines(): Collection
+    {
+        return $this->lines;
+    }
+
+    public function addLine(DolibarrContractLine $line): self
+    {
+        $this->lines[] = $line;
+        return $this;
+    }
+
+    public function removeBill(DolibarrContractLine $line): self
+    {
+        $this->lines->removeElement($line);
+        return $this;
+    }
+}

+ 121 - 0
src/ApiResources/Dolibarr/DolibarrContractLine.php

@@ -0,0 +1,121 @@
+<?php
+declare(strict_types=1);
+
+namespace App\ApiResources\Dolibarr;
+
+use ApiPlatform\Core\Annotation\ApiProperty;
+use ApiPlatform\Core\Annotation\ApiResource;
+use App\ApiResources\ApiResourcesInterface;
+use Symfony\Component\Serializer\Annotation\Groups;
+
+/**
+ *  Lines (services) included in a society contract, as retrieved from dolibarr
+ */
+#[ApiResource(
+    collectionOperations:[],
+    itemOperations: [
+        'get'
+    ]
+)]
+class DolibarrContractLine implements ApiResourcesInterface
+{
+    #[ApiProperty(identifier: true)]
+    #[Groups('dolibarr_get')]
+    private int $id;
+
+    /**
+     * Id of the contract's line
+     */
+    #[Groups('dolibarr_get')]
+    private int $contractId;
+
+    /**
+     * Reference of the contracted service ( = product's reference)
+     */
+    #[Groups('dolibarr_get')]
+    private string $serviceRef;
+
+    /**
+     * Label of the contracted service
+     */
+    #[Groups('dolibarr_get')]
+    private string $serviceLabel;
+
+    /**
+     * Service active from date ...
+     */
+    #[Groups('dolibarr_get')]
+    private \DateTime $dateStart;
+
+    /**
+     * Service active to date ...
+     */
+    #[Groups('dolibarr_get')]
+    private \DateTime $dateEnd;
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): self
+    {
+        $this->id = $id;
+        return $this;
+    }
+
+    public function getContractId(): int
+    {
+        return $this->contractId;
+    }
+
+    public function setContractId(int $contractId): self
+    {
+        $this->contractId = $contractId;
+        return $this;
+    }
+
+    public function getServiceRef(): string
+    {
+        return $this->serviceRef;
+    }
+
+    public function setServiceRef(string $serviceRef): self
+    {
+        $this->serviceRef = $serviceRef;
+        return $this;
+    }
+
+    public function getServiceLabel(): string
+    {
+        return $this->serviceLabel;
+    }
+
+    public function setServiceLabel(string $serviceLabel): self
+    {
+        $this->serviceLabel = $serviceLabel;
+        return $this;
+    }
+
+    public function getDateStart(): \DateTime
+    {
+        return $this->dateStart;
+    }
+
+    public function setDateStart(\DateTime $dateStart): self
+    {
+        $this->dateStart = $dateStart;
+        return $this;
+    }
+
+    public function isDateEnd(): \DateTime
+    {
+        return $this->dateEnd;
+    }
+
+    public function setDateEnd(\DateTime $dateEnd): self
+    {
+        $this->dateEnd = $dateEnd;
+        return $this;
+    }
+}

+ 17 - 19
src/ApiResources/Enum/Enum.php

@@ -5,37 +5,35 @@ namespace App\ApiResources\Enum;
 
 use ApiPlatform\Core\Annotation\ApiProperty;
 use ApiPlatform\Core\Annotation\ApiResource;
+use App\ApiResources\ApiResourcesInterface;
 
 /**
  * Classe resource qui contient les champs disponibles lors d'un appel à enum.
- *
- * @ApiResource(
- *     collectionOperations={},
- *     itemOperations={
- *          "get"={
- *             "method"="GET",
- *             "path"="/enum/{name}"
- *          }
- *     }
- * )
  */
-class Enum
+#[ApiResource(
+    collectionOperations: [],
+    itemOperations: [
+        'get' => [
+            'method' => 'GET',
+            'path' => '/enum/{name}'
+        ]
+    ]
+)]
+class Enum implements ApiResourcesInterface
 {
-    /**
-     * @ApiProperty(identifier=true)
-     */
-    private $name;
-    private $items = [];
+    #[ApiProperty(identifier: true)]
+    private string $name;
+    private array $items = [];
 
     public function __construct()
     {
     }
-    public function getName(): ?string
+    public function getName(): string
     {
         return $this->name;
     }
 
-    public function setName(?string $name): self
+    public function setName(string $name): self
     {
         $this->name = $name;
 
@@ -49,7 +47,7 @@ class Enum
         return $this;
     }
 
-    public function getItems(): ?array
+    public function getItems(): array
     {
         return $this->items;
     }

+ 84 - 0
src/ApiResources/Mobyt/MobytUserStatus.php

@@ -0,0 +1,84 @@
+<?php
+declare(strict_types=1);
+
+namespace App\ApiResources\Mobyt;
+
+use ApiPlatform\Core\Annotation\ApiProperty;
+use ApiPlatform\Core\Annotation\ApiResource;
+use App\ApiResources\ApiResourcesInterface;
+use Symfony\Component\Serializer\Annotation\Groups;
+
+/**
+ * Statut de l'utilisateur Mobyt correspondant à l'organization donnée en paramètre
+ */
+#[ApiResource(
+    collectionOperations:[],
+    itemOperations: [
+        'get' => [
+            'security' => 'is_granted("ROLE_TEXTO") and object.getOrganizationId() == user.getOrganization().getId()',
+            'method' => 'GET',
+            'path' => '/mobyt/status/{organizationId}',
+            'requirements' => ['organizationId' => '\d+'],
+        ],
+    ]
+)]
+class MobytUserStatus implements ApiResourcesInterface
+{
+    #[ApiProperty(identifier: true)]
+    private int $organizationId;
+
+    /**
+     * Is there a Mobyt account active for this user
+     */
+    private bool $active = false;
+
+    /**
+     * Amount of sms remaining
+     */
+    private int $amount = 0;
+
+    /**
+     * Money remaining
+     */
+    private float $money = 0;
+
+    public function getOrganizationId(): int
+    {
+        return $this->organizationId;
+    }
+
+    public function setOrganizationId(int $organizationId): void
+    {
+        $this->organizationId = $organizationId;
+    }
+
+    public function isActive(): bool
+    {
+        return $this->active;
+    }
+
+    public function setActive(bool $active): void
+    {
+        $this->active = $active;
+    }
+
+    public function getAmount(): int
+    {
+        return $this->amount;
+    }
+
+    public function setAmount(int $amount): void
+    {
+        $this->amount = $amount;
+    }
+
+    public function getMoney(): float
+    {
+        return $this->money;
+    }
+
+    public function setMoney(float $money): void
+    {
+        $this->money = $money;
+    }
+}

+ 201 - 22
src/ApiResources/Profile/AccessProfile.php

@@ -5,34 +5,83 @@ namespace App\ApiResources\Profile;
 
 use ApiPlatform\Core\Annotation\ApiProperty;
 use ApiPlatform\Core\Annotation\ApiResource;
+use App\ApiResources\ApiResourcesInterface;
+use JetBrains\PhpStorm\Pure;
+use Symfony\Component\Serializer\Annotation\Groups;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
 
 /**
  * Classe resource qui contient les champs disponibles lors d'un appel à my_profile.
- *
- * @ApiResource(
- *     collectionOperations={},
- *     itemOperations={
- *          "get"={
- *             "method"="GET",
- *             "path"="/my_profile/{id}"
- *          }
- *     }
- * )
  */
-class AccessProfile
+#[ApiResource(
+    collectionOperations:[],
+    itemOperations: [
+        'get' => [
+            'normalization_context' => [
+                'groups' => ['access_profile_read']
+            ],
+            'method' => 'GET',
+            'path' => '/my_profile/{id}',
+            'defaults' => ['id' => 0]
+        ]
+    ]
+)]
+class AccessProfile implements ApiResourcesInterface
 {
-    /**
-     * @ApiProperty(identifier=true)
-     */
-    public $id;
-    private $isAdminAccess;
-    private $name;
-    private $givenName;
-    private $roles = [];
-    private $organization;
+    #[ApiProperty(identifier: true)]
+    #[Groups('access_profile_read')]
+    public ?int $id = null;
 
-    public function __construct()
+    #[Groups('access_profile_read')]
+    private bool $isAdminAccess = false;
+
+    #[Groups('access_profile_read')]
+    private bool $isSuperAdminAccess = false;
+
+    #[Groups('access_profile_read')]
+    private ?string $name = null;
+
+    #[Groups('access_profile_read')]
+    private ?string $givenName = null;
+
+    #[Groups('access_profile_read')]
+    private ?string $gender = null;
+
+    #[Groups('access_profile_read')]
+    private ?int $avatarId = null;
+
+    #[Groups('access_profile_read')]
+    private ?array $roles = [];
+
+    #[Groups('access_profile_read')]
+    private ?int $activityYear = null;
+
+    #[Groups('access_profile_read')]
+    private ?array $historical=[];
+
+    #[Groups('access_profile_read')]
+    private bool $isGuardian = false;
+
+    #[Groups('access_profile_read')]
+    private bool $isPayor = false;
+
+    #[Groups('access_profile_read')]
+    private ?OrganizationProfile $organization = null;
+
+    #[Groups('access_profile_read')]
+    private Collection $multiAccesses;
+
+    #[Groups('access_profile_read')]
+    private Collection $familyAccesses;
+
+    #[Groups('access_profile_read')]
+    private ?AccessProfile $originalAccess = null;
+
+    #[Pure] public function __construct()
     {
+        $this->multiAccesses = new ArrayCollection();
+        $this->familyAccesses = new ArrayCollection();
     }
 
     public function getId(): ?int
@@ -47,7 +96,7 @@ class AccessProfile
         return $this;
     }
 
-    public function getIsAdminAccess(): ?bool
+    public function getIsAdminAccess(): bool
     {
         return $this->isAdminAccess;
     }
@@ -59,6 +108,18 @@ class AccessProfile
         return $this;
     }
 
+    public function getIsSuperAdminAccess(): bool
+    {
+        return $this->isSuperAdminAccess;
+    }
+
+    public function setIsSuperAdminAccess(bool $isSuperAdminAccess): self
+    {
+        $this->isSuperAdminAccess = $isSuperAdminAccess;
+
+        return $this;
+    }
+
     public function getOrganization(): ?OrganizationProfile
     {
         return $this->organization;
@@ -95,6 +156,28 @@ class AccessProfile
         return $this;
     }
 
+    public function getGender(): ?string
+    {
+        return $this->gender;
+    }
+
+    public function setGender(?string $gender): self
+    {
+        $this->gender = $gender;
+        return $this;
+    }
+
+    public function getAvatarId(): ?int
+    {
+        return $this->avatarId;
+    }
+
+    public function setAvatarId(?int $avatarId): self
+    {
+        $this->avatarId = $avatarId;
+        return $this;
+    }
+
     public function getRoles(): array
     {
         $roles = $this->roles;
@@ -107,4 +190,100 @@ class AccessProfile
         $this->roles = $roles;
         return $this;
     }
+
+    public function getIsGuardian(): bool
+    {
+        return $this->isGuardian;
+    }
+
+    public function setIsGuardian(bool $isGuardian): self
+    {
+        $this->isGuardian = $isGuardian;
+
+        return $this;
+    }
+
+    public function getIsPayor(): bool
+    {
+        return $this->isPayor;
+    }
+
+    public function setIsPayor(bool $isPayor): self
+    {
+        $this->isPayor = $isPayor;
+
+        return $this;
+    }
+
+    public function getMultiAccesses(): Collection
+    {
+        return $this->multiAccesses;
+    }
+
+    public function addMultiAccess(OrganizationProfile $organizationProfile): self
+    {
+        if (!$this->multiAccesses->contains($organizationProfile)) {
+            $this->multiAccesses[] = $organizationProfile;
+        }
+        return $this;
+    }
+
+    public function removeMultiAccess(OrganizationProfile $organizationProfile): self
+    {
+        $this->multiAccesses->removeElement($organizationProfile);
+        return $this;
+    }
+
+    public function getFamilyAccesses(): Collection
+    {
+        return $this->familyAccesses;
+    }
+
+    public function addFamilyAccess(AccessProfile $accessProfile): self
+    {
+        if (!$this->familyAccesses->contains($accessProfile)) {
+            $this->familyAccesses[] = $accessProfile;
+        }
+        return $this;
+    }
+
+    public function removeFamilyAccess(AccessProfile $accessProfile): self
+    {
+        $this->familyAccesses->removeElement($accessProfile);
+        return $this;
+    }
+
+    public function getOriginalAccess(): ?AccessProfile
+    {
+        return $this->originalAccess;
+    }
+
+    public function setOriginalAccess(?AccessProfile $originalAccess): self
+    {
+        $this->originalAccess = $originalAccess;
+        return $this;
+    }
+
+    public function getActivityYear(): ?int
+    {
+        return $this->activityYear;
+    }
+
+    public function setActivityYear(?int $activityYear): self
+    {
+        $this->activityYear = $activityYear;
+
+        return $this;
+    }
+
+    public function getHistorical(): array
+    {
+        return $this->historical;
+    }
+
+    public function setHistorical(array $historical): self
+    {
+        $this->historical = $historical;
+        return $this;
+    }
 }

+ 67 - 18
src/ApiResources/Profile/OrganizationProfile.php

@@ -4,29 +4,55 @@ declare(strict_types=1);
 namespace App\ApiResources\Profile;
 
 use ApiPlatform\Core\Annotation\ApiProperty;
+use App\ApiResources\ApiResourcesInterface;
+use Symfony\Component\Serializer\Annotation\Groups;
+use ApiPlatform\Core\Annotation\ApiResource;
 
 /**
  * Classe resource qui contient les champs relatifs aux organizations présentent dans la requete my_profile.
- * @package App\ApiResources\Profile
  */
-class OrganizationProfile
+
+#[ApiResource(
+    collectionOperations:[],
+    itemOperations: [
+        'get'
+    ]
+)]
+class OrganizationProfile implements ApiResourcesInterface
 {
-    /**
-     * @ApiProperty(identifier=true)
-     */
-    public $id;
-    private $name;
-    private $product;
-    private $subDomain;
-    private $networks = [];
-    private $website;
-    private $modules = [];
-    private $hasChildren = false;
-    private $parents = [];
+    #[ApiProperty(identifier: true)]
+    #[Groups('access_profile_read')]
+    public ?int $id = null;
 
-    public function __construct()
-    {
-    }
+    #[Groups('access_profile_read')]
+    private ?string $name = null;
+
+    #[Groups('access_profile_read')]
+    private ?string $product = null;
+
+    #[Groups('access_profile_read')]
+    private ?string $subDomain = null;
+
+    #[Groups('access_profile_read')]
+    private array $networks = [];
+
+    #[Groups('access_profile_read')]
+    private ?string $website = null;
+
+    #[Groups('access_profile_read')]
+    private ?array $modules = [];
+
+    #[Groups('access_profile_read')]
+    private bool $hasChildren = false;
+
+    #[Groups('access_profile_read')]
+    private ?array $parents = [];
+
+    #[Groups('access_profile_read')]
+    private bool $showAdherentList = false;
+
+    #[Groups('access_profile_read')]
+    private ?int $currentYear = null;
 
     public function getId(): ?int
     {
@@ -125,7 +151,6 @@ class OrganizationProfile
         return $this;
     }
 
-
     public function getParents(): array
     {
         return $this->parents;
@@ -136,4 +161,28 @@ class OrganizationProfile
         $this->parents[] = $parent;
         return $this;
     }
+
+    public function getShowAdherentList(): bool
+    {
+        return $this->showAdherentList;
+    }
+
+    public function setShowAdherentList(bool $showAdherentList): self
+    {
+        $this->showAdherentList = $showAdherentList;
+
+        return $this;
+    }
+
+    public function getCurrentYear(): ?int
+    {
+        return $this->currentYear;
+    }
+
+    public function setCurrentYear(?int $currentYear): self
+    {
+        $this->currentYear = $currentYear;
+
+        return $this;
+    }
 }

+ 137 - 0
src/ApiResources/Utils/GpsCoordinate.php

@@ -0,0 +1,137 @@
+<?php
+declare(strict_types=1);
+
+namespace App\ApiResources\Utils;
+
+use ApiPlatform\Core\Annotation\ApiProperty;
+use ApiPlatform\Core\Annotation\ApiResource;
+use App\ApiResources\ApiResourcesInterface;
+
+/**
+ * Classe resource qui contient les champs de recherche des coordonnées GPS d'une adresse
+ */
+#[ApiResource(
+    collectionOperations: [
+        'get' => [
+            'method' => 'GET',
+            'path' => '/gps-coordinate-searching'
+        ]
+    ],
+    itemOperations: [
+        'get' => [
+            'method' => 'GET',
+            'path' => '/gps-coordinate-reverse/{latitude}/{longitude}'
+        ]
+    ],
+    compositeIdentifier: false
+)]
+class GpsCoordinate implements ApiResourcesInterface
+{
+    #[ApiProperty(identifier: true)]
+    private float $latitude;
+
+    #[ApiProperty(identifier: true)]
+    private float $longitude;
+
+    private ?string $streetAddress = null;
+    private ?string $streetAddressSecond = null;
+    private ?string $streetAddressThird = null;
+    private ?string $cp = null;
+    private ?string $city = null;
+    private ?string $country = null;
+
+    public function __construct()
+    {
+        $this->setLatitude(0.0);
+        $this->setLongitude(0.0);
+    }
+
+    public function setLatitude(?float $latitude): self
+    {
+        $this->latitude = $latitude;
+        return $this;
+    }
+
+    public function getLatitude(): ?float
+    {
+        return $this->latitude;
+    }
+
+
+    public function getLongitude(): ?float
+    {
+        return $this->longitude;
+    }
+
+    public function setLongitude(?float $longitude): self
+    {
+        $this->longitude = $longitude;
+        return $this;
+    }
+
+    public function getStreetAddress(): ?string
+    {
+        return $this->streetAddress;
+    }
+
+    public function setStreetAddress(?string $streetAddress): self
+    {
+        $this->streetAddress = $streetAddress;
+        return $this;
+    }
+
+    public function getStreetAddressSecond(): ?string
+    {
+        return $this->streetAddressSecond;
+    }
+
+    public function setStreetAddressSecond(?string $streetAddressSecond): self
+    {
+        $this->streetAddressSecond = $streetAddressSecond;
+        return $this;
+    }
+
+    public function getStreetAddressThird(): ?string
+    {
+        return $this->streetAddressThird;
+    }
+
+    public function setStreetAddressThird(?string $streetAddressThird): self
+    {
+        $this->streetAddressThird = $streetAddressThird;
+        return $this;
+    }
+
+    public function getCp(): ?string
+    {
+        return $this->cp;
+    }
+
+    public function setCp(?string $cp): self
+    {
+        $this->cp = $cp;
+        return $this;
+    }
+
+    public function getCity(): ?string
+    {
+        return $this->city;
+    }
+
+    public function setCity(?string $city): self
+    {
+        $this->city = $city;
+        return $this;
+    }
+
+    public function getCountry(): ?string
+    {
+        return $this->country;
+    }
+
+    public function setCountry(?string $country): self
+    {
+        $this->country = $country;
+        return $this;
+    }
+}

+ 17 - 17
src/ApiResources/Utils/Siret.php

@@ -5,27 +5,27 @@ namespace App\ApiResources\Utils;
 
 use ApiPlatform\Core\Annotation\ApiProperty;
 use ApiPlatform\Core\Annotation\ApiResource;
+use App\ApiResources\ApiResourcesInterface;
 
 /**
  * Classe resource qui contient les champs de vérification d'un siret
- *
- * @ApiResource(
- *     collectionOperations={},
- *     itemOperations={
- *          "get"={
- *             "method"="GET",
- *             "path"="/siret-checking/{number}"
- *          }
- *     }
- * )
  */
-class Siret
+
+#[ApiResource(
+    collectionOperations: [],
+    itemOperations: [
+        'get' => [
+            'method' => 'GET',
+            'path' => '/siret-checking/{number}'
+        ]
+    ]
+)]
+class Siret implements ApiResourcesInterface
 {
-    /**
-     * @ApiProperty(identifier=true)
-     */
-    private $number;
-    private $isCorrect;
+    #[ApiProperty(identifier: true)]
+    private ?string $number = null;
+
+    private bool $isCorrect = false;
 
     public function __construct()
     {
@@ -47,7 +47,7 @@ class Siret
         return $this;
     }
 
-    public function getIsCorrect(): ?bool
+    public function getIsCorrect(): bool
     {
         return $this->isCorrect;
     }

+ 0 - 49
src/Controller/EsController.php

@@ -1,49 +0,0 @@
-<?php
-// src/Controller/LuckyController.php
-namespace App\Controller;
-
-use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
-use Symfony\Component\HttpFoundation\Response;
-use FOS\ElasticaBundle\Index\IndexManager;
-use FOS\ElasticaBundle\Transformer\ElasticaToModelTransformerCollection;
-use Symfony\Component\Routing\Annotation\Route;
-
-
-/**
- * Class EsController
- * @package App\Controller
- */
-class EsController extends AbstractController
-{
-    private $elasticaIndexManager;
-    private $elasticaToModelTransformerCollectionSearch;
-
-    public function __construct(IndexManager $elasticaIndexManager, ElasticaToModelTransformerCollection $elasticaToModelTransformerCollectionSearch)
-    {
-        $this->elasticaToModelTransformerCollectionSearch = $elasticaToModelTransformerCollectionSearch;
-        $this->elasticaIndexManager = $elasticaIndexManager;
-    }
-
-    /**
-     * @Route("/es_test")
-     * @return Response
-     */
-    public function es_test(): Response
-    {
-        $search = $this->elasticaIndexManager->getIndex('search')->createSearch();
-        $search->addType('organization');
-        $options['limit'] = 10;
-
-        $queryPart = new \Elastica\Query\BoolQuery();
-        $filtered = new \Elastica\Query\Filtered($queryPart);
-
-
-        $query = \Elastica\Query::create($filtered);
-        $resultSet = $search->search($query->getQuery(), $options);
-
-        $response = $this->elasticaToModelTransformerCollectionSearch->transform($resultSet->getResults());
-
-        dump($response);
-        die;
-    }
-}

+ 49 - 0
src/Controller/EsController.php.ori

@@ -0,0 +1,49 @@
+<?php
+//// src/Controller/LuckyController.php
+//namespace App\Controller;
+//
+//use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+//use Symfony\Component\HttpFoundation\Response;
+//use FOS\ElasticaBundle\Index\IndexManager;
+//use FOS\ElasticaBundle\Transformer\ElasticaToModelTransformerCollection;
+//use Symfony\Component\Routing\Annotation\Route;
+//
+//
+///**
+// * Class EsController
+// * @package App\Controller
+// */
+//class EsController extends AbstractController
+//{
+//    private $elasticaIndexManager;
+//    private $elasticaToModelTransformerCollectionSearch;
+//
+//    public function __construct(IndexManager $elasticaIndexManager, ElasticaToModelTransformerCollection $elasticaToModelTransformerCollectionSearch)
+//    {
+//        $this->elasticaToModelTransformerCollectionSearch = $elasticaToModelTransformerCollectionSearch;
+//        $this->elasticaIndexManager = $elasticaIndexManager;
+//    }
+//
+//    /**
+//     * @Route("/es_test")
+//     * @return Response
+//     */
+//    public function es_test(): Response
+//    {
+//        $search = $this->elasticaIndexManager->getIndex('search')->createSearch();
+//        $search->addType('organization');
+//        $options['limit'] = 10;
+//
+//        $queryPart = new \Elastica\Query\BoolQuery();
+//        $filtered = new \Elastica\Query\Filtered($queryPart);
+//
+//
+//        $query = \Elastica\Query::create($filtered);
+//        $resultSet = $search->search($query->getQuery(), $options);
+//
+//        $response = $this->elasticaToModelTransformerCollectionSearch->transform($resultSet->getResults());
+//
+//        dump($response);
+//        die;
+//    }
+//}

+ 19 - 0
src/DQL/DateConditions.php

@@ -0,0 +1,19 @@
+<?php
+declare(strict_types=1);
+
+namespace App\DQL;
+
+use Doctrine\ORM\QueryBuilder;
+
+class DateConditions{
+    public static function addDateInPeriodCondition(QueryBuilder $qb, string $table, string $date): QueryBuilder{
+        return $qb
+                ->andWhere(sprintf('%s.startDate <= :date AND (%s.endDate >= :date  OR  %s.endDate IS NULL)',
+                    $table,
+                    $table,
+                    $table
+                ))
+                ->setParameter('date', $date)
+            ;
+    }
+}

+ 15 - 70
src/DataProvider/Access/AccessProfileDataProvider.php

@@ -1,4 +1,5 @@
 <?php
+
 declare(strict_types=1);
 
 namespace App\DataProvider\Access;
@@ -6,13 +7,10 @@ namespace App\DataProvider\Access;
 use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
 use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
 use App\ApiResources\Profile\AccessProfile;
-use App\ApiResources\Profile\OrganizationProfile;
 use App\Entity\Access\Access;
-use App\Entity\Organization\Organization;
-use App\Service\Network\Tree;
-use App\Service\Security\Module;
-use Symfony\Component\Security\Core\Role\Role;
-use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
+use App\Service\Access\AccessProfileCreator;
+use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
+use Symfony\Component\Security\Core\Exception\AuthenticationException;
 use Symfony\Component\Security\Core\Security;
 
 /**
@@ -21,23 +19,11 @@ use Symfony\Component\Security\Core\Security;
  */
 final class AccessProfileDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface
 {
-    private Security $security;
-    private RoleHierarchyInterface $roleHierarchy;
-    private Module $module;
-    private Tree $tree;
-
     public function __construct(
-        Security $security,
-        RoleHierarchyInterface $roleHierarchy,
-        Module $module,
-        Tree $tree
+        private Security $security,
+        private AccessProfileCreator $accessProfileCreator
     )
-    {
-        $this->security = $security;
-        $this->roleHierarchy = $roleHierarchy;
-        $this->module = $module;
-        $this->tree = $tree;
-    }
+    { }
 
     public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
     {
@@ -48,58 +34,17 @@ final class AccessProfileDataProvider implements ItemDataProviderInterface, Rest
     {
         /** @var Access $access */
         $access = $this->security->getUser();
+        $originalAccess = null;
 
-        $myProfile = $this->setProfileFromAccess($access);
-        $myProfile->setRoles($this->roleHierarchy->getReachableRoleNames($this->security->getToken()->getRoleNames()));
-
-        $myProfile->setOrganization($this->setOrganizationProfileFromOrganization($access->getOrganization()));
-
-        return $myProfile;
-    }
-
-    /**
-     * Hydratation du profile de l'access connecté via la resource accessProfile
-     * @param Access $access
-     * @return AccessProfile
-     */
-    public function setProfileFromAccess(Access $access): AccessProfile
-    {
-        $accessProfile = new AccessProfile();
-        $accessProfile->setId($access->getId());
-        $accessProfile->setIsAdminAccess($access->getAdminAccess());
-        $accessProfile->setName($access->getPerson()->getName());
-        $accessProfile->setGivenName($access->getPerson()->getGivenName());
-        return $accessProfile;
-    }
-
-    /**
-     * Hydratation du profile des organizations auxquelles l'access connecté est inscrit
-     * @param Organization $organization
-     * @return OrganizationProfile
-     */
-    public function setOrganizationProfileFromOrganization(Organization $organization): OrganizationProfile{
-        $organizationProfile = new OrganizationProfile();
-        $organizationProfile->setId($organization->getId());
-        $organizationProfile->setName($organization->getName());
-        $organizationProfile->setModules($this->module->getOrganizationModules($organization));
-        $organizationProfile->setProduct($organization->getSettings()->getProduct());
-        $organizationProfile->setHasChildren($organization->getNetworkOrganizationChildren()->count() > 1);
-        $organizationProfile->setSubDomain($organization->getParameters()->getSubDomain());
-        $organizationProfile->setWebsite($organization->getParameters()->getWebsite());
-
-        foreach ($organization->getNetworkOrganizations() as $networkOrganization){
-            $organizationProfile->addNetwork($networkOrganization->getNetwork()->getName());
+        $token = $this->security->getToken();
+        if($token instanceof SwitchUserToken){
+            $originalAccess = $token->getOriginalToken()->getUser();
         }
 
-        /** @var Organization $parent */
-        foreach ($this->tree->findAllParentsAndSortByType($organization) as $parent){
-            $parentProfile = new OrganizationProfile();
-            $parentProfile->setId($parent->getId());
-            $parentProfile->setName($parent->getName());
-            $parentProfile->setSubDomain($parent->getParameters()->getSubDomain());
-            $parentProfile->setWebsite($parent->getParameters()->getWebsite());
-            $organizationProfile->addParent($parentProfile);
+        try {
+            return $this->accessProfileCreator->getAccessProfile($access, $originalAccess);
+        } catch (\Exception $e) {
+            return null;
         }
-        return $organizationProfile;
     }
 }

+ 34 - 0
src/DataProvider/Cotisation/CotisationDataProvider.php

@@ -0,0 +1,34 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\DataProvider\Cotisation;
+
+use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
+use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
+use App\ApiResources\Cotisation\Cotisation;
+use App\Service\Cotisation\CotisationCreator;
+
+/**
+ * Class CotisationDataProvider : custom provider pour assurer l'alimentation de la réponse du GET cotisation
+ * @package App\DataProvider\Cotisation
+ */
+final class CotisationDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface
+{
+    public function __construct(private CotisationCreator $cotisationCreator)
+    { }
+
+    public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
+    {
+        return Cotisation::class === $resourceClass;
+    }
+
+    public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []): ?Cotisation
+    {
+        try {
+            return $this->cotisationCreator->getCotisation($id);
+        } catch (\Exception $e) {
+            return null;
+        }
+    }
+}

+ 32 - 0
src/DataProvider/Dolibarr/DolibarrAccountDataProvider.php

@@ -0,0 +1,32 @@
+<?php
+declare(strict_types=1);
+
+namespace App\DataProvider\Dolibarr;
+
+use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
+use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
+use App\ApiResources\Dolibarr\DolibarrAccount;
+use App\Service\Dolibarr\DolibarrAccountCreator;
+
+/**
+ * Custom provider pour les DolibarrAccounts récupérés via l'api dolibarr
+ * @package App\DataProvider\Utils
+ */
+final class DolibarrAccountDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface
+{
+
+    public function __construct(
+        private DolibarrAccountCreator $dolibarrAccountCreator,
+    )
+    {}
+
+    public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
+    {
+        return DolibarrAccount::class === $resourceClass;
+    }
+
+    public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []): ?DolibarrAccount
+    {
+        return $this->dolibarrAccountCreator->getDolibarrAccount($id);
+    }
+}

+ 10 - 24
src/DataProvider/Enum/EnumDataProvider.php

@@ -16,51 +16,37 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  */
 final class EnumDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface
 {
-    private Parser $parser;
-    private Reflection $reflection;
-    private string $opentalentConfig;
-
     public function __construct(
-        Parser $parser,
-        string $opentalentConfig,
-        Reflection $reflection
+        private Parser $parser,
+        private string $opentalentConfig,
+        private Reflection $reflection
     )
-    {
-        $this->parser = $parser;
-        $this->opentalentConfig = $opentalentConfig;
-        $this->reflection = $reflection;
-    }
+    { }
 
     public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
     {
         return Enum::class === $resourceClass;
     }
 
-    public function getItem(string $resourceClass, $name, string $operationName = null, array $context = []): ?Enum
+    public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []): ?Enum
     {
         $enums = $this->parser->yamlParser($this->opentalentConfig, 'enum.yaml');
-        $enumClass = $enums['opentalent'][$name];
+        $enumClass = $enums['opentalent'][$id];
 
         if(!$enumClass)
-            throw new NotFoundHttpException(sprintf('Enum %s does\'nt exist', $name));
+            throw new NotFoundHttpException(sprintf('Enum %s does\'nt exist', $id));
 
-        $items = [];
         try{
             $items = $this->reflection->dynamicInvokeClassWithArgsAndMethod(
                 $enumClass,
-                'toArrayCustom'
+                'toArray'
             );
         }catch (\Exception $exception){
-            try{
-                $items = $this->reflection->dynamicInvokeClassWithArgsAndMethod(
-                    $enumClass,
-                    'toArray'
-                );
-            }catch (\Exception $exception){}
+            throw new NotFoundHttpException(sprintf('Enum %s does\'nt exist', $id));
         }
 
         $enumResponse = new Enum();
-        $enumResponse->setName($name);
+        $enumResponse->setName($id);
         $enumResponse->setItems($items);
         return $enumResponse;
     }

+ 31 - 0
src/DataProvider/Mobyt/MobytUserStatusDataProvider.php

@@ -0,0 +1,31 @@
+<?php
+declare(strict_types=1);
+
+namespace App\DataProvider\Mobyt;
+
+use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
+use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
+use App\ApiResources\Mobyt\MobytUserStatus;
+use App\Service\Mobyt\MobytUserStatusCreator;
+
+/**
+ * Custom provider pour les MobytUserStatus récupérés via l'api Mobyt
+ * @package App\DataProvider\Utils
+ */
+final class MobytUserStatusDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface
+{
+    public function __construct(
+        private MobytUserStatusCreator $mobytUserStatusCreator,
+    )
+    {}
+
+    public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
+    {
+        return MobytUserStatus::class === $resourceClass;
+    }
+
+    public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []): ?MobytUserStatus
+    {
+        return $this->mobytUserStatusCreator->getUserStatus($id);
+    }
+}

+ 62 - 0
src/DataProvider/Utils/GpsCoordinateSearchingDataProvider.php

@@ -0,0 +1,62 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\DataProvider\Utils;
+
+use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
+use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
+use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
+use ApiPlatform\Core\Identifier\CompositeIdentifierParser;
+use App\ApiResources\Utils\GpsCoordinate;
+use App\Service\Utils\GpsCoordinateUtils;
+use Symfony\Component\HttpFoundation\RequestStack;
+
+/**
+ * Class GpsCoordinateSearchingDataProvider : custom provider pour assurer l'alimentation de la ressource GpsCoordinate
+ * @package App\DataProvider\Utils
+ */
+final class GpsCoordinateSearchingDataProvider implements ItemDataProviderInterface, CollectionDataProviderInterface, RestrictedDataProviderInterface
+{
+    public function __construct(
+        private GpsCoordinateUtils $gpsCoordinateUtils,
+        private RequestStack $requestStack
+    )
+    { }
+
+    public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
+    {
+        return GpsCoordinate::class === $resourceClass;
+    }
+
+    public function getCollection(string $resourceClass, string $operationName = null): iterable
+    {
+        $request = $this->requestStack->getCurrentRequest();
+        $responses = [];
+        try{
+            $addresses = $this->gpsCoordinateUtils->searchGpsCoordinates(
+                $request->get('street'),
+                $request->get('cp'),
+                $request->get('city')
+            );
+            foreach ($addresses as $address){
+                $responses[] = $this->gpsCoordinateUtils->createGpsCoordinate($address);
+            }
+        }catch (\Exception $exception){
+            $responses[] = new GpsCoordinate();
+        }
+        return $responses;
+    }
+
+    public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []): GpsCoordinate
+    {
+        $ids = CompositeIdentifierParser::parse($id);
+        try{
+            $address = $this->gpsCoordinateUtils->reverseGpsCoordinates(floatval($ids['latitude']), floatval($ids['longitude']));
+            $gpsCoordinateResponse = $this->gpsCoordinateUtils->createGpsCoordinate($address);
+        }catch (\Exception $exception){
+            $gpsCoordinateResponse = new GpsCoordinate();
+        }
+        return $gpsCoordinateResponse;
+    }
+}

+ 6 - 10
src/DataProvider/Utils/SiretDataProvider.php

@@ -10,29 +10,25 @@ use App\Service\Utils\Siret as SiretUtils;
 
 /**
  * Class SiretDataProvider : custom provider pour assurer l'alimentation des utils Siret
- * @package App\DataProvider\Access
+ * @package App\DataProvider\Utils
  */
 final class SiretDataProvider implements ItemDataProviderInterface, RestrictedDataProviderInterface
 {
-    private SiretUtils $siretUtils;
-
     public function __construct(
-        SiretUtils $siretUtils
+        private SiretUtils $siretUtils
     )
-    {
-        $this->siretUtils = $siretUtils;
-    }
+    { }
 
     public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
     {
         return Siret::class === $resourceClass;
     }
 
-    public function getItem(string $resourceClass, $number, string $operationName = null, array $context = []): ?Siret
+    public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []): ?Siret
     {
         $siretResponse = new Siret();
-        $siretResponse->setNumber($number);
-        $siretResponse->setIsCorrect($this->siretUtils->isSiretIsCorrect($number));
+        $siretResponse->setNumber($id);
+        $siretResponse->setIsCorrect($this->siretUtils->isSiretIsCorrect($id));
         return $siretResponse;
     }
 }

+ 6 - 9
src/Doctrine/Access/AccessExtension.php

@@ -16,24 +16,20 @@ use Symfony\Component\Security\Core\Security;
  */
 final class AccessExtension implements QueryCollectionExtensionInterface, QueryItemExtensionInterface
 {
-    private Security $security;
-
-    public function __construct(Security $security)
-    {
-        $this->security = $security;
-    }
+    public function __construct(private Security $security, private HandleAccessExtension $handleAccessExtension)
+    { }
 
     public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null): void
     {
-        $this->addWhere($queryBuilder, $resourceClass);
+        $this->addWhere($queryBuilder, $resourceClass, $operationName);
     }
 
     public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, string $operationName = null, array $context = []): void
     {
-        $this->addWhere($queryBuilder, $resourceClass);
+        $this->addWhere($queryBuilder, $resourceClass, $operationName);
     }
 
-    private function addWhere(QueryBuilder $queryBuilder, string $resourceClass): void
+    private function addWhere(QueryBuilder $queryBuilder, string $resourceClass, string $operationName): void
     {
         if (Access::class !== $resourceClass) {
             return;
@@ -45,5 +41,6 @@ final class AccessExtension implements QueryCollectionExtensionInterface, QueryI
         $queryBuilder->andWhere(sprintf('%s.organization = :current_organization', $rootAlias));
         $queryBuilder->setParameter('current_organization', $currentUser->getOrganization());
 
+        $this->handleAccessExtension->addWhere($queryBuilder, $operationName);
     }
 }

+ 11 - 0
src/Doctrine/Access/AccessExtensionInterface.php

@@ -0,0 +1,11 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Doctrine\Access;
+
+use Doctrine\ORM\QueryBuilder;
+
+interface AccessExtensionInterface{
+    public function support(string $name);
+    public function addWhere(QueryBuilder $queryBuilder);
+}

+ 21 - 0
src/Doctrine/Access/Extensions/AdminExtension.php

@@ -0,0 +1,21 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Doctrine\Access\Extensions;
+
+use App\Doctrine\Access\AccessExtensionInterface;
+use Doctrine\ORM\QueryBuilder;
+
+class AdminExtension implements AccessExtensionInterface {
+    public function support(string $name): bool
+    {
+        return $name === 'cget_admin';
+    }
+
+    public function addWhere(QueryBuilder $queryBuilder)
+    {
+        $rootAlias = $queryBuilder->getRootAliases()[0];
+        $queryBuilder->andWhere(sprintf('%s.adminAccess = :adminAccess', $rootAlias));
+        $queryBuilder->setParameter('adminAccess', true);
+    }
+}

+ 20 - 0
src/Doctrine/Access/Extensions/StudentsExtension.php

@@ -0,0 +1,20 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Doctrine\Access\Extensions;
+
+use App\Doctrine\Access\AccessExtensionInterface;
+use Doctrine\ORM\QueryBuilder;
+
+class StudentsExtension implements AccessExtensionInterface {
+
+    public function support(string $name): bool
+    {
+        return $name === 'cget_students';
+    }
+
+    public function addWhere(QueryBuilder $queryBuilder)
+    {
+        dd('ok');
+    }
+}

+ 19 - 0
src/Doctrine/Access/HandleAccessExtension.php

@@ -0,0 +1,19 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Doctrine\Access;
+
+use Doctrine\ORM\QueryBuilder;
+
+class HandleAccessExtension{
+    public function __construct(private iterable $extensions)
+    { }
+
+    public function addWhere(QueryBuilder $queryBuilder, $operationName){
+        /** @var AccessExtensionInterface $extension */
+        foreach ($this->extensions as $extension){
+            if($extension->support($operationName))
+                return $extension->addWhere($queryBuilder);
+        }
+    }
+}

+ 44 - 0
src/Doctrine/Access/PersonalizedListExtension.php

@@ -0,0 +1,44 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Doctrine\Access;
+
+use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryCollectionExtensionInterface;
+use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryItemExtensionInterface;
+use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface;
+use App\Entity\Access\PersonalizedList;
+use Doctrine\ORM\QueryBuilder;
+use Symfony\Component\Security\Core\Security;
+
+/**
+ * Class PersonalizedListExtension : Filtre de sécurité par défaut pour une resource PersonalizedList
+ * @package App\Doctrine\Access
+ */
+final class PersonalizedListExtension implements QueryCollectionExtensionInterface, QueryItemExtensionInterface
+{
+    public function __construct(private Security $security)
+    { }
+
+    public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null): void
+    {
+        $this->addWhere($queryBuilder, $resourceClass, $operationName);
+    }
+
+    public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, string $operationName = null, array $context = []): void
+    {
+        $this->addWhere($queryBuilder, $resourceClass, $operationName);
+    }
+
+    private function addWhere(QueryBuilder $queryBuilder, string $resourceClass, string $operationName): void
+    {
+        if (PersonalizedList::class !== $resourceClass) {
+            return;
+        }
+
+        /** @var PersonalizedList $currentUser */
+        $currentUser = $this->security->getUser();
+        $rootAlias = $queryBuilder->getRootAliases()[0];
+        $queryBuilder->andWhere(sprintf('%s.access = :current_access', $rootAlias));
+        $queryBuilder->setParameter('current_access', $currentUser);
+    }
+}

+ 54 - 0
src/Doctrine/Core/NotificationExtension.php

@@ -0,0 +1,54 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Doctrine\Core;
+
+use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryCollectionExtensionInterface;
+use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryItemExtensionInterface;
+use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface;
+use App\Entity\Access\Access;
+use App\Entity\Core\Notification;
+use Doctrine\ORM\QueryBuilder;
+use Symfony\Component\Security\Core\Security;
+
+/**
+ * Class NotificationExtension : Filtre de sécurité par défaut pour une resource Notification
+ * @package App\Doctrine\Core
+ */
+final class NotificationExtension implements QueryCollectionExtensionInterface, QueryItemExtensionInterface
+{
+    public function __construct(private Security $security)
+    { }
+
+    public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null): void
+    {
+        $this->addWhere($queryBuilder, $resourceClass, $operationName);
+    }
+
+    public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, string $operationName = null, array $context = []): void
+    {
+        $this->addWhere($queryBuilder, $resourceClass, $operationName);
+    }
+
+    /**
+     * @todo : A la suite de la migration, il faut supprimer le where avec le discr.
+     */
+    private function addWhere(QueryBuilder $queryBuilder, string $resourceClass, string $operationName): void
+    {
+        if (Notification::class !== $resourceClass) {
+            return;
+        }
+
+        /** @var Access $currentUser */
+        $currentUser = $this->security->getUser();
+        $rootAlias = $queryBuilder->getRootAliases()[0];
+        $queryBuilder
+            ->andWhere(sprintf('%s.discr = :discr', $rootAlias))
+            ->andWhere(sprintf('%s.recipientAccess = :current_access', $rootAlias))
+            ->andWhere('o.availabilityDate IS NULL or o.availabilityDate <= :today')
+            ->setParameter('discr', 'notification')
+            ->setParameter('current_access', $currentUser)
+            ->setParameter('today', new \DateTime())
+        ;
+    }
+}

+ 50 - 0
src/Doctrine/Core/NotificationUserExtension.php

@@ -0,0 +1,50 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Doctrine\Core;
+
+use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryCollectionExtensionInterface;
+use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryItemExtensionInterface;
+use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface;
+use App\Entity\Access\Access;
+use App\Entity\Core\NotificationUser;
+use Doctrine\ORM\QueryBuilder;
+use Symfony\Component\Security\Core\Security;
+
+/**
+ * Class NotificationExtension : Filtre de sécurité par défaut pour une resource Notification
+ * @package App\Doctrine\Core
+ */
+final class NotificationUserExtension implements QueryCollectionExtensionInterface, QueryItemExtensionInterface
+{
+    public function __construct(private Security $security)
+    { }
+
+    public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null): void
+    {
+        $this->addWhere($queryBuilder, $resourceClass, $operationName);
+    }
+
+    public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, string $operationName = null, array $context = []): void
+    {
+        $this->addWhere($queryBuilder, $resourceClass, $operationName);
+    }
+
+    /**
+     * @todo : A la suite de la migration, il faut supprimer le where avec le discr.
+     */
+    private function addWhere(QueryBuilder $queryBuilder, string $resourceClass, string $operationName): void
+    {
+        if (NotificationUser::class !== $resourceClass) {
+            return;
+        }
+
+        /** @var Access $currentUser */
+        $currentUser = $this->security->getUser();
+        $rootAlias = $queryBuilder->getRootAliases()[0];
+        $queryBuilder
+            ->andWhere(sprintf('%s.access = :current_access', $rootAlias))
+            ->setParameter('current_access', $currentUser)
+        ;
+    }
+}

+ 409 - 100
src/Entity/Access/Access.php

@@ -5,6 +5,10 @@ namespace App\Entity\Access;
 
 use ApiPlatform\Core\Annotation\ApiResource;
 use ApiPlatform\Core\Annotation\ApiSubresource;
+use App\Entity\Billing\AccessIntangible;
+use App\Entity\Billing\AccessPayer;
+use App\Entity\Core\Notification;
+use App\Entity\Core\NotificationUser;
 use App\Entity\Organization\Organization;
 use App\Entity\Organization\OrganizationLicence;
 use App\Repository\Access\AccessRepository;
@@ -13,70 +17,124 @@ use App\Entity\Person\PersonActivity;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
+use JetBrains\PhpStorm\Pure;
 use Symfony\Component\Security\Core\User\UserInterface;
+use Symfony\Component\Serializer\Annotation\Groups;
 
 /**
  * Fais le lien entre une Person et une Organization
- * @ApiResource(
- *     collectionOperations={
- *         "get"={"security"="is_granted('ROLE_USERS_VIEW')"},
- *         "post"
- *     },
- *     itemOperations={
- *         "get"={"security"="(is_granted('ROLE_USERS_VIEW') and object.getOrganization().getId() == user.getOrganization().getId()) or (object.getId() == user.getId())"},
- *         "put"={"security"="is_granted('ROLE_USERS')"},
- *         "delete"
- *     }
- * )
- * @ORM\Entity(repositoryClass=AccessRepository::class)
  */
+#[ApiResource(
+    collectionOperations:[
+        'cget_students'=> [
+            'method' => 'GET',
+            'path' => '/students',
+            'security' => 'is_granted("ROLE_USERS_VIEW")'
+        ],
+        'cget_admin'=> [
+            'method' => 'GET',
+            'path' => '/admin'
+        ],
+        'get'
+    ],
+    itemOperations: [
+        'get' => [
+            'security' => '(is_granted("ROLE_USERS_VIEW") and object.getOrganization().getId() == user.getOrganization().getId()) or (object.getId() == user.getId())'
+        ],
+        'put' => [
+            'security' => 'is_granted("ROLE_USERS") or (object.getId() == user.getId())'
+        ],
+        'delete'
+    ]
+)]
+#[ORM\Entity(repositoryClass: AccessRepository::class)]
 class Access implements UserInterface
 {
-    /**
-     * @ORM\Id
-     * @ORM\GeneratedValue
-     * @ORM\Column(type="integer")
-     */
-    private $id;
-
-    /**
-     * @ORM\Column(type="boolean", options={"default" : false})
-     */
-    private $adminAccess = false;
-
-    /**
-     * @ORM\ManyToOne(targetEntity=Person::class, cascade={"persist"})
-     * @ORM\JoinColumn(nullable=false)
-     */
-    private $person;
-
-    /**
-     * @ORM\ManyToOne(targetEntity=Organization::class)
-     * @ORM\JoinColumn(nullable=false)
-     */
-    public $organization;
-
-    /**
-     * @var array
-     * @ORM\Column(type="json_array", length=4294967295, nullable=true)
-     */
-    private $roles = [];
-
-    /**
-     * @ORM\OneToMany(targetEntity=PersonActivity::class, mappedBy="access")
-     * @ApiSubresource()
-     */
-    private $personActivity;
-
-    /**
-     * @ORM\OneToMany(targetEntity=OrganizationLicence::class, mappedBy="licensee", orphanRemoval=true)
-     */
-    private $organizationLicences;
-
-    public function __construct()
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    #[ORM\Column(options: ['default' => false])]
+    private bool $adminAccess = false;
+
+    #[ORM\Column(options: ['default' => false])]
+    #[Groups(['private'])]
+    private bool $superAdminAccess = false;
+
+    #[ORM\Column(nullable: true)]
+    #[Groups(['my_access:input'])]
+    private ?int $activityYear = null;
+
+    #[ORM\ManyToOne(cascade: ['persist'])]
+    #[ORM\JoinColumn(nullable: false)]
+    private Person $person;
+
+    #[ORM\ManyToOne]
+    #[ORM\JoinColumn(nullable: false)]
+    private Organization $organization;
+
+    #[ORM\Column(type: 'json', length: 4294967295, nullable: true)]
+    private ?array $roles = [];
+
+    #[Groups(['my_access:input'])]
+    #[ORM\Column(type: 'json', length: 4294967295, nullable: true)]
+    private ?array $setting = [];
+
+    #[Groups(['my_access:input'])]
+    private array $historical  = [];
+
+    #[ORM\OneToMany(mappedBy: 'access', targetEntity: PersonActivity::class, cascade: ['persist'], orphanRemoval: true)]
+    #[ApiSubresource]
+    private Collection $personActivity;
+
+    #[ORM\OneToMany(mappedBy: 'access', targetEntity: OrganizationFunction::class, cascade: ['persist'], orphanRemoval: true)]
+    #[ApiSubresource]
+    private Collection $organizationFunction;
+
+    #[ORM\OneToMany(mappedBy: 'licensee', targetEntity: OrganizationLicence::class, cascade: ['persist'], orphanRemoval: true)]
+    private Collection $organizationLicences;
+
+    #[ORM\OneToMany(mappedBy: 'access', targetEntity: PersonalizedList::class, cascade: ['persist'], orphanRemoval: true)]
+    private Collection $personalizedLists;
+
+    #[ORM\OneToMany(mappedBy: 'recipientAccess', targetEntity: Notification::class, orphanRemoval: true)]
+    private Collection $notifications;
+
+    #[ORM\OneToMany(mappedBy: 'access', targetEntity: NotificationUser::class, orphanRemoval: true)]
+    private Collection $notificationUsers;
+
+    #[ORM\ManyToMany(targetEntity: Access::class, mappedBy: 'children', cascade: ['persist'])]
+    private Collection $guardians;
+
+    #[ORM\ManyToMany(targetEntity: Access::class, inversedBy: 'guardians', cascade: ['persist'])]
+    #[ORM\JoinTable(name: 'children_guardians')]
+    #[ORM\JoinColumn(name: 'guardians_id', referencedColumnName: 'id')]
+    #[ORM\InverseJoinColumn(name: 'children_id', referencedColumnName: 'id')]
+    private Collection $children;
+
+    #[ORM\OneToMany(mappedBy: 'accessPayer', targetEntity: AccessPayer::class, cascade: ['persist'], orphanRemoval: true)]
+    private Collection $billingPayers;
+
+    #[ORM\OneToMany(mappedBy: 'accessReceiver', targetEntity: AccessPayer::class, cascade: ['persist'], orphanRemoval: true)]
+    private Collection $billingReceivers;
+
+    #[ORM\OneToMany(mappedBy: 'access', targetEntity: AccessIntangible::class, cascade: ['persist'], orphanRemoval: true)]
+    private Collection $accessIntangibles;
+
+    #[Pure] public function __construct()
     {
         $this->personActivity = new ArrayCollection();
+        $this->organizationFunction = new ArrayCollection();
         $this->organizationLicences = new ArrayCollection();
+        $this->personalizedLists = new ArrayCollection();
+        $this->guardians = new ArrayCollection();
+        $this->children = new ArrayCollection();
+        $this->billingPayers = new ArrayCollection();
+        $this->billingReceivers = new ArrayCollection();
+        $this->accessIntangibles = new ArrayCollection();
+        $this->notifications = new ArrayCollection();
+        $this->notificationUsers = new ArrayCollection();
     }
 
     public function getId(): ?int
@@ -96,6 +154,18 @@ class Access implements UserInterface
         return $this;
     }
 
+    public function getSuperAdminAccess(): ?bool
+    {
+        return $this->superAdminAccess;
+    }
+
+    public function setSuperAdminAccess(bool $superAdminAccess): self
+    {
+        $this->superAdminAccess = $superAdminAccess;
+
+        return $this;
+    }
+
     public function getPerson(): ?Person
     {
         return $this->person;
@@ -120,9 +190,44 @@ class Access implements UserInterface
         return $this;
     }
 
-    /**
-     * @return Collection|PersonActivity[]
-     */
+    public function getActivityYear(): ?int
+    {
+        return $this->activityYear;
+    }
+
+    public function setActivityYear(?int $activityYear): self
+    {
+        $this->activityYear = $activityYear;
+
+        return $this;
+    }
+
+    public function getHistorical(): array
+    {
+        return array_key_exists('historical', $this->setting) && $this->setting['historical'] ? $this->setting['historical'] : ['present' => true];
+    }
+
+    public function setHistorical(array $historical): self
+    {
+        if(!$historical['past'] && !$historical['present'] && !$historical['future'])
+            $historical['present'] = true;
+
+        $this->setting['historical'] = $historical;
+        return $this;
+    }
+
+    public function setRoles(?array $roles): self
+    {
+        $this->roles = $roles;
+        return $this;
+    }
+
+    public function getRoles(): ?array
+    {
+        $roles = $this->roles;
+        return array_unique($roles);
+    }
+
     public function getPersonActivity(): Collection
     {
         return $this->personActivity;
@@ -150,60 +255,33 @@ class Access implements UserInterface
         return $this;
     }
 
-    /**
-     * A visual identifier that represents this user.
-     *
-     * @see string
-     */
-    public function getUserIdentifier(): string
+    public function getOrganizationFunction(): Collection
     {
-        return $this->getPerson()->getUsername();
-    }
-
-    /**
-     * @inheritDoc
-     */
-    public function getRoles()
-    {
-        $roles = $this->roles;
-        return array_unique($roles);
+        return $this->organizationFunction;
     }
 
-    /**
-     * @inheritDoc
-     */
-    public function getPassword()
+    public function addOrganizationFunction (OrganizationFunction $organizationFunction): self
     {
-        // TODO: Implement getPassword() method.
-    }
+        if (!$this->organizationFunction->contains($organizationFunction)) {
+            $this->organizationFunction[] = $organizationFunction;
+            $organizationFunction->setAccess($this);
+        }
 
-    /**
-     * @inheritDoc
-     */
-    public function getSalt()
-    {
-        // TODO: Implement getSalt() method.
+        return $this;
     }
 
-    /**
-     * @inheritDoc
-     */
-    public function getUsername()
+    public function removeOrganizationFunction(OrganizationFunction $organizationFunction): self
     {
-        // TODO: Implement getUsername() method.
-    }
+        if ($this->organizationFunction->removeElement($organizationFunction)) {
+            // set the owning side to null (unless already changed)
+            if ($organizationFunction->getAccess() === $this) {
+                $organizationFunction->setAccess(null);
+            }
+        }
 
-    /**
-     * @inheritDoc
-     */
-    public function eraseCredentials()
-    {
-        // TODO: Implement eraseCredentials() method.
+        return $this;
     }
 
-    /**
-     * @return Collection|OrganizationLicence[]
-     */
     public function getOrganizationLicences(): Collection
     {
         return $this->organizationLicences;
@@ -230,4 +308,235 @@ class Access implements UserInterface
 
         return $this;
     }
+
+    public function getPersonalizedLists(): Collection
+    {
+        return $this->personalizedLists;
+    }
+
+    public function addPersonalizedList(PersonalizedList $personalizedList): self
+    {
+        if (!$this->personalizedLists->contains($personalizedList)) {
+            $this->personalizedLists[] = $personalizedList;
+            $personalizedList->setAccess($this);
+        }
+
+        return $this;
+    }
+
+    public function removePersonalizedList(PersonalizedList $personalizedList): self
+    {
+        if ($this->personalizedLists->removeElement($personalizedList)) {
+            // set the owning side to null (unless already changed)
+            if ($personalizedList->getAccess() === $this) {
+                $personalizedList->setAccess(null);
+            }
+        }
+
+        return $this;
+    }
+
+    public function getChildren(): Collection
+    {
+        return $this->children;
+    }
+
+    public function addChild (Access $access): self
+    {
+        if (!$this->children->contains($access)) {
+            $this->children[] = $access;
+            $access->addGuardian($this);
+        }
+        return $this;
+    }
+
+    public function removeChild(Access $access): self
+    {
+        if ($this->children->removeElement($access)) {
+            $access->removeGuardian($this);
+        }
+        return $this;
+    }
+
+    public function getGuardians(): Collection
+    {
+        return $this->guardians;
+    }
+
+    public function addGuardian(Access $access): self
+    {
+        if (!$this->guardians->contains($access)) {
+            $this->guardians[] = $access;
+            $access->addChild($this);
+        }
+        return $this;
+    }
+
+    public function removeGuardian(Access $access): self
+    {
+        if ($this->guardians->removeElement($access)) {
+            $access->removeChild($this);
+        }
+        return $this;
+    }
+
+    public function getBillingPayers(): Collection
+    {
+        return $this->billingPayers;
+    }
+
+    public function addBillingPayer(AccessPayer $billingPayer): self
+    {
+        if (!$this->billingPayers->contains($billingPayer)) {
+            $this->billingPayers[] = $billingPayer;
+            $billingPayer->setAccessPayer($this);
+        }
+
+        return $this;
+    }
+
+    public function removeBillingPayer(AccessPayer $billingPayer): self
+    {
+        if ($this->billingPayers->removeElement($billingPayer)) {
+            // set the owning side to null (unless already changed)
+            if ($billingPayer->getAccessPayer() === $this) {
+                $billingPayer->setAccessPayer(null);
+            }
+        }
+
+        return $this;
+    }
+
+    public function getBillingReceivers(): Collection
+    {
+        return $this->billingReceivers;
+    }
+
+    public function addBillingReceiver(AccessPayer $billingReceiver): self
+    {
+        if (!$this->billingReceivers->contains($billingReceiver)) {
+            $this->billingReceivers[] = $billingReceiver;
+            $billingReceiver->setAccessReceiver($this);
+        }
+
+        return $this;
+    }
+
+    public function removeBillingReceiver(AccessPayer $billingPayer): self
+    {
+        if ($this->billingReceivers->removeElement($billingPayer)) {
+            // set the owning side to null (unless already changed)
+            if ($billingPayer->getAccessReceiver() === $this) {
+                $billingPayer->setAccessReceiver(null);
+            }
+        }
+
+        return $this;
+    }
+
+    public function getAccessIntangibles(): Collection
+    {
+        return $this->accessIntangibles;
+    }
+
+    public function addAccessIntangible(AccessIntangible $accessIntangibles): self
+    {
+        if (!$this->accessIntangibles->contains($accessIntangibles)) {
+            $this->accessIntangibles[] = $accessIntangibles;
+            $accessIntangibles->setAccess($this);
+        }
+
+        return $this;
+    }
+
+    public function removeAccessIntangible(AccessIntangible $accessIntangibles): self
+    {
+        if ($this->accessIntangibles->removeElement($accessIntangibles)) {
+            // set the owning side to null (unless already changed)
+            if ($accessIntangibles->getAccess() === $this) {
+                $accessIntangibles->setAccess(null);
+            }
+        }
+
+        return $this;
+    }
+
+    public function getNotifications(): Collection
+    {
+        return $this->notifications;
+    }
+
+    public function addNotification(Notification $notification): self
+    {
+        if (!$this->notifications->contains($notification)) {
+            $this->notifications[] = $notification;
+            $notification->setRecipientAccess($this);
+        }
+
+        return $this;
+    }
+
+    public function removeNotification(Notification $notification): self
+    {
+        if ($this->notifications->removeElement($notification)) {
+            // set the owning side to null (unless already changed)
+            if ($notification->getRecipientAccess() === $this) {
+                $notification->setRecipientAccess(null);
+            }
+        }
+
+        return $this;
+    }
+
+    public function getNotificationUsers(): Collection
+    {
+        return $this->notificationUsers;
+    }
+
+    public function addNotificationUser(NotificationUser $notificationUser): self
+    {
+        if (!$this->notificationUsers->contains($notificationUser)) {
+            $this->notificationUsers[] = $notificationUser;
+            $notificationUser->setAccess($this);
+        }
+
+        return $this;
+    }
+
+    public function removeNotificationUser(NotificationUser $notificationUser): self
+    {
+        if ($this->notificationUsers->removeElement($notificationUser)) {
+            // set the owning side to null (unless already changed)
+            if ($notificationUser->getAccess() === $this) {
+                $notificationUser->setAccess(null);
+            }
+        }
+
+        return $this;
+    }
+
+    #[Pure] public function getUserIdentifier(): string
+    {
+        return $this->person->getUsername();
+    }
+
+    public function getPassword()
+    {
+        // TODO: Implement getPassword() method.
+    }
+
+    public function getSalt()
+    {
+        // TODO: Implement getSalt() method.
+    }
+
+    public function getUsername()
+    {
+        // TODO: Implement getUsername() method.
+    }
+
+    public function eraseCredentials()
+    {
+        // TODO: Implement eraseCredentials() method.
+    }
 }

+ 71 - 0
src/Entity/Access/FunctionType.php

@@ -0,0 +1,71 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Entity\Access;
+
+use App\Repository\Access\FunctionTypeRepository;
+use Doctrine\ORM\Mapping as ORM;
+use Symfony\Component\Validator\Constraints as Assert;
+
+/**
+ * Enum des fonctions que peuvent occuper un Access au sein d'une Organization
+ *
+ */
+#[ORM\Entity(repositoryClass: FunctionTypeRepository::class)]
+class FunctionType
+{
+    #[ORM\Id]
+    #[ORM\GeneratedValue]
+    #[ORM\Column]
+    private ?int $id = null;
+
+    #[ORM\Column]
+    #[Assert\Choice(callback: ['\App\Enum\Access\TypeFunctionEnum', 'toArray'], message: 'invalid-function-type')]
+    private string $functionType;
+
+    #[ORM\Column]
+    #[Assert\Choice(callback: ['\App\Enum\Access\FunctionEnum', 'toArray'], message: 'invalid-function')]
+    private string $mission;
+
+    #[ORM\Column]
+    #[Assert\Choice(callback: ['\App\Enum\Access\RoleEnum', 'toArray'], message: 'invalid-role')]
+    private string $roleByDefault;
+
+    public function getId(): ?int
+    {
+        return $this->id;
+    }
+
+    public function getFunctionType(): string
+    {
+        return $this->functionType;
+    }
+
+    public function setFunctionType(string $functionType): self
+    {
+        $this->functionType = $functionType;
+        return $this;
+    }
+
+    public function getMission(): string
+    {
+        return $this->mission;
+    }
+
+    public function setMission(string $mission): self
+    {
+        $this->mission = $mission;
+        return $this;
+    }
+
+    public function getRoleByDefault(): string
+    {
+        return $this->roleByDefault;
+    }
+
+    public function setRoleByDefault(string $roleByDefault): self
+    {
+        $this->roleByDefault = $roleByDefault;
+        return $this;
+    }
+}

+ 61 - 34
src/Entity/Access/OrganizationFunction.php

@@ -4,66 +4,69 @@ declare(strict_types=1);
 namespace App\Entity\Access;
 
 use ApiPlatform\Core\Annotation\ApiResource;
+use App\Entity\Traits\ActivityPeriodTrait;
 use App\Repository\Access\OrganizationFunctionRepository;
 use Doctrine\ORM\Mapping as ORM;
+use Symfony\Component\Validator\Constraints as Assert;
 
 /**
  * Fonction d'un Access dans une Organization sur une période donnée
- *
- * @ApiResource()
- * @ORM\Entity(repositoryClass=OrganizationFunctionRepository::class)
  */
+#[ApiResource]
+#[ORM\Entity(repositoryClass: OrganizationFunctionRepository::class)]
 class OrganizationFunction
 {
-    /**
-     * @ORM\Id
-     * @ORM\GeneratedValue
-     * @ORM\Column(type="integer")
-     */
-    private $id;
-
-    /**
-     * @ORM\Column(type="date")
-     */
-    private $startDate;
-
-    /**
-     * @ORM\Column(type="date", nullable=true)
-     */
-    private $endDate;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $functionComplement;
+    use ActivityPeriodTrait;
+
+    #[ORM\Id]
+    #[ORM\GeneratedValue]
+    #[ORM\Column]
+    private ?int $id = null;
+
+    #[ORM\ManyToOne(inversedBy: 'organizationFunction')]
+    private ?Access $access = null;
+
+    #[ORM\ManyToOne]
+    #[ORM\JoinColumn(nullable: false)]
+    private FunctionType $functionType;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $functionComplement = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    #[Assert\Choice(callback: ['\App\Enum\Access\DeparturesCauseEnum', 'toArray'], message: 'invalid-departure-cause')]
+    private ?string $departureCause = null;
+
+    #[ORM\Column(options: ['default' => true])]
+    private bool $isMemberSection = true;
 
     public function getId(): ?int
     {
         return $this->id;
     }
 
-    public function getStartDate(): ?\DateTimeInterface
+    public function getAccess(): ?Access
     {
-        return $this->startDate;
+        return $this->access;
     }
 
-    public function setStartDate(\DateTimeInterface $startDate): self
+    public function setAccess(?Access $access): self
     {
-        $this->startDate = $startDate;
+        $this->access = $access;
 
         return $this;
     }
 
-    public function getEndDate(): ?\DateTimeInterface
+    public function setFunctionType(FunctionType $functionType): self
     {
-        return $this->endDate;
+        $this->functionType = $functionType;
+
+        return $this;
     }
 
-    public function setEndDate(?\DateTimeInterface $endDate): self
+    public function getFunctionType(): FunctionType
     {
-        $this->endDate = $endDate;
-
-        return $this;
+        return $this->functionType;
     }
 
     public function getFunctionComplement(): ?string
@@ -77,4 +80,28 @@ class OrganizationFunction
 
         return $this;
     }
+
+    public function setDepartureCause(?string $departureCause): self
+    {
+        $this->departureCause = $departureCause;
+
+        return $this;
+    }
+
+    public function getDepartureCause():?string
+    {
+        return $this->departureCause;
+    }
+
+    public function setIsMemberSection(bool $isMemberSection): self
+    {
+        $this->isMemberSection = $isMemberSection;
+
+        return $this;
+    }
+
+    public function getIsMemberSection(): bool
+    {
+        return $this->isMemberSection;
+    }
 }

+ 147 - 0
src/Entity/Access/PersonalizedList.php

@@ -0,0 +1,147 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Access;
+
+use ApiPlatform\Core\Annotation\ApiResource;
+use App\Repository\Access\PersonalizedListRepository;
+use Doctrine\ORM\Mapping as ORM;
+use JetBrains\PhpStorm\Pure;
+use Symfony\Component\Serializer\Annotation\Groups;
+
+/**
+ * Liste personnalisées
+ */
+#[ApiResource(
+    collectionOperations: [
+        'get' => [
+            'normalization_context' => [
+                'groups' => ['lists:output']
+            ]
+        ]
+    ],
+    itemOperations: [
+        'get' => [
+            'security' => 'object.getAccess().getId() == user.getId()'
+        ]
+    ],
+    attributes: [
+        'pagination_enabled' => false
+    ]
+)]
+#[ORM\Entity(repositoryClass: PersonalizedListRepository::class)]
+class PersonalizedList
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    #[Groups(['lists:output'])]
+    private ?int $id = null;
+
+    #[ORM\ManyToOne(inversedBy: 'personalizedLists')]
+    #[ORM\JoinColumn(nullable: false)]
+    private ?Access $access = null;
+
+
+    #[ORM\Column(length: 200, nullable: true)]
+    #[Groups(['lists:output'])]
+    private ?string $label = null;
+
+    #[ORM\Column(length: 4294967295, nullable: true)]
+    private ?array $filters = null;
+
+    #[ORM\Column(length: 150)]
+    #[Groups(['lists:output'])]
+    private string $entity;
+
+    #[ORM\Column(length: 4294967295, nullable: true)]
+    private array $columns;
+
+    #[ORM\Column(length: 150, nullable: true)]
+    #[Groups(['lists:output'])]
+    private string $menuKey;
+
+    #[Pure] public function __construct()
+    {
+    }
+
+    public function getId(): ?int
+    {
+        return $this->id;
+    }
+
+
+    public function setFilters(array $filters):self
+    {
+        $this->filters = $filters;
+
+        return $this;
+    }
+
+    public function getFilters(): ?array
+    {
+        return $this->filters;
+    }
+
+    public function setColumns(array $columns):self
+    {
+        $this->columns = $columns;
+
+        return $this;
+    }
+
+    public function getColumns(): ?array
+    {
+        return $this->columns;
+    }
+
+
+    public function setAccess(Access $access):self
+    {
+        $this->access = $access;
+
+        return $this;
+    }
+
+    public function getAccess(): ?Access
+    {
+        return $this->access;
+    }
+
+    public function setMenuKey(string $menuKey):self
+    {
+        $this->menuKey = $menuKey;
+
+        return $this;
+    }
+
+    public function getMenuKey(): ?string
+    {
+        return $this->menuKey;
+    }
+
+    public function setLabel(string $label):self
+    {
+        $this->label = $label;
+
+        return $this;
+    }
+
+    public function getLabel(): ?string
+    {
+        return $this->label;
+    }
+
+    public function setEntity(string $entity):self
+    {
+        $this->entity = $entity;
+
+        return $this;
+    }
+
+    public function getEntity(): ?string
+    {
+        return $this->entity;
+    }
+}

+ 30 - 0
src/Entity/Billing/AbstractBillingIntangible.php

@@ -0,0 +1,30 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * Enregistrement d'un produit à facturer par une Organization, un Access ou un EducationalProject
+ * Classe de base de @see AccessIntangible, EducationalProjectIntangible
+ */
+
+#[ORM\Entity]
+#[ORM\Table(name: 'BillingIntangible')]
+#[ORM\InheritanceType('SINGLE_TABLE')]
+#[ORM\DiscriminatorColumn(name: 'discr', type: 'string')]
+#[ORM\DiscriminatorMap([
+    'access' => 'AccessIntangible'
+])]
+abstract class AbstractBillingIntangible{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    public function getId(): ?int
+    {
+        return $this->id;
+    }
+}

+ 30 - 0
src/Entity/Billing/AbstractBillingPayer.php

@@ -0,0 +1,30 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * Fais le lien entre l'Access qui règle la facture et l'Access ou
+ * l'EducationalProject concerné par la facture
+ * Classe de base de @see  AccessPayer, EducationalProjectPayer
+ */
+#[ORM\Entity]
+#[ORM\Table(name: 'BillingPayer')]
+#[ORM\InheritanceType('SINGLE_TABLE')]
+#[ORM\DiscriminatorColumn(name: 'discr', type: 'string')]
+#[ORM\DiscriminatorMap([
+    'access' => 'AccessPayer'
+])]
+abstract class AbstractBillingPayer{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    public function getId(): ?int
+    {
+        return $this->id;
+    }
+}

+ 31 - 0
src/Entity/Billing/AccessIntangible.php

@@ -0,0 +1,31 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use ApiPlatform\Core\Annotation\ApiResource;
+use App\Entity\Access\Access;
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * Enregistrement d'un produit à facturer par un Access
+ */
+#[ApiResource]
+#[ORM\Entity(repositoryClass: AccessIntangible::class)]
+class AccessIntangible extends AbstractBillingIntangible
+{
+    #[ORM\ManyToOne(inversedBy: 'accessIntangibles')]
+    private ?Access $access = null;
+
+    public function setAccess(?Access $access): self
+    {
+        $this->access = $access;
+
+        return $this;
+    }
+
+    public function getAccess(): ?Access
+    {
+        return $this->access;
+    }
+}

+ 49 - 0
src/Entity/Billing/AccessPayer.php

@@ -0,0 +1,49 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use ApiPlatform\Core\Annotation\ApiResource;
+use App\Repository\Billing\AccessPayerRepository;
+use App\Entity\Access\Access;
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * Fais le lien entre l'Access qui règle la facture et l'Access concerné
+ *
+ */
+#[ApiResource]
+#[ORM\Entity(repositoryClass: AccessPayerRepository::class)]
+class AccessPayer extends AbstractBillingPayer
+{
+    #[ORM\ManyToOne(inversedBy: 'billingPayers')]
+    private ?Access $accessPayer = null;
+
+    #[ORM\ManyToOne(inversedBy: 'billingReceivers')]
+    private ?Access $accessReceiver = null;
+
+    public function setAccessPayer(?Access $accessPayer): self
+    {
+        $this->accessPayer = $accessPayer;
+
+        return $this;
+    }
+
+    public function getAccessPayer():?Access
+    {
+        return $this->accessPayer;
+    }
+
+    public function setAccessReceiver(?Access $accessReceiver): self
+    {
+        $this->accessReceiver = $accessReceiver;
+
+        return $this;
+    }
+
+    public function getAccessReceiver():?Access
+    {
+        return $this->accessReceiver;
+    }
+}

+ 35 - 60
src/Entity/Core/AddressPostal.php

@@ -3,72 +3,47 @@ declare(strict_types=1);
 
 namespace App\Entity\Core;
 
-use ApiPlatform\Core\Annotation\ApiResource;
 use App\Entity\Organization\OrganizationAddressPostal;
 use App\Repository\Core\AddressPostalRepository;
 use Doctrine\ORM\Mapping as ORM;
 
-/**
- * @ORM\Entity(repositoryClass=AddressPostalRepository::class)
- */
+#[ORM\Entity(repositoryClass: AddressPostalRepository::class)]
 class AddressPostal
 {
-    /**
-     * @ORM\Id
-     * @ORM\GeneratedValue
-     * @ORM\Column(type="integer")
-     */
-    private $id;
-
-    /**
-     * @ORM\ManyToOne(targetEntity=Country::class)
-     */
-    private $addressCountry;
-
-    /**
-     * @ORM\Column(type="string", length=100, nullable=true)
-     */
-    private $addressCity;
-
-    /**
-     * @ORM\Column(type="string", length=100, nullable=true)
-     */
-    private $addressOwner;
-
-    /**
-     * @ORM\Column(type="string", length=20, nullable=true)
-     */
-    private $postalCode;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $streetAddress;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $streetAddressSecond;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $streetAddressThird;
-
-    /**
-     * @ORM\Column(type="float", nullable=true)
-     */
-    private $latitude;
-
-    /**
-     * @ORM\Column(type="float", nullable=true)
-     */
-    private $longitude;
-
-    /**
-     * @ORM\OneToOne(targetEntity=OrganizationAddressPostal::class, mappedBy="addressPostal", cascade={"persist", "remove"})
-     */
-    private $organizationAddressPostal;
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    #[ORM\ManyToOne]
+    private ?Country $addressCountry = null;
+
+    #[ORM\Column(length: 100, nullable: true)]
+    private ?string $addressCity = null;
+
+    #[ORM\Column(length: 100, nullable: true)]
+    private ?string $addressOwner = null;
+
+    #[ORM\Column(length: 20, nullable: true)]
+    private ?string $postalCode = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $streetAddress = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $streetAddressSecond = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $streetAddressThird = null;
+
+    #[ORM\Column(nullable: true)]
+    private ?float $latitude = null;
+
+    #[ORM\Column(nullable: true)]
+    private ?float $longitude = null;
+
+    #[ORM\OneToOne(mappedBy: 'addressPostal', cascade: ['persist', 'remove'])]
+    private OrganizationAddressPostal $organizationAddressPostal;
 
     public function getId(): ?int
     {

+ 50 - 79
src/Entity/Core/BankAccount.php

@@ -9,103 +9,77 @@ use App\Repository\Core\BankAccountRepository;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
+use JetBrains\PhpStorm\Pure;
 use Symfony\Component\Validator\Constraints as Assert;
 
 /**
  * Données bancaire d'une Person ou d'une Organization
- *
- * @ApiResource(
- *     itemOperations={
- *           "get"={"security"="is_granted('BANK_ACCOUNT_READ', object)"},
- *           "put"={"security"="is_granted('BANK_ACCOUNT_EDIT', object)"},
- *     }
- * )
- * @ORM\Entity(repositoryClass=BankAccountRepository::class)
  */
+#[ApiResource(
+    itemOperations: [
+        'get' => [
+            'security' => 'is_granted("BANK_ACCOUNT_READ", object)'
+        ],
+        'put' => [
+            'security' => 'is_granted("BANK_ACCOUNT_EDIT", object)'
+        ]
+    ]
+)]
+#[ORM\Entity(repositoryClass: BankAccountRepository::class)]
 class BankAccount
 {
-    /**
-     * @ORM\Id
-     * @ORM\GeneratedValue
-     * @ORM\Column(type="integer")
-     */
-    private $id;
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
 
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $bankName;
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $bankName = null;
 
-    /**
-     * @ORM\Column(type="string", length=11, nullable=true)
-     * @Assert\Bic(
-     *    message="invalid_bic"
-     * )
-     */
-    private $bic;
+    #[ORM\Column(length: 11, nullable: true)]
+    #[Assert\Bic(message: 'invalid_bic')]
+    private ?string $bic = null;
 
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $bicInvalid;
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $bicInvalid = null;
 
-    /**
-     * @ORM\Column(type="string", length=34, nullable=true)
-     * @Assert\Iban(
-     *    message="invalid_iban"
-     * )
-     */
-    private $iban;
+    #[ORM\Column(length: 34, nullable: true)]
+    #[Assert\Iban(message: 'invalid_iban')]
+    private ?string $iban = null;
 
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $ibanInvalid;
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $ibanInvalid = null;
 
-    /**
-     * @ORM\Column(type="boolean", options={"default" : false})
-     */
-    private $holderIdDifferent = false;
+    #[ORM\Column(options: ['default'=>false])]
+    private bool $holderIdDifferent = false;
 
     /**
      * 0 => jamais facturé, 1 => facturé 1 fois, 2 => facturé plusieurs fois
-     * @ORM\Column(type="integer", options={"default" : 0})
      */
-    private $countInvoiced;
+    #[ORM\Column(options: ['default'=>0])]
+    private int $countInvoiced;
 
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $holder;
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $holder = null;
 
-    /**
-     * @ORM\Column(type="boolean", options={"default" : false})
-     * @Assert\NotNull
-     */
-    private $principal = false;
+    #[ORM\Column(options: ['default'=>false])]
+    #[Assert\NotNull]
+    private bool $principal = false;
 
-    /**
-     * @ORM\Column(type="text", nullable=true)
-     */
-    private $debitAddress;
+    #[ORM\Column(type: 'text', nullable: true)]
+    private ?string $debitAddress = null;
 
-    /**
-     * @ORM\Column(type="string", length=35, nullable=true, unique=true)
-     */
-    private $rum;
+    #[ORM\Column(length: 35, unique: true, nullable: true)]
+    private ?string $rum = null;
 
-    /**
-     * @ORM\Column(type="date", nullable=true)
-     */
-    private $signatureDateSamplingMandate;
+    #[ORM\Column(type: 'date', nullable: true)]
+    private \DateTimeInterface $signatureDateSamplingMandate;
 
-    /**
-     * @ORM\ManyToMany(targetEntity=Organization::class, inversedBy="bankAccounts")
-     * @ORM\JoinTable(name="organization_bankaccount")
-     */
-    private $organization;
+    #[ORM\ManyToMany(targetEntity: Organization::class, inversedBy: 'bankAccounts')]
+    #[ORM\JoinTable(name: 'organization_bankaccount')]
+    private Collection $organization;
 
-    public function __construct()
+    #[Pure] public function __construct()
     {
         $this->organization = new ArrayCollection();
     }
@@ -175,7 +149,7 @@ class BankAccount
         return $this;
     }
 
-    public function getHolderIdDifferent(): ?bool
+    public function getHolderIdDifferent(): bool
     {
         return $this->holderIdDifferent;
     }
@@ -187,7 +161,7 @@ class BankAccount
         return $this;
     }
 
-    public function getCountInvoiced(): ?int
+    public function getCountInvoiced(): int
     {
         return $this->countInvoiced;
     }
@@ -211,7 +185,7 @@ class BankAccount
         return $this;
     }
 
-    public function getPrincipal(): ?bool
+    public function getPrincipal(): bool
     {
         return $this->principal;
     }
@@ -235,9 +209,6 @@ class BankAccount
         return $this;
     }
 
-    /**
-     * @return Collection|Organization[]
-     */
     public function getOrganization(): Collection
     {
         return $this->organization;

+ 60 - 82
src/Entity/Core/ContactPoint.php

@@ -6,6 +6,7 @@ namespace App\Entity\Core;
 use ApiPlatform\Core\Annotation\ApiResource;
 use App\Entity\Organization\Organization;
 use App\Entity\Person\Person;
+use JetBrains\PhpStorm\Pure;
 use libphonenumber\PhoneNumber;
 use App\Repository\Core\ContactPointRepository;
 use Doctrine\Common\Collections\ArrayCollection;
@@ -15,84 +16,67 @@ use Symfony\Component\Validator\Constraints as Assert;
 
 /**
  * Données de contact d'une Person ou d'une Organization ou d'un lieu
- * @ApiResource(
- *     itemOperations={
- *           "get"={"security"="is_granted('CONTACT_POINT_READ', object)"},
- *           "put"={"security"="is_granted('CONTACT_POINT_EDIT', object)"},
- *     }
- * )
- * @ORM\Entity(repositoryClass=ContactPointRepository::class)
  */
+#[ApiResource(
+    itemOperations: [
+        'get' => [
+            'security' => 'is_granted("CONTACT_POINT_READ", object)'
+        ],
+        'put' => [
+            'security' => 'is_granted("CONTACT_POINT_EDIT", object)'
+        ],
+        'delete' => [
+            'security' => 'is_granted("CONTACT_POINT_DELETE", object)'
+        ]
+    ]
+)]
+#[ORM\Entity(repositoryClass: ContactPointRepository::class)]
 class ContactPoint
 {
-    /**
-     * @ORM\Id
-     * @ORM\GeneratedValue
-     * @ORM\Column(type="integer")
-     */
-    private $id;
-
-    /**
-     * @ORM\Column(type="string", length=255)
-     * @Assert\Choice(callback={"\App\Enum\Core\ContactPointTypeEnum", "toArray"}, message="invalid-choice")
-     */
-    private $contactType;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     * @Assert\Email(mode="strict", message="invalid-email-format")
-     * @Assert\Regex(pattern="/^[a-zA-Z0-9._%-]{1,64}@[a-zA-Z0-9.-]{2,249}\.[a-zA-Z]{2,6}$/", message="email-error")
-     */
-    private $email;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $emailInvalid;
-
-    /**
-     * @ORM\Column(type="phone_number", nullable=true)
-     */
-    private $faxNumber;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $faxNumberInvalid;
-
-    /**
-     * @ORM\Column(type="phone_number", nullable=true)
-     */
-    private $telphone;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $telphoneInvalid;
-
-    /**
-     * @ORM\Column(type="phone_number", nullable=true)
-     */
-    private $mobilPhone;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $mobilPhoneInvalid;
-
-    /**
-     * @ORM\ManyToMany(targetEntity=Organization::class, inversedBy="contactPoints")
-     * @ORM\JoinTable(name="organization_contactpoint")
-     */
-    private $organization;
-
-    /**
-     * @ORM\ManyToMany(targetEntity=Person::class, inversedBy="contactPoints")
-     * @ORM\JoinTable(name="person_contactpoint")
-     */
-    private $person;
-
-    public function __construct()
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    #[ORM\Column(length: 255)]
+    #[Assert\Choice(callback: ['\App\Enum\Core\ContactPointTypeEnum', 'toArray'], message: 'invalid-contact-type')]
+    private string $contactType;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    #[Assert\Email(message: 'invalid-email-format', mode: 'strict')]
+    #[Assert\Regex(pattern: '/^[a-zA-Z0-9._%-]{1,64}@[a-zA-Z0-9.-]{2,249}\.[a-zA-Z]{2,6}$/', message: 'email-error')]
+    private ?string $email = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $emailInvalid = null;
+
+    #[ORM\Column(type: 'phone_number', nullable: true)]
+    private ?PhoneNumber $faxNumber = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $faxNumberInvalid = null;
+
+    #[ORM\Column(type: 'phone_number', nullable: true)]
+    private ?PhoneNumber $telphone = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $telphoneInvalid = null;
+
+    #[ORM\Column(type: 'phone_number', nullable: true)]
+    private ?PhoneNumber $mobilPhone = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $mobilPhoneInvalid = null;
+
+    #[ORM\ManyToMany(targetEntity: Organization::class, inversedBy: 'contactPoints')]
+    #[ORM\JoinTable(name: 'organization_contactpoint')]
+    private Collection $organization;
+
+    #[ORM\ManyToMany(targetEntity: Person::class ,inversedBy: 'contactPoints')]
+    #[ORM\JoinTable(name: 'person_contactpoint')]
+    private Collection $person;
+
+    #[Pure] public function __construct()
     {
         $this->organization = new ArrayCollection();
         $this->person = new ArrayCollection();
@@ -103,7 +87,7 @@ class ContactPoint
         return $this->id;
     }
 
-    public function getContactType(): ?string
+    public function getContactType(): string
     {
         return $this->contactType;
     }
@@ -223,9 +207,6 @@ class ContactPoint
         return $this;
     }
 
-    /**
-     * @return Collection|Organization[]
-     */
     public function getOrganization(): Collection
     {
         return $this->organization;
@@ -247,9 +228,6 @@ class ContactPoint
         return $this;
     }
 
-    /**
-     * @return Collection|Person[]
-     */
     public function getPerson(): Collection
     {
         return $this->person;

+ 10 - 15
src/Entity/Core/Country.php

@@ -1,33 +1,28 @@
 <?php
+declare(strict_types=1);
 
 namespace App\Entity\Core;
 
 use App\Repository\Core\CountryRepository;
 use Doctrine\ORM\Mapping as ORM;
 
-/**
- * @ORM\Entity(repositoryClass=CountryRepository::class)
- */
+#[ORM\Entity(repositoryClass: CountryRepository::class)]
 class Country
 {
-    /**
-     * @ORM\Id
-     * @ORM\GeneratedValue
-     * @ORM\Column(type="integer")
-     */
-    private $id;
-
-    /**
-     * @ORM\Column(type="string", length=255)
-     */
-    private $name;
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    #[ORM\Column(length: 255)]
+    private string $name;
 
     public function getId(): ?int
     {
         return $this->id;
     }
 
-    public function getName(): ?string
+    public function getName(): string
     {
         return $this->name;
     }

+ 117 - 0
src/Entity/Core/File.php

@@ -0,0 +1,117 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Entity\Core;
+
+use App\Entity\Person\Person;
+use App\Repository\Core\FileRepository;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
+use Doctrine\ORM\Mapping as ORM;
+use JetBrains\PhpStorm\Pure;
+
+#[ORM\Entity(repositoryClass: FileRepository::class)]
+class File
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    #[ORM\Column(length: 255)]
+    private string $slug;
+
+    #[ORM\Column(length: 255)]
+    private string $path;
+
+    #[ORM\Column(length: 255)]
+    private string $name;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $mimeType = null;
+
+    #[ORM\OneToMany(mappedBy: 'image', targetEntity: Person::class, orphanRemoval: true)]
+    private Collection $personImages;
+
+    #[Pure] public function __construct()
+    {
+        $this->personImages = new ArrayCollection();
+    }
+
+    public function getId(): ?int
+    {
+        return $this->id;
+    }
+
+    public function getSlug(): string
+    {
+        return $this->slug;
+    }
+
+    public function setSlug(string $slug): self
+    {
+        $this->slug = $slug;
+        return $this;
+    }
+
+    public function getPath(): string
+    {
+        return $this->path;
+    }
+
+    public function setPath(string $path): self
+    {
+        $this->path = $path;
+        return $this;
+
+    }
+
+    public function getName(): string
+    {
+        return $this->name;
+    }
+
+    public function setName(string $name): self
+    {
+        $this->name = $name;
+        return $this;
+    }
+
+    public function getMimeType(): ?string
+    {
+        return $this->mimeType;
+    }
+
+    public function setMimeType(?string $mimeType): self
+    {
+        $this->mimeType = $mimeType;
+        return $this;
+    }
+
+    public function getPersonImages(): Collection
+    {
+        return $this->personImages;
+    }
+
+    public function addPersonImage (Person $person): self
+    {
+        if (!$this->personImages->contains($person)) {
+            $this->personImages[] = $person;
+            $person->setImage($this);
+        }
+
+        return $this;
+    }
+
+    public function removePersonImage(Person $person): self
+    {
+        if ($this->personImages->removeElement($person)) {
+            // set the owning side to null (unless already changed)
+            if ($person->getImage() === $this) {
+                $person->setImage(null);
+            }
+        }
+
+        return $this;
+    }
+}

+ 174 - 0
src/Entity/Core/Notification.php

@@ -0,0 +1,174 @@
+<?php
+declare(strict_types=1);
+
+
+namespace App\Entity\Core;
+
+use ApiPlatform\Core\Annotation\ApiResource;
+use App\Entity\Access\Access;
+use App\Repository\Core\NotificationRepository;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
+use Doctrine\ORM\Mapping as ORM;
+use JetBrains\PhpStorm\Pure;
+use Symfony\Component\Validator\Constraints as Assert;
+
+/**
+ * @todo : A la suite de la migration, il faut supprimer le nom de la table pour avoir une table Notification, et supprimer l'attribut discr.
+ *
+ * Classe Notification. qui permet de gérer les notifications aux utilisateurs.
+ */
+#[ApiResource(
+    collectionOperations:[
+        'get' => [
+            'pagination_client_items_per_page' => true,
+            'pagination_maximum_items_per_page' => 20,
+            'order' => [
+                'id' => 'DESC'
+            ]
+        ]
+    ],
+    itemOperations: [
+        'get'
+    ]
+)]
+#[ORM\Entity(repositoryClass:NotificationRepository::class)]
+#[ORM\Table(name: 'Information')]
+class Notification
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    #[ORM\Column(length: 255, nullable: false)]
+    private string $discr = 'notification';
+
+    #[ORM\ManyToOne(inversedBy: 'notifications')]
+    #[ORM\JoinColumn(nullable: false)]
+    private ?Access $recipientAccess;
+
+    #[ORM\Column(length: 40, nullable: true)]
+    private ?string $name = null;
+
+    #[ORM\Column(type: 'json', length: 4294967295, nullable: true)]
+    private mixed $message = [];
+
+    #[ORM\Column(nullable: true)]
+    #[Assert\Choice(callback: ['\App\Enum\Core\NotificationTypeEnum', 'toArray'], message: 'invalid-type')]
+    private ?string $type = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $link = null;
+
+    #[ORM\Column(type: 'date', nullable: true)]
+    private ?\DateTimeInterface $availabilityDate = null;
+
+    #[ORM\OneToMany(mappedBy: 'notification', targetEntity: NotificationUser::class, cascade: ['persist'], orphanRemoval: true)]
+    private Collection $notificationUsers;
+
+    #[Pure] public function __construct()
+    {
+        $this->notificationUsers = new ArrayCollection();
+    }
+
+    public function getId(): ?int
+    {
+        return $this->id;
+    }
+
+    public function setName(?string $name): self
+    {
+        $this->name = $name;
+        return $this;
+    }
+
+    public function getName(): ?string
+    {
+        return $this->name;
+    }
+
+    public function setRecipientAccess(?Access $recipientAccess): self
+    {
+        $this->recipientAccess = $recipientAccess;
+        return $this;
+    }
+
+    public function getRecipientAccess(): ?Access
+    {
+        return $this->recipientAccess;
+    }
+
+    public function setMessage(mixed $message): self
+    {
+        $this->message = $message;
+        return $this;
+    }
+
+    public function getMessage(): mixed
+    {
+        if(!is_array( $this->message)){
+            return ['about' => $this->message];
+        }
+        return $this->message;
+    }
+
+    public function setType(?string $type): self
+    {
+        $this->type = $type;
+        return $this;
+    }
+
+    public function getType(): ?string
+    {
+        return $this->type;
+    }
+
+    public function setLink(?string $link): self
+    {
+        $this->link = $link;
+        return $this;
+    }
+
+    public function getLink(): ?string
+    {
+        return $this->link;
+    }
+
+    public function getAvailabilityDate(): ?string {
+        return $this->availabilityDate?->format('Y-m-d');
+    }
+
+    public function setAvailabilityDate(?\DateTime $availabilityDate = null): self {
+        if($availabilityDate == null) $availabilityDate = new \DateTime();
+        $this->availabilityDate = $availabilityDate;
+        return $this;
+    }
+
+    public function getNotificationUsers(): Collection
+    {
+        return $this->notificationUsers;
+    }
+
+    public function addNotificationUser(NotificationUser $notificationUsers): self
+    {
+        if (!$this->notificationUsers->contains($notificationUsers)) {
+            $this->notificationUsers[] = $notificationUsers;
+            $notificationUsers->setNotification($this);
+        }
+
+        return $this;
+    }
+
+    public function removeNotificationUser(NotificationUser $notificationUsers): self
+    {
+        if ($this->notificationUsers->removeElement($notificationUsers)) {
+            // set the owning side to null (unless already changed)
+            if ($notificationUsers->getNotification() === $this) {
+                $notificationUsers->setNotification(null);
+            }
+        }
+
+        return $this;
+    }
+}

+ 82 - 0
src/Entity/Core/NotificationUser.php

@@ -0,0 +1,82 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Entity\Core;
+
+use ApiPlatform\Core\Annotation\ApiResource;
+use App\Entity\Access\Access;
+use App\Repository\Core\NotificationUserRepository;
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ *
+ * Classe NotificationUser. qui permet de gérer les notifications qui ont été lues par les Users.
+ */
+#[ApiResource(
+    collectionOperations: [
+        'post' => [
+            'security_post_denormalize' => 'object.getAccess().getId() == user.getId() 
+                       and object.getNotification().getRecipientAccess().getOrganization().getId() == user.getOrganization().getId()'
+        ]
+    ],
+    itemOperations: [
+        'get'
+    ]
+)]
+#[ORM\Entity(repositoryClass:NotificationUserRepository::class)]
+class NotificationUser
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    #[ORM\ManyToOne(inversedBy: 'notificationUsers')]
+    #[ORM\JoinColumn(nullable: false)]
+    private Notification $notification;
+
+    #[ORM\ManyToOne(inversedBy: 'notificationUsers')]
+    #[ORM\JoinColumn(nullable: false)]
+    private Access $access;
+
+    #[ORM\Column(nullable: false)]
+    private bool $isRead = true;
+
+    public function getId(): ?int
+    {
+        return $this->id;
+    }
+
+    public function setNotification(?Notification $notification): self
+    {
+        $this->notification = $notification;
+        return $this;
+    }
+
+    public function getNotification(): Notification
+    {
+        return $this->notification;
+    }
+
+    public function setAccess(?Access $access): self
+    {
+        $this->access = $access;
+        return $this;
+    }
+
+    public function getAccess(): Access
+    {
+        return $this->access;
+    }
+
+    public function setIsRead(?bool $isRead): self
+    {
+        $this->isRead = $isRead;
+        return $this;
+    }
+
+    public function getIsRead(): ?bool
+    {
+        return $this->isRead;
+    }
+}

+ 15 - 24
src/Entity/Network/Network.php

@@ -8,32 +8,23 @@ use Doctrine\ORM\Mapping as ORM;
 
 /**
  * Enum des différents réseaux auxquels peut appartenir une Organization
- *
- * @ORM\Entity(repositoryClass=NetworkRepository::class)
  */
+#[ORM\Entity(repositoryClass: NetworkRepository::class)]
 class Network
 {
-    /**
-     * @ORM\Id
-     * @ORM\GeneratedValue
-     * @ORM\Column(type="integer")
-     */
-    private $id;
-
-    /**
-     * @ORM\Column(type="string", length=255)
-     */
-    private $name;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $logo;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $url;
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    #[ORM\Column(length: 255)]
+    private string $name;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $logo = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $url = null;
 
     public function setId($id): self
     {
@@ -46,7 +37,7 @@ class Network
         return $this->id;
     }
 
-    public function getName(): ?string
+    public function getName(): string
     {
         return $this->name;
     }

+ 23 - 30
src/Entity/Network/NetworkOrganization.php

@@ -6,43 +6,36 @@ namespace App\Entity\Network;
 use ApiPlatform\Core\Annotation\ApiResource;
 use App\Entity\Organization\Organization;
 use App\Repository\Network\NetworkOrganizationRepository;
+use App\Entity\Traits\ActivityPeriodTrait;
 use Doctrine\ORM\Mapping as ORM;
 
 /**
  * Fait le lien entre une Organization et un Network
- * @ApiResource()
- * @ORM\Entity(repositoryClass=NetworkOrganizationRepository::class)
  */
+#[ApiResource]
+#[ORM\Entity(repositoryClass: NetworkOrganizationRepository::class)]
 class NetworkOrganization
 {
-    /**
-     * @ORM\Id
-     * @ORM\GeneratedValue
-     * @ORM\Column(type="integer")
-     */
-    private $id;
-
-    /**
-     * @ORM\ManyToOne(targetEntity=Network::class)
-     * @ORM\JoinColumn(nullable=false)
-     */
-    private $network;
-
-    /**
-     * @ORM\ManyToOne(targetEntity=Organization::class, inversedBy="networkOrganizations")
-     * @ORM\JoinColumn(nullable=false)
-     */
-    private $organization;
-
-    /**
-     * @ORM\ManyToOne(targetEntity=Organization::class, inversedBy="networkOrganizationChildren")
-     */
-    private $parent;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $leadingCause;
+    use ActivityPeriodTrait;
+
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    #[ORM\ManyToOne]
+    #[ORM\JoinColumn(nullable: true)]
+    private Network $network;
+
+    #[ORM\ManyToOne(inversedBy: 'networkOrganizations')]
+    #[ORM\JoinColumn(nullable: true)]
+    private Organization $organization;
+
+    #[ORM\ManyToOne(inversedBy: 'networkOrganizationChildren')]
+    private Organization $parent;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $leadingCause = null;
 
     public function getId(): ?int
     {

+ 169 - 275
src/Entity/Organization/Organization.php

@@ -12,265 +12,177 @@ use App\Repository\Organization\OrganizationRepository;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
+use JetBrains\PhpStorm\Pure;
 use Symfony\Component\Validator\Constraints as Assert;
 
 /**
  * Structure, organisation
- *
- * @ApiResource(
- *     itemOperations={
- *         "get"={"security"="(is_granted('ROLE_ORGANIZATION_VIEW') or is_granted('ROLE_ORGANIZATION')) and object.getId() == user.organization.getId() "},
- *         "put"={"security"="is_granted('ROLE_ORGANIZATION') and object.getId() == user.organization.getId() "}
- *     }
- * )
- * @ORM\Entity(repositoryClass=OrganizationRepository::class)
  */
+#[ApiResource(
+    itemOperations: [
+        'get' => [
+            'security' => '(is_granted("ROLE_ORGANIZATION_VIEW") or is_granted("ROLE_ORGANIZATION")) and object.getId() == user.getOrganization().getId()'
+        ],
+        'put' => [
+            'security' => 'is_granted("ROLE_ORGANIZATION") and object.getId() == user.getOrganization()s.getId()'
+        ]
+    ]
+)]
+#[ORM\Entity(repositoryClass: OrganizationRepository::class)]
 class Organization
 {
-    /**
-     * @ORM\Id
-     * @ORM\GeneratedValue
-     * @ORM\Column(type="integer")
-     */
-    private $id;
-
-    /**
-     * @ORM\Column(type="string", length=128)
-     */
-    private $name;
-
-    /**
-     * @ORM\Column(type="string", length=128)
-     */
-    private $identifier;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     * @Assert\Choice(callback={"\App\Enum\Organization\LegalEnum", "toArray"})
-     */
-    private $legalStatus;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     * @Assert\Choice(callback={"\App\Enum\Organization\PrincipalTypeEnum", "toArray"})
-     */
-    private $principalType;
-
-    /**
-     * @ORM\OneToOne(targetEntity=Settings::class, mappedBy="organization", cascade={"persist", "remove"})
-     */
-    private $settings;
-
-    /**
-     * @ORM\OneToMany(targetEntity=NetworkOrganization::class, mappedBy="organization", orphanRemoval=true)
-     */
-    private $networkOrganizations;
-
-    /**
-     * @ORM\OneToMany(targetEntity=NetworkOrganization::class, mappedBy="parent")
-     */
-    private $networkOrganizationChildren;
-
-    /**
-     * @ORM\OneToOne(targetEntity=Parameters::class, cascade={"persist", "remove"})
-     * @ORM\JoinColumn(nullable=false)
-     */
-    private $parameters;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $description;
-
-    /**
-     * @ORM\Column(type="date", nullable=true)
-     */
-    private $creationDate;
-
-    /**
-     * @ORM\Column(type="date", nullable=true)
-     */
-    private $declarationDate;
-
-    /**
-     * @ORM\Column(type="string", length=14, nullable=true)
-     */
-    private $siretNumber;
-
-    /**
-     * @ORM\Column(type="string", length=10, nullable=true)
-     */
-    private $waldecNumber;
-
-    /**
-     * @ORM\Column(type="string", length=5, nullable=true)
-     */
-    private $apeNumber;
-
-    /**
-     * @ORM\Column(type="string", length=50, nullable=true)
-     */
-    private $tvaNumber;
-
-    /**
-     * @ORM\Column(type="string", length=40, nullable=true)
-     */
-    private $otherType;
-
-    /**
-     * @ORM\Column(type="string", length=80, nullable=true)
-     */
-    private $acronym;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $facebook;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $twitter;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $instagram;
-
-    /**
-     * @ORM\Column(type="string", length=35, nullable=true)
-     */
-    private $collectiveAgreement;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     * @Assert\Choice(callback={"\App\Enum\Organization\OpcaEnum", "toArray"})
-     */
-    private $opca;
-
-    /**
-     * @ORM\Column(type="string", length=35, nullable=true)
-     */
-    private $icomNumber;
-
-    /**
-     * @ORM\Column(type="string", length=35, nullable=true)
-     */
-    private $urssafNumber;
-
-    /**
-     * @ORM\Column(type="string", length=20, nullable=true)
-     */
-    private $youngApproval;
-
-    /**
-     * @ORM\Column(type="string", length=20, nullable=true)
-     */
-    private $trainingApproval;
-
-    /**
-     * @ORM\Column(type="string", length=50, nullable=true)
-     */
-    private $otherApproval;
-
-    /**
-     * @ORM\Column(type="string", length=35, nullable=true)
-     */
-    private $prefectureName;
-
-    /**
-     * @ORM\Column(type="string", length=20, nullable=true)
-     */
-    private $prefectureNumber;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     * @Assert\Choice(callback={"\App\Enum\Organization\CategoryEnum", "toArray"})
-     */
-    private $category;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     * @Assert\Choice(callback={"\App\Enum\Organization\SchoolCategoryEnum", "toArray"})
-     */
-    private $schoolCategory;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     * @Assert\Choice(callback={"\App\Enum\Organization\TypeEstablishmentEnum", "toArray"})
-     */
-    private $typeEstablishment;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     * @Assert\Choice(callback={"\App\Enum\Organization\TypeEstablishmentDetailEnum", "toArray"})
-     */
-    private $typeEstablishmentDetail;
-
-    /**
-     * @ORM\Column(type="float", nullable=true)
-     */
-    private $budget;
-
-    /**
-     * @ORM\Column(type="boolean", nullable=true)
-     */
-    private $isPedagogicIsPrincipalActivity;
-
-    /**
-     * @ORM\Column(type="float", nullable=true)
-     */
-    private $pedagogicBudget;
-
-    /**
-     * @ORM\Column(type="boolean", nullable=true)
-     */
-    private $isPerformanceContractor;
-
-    /**
-     * @ORM\Column(type="string", length=20, nullable=true)
-     */
-    private $ffecApproval;
-
-    /**
-     * @ORM\Column(type="boolean")
-     */
-    private $portailVisibility;
-
-    /**
-     * @ORM\Column(type="integer", nullable=true)
-     */
-    private $cmsId;
-
-    /**
-     * @ORM\Column(type="text", nullable=true)
-     */
-    private $otherPractice;
-
-    /**
-     * @ORM\ManyToMany(targetEntity=ContactPoint::class, mappedBy="organization")
-     * @ApiSubresource()
-     */
-    private $contactPoints;
-
-    /**
-     * @ORM\ManyToMany(targetEntity=BankAccount::class, mappedBy="organization")
-     * @ApiSubresource()
-     */
-    private $bankAccounts;
-
-    /**
-     * @ORM\OneToMany(targetEntity=OrganizationAddressPostal::class, mappedBy="organization", orphanRemoval=true)
-     * @ApiSubresource()
-     */
-    private $organizationAddressPostals;
-
-    /**
-     * @ORM\OneToMany(targetEntity=OrganizationLicence::class, mappedBy="organization", orphanRemoval=true)
-     */
-    private $organizationLicences;
-
-    public function __construct()
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    #[ORM\Column(length: 128)]
+    public string $name;
+
+    #[ORM\Column(length: 128)]
+    private string $identifier;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    #[Assert\Choice(callback: ['\App\Enum\Organization\LegalEnum', 'toArray'], message: 'invalid-legal-status')]
+    private ?string $legalStatus = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    #[Assert\Choice(callback: ['\App\Enum\Organization\PrincipalTypeEnum', 'toArray'], message: 'invalid-principal-type')]
+    private ?string $principalType = null;
+
+    #[ORM\OneToOne(mappedBy: 'organization', cascade: ['persist', 'remove'])]
+    private Settings $settings;
+
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: NetworkOrganization::class, orphanRemoval: true)]
+    private Collection $networkOrganizations;
+
+    #[ORM\OneToMany(mappedBy: 'parent', targetEntity: NetworkOrganization::class, orphanRemoval: true)]
+    private Collection $networkOrganizationChildren;
+
+    #[ORM\OneToOne(cascade: ['persist', 'remove'])]
+    #[ORM\JoinColumn(nullable: false)]
+    private Parameters $parameters;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $description = null;
+
+    #[ORM\Column(type: 'date', nullable: true)]
+    private ?\DateTimeInterface $creationDate = null;
+
+    #[ORM\Column(type: 'date', nullable: true)]
+    private ?\DateTimeInterface $declarationDate = null;
+
+    #[ORM\Column(length: 14, nullable: true)]
+    private ?string $siretNumber = null;
+
+    #[ORM\Column(length: 10, nullable: true)]
+    private ?string $waldecNumber = null;
+
+    #[ORM\Column(length: 5, nullable: true)]
+    private ?string $apeNumber = null;
+
+    #[ORM\Column(length: 50, nullable: true)]
+    private ?string $tvaNumber = null;
+
+    #[ORM\Column(length: 40, nullable: true)]
+    private ?string $otherType = null;
+
+    #[ORM\Column(length: 80, nullable: true)]
+    private ?string $acronym = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $facebook = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $twitter = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $instagram = null;
+
+    #[ORM\Column(length: 35, nullable: true)]
+    private ?string $collectiveAgreement = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    #[Assert\Choice(callback: ['\App\Enum\Organization\OpcaEnum', 'toArray'], message: 'invalid-opca')]
+    private ?string $opca = null;
+
+    #[ORM\Column(length: 35, nullable: true)]
+    private ?string $icomNumber = null;
+
+    #[ORM\Column(length: 35, nullable: true)]
+    private ?string $urssafNumber = null;
+
+    #[ORM\Column(length: 20, nullable: true)]
+    private ?string $youngApproval = null;
+
+    #[ORM\Column(length: 20, nullable: true)]
+    private ?string $trainingApproval = null;
+
+    #[ORM\Column(length: 50, nullable: true)]
+    private ?string $otherApproval = null;
+
+    #[ORM\Column(length: 35, nullable: true)]
+    private ?string $prefectureName = null;
+
+    #[ORM\Column(length: 20, nullable: true)]
+    private ?string $prefectureNumber = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    #[Assert\Choice(callback: ['\App\Enum\Organization\CategoryEnum', 'toArray'], message: 'invalid-category')]
+    private ?string $category = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    #[Assert\Choice(callback: ['\App\Enum\Organization\SchoolCategoryEnum', 'toArray'], message: 'invalid-school-category')]
+    private ?string $schoolCategory = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    #[Assert\Choice(callback: ['\App\Enum\Organization\TypeEstablishmentEnum', 'toArray'], message: 'invalid-type-establishment')]
+    private ?string $typeEstablishment = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    #[Assert\Choice(callback: ['\App\Enum\Organization\TypeEstablishmentDetailEnum', 'toArray'], message: 'invalid-type-establishment-detail')]
+    private ?string $typeEstablishmentDetail = null;
+
+    #[ORM\Column(nullable: true)]
+    private ?float $budget = null;
+
+    #[ORM\Column(nullable: true)]
+    private ?bool $isPedagogicIsPrincipalActivity = null;
+
+    #[ORM\Column(nullable: true)]
+    private ?float $pedagogicBudget = null;
+
+    #[ORM\Column(nullable: true)]
+    private ?bool $isPerformanceContractor = null;
+
+    #[ORM\Column(length:20, nullable: true)]
+    private ?string $ffecApproval = null;
+
+    #[ORM\Column]
+    private bool $portailVisibility;
+
+    #[ORM\Column(nullable: true)]
+    private ?int $cmsId = null;
+
+    #[ORM\Column(nullable: true)]
+    private ?string $otherPractice = null;
+
+    #[ORM\ManyToMany(targetEntity: ContactPoint::class, mappedBy: 'organization')]
+    #[ApiSubresource]
+    private Collection $contactPoints;
+
+    #[ORM\ManyToMany(targetEntity: BankAccount::class, mappedBy: 'organization')]
+    #[ApiSubresource]
+    private Collection $bankAccounts;
+
+    #[ORM\OneToMany( mappedBy: 'organization', targetEntity: OrganizationAddressPostal::class, orphanRemoval: true)]
+    #[ApiSubresource]
+    private Collection $organizationAddressPostals;
+
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: OrganizationLicence::class, orphanRemoval: true)]
+    private Collection $organizationLicences;
+
+    #[Pure] public function __construct()
     {
         $this->networkOrganizations = new ArrayCollection();
         $this->networkOrganizationChildren = new ArrayCollection();
@@ -285,7 +197,7 @@ class Organization
         return $this->id;
     }
 
-    public function getName(): ?string
+    public function getName(): string
     {
         return $this->name;
     }
@@ -297,7 +209,7 @@ class Organization
         return $this;
     }
 
-    public function getIdentifier(): ?string
+    public function getIdentifier(): string
     {
         return $this->identifier;
     }
@@ -333,7 +245,7 @@ class Organization
         return $this;
     }
 
-    public function getSettings(): ?Settings
+    public function getSettings(): Settings
     {
         return $this->settings;
     }
@@ -350,9 +262,6 @@ class Organization
         return $this;
     }
 
-    /**
-     * @return Collection|NetworkOrganization[]
-     */
     public function getNetworkOrganizations(): Collection
     {
         return $this->networkOrganizations;
@@ -380,9 +289,6 @@ class Organization
         return $this;
     }
 
-    /**
-     * @return Collection|NetworkOrganization[]
-     */
     public function getNetworkOrganizationChildren(): Collection
     {
         return $this->networkOrganizationChildren;
@@ -410,7 +316,7 @@ class Organization
         return $this;
     }
 
-    public function getParameters(): ?Parameters
+    public function getParameters(): Parameters
     {
         return $this->parameters;
     }
@@ -782,7 +688,7 @@ class Organization
         return $this;
     }
 
-    public function getPortailVisibility(): ?bool
+    public function getPortailVisibility(): bool
     {
         return $this->portailVisibility;
     }
@@ -818,9 +724,6 @@ class Organization
         return $this;
     }
 
-    /**
-     * @return Collection|ContactPoint[]
-     */
     public function getContactPoints(): Collection
     {
         return $this->contactPoints;
@@ -845,9 +748,6 @@ class Organization
         return $this;
     }
 
-    /**
-     * @return Collection|BankAccount[]
-     */
     public function getBankAccounts(): Collection
     {
         return $this->bankAccounts;
@@ -872,9 +772,6 @@ class Organization
         return $this;
     }
 
-    /**
-     * @return Collection|OrganizationAddressPostal[]
-     */
     public function getOrganizationAddressPostals(): Collection
     {
         return $this->organizationAddressPostals;
@@ -902,9 +799,6 @@ class Organization
         return $this;
     }
 
-    /**
-     * @return Collection|OrganizationLicence[]
-     */
     public function getOrganizationLicences(): Collection
     {
         return $this->organizationLicences;

+ 20 - 30
src/Entity/Organization/OrganizationAddressPostal.php

@@ -9,36 +9,26 @@ use App\Repository\Organization\OrganizationAddressPostalRepository;
 use Doctrine\ORM\Mapping as ORM;
 use Symfony\Component\Validator\Constraints as Assert;
 
-/**
- * @ApiResource()
- * @ORM\Entity(repositoryClass=OrganizationAddressPostalRepository::class)
- */
+#[ApiResource]
+#[ORM\Entity(repositoryClass: OrganizationAddressPostalRepository::class)]
 class OrganizationAddressPostal
 {
-    /**
-     * @ORM\Id
-     * @ORM\GeneratedValue
-     * @ORM\Column(type="integer")
-     */
-    private $id;
-
-    /**
-     * @ORM\ManyToOne(targetEntity=Organization::class, inversedBy="organizationAddressPostals")
-     * @ORM\JoinColumn(nullable=false)
-     */
-    private $organization;
-
-    /**
-     * @ORM\OneToOne(targetEntity=AddressPostal::class, inversedBy="organizationAddressPostal", cascade={"persist", "remove"})
-     * @ORM\JoinColumn(nullable=false)
-     */
-    private $addressPostal;
-
-    /**
-     * @ORM\Column(type="string", length=255)
-     * @Assert\Choice(callback={"AppBundle\Enum\Core\AddressPostalTypeEnum", "toArray"})
-     */
-    private $type;
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    #[ORM\ManyToOne(inversedBy: 'organizationAddressPostals')]
+    #[ORM\JoinColumn(nullable: false)]
+    private ?Organization $organization = null;
+
+    #[ORM\OneToOne(inversedBy: 'organizationAddressPostal', cascade: ['persist', 'remove'])]
+    #[ORM\JoinColumn(nullable: false)]
+    private ?AddressPostal $addressPostal = null;
+
+    #[ORM\Column(length: 255)]
+    #[Assert\Choice(callback: ['\App\Enum\Core\AddressPostalTypeEnum', 'toArray'], message: 'invalid-address-postal-type')]
+    private string $type;
 
     public function getId(): ?int
     {
@@ -50,7 +40,7 @@ class OrganizationAddressPostal
         return $this->organization;
     }
 
-    public function setOrganization(?Organization $organization): self
+    public function setOrganization(Organization $organization): self
     {
         $this->organization = $organization;
 
@@ -69,7 +59,7 @@ class OrganizationAddressPostal
         return $this;
     }
 
-    public function getType(): ?string
+    public function getType(): string
     {
         return $this->type;
     }

+ 27 - 40
src/Entity/Organization/OrganizationLicence.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 
 namespace App\Entity\Organization;
 
@@ -7,57 +8,43 @@ use App\Entity\Access\Access;
 use App\Repository\Organization\OrganizationLicenceRepository;
 use Doctrine\ORM\Mapping as ORM;
 
-/**
- * @ApiResource()
- * @ORM\Entity(repositoryClass=OrganizationLicenceRepository::class)
- */
+#[ApiResource]
+#[ORM\Entity(repositoryClass: OrganizationLicenceRepository::class)]
 class OrganizationLicence
 {
-    /**
-     * @ORM\Id
-     * @ORM\GeneratedValue
-     * @ORM\Column(type="integer")
-     */
-    private $id;
-
-    /**
-     * @ORM\ManyToOne(targetEntity=Organization::class, inversedBy="organizationLicences")
-     * @ORM\JoinColumn(nullable=false)
-     */
-    private $organization;
-
-    /**
-     * @ORM\ManyToOne(targetEntity=Access::class, inversedBy="organizationLicences")
-     * @ORM\JoinColumn(nullable=false)
-     */
-    private $licensee;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $licenceNumber;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $categorie;
-
-    /**
-     * @ORM\Column(type="date", nullable=true)
-     */
-    private $validityDate;
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    #[ORM\ManyToOne(inversedBy: 'organizationLicences')]
+    #[ORM\JoinColumn(nullable: false)]
+    private Organization $organization;
+
+    #[ORM\ManyToOne(inversedBy: 'organizationLicences')]
+    #[ORM\JoinColumn(nullable: false)]
+    private ?Access $licensee = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $licenceNumber = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $categorie = null;
+
+    #[ORM\Column(type: 'date', nullable: true)]
+    private ?\DateTimeInterface $validityDate = null;
 
     public function getId(): ?int
     {
         return $this->id;
     }
 
-    public function getOrganization(): ?Organization
+    public function getOrganization(): Organization
     {
         return $this->organization;
     }
 
-    public function setOrganization(?Organization $organization): self
+    public function setOrganization(Organization $organization): self
     {
         $this->organization = $organization;
 
@@ -69,7 +56,7 @@ class OrganizationLicence
         return $this->licensee;
     }
 
-    public function setLicensee(?Access $licensee): self
+    public function setLicensee(Access $licensee): self
     {
         $this->licensee = $licensee;
 

+ 117 - 181
src/Entity/Organization/Parameters.php

@@ -8,173 +8,109 @@ use App\Repository\Organization\ParametersRepository;
 use Doctrine\ORM\Mapping as ORM;
 use Symfony\Component\Validator\Constraints as Assert;
 
-/**
- * @ApiResource()
- * @ORM\Entity(repositoryClass=ParametersRepository::class)
- */
+#[ApiResource]
+#[ORM\Entity(repositoryClass: ParametersRepository::class)]
 class Parameters
 {
-    /**
-     * @ORM\Id
-     * @ORM\GeneratedValue
-     * @ORM\Column(type="integer")
-     */
-    private $id;
-
-    /**
-     * @ORM\Column(type="date", nullable=true)
-     */
-    private $financialDate;
-
-    /**
-     * @ORM\Column(type="date", nullable=true)
-     */
-    private $musicalDate;
-
-    /**
-     * @ORM\Column(type="date", nullable=true)
-     */
-    private $startCourseDate;
-
-    /**
-     * @ORM\Column(type="date", nullable=true)
-     */
-    private $endCourseDate;
-
-    /**
-     * @ORM\Column(type="boolean", options={"default" : false})
-     */
-    private $trackingValidation = false;
-
-    /**
-     * @ORM\Column(type="boolean", options={"default" : true})
-     */
-    private $editCriteriaNotationByAdminOnly = true;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $smsSenderName;
-
-    /**
-     * @ORM\Column(type="boolean", options={"default" : false})
-     */
-    private $logoDonorsMove = false;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $subDomain;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $website;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $otherWebsite;
-
-    /**
-     * @ORM\Column(type="boolean", options={"default" : false})
-     */
-    private $desactivateOpentalentSiteWeb = false;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     * @Assert\Choice(callback={"\App\Enum\Organization\BulletinPeriodEnum", "toArray"})
-     */
-    private $bulletinPeriod;
-
-    /**
-     * @ORM\Column(type="boolean", options={"default" : false})
-     */
-    private $bulletinWithTeacher = false;
-
-    /**
-     * @ORM\Column(type="boolean", options={"default" : false})
-     */
-    private $bulletinPrintAddress = false;
-
-    /**
-     * @ORM\Column(type="boolean", options={"default" : true})
-     */
-    private $bulletinSignatureDirector = true;
-
-    /**
-     * @ORM\Column(type="boolean", options={"default" : true})
-     */
-    private $bulletinDisplayLevelAcquired = true;
-
-    /**
-     * @ORM\Column(type="boolean", options={"default" : false})
-     */
-    private $bulletinShowEducationWithoutEvaluation = false;
-
-    /**
-     * @ORM\Column(type="boolean", options={"default" : false})
-     */
-    private $bulletinViewTestResults = false;
-
-    /**
-     * @ORM\Column(type="boolean", options={"default" : false})
-     */
-    private $bulletinShowAbsences = false;
-
-    /**
-     * @ORM\Column(type="boolean", options={"default" : true})
-     */
-    private $bulletinShowAverages = true;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     * @Assert\Choice(callback={"\App\Enum\Organization\BulletinOutputEnum", "toArray"})
-     */
-    private $bulletinOutput;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $usernameSMS;
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $passwordSMS;
-
-    /**
-     * @ORM\Column(type="boolean", options={"default" : true})
-     */
-    private $bulletinEditWithoutEvaluation = true;
-
-    /**
-     * @ORM\Column(type="string", length=255, options={"default":"STUDENTS_AND_THEIR_GUARDIANS"})
-     * @Assert\Choice(callback={"\App\Enum\Organization\SendToBulletinEnum", "toArray"})
-     */
-    private $bulletinReceiver;
-
-    /**
-     * @ORM\Column(type="boolean", options={"default" : true})
-     */
-    private $showAdherentList = true;
-
-    /**
-     * @ORM\Column(type="boolean", options={"default" : false})
-     */
-    private $studentsAreAdherents = false;
-
-    /**
-     * @ORM\Column(type="string", length=255, options={"default" : "Europe/Paris"})
-     * @Assert\Choice(callback={"\App\Enum\Core\TimeZoneEnum", "toArrayCustom"})
-     */
-    private $timezone = "Europe/Paris";
-
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     * @Assert\Choice(callback={"\App\Enum\Education\PeriodicityEnum", "toArray"})
-     */
-    private $educationPeriodicity;
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    #[ORM\Column(type: 'date', nullable: true)]
+    private ?\DateTimeInterface $financialDate = null;
+
+    #[ORM\Column(type: 'date', nullable: true)]
+    private ?\DateTimeInterface $musicalDate = null;
+
+    #[ORM\Column(type: 'date', nullable: true)]
+    private ?\DateTimeInterface $startCourseDate = null;
+
+    #[ORM\Column(type: 'date', nullable: true)]
+    private ?\DateTimeInterface $endCourseDate = null;
+
+    #[ORM\Column(options: ['default' => false])]
+    private bool $trackingValidation = false;
+
+    #[ORM\Column(options: ['default' => true])]
+    private bool $editCriteriaNotationByAdminOnly = true;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $smsSenderName = null;
+
+    #[ORM\Column(options: ['default' => false])]
+    private bool $logoDonorsMove = false;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $subDomain = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $website = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $otherWebsite = null;
+
+    #[ORM\Column(options: ['default' => false])]
+    private bool $desactivateOpentalentSiteWeb = false;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    #[Assert\Choice(callback: ['\App\Enum\Organization\OpcBulletinPeriodEnumaEnum', 'toArray'], message: 'invalid-bulletin-period')]
+    private ?string $bulletinPeriod = null;
+
+    #[ORM\Column(options: ['default' => false])]
+    private bool $bulletinWithTeacher = false;
+
+    #[ORM\Column(options: ['default' => false])]
+    private bool $bulletinPrintAddress = false;
+
+    #[ORM\Column(options: ['default' => true])]
+    private bool $bulletinSignatureDirector = true;
+
+    #[ORM\Column(options: ['default' => true])]
+    private bool $bulletinDisplayLevelAcquired = true;
+
+    #[ORM\Column(options: ['default' => false])]
+    private bool $bulletinShowEducationWithoutEvaluation = false;
+
+    #[ORM\Column(options: ['default' => false])]
+    private bool $bulletinViewTestResults = false;
+
+    #[ORM\Column(options: ['default' => false])]
+    private bool $bulletinShowAbsences = false;
+
+    #[ORM\Column(options: ['default' => true])]
+    private bool $bulletinShowAverages = true;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    #[Assert\Choice(callback: ['\App\Enum\Organization\BulletinOutputEnum', 'toArray'], message: 'invalid-bulletin-output')]
+    private ?string $bulletinOutput = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $usernameSMS = null;
+
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $passwordSMS = null;
+
+    #[ORM\Column(options: ['default' => true])]
+    private bool $bulletinEditWithoutEvaluation = true;
+
+    #[ORM\Column(length: 255, nullable: true, options: ['default' => 'STUDENTS_AND_THEIR_GUARDIANS'])]
+    #[Assert\Choice(callback: ['\App\Enum\Organization\SendToBulletinEnum', 'toArray'], message: 'invalid-send-to-bulletin')]
+    private ?string $bulletinReceiver = null;
+
+    #[ORM\Column(options: ['default' => true])]
+    private bool $showAdherentList = true;
+
+    #[ORM\Column(options: ['default' => false])]
+    private bool $studentsAreAdherents = false;
+
+    #[ORM\Column(length: 255, options: ['default' => 'Europe/Paris'])]
+    #[Assert\Choice(callback: ['\App\Enum\Organization\TimeZoneEnum', 'toArray'], message: 'invalid-timezone')]
+    private ?string $timezone = "Europe/Paris";
+
+    #[ORM\Column(length: 255, nullable: true)]
+    #[Assert\Choice(callback: ['\App\Enum\Organization\PeriodicityEnum', 'toArray'], message: 'invalid-periodicity')]
+    private ?string $educationPeriodicity = null;
 
     public function getId(): ?int
     {
@@ -229,7 +165,7 @@ class Parameters
         return $this;
     }
 
-    public function getTrackingValidation(): ?bool
+    public function getTrackingValidation(): bool
     {
         return $this->trackingValidation;
     }
@@ -241,7 +177,7 @@ class Parameters
         return $this;
     }
 
-    public function getEditCriteriaNotationByAdminOnly(): ?bool
+    public function getEditCriteriaNotationByAdminOnly(): bool
     {
         return $this->editCriteriaNotationByAdminOnly;
     }
@@ -265,7 +201,7 @@ class Parameters
         return $this;
     }
 
-    public function getLogoDonorsMove(): ?bool
+    public function getLogoDonorsMove(): bool
     {
         return $this->logoDonorsMove;
     }
@@ -313,7 +249,7 @@ class Parameters
         return $this;
     }
 
-    public function getDesactivateOpentalentSiteWeb(): ?bool
+    public function getDesactivateOpentalentSiteWeb(): bool
     {
         return $this->desactivateOpentalentSiteWeb;
     }
@@ -337,7 +273,7 @@ class Parameters
         return $this;
     }
 
-    public function getBulletinWithTeacher(): ?bool
+    public function getBulletinWithTeacher(): bool
     {
         return $this->bulletinWithTeacher;
     }
@@ -349,7 +285,7 @@ class Parameters
         return $this;
     }
 
-    public function getBulletinPrintAddress(): ?bool
+    public function getBulletinPrintAddress(): bool
     {
         return $this->bulletinPrintAddress;
     }
@@ -361,7 +297,7 @@ class Parameters
         return $this;
     }
 
-    public function getBulletinSignatureDirector(): ?bool
+    public function getBulletinSignatureDirector(): bool
     {
         return $this->bulletinSignatureDirector;
     }
@@ -373,7 +309,7 @@ class Parameters
         return $this;
     }
 
-    public function getBulletinDisplayLevelAcquired(): ?bool
+    public function getBulletinDisplayLevelAcquired(): bool
     {
         return $this->bulletinDisplayLevelAcquired;
     }
@@ -385,7 +321,7 @@ class Parameters
         return $this;
     }
 
-    public function getBulletinShowEducationWithoutEvaluation(): ?bool
+    public function getBulletinShowEducationWithoutEvaluation(): bool
     {
         return $this->bulletinShowEducationWithoutEvaluation;
     }
@@ -397,7 +333,7 @@ class Parameters
         return $this;
     }
 
-    public function getBulletinViewTestResults(): ?bool
+    public function getBulletinViewTestResults(): bool
     {
         return $this->bulletinViewTestResults;
     }
@@ -409,7 +345,7 @@ class Parameters
         return $this;
     }
 
-    public function getBulletinShowAbsences(): ?bool
+    public function getBulletinShowAbsences(): bool
     {
         return $this->bulletinShowAbsences;
     }
@@ -421,7 +357,7 @@ class Parameters
         return $this;
     }
 
-    public function getBulletinShowAverages(): ?bool
+    public function getBulletinShowAverages(): bool
     {
         return $this->bulletinShowAverages;
     }
@@ -469,7 +405,7 @@ class Parameters
         return $this;
     }
 
-    public function getBulletinEditWithoutEvaluation(): ?bool
+    public function getBulletinEditWithoutEvaluation(): bool
     {
         return $this->bulletinEditWithoutEvaluation;
     }
@@ -493,7 +429,7 @@ class Parameters
         return $this;
     }
 
-    public function getShowAdherentList(): ?bool
+    public function getShowAdherentList(): bool
     {
         return $this->showAdherentList;
     }
@@ -505,7 +441,7 @@ class Parameters
         return $this;
     }
 
-    public function getStudentsAreAdherents(): ?bool
+    public function getStudentsAreAdherents(): bool
     {
         return $this->studentsAreAdherents;
     }
@@ -517,7 +453,7 @@ class Parameters
         return $this;
     }
 
-    public function getTimezone(): ?string
+    public function getTimezone(): string
     {
         return $this->timezone;
     }

+ 25 - 39
src/Entity/Organization/Settings.php

@@ -4,52 +4,38 @@ declare(strict_types=1);
 namespace App\Entity\Organization;
 
 use ApiPlatform\Core\Annotation\ApiResource;
-use App\Enum\Organization\settingsProductEnum;
 use App\Repository\Organization\SettingsRepository;
 use Doctrine\ORM\Mapping as ORM;
 use Symfony\Component\Validator\Constraints as Assert;
 
 /**
  * Caractéristiques d'une Organization (produits, options...etc)
- *
- * @ApiResource()
- * @ORM\Entity(repositoryClass=SettingsRepository::class)
  */
+#[ApiResource]
+#[ORM\Entity(repositoryClass: SettingsRepository::class)]
 class Settings
 {
-    /**
-     * @ORM\Id
-     * @ORM\GeneratedValue
-     * @ORM\Column(type="integer")
-     */
-    private $id;
-
-    /**
-     * @ORM\OneToOne(targetEntity=Organization::class, inversedBy="settings", cascade={"persist", "remove"})
-     * @ORM\JoinColumn(nullable=false)
-     */
-    private $organization;
-
-    /**
-     * @ORM\Column(type="string", length=255)
-     * @Assert\Choice(callback={"\App\Enum\Organization\SettingsProductEnum", "toArray"})
-     */
-    private $product;
-
-    /**
-     * @ORM\Column(type="json", nullable=true)
-     */
-    private $modules = [];
-
-    /**
-     * @ORM\Column(type="json", nullable=true)
-     */
-    private $actions = [];
-
-    /**
-     * @ORM\Column(type="string", length=255, options={"default":"FRANCE"})
-     */
-    private $country;
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    #[ORM\OneToOne(inversedBy: 'settings', cascade: ['persist', 'remove'])]
+    #[ORM\JoinColumn(nullable: false)]
+    private ?Organization $organization = null;
+
+    #[ORM\Column(length: 255)]
+    #[Assert\Choice(callback: ['\App\Enum\Organization\SettingsProductEnum', 'toArray'], message: 'invalid-product')]
+    private string $product;
+
+    #[ORM\Column(type: 'json', length: 4294967295, nullable: true)]
+    private ?array $modules = [];
+
+    #[ORM\Column(type: 'json', length: 4294967295, nullable: true)]
+    private ?array $actions = [];
+
+    #[ORM\Column(length: 255, options: ['default' => 'FRANCE'])]
+    private string $country;
 
     public function getId(): ?int
     {
@@ -68,7 +54,7 @@ class Settings
         return $this;
     }
 
-    public function getProduct(): ?string
+    public function getProduct(): string
     {
         return $this->product;
     }
@@ -104,7 +90,7 @@ class Settings
         return $this;
     }
 
-    public function getCountry(): ?string
+    public function getCountry(): string
     {
         return $this->country;
     }

+ 56 - 62
src/Entity/Person/Person.php

@@ -3,61 +3,55 @@ declare(strict_types=1);
 
 namespace App\Entity\Person;
 
+use ApiPlatform\Core\Annotation\ApiResource;
 use App\Entity\Core\ContactPoint;
+use App\Entity\Core\File;
 use App\Repository\Person\PersonRepository;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
+use JetBrains\PhpStorm\Pure;
 use Symfony\Component\Security\Core\User\UserInterface;
+use Symfony\Component\Validator\Constraints as Assert;
 
 /**
  * Personne physique ou morale
- *
- * @ORM\Entity(repositoryClass=PersonRepository::class)
- *
  */
+#[ApiResource]
+#[ORM\Entity(repositoryClass: PersonRepository::class)]
 class Person implements UserInterface
 {
-    /**
-     * @ORM\Id
-     * @ORM\GeneratedValue
-     * @ORM\Column(type="integer")
-     */
-    private $id;
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
 
-    /**
-     * @ORM\Column(type="string", length=180, unique=true)
-     */
-    private $username;
+    #[ORM\Column(length: 180, unique: true, nullable: true)]
+    private ?string $username = null;
 
-    /**
-     *
-     */
-    private $roles = [];
+    private array $roles = [];
 
-    /**
-     * @var string The hashed password
-     * @ORM\Column(type="string")
-     */
-    private $password;
+    #[ORM\Column(nullable: true)]
+    private ?string $password = null;
 
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $name;
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $name = null;
 
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $givenName;
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $givenName = null;
 
-    /**
-     * @ORM\ManyToMany(targetEntity=ContactPoint::class, mappedBy="person")
-     */
-    private $contactPoints;
+    #[ORM\ManyToMany(targetEntity: ContactPoint::class, mappedBy: 'person')]
+    private Collection $contactPoints;
 
+    #[ORM\Column(nullable: true)]
+    #[Assert\Choice(callback: ['\App\Enum\Person\GenderEnum', 'toArray'], message: 'invalid-gender')]
+    private ?string $gender = null;
 
-    public function __construct()
+    #[ORM\ManyToOne(inversedBy: 'personImages')]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
+    private ?File $image = null;
+
+    #[Pure] public function __construct()
     {
         $this->contactPoints = new ArrayCollection();
     }
@@ -67,36 +61,23 @@ class Person implements UserInterface
         return $this->id;
     }
 
-    /**
-     * A visual identifier that represents this user.
-     *
-     * @see UserInterface
-     */
-    public function getUsername(): string
+    public function getUsername(): ?string
     {
         return (string) $this->username;
     }
 
-    /**
-     * A visual identifier that represents this user.
-     *
-     * @see string
-     */
-    public function getUserIdentifier(): string
+    public function getUserIdentifier(): ?string
     {
         return (string) $this->username;
     }
 
-    public function setUsername(string $username): self
+    public function setUsername(?string $username): self
     {
         $this->username = $username;
 
         return $this;
     }
 
-    /**
-     * @see UserInterface
-     */
     public function getRoles(): array
     {
         $roles = $this->roles;
@@ -113,32 +94,23 @@ class Person implements UserInterface
         return $this;
     }
 
-    /**
-     * @see UserInterface
-     */
-    public function getPassword(): string
+    public function getPassword(): ?string
     {
         return (string) $this->password;
     }
 
-    public function setPassword(string $password): self
+    public function setPassword(?string $password): self
     {
         $this->password = $password;
 
         return $this;
     }
 
-    /**
-     * @see UserInterface
-     */
     public function getSalt()
     {
         // not needed when using the "bcrypt" algorithm in security.yaml
     }
 
-    /**
-     * @see UserInterface
-     */
     public function eraseCredentials()
     {
         // If you store any temporary, sensitive data on the user, clear it here
@@ -169,6 +141,17 @@ class Person implements UserInterface
         return $this;
     }
 
+    public function setGender(?string $gender): self
+    {
+        $this->gender = $gender;
+        return $this;
+    }
+
+    public function getGender(): ?string
+    {
+        return $this->gender;
+    }
+
     /**
      * @return Collection|ContactPoint[]
      */
@@ -195,4 +178,15 @@ class Person implements UserInterface
 
         return $this;
     }
+
+    public function setImage(?File $image):self
+    {
+        $this->image = $image;
+        return $this;
+    }
+
+    public function getImage(): ?File
+    {
+        return $this->image;
+    }
 }

+ 12 - 50
src/Entity/Person/PersonActivity.php

@@ -5,43 +5,29 @@ namespace App\Entity\Person;
 
 use ApiPlatform\Core\Annotation\ApiResource;
 use App\Entity\Access\Access;
+use App\Entity\Traits\ActivityPeriodTrait;
 use App\Repository\Person\PersonActivityRepository;
 use Doctrine\ORM\Mapping as ORM;
 
 /**
  * Lien entre une Person et une Activity
- *
- * @ApiResource()
- * @ORM\Entity(repositoryClass=PersonActivityRepository::class)
  */
+#[ApiResource]
+#[ORM\Entity(repositoryClass: PersonActivityRepository::class)]
 class PersonActivity
 {
-    /**
-     * @ORM\Id
-     * @ORM\GeneratedValue
-     * @ORM\Column(type="integer")
-     */
-    private $id;
+    use ActivityPeriodTrait;
 
-    /**
-     * @ORM\Column(type="string", length=255, nullable=true)
-     */
-    private $complementSpeciality;
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
 
-    /**
-     * @ORM\Column(type="date")
-     */
-    private $startDate;
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $complementSpeciality = null;
 
-    /**
-     * @ORM\Column(type="date", nullable=true)
-     */
-    private $endDate;
-
-    /**
-     * @ORM\ManyToOne(targetEntity=Access::class, inversedBy="personActivity")
-     */
-    private $access;
+    #[ORM\ManyToOne(inversedBy: 'personActivity')]
+    private ?Access $access = null;
 
     public function getId(): ?int
     {
@@ -60,30 +46,6 @@ class PersonActivity
         return $this;
     }
 
-    public function getStartDate(): ?\DateTimeInterface
-    {
-        return $this->startDate;
-    }
-
-    public function setStartDate(\DateTimeInterface $startDate): self
-    {
-        $this->startDate = $startDate;
-
-        return $this;
-    }
-
-    public function getEndDate(): ?\DateTimeInterface
-    {
-        return $this->endDate;
-    }
-
-    public function setEndDate(?\DateTimeInterface $endDate): self
-    {
-        $this->endDate = $endDate;
-
-        return $this;
-    }
-
     public function getAccess(): ?Access
     {
         return $this->access;

+ 34 - 0
src/Entity/Traits/ActivityPeriodTrait.php

@@ -0,0 +1,34 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Entity\Traits;
+
+use Doctrine\ORM\Mapping as ORM;
+
+trait ActivityPeriodTrait
+{
+    #[ORM\Column(type: 'date', nullable: true)]
+    private ?\DateTimeInterface $startDate = null;
+
+    #[ORM\Column(type: 'date', nullable: true)]
+    private ?\DateTimeInterface $endDate = null;
+
+    public function getStartDate(): ?\DateTimeInterface {
+        return $this->startDate;
+    }
+
+    public function setStartDate(?\DateTime $startDate = null): self {
+        if($startDate == null) $startDate = new \DateTime();
+        $this->startDate = $startDate;
+        return $this;
+    }
+
+    public function getEndDate(): ?\DateTimeInterface {
+        return $this->endDate;
+    }
+
+    public function setEndDate(?\DateTime $endDate = null) :self {
+        $this->endDate = $endDate;
+        return $this;
+    }
+}

+ 35 - 0
src/Entity/Traits/ActivityYearTrait.php

@@ -0,0 +1,35 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Entity\Traits;
+
+use Doctrine\ORM\Mapping as ORM;
+
+trait ActivityYearTrait
+{
+
+    #[ORM\Column(nullable: true)]
+    private ?int $startYear = null;
+
+    #[ORM\Column(nullable: true)]
+    private ?int $endYear = null;
+
+    public function getStartYear(): ?int {
+        return $this->startYear;
+    }
+
+    public function setStartYear(?int $startYear = null):self {
+        if($startYear == null) $startYear = date('Y');
+        $this->startYear = $startYear;
+        return $this;
+    }
+
+    public function getEndYear():?int {
+        return $this->endYear;
+    }
+
+    public function setEndYear(?int $endYear):self {
+        $this->endYear = $endYear;
+        return $this;
+    }
+}

+ 23 - 0
src/Enum/Access/DeparturesCauseEnum.php

@@ -0,0 +1,23 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Enum\Access;
+
+use MyCLabs\Enum\Enum;
+
+/**
+ * Due to departures.
+ */
+class DeparturesCauseEnum extends Enum
+{
+    private const LEFT_THE_STRUCTURE = 'LEFT_THE_STRUCTURE';
+    private const DEATH = 'DEATH';
+    private const REFERENCE = 'REFERENCE';
+    private const ABANDONMENT = 'ABANDONMENT';
+    private const SABBATICAL = 'SABBATICAL';
+    private const OTHER = 'OTHER';
+    private const MOVE = 'MOVE';
+    private const DISEASE = 'DISEASE';
+    private const RESIGNATION = 'RESIGNATION';
+    private const END_OF_TERM = 'END_OF_TERM';
+}

+ 103 - 0
src/Enum/Access/FunctionEnum.php

@@ -0,0 +1,103 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Enum\Access;
+
+use MyCLabs\Enum\Enum;
+
+/**
+ * Activities functions.
+ */
+class FunctionEnum extends Enum
+{
+    private const STUDENT = 'STUDENT';
+    private const TEACHER = 'TEACHER';
+    private const DIRECTOR = 'DIRECTOR';
+    private const DIRECTOR_ASSISTANT = 'DIRECTOR_ASSISTANT';
+    private const INITIATOR = 'INITIATOR';
+    private const MONITOR = 'MONITOR';
+
+    private const MUSIC_DIRECTOR_AND_HEAD = 'MUSIC_DIRECTOR_AND_HEAD';
+    private const MUSIC_DIRECTOR_AND_HEAD_ASSISTANT = 'MUSIC_DIRECTOR_AND_HEAD_ASSISTANT';
+    private const DESK_OFFICER = 'DESK_OFFICER';
+
+    private const ADMINISTRATIVE_OFFICER = 'ADMINISTRATIVE_OFFICER';
+    private const ADMINISTRATIVE_SECRETARY = 'ADMINISTRATIVE_SECRETARY';
+    private const ADMINISTRATIVE_DIRECTOR = 'ADMINISTRATIVE_DIRECTOR';
+    private const ADMINISTRATIVE_DIRECTOR_ASSISTANT = 'ADMINISTRATIVE_DIRECTOR_ASSISTANT';
+    private const ARCHIVIST = 'ARCHIVIST';
+    private const PRESENTER = 'PRESENTER';
+    private const ADMINISTRATIVE_STAFF = 'ADMINISTRATIVE_STAFF';
+    private const NETWORK_ANIMATOR = 'NETWORK_ANIMATOR';
+    private const CORRESPONDING = 'CORRESPONDING';
+    private const COORDINATOR = 'COORDINATOR';
+    private const TECHNICAL_STAFF = 'TECHNICAL_STAFF';
+    private const ACCOUNTANT = 'ACCOUNTANT';
+
+    private const ACTIVE_MEMBER_OF_THE_CA = 'ACTIVE_MEMBER_OF_THE_CA';
+    private const HONORARY_PRESIDENT = 'HONORARY_PRESIDENT';
+    private const PRESIDENT = 'PRESIDENT';
+    private const YOUTH_REPRESENTATIVE = 'YOUTH_REPRESENTATIVE';
+    private const SECRETARY = 'SECRETARY';
+    private const ASSISTANT_SECRETARY = 'ASSISTANT_SECRETARY';
+    private const TREASURER = 'TREASURER';
+    private const TREASURER_ASSISTANT = 'TREASURER_ASSISTANT';
+    private const VICE_PRESIDENT = 'VICE_PRESIDENT';
+    private const ADHERENT = 'ADHERENT';
+    private const NO_MEMBER = 'NO_MEMBER';
+    private const VICE_PRESIDENT_OF_HONOR = 'VICE_PRESIDENT_OF_HONOR';
+    private const HOUR_PRESIDENT = 'HOUR_PRESIDENT';
+    private const PRESIDENT_ASSISTANT = 'PRESIDENT_ASSISTANT';
+    private const ACTIVE_COOPTED_MEMBER_OF_THE_CA = 'ACTIVE_COOPTED_MEMBER_OF_THE_CA';
+    private const ACTIVE_SUBSTITUTE_MEMBER_OF_THE_CA = 'ACTIVE_SUBSTITUTE_MEMBER_OF_THE_CA';
+    private const MEMBER_OF_THE_BOARD = 'MEMBER_OF_THE_BOARD';
+    private const MEMBER_OF_BOARD_OF_HONOR = 'MEMBER_OF_BOARD_OF_HONOR';
+    private const HONORARY_MEMBER = 'HONORARY_MEMBER';
+    private const BENEFACTOR_MEMBER = 'BENEFACTOR_MEMBER';
+    private const HOUR_MEMBER = 'HOUR_MEMBER';
+
+    private const OTHER = 'OTHER';
+
+    public static function getOrganizationStaffAndBoardOfDirectorsMission(){
+        return [
+            self::ACTIVE_MEMBER_OF_THE_CA,
+            self::HONORARY_PRESIDENT,
+            self::PRESIDENT,
+            self::YOUTH_REPRESENTATIVE,
+            self::SECRETARY,
+            self::ASSISTANT_SECRETARY,
+            self::TREASURER,
+            self::TREASURER_ASSISTANT,
+            self::VICE_PRESIDENT,
+            self::VICE_PRESIDENT_OF_HONOR,
+            self::HOUR_PRESIDENT,
+            self::PRESIDENT_ASSISTANT,
+            self::ACTIVE_COOPTED_MEMBER_OF_THE_CA,
+            self::ACTIVE_SUBSTITUTE_MEMBER_OF_THE_CA,
+            self::MEMBER_OF_THE_BOARD,
+            self::MEMBER_OF_BOARD_OF_HONOR,
+            self::SECRETARY,
+            self::TREASURER,
+            self::DIRECTOR,
+            self::DIRECTOR_ASSISTANT,
+            self::ADMINISTRATIVE_DIRECTOR,
+            self::ADMINISTRATIVE_DIRECTOR_ASSISTANT,
+            self::MUSIC_DIRECTOR_AND_HEAD,
+            self::MUSIC_DIRECTOR_AND_HEAD_ASSISTANT,
+            self::DESK_OFFICER,
+            self::ADMINISTRATIVE_OFFICER,
+            self::ADMINISTRATIVE_SECRETARY,
+            self::ARCHIVIST,
+            self::PRESENTER,
+            self::ADMINISTRATIVE_STAFF,
+            self::NETWORK_ANIMATOR,
+            self::CORRESPONDING,
+            self::COORDINATOR,
+            self::TECHNICAL_STAFF,
+            self::ACCOUNTANT,
+            self::MUSIC_DIRECTOR_AND_HEAD
+        ];
+    }
+}
+
+

+ 24 - 0
src/Enum/Access/RoleEnum.php

@@ -0,0 +1,24 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Enum\Access;
+
+use MyCLabs\Enum\Enum;
+
+/**
+ * Role
+ */
+class RoleEnum extends Enum
+{
+    private const ROLE_ADMIN = 'ROLE_ADMIN';
+    private const ROLE_ADMINISTRATIF_MANAGER = 'ROLE_ADMINISTRATIF_MANAGER';
+    private const ROLE_PEDAGOGICS_MANAGER = 'ROLE_PEDAGOGICS_MANAGER';
+    private const ROLE_FINANCIAL_MANAGER = 'ROLE_FINANCIAL_MANAGER';
+    private const ROLE_CA = 'ROLE_CA';
+    private const ROLE_STUDENT = 'ROLE_STUDENT';
+    private const ROLE_TEACHER = 'ROLE_TEACHER';
+    private const ROLE_MEMBER = 'ROLE_MEMBER';
+    private const ROLE_OTHER = 'ROLE_OTHER';
+}
+
+

+ 18 - 0
src/Enum/Access/TypeFunctionEnum.php

@@ -0,0 +1,18 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Enum\Access;
+
+use MyCLabs\Enum\Enum;
+
+/**
+ * Type of function.
+ */
+class TypeFunctionEnum extends Enum
+{
+   private const ACTIVITIES_FUNCTION = 'ACTIVITIES_FUNCTION';
+   private const ADMINISTRATIVES_FUNCTION = 'ADMINISTRATIVES_FUNCTION';
+   private const PEDAGOGICS_FUNCTION = 'PEDAGOGICS_FUNCTION';
+   private const ASSOCIATIVES_FUNCTION = 'ASSOCIATIVES_FUNCTION';
+   private const OTHER_FUNCTION = 'OTHER_FUNCTION';
+}

+ 2 - 5
src/Enum/Core/ContactPointTypeEnum.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 
 namespace App\Enum\Core;
 
@@ -15,11 +16,7 @@ class ContactPointTypeEnum extends Enum
     private const OTHER = 'OTHER';
     private const CONTACT = 'CONTACT';
 
-    /**
-     * @param bool $type
-     * @return array
-     */
-    public static function toArrayCustom($type = false)
+    public static function toArray(bool $type = false): array
     {
         if($type == 'person'){
             return ['PRINCIPAL'=>self::PRINCIPAL,'OTHER'=>self::OTHER];

+ 19 - 0
src/Enum/Core/NotificationTypeEnum.php

@@ -0,0 +1,19 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Enum\Core;
+
+use MyCLabs\Enum\Enum;
+
+/**
+ * Type de notifications
+ *
+ */
+class NotificationTypeEnum extends Enum
+{
+    private const SYSTEM = 'SYSTEM';
+    private const FILE = 'FILE';
+    private const MESSAGE = 'MESSAGE';
+    private const PRINTING = 'PRINTING';
+    private const ERROR = 'ERROR';
+}

+ 2 - 2
src/Enum/Core/TimeZoneEnum.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 
 namespace App\Enum\Core;
 
@@ -12,9 +13,8 @@ class TimeZoneEnum extends Enum
 {
     /**
      * Return a custom array instead the original array
-     * @return mixed
      */
-    public static function toArrayCustom()
+    public static function toArray(): array
     {
         return [
          'Indian/Reunion' => 'Indian/Reunion',

+ 17 - 0
src/Enum/Cotisation/AlertStateEnum.php

@@ -0,0 +1,17 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Enum\Cotisation;
+
+use MyCLabs\Enum\Enum;
+
+/**
+ * état des alertes des cotisations disponibles.
+ */
+class AlertStateEnum extends Enum
+{
+    private const AFFILIATION ='AFFILIATION';
+    private const INVOICE ='INVOICE';
+    private const INSURANCE = 'INSURANCE';
+    private const ADVERTISINGINSURANCE = 'ADVERTISINGINSURANCE';
+}

+ 1 - 0
src/Enum/Education/PeriodicityEnum.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 
 namespace App\Enum\Education;
 

+ 1 - 0
src/Enum/Network/LeadingCauseEnum.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 
 namespace App\Enum\Network;
 

+ 1 - 0
src/Enum/Network/NetworkEnum.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 
 namespace App\Enum\Network;
 

+ 2 - 0
src/Enum/Organization/AddressPostalOrganizationTypeEnum.php

@@ -1,4 +1,6 @@
 <?php
+declare(strict_types=1);
+
 namespace App\Enum\Organization;
 
 use MyCLabs\Enum\Enum;

+ 1 - 0
src/Enum/Organization/BulletinOutputEnum.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 
 namespace App\Enum\Organization;
 

+ 1 - 0
src/Enum/Organization/BulletinPeriodEnum.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 
 namespace App\Enum\Organization;
 

+ 1 - 0
src/Enum/Organization/CategoryEnum.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 
 namespace App\Enum\Organization;
 

+ 1 - 0
src/Enum/Organization/LegalEnum.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 
 namespace App\Enum\Organization;
 

+ 1 - 0
src/Enum/Organization/OpcaEnum.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 
 namespace App\Enum\Organization;
 

+ 1 - 0
src/Enum/Organization/OrganizationIdsEnum.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 
 namespace App\Enum\Organization;
 

+ 1 - 0
src/Enum/Organization/PrincipalTypeEnum.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 
 namespace App\Enum\Organization;
 

+ 1 - 0
src/Enum/Organization/SchoolCategoryEnum.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 
 namespace App\Enum\Organization;
 

+ 1 - 0
src/Enum/Organization/SendToBulletinEnum.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 
 namespace App\Enum\Organization;
 

+ 1 - 0
src/Enum/Organization/SettingsProductEnum.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 
 namespace App\Enum\Organization;
 

+ 1 - 0
src/Enum/Organization/TypeEstablishmentDetailEnum.php

@@ -1,4 +1,5 @@
 <?php
+declare(strict_types=1);
 
 namespace App\Enum\Organization;
 

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä