Ver código fonte

Merge branch 'release/2.5' into develop

Olivier Massot 6 meses atrás
pai
commit
e1d7d30f5a
100 arquivos alterados com 1208 adições e 405 exclusões
  1. 1 1
      .gitlab-ci.yml
  2. 2 2
      composer.json
  3. 6 6
      config/packages/docker/messenger.yaml
  4. 7 0
      config/services.yaml
  5. 4 2
      phpstan.neon.dist
  6. 1 1
      sql/schema-extensions/002-view_federation_structures.sql
  7. 2 1
      sql/schema-extensions/003-view_search_user.sql
  8. 5 4
      src/ApiResources/Access/AdminAccess.php
  9. 1 1
      src/ApiResources/Dolibarr/DolibarrAccount.php
  10. 3 3
      src/ApiResources/Profile/OrganizationProfile.php
  11. 2 5
      src/Commands/CronCommand.php
  12. 19 3
      src/Commands/Doctrine/SchemaUpdateCommand.php
  13. 3 3
      src/Commands/PostUpgrade/V0_2/PostUpgradeCommand.php
  14. 0 1
      src/Doctrine/Access/CurrentAccessExtension.php
  15. 2 2
      src/Doctrine/Custom/Search/RestrictToOrganizationIdExtension.php
  16. 200 92
      src/Entity/Access/Access.php
  17. 3 7
      src/Entity/Awin/Product.php
  18. 2 2
      src/Entity/Billing/AbstractBillAccounting.php
  19. 2 1
      src/Entity/Billing/AbstractBillingPayer.php
  20. 0 1
      src/Entity/Billing/AccessIntangible.php
  21. 0 1
      src/Entity/Billing/AccessPayer.php
  22. 0 1
      src/Entity/Billing/AdvancePayment.php
  23. 35 4
      src/Entity/Billing/Bill.php
  24. 0 2
      src/Entity/Billing/BillAccounting.php
  25. 0 1
      src/Entity/Billing/BillCredit.php
  26. 3 3
      src/Entity/Billing/BillingIntangibleExcludeDate.php
  27. 1 1
      src/Entity/Billing/BillingSetting.php
  28. 16 0
      src/Entity/Billing/BillingSettingRent.php
  29. 0 1
      src/Entity/Billing/EducationalProjectIntangible.php
  30. 0 1
      src/Entity/Billing/EducationalProjectPayer.php
  31. 34 0
      src/Entity/Billing/FamilyQuotientModel.php
  32. 1 1
      src/Entity/Billing/PayfipPaymentReturn.php
  33. 4 0
      src/Entity/Billing/ResidenceArea.php
  34. 4 2
      src/Entity/Billing/SddRegie.php
  35. 2 1
      src/Entity/Booking/AbstractBooking.php
  36. 2 1
      src/Entity/Booking/AbstractBookingRecur.php
  37. 1 2
      src/Entity/Booking/Attendance.php
  38. 6 0
      src/Entity/Booking/AttendanceBooking.php
  39. 11 3
      src/Entity/Booking/AttendanceBookingReason.php
  40. 9 6
      src/Entity/Booking/Course.php
  41. 0 1
      src/Entity/Booking/CourseRecur.php
  42. 5 6
      src/Entity/Booking/EducationalProject.php
  43. 0 1
      src/Entity/Booking/EducationalProjectRecur.php
  44. 7 9
      src/Entity/Booking/Event.php
  45. 0 1
      src/Entity/Booking/EventRecur.php
  46. 1 1
      src/Entity/Booking/EventReport.php
  47. 5 6
      src/Entity/Booking/Examen.php
  48. 0 1
      src/Entity/Booking/ExamenRecur.php
  49. 1 2
      src/Entity/Booking/OrganizationHoliday.php
  50. 0 1
      src/Entity/Booking/OrganizationHolidayRecur.php
  51. 1 2
      src/Entity/Booking/PersonHoliday.php
  52. 0 1
      src/Entity/Booking/PersonHolidayRecur.php
  53. 34 1
      src/Entity/Core/AbstractControl.php
  54. 2 1
      src/Entity/Core/AbstractRepair.php
  55. 2 2
      src/Entity/Core/BankAccount.php
  56. 1 1
      src/Entity/Core/Categories.php
  57. 1 1
      src/Entity/Core/City.php
  58. 2 1
      src/Entity/Core/Country.php
  59. 35 4
      src/Entity/Core/File.php
  60. 0 1
      src/Entity/Core/Notification.php
  61. 34 7
      src/Entity/Core/Tagg.php
  62. 36 1
      src/Entity/Core/Tips.php
  63. 13 6
      src/Entity/Custom/Search/UserSearchItem.php
  64. 2 2
      src/Entity/Education/Cycle.php
  65. 7 7
      src/Entity/Education/EducationCurriculum.php
  66. 42 33
      src/Entity/Education/EducationCurriculumPack.php
  67. 1 1
      src/Entity/Education/EducationNotationConfig.php
  68. 5 0
      src/Entity/Education/EducationTiming.php
  69. 93 0
      src/Entity/Education/RequiredChoicesBlock.php
  70. 2 1
      src/Entity/Message/AbstractMessage.php
  71. 11 1
      src/Entity/Message/AbstractReport.php
  72. 0 1
      src/Entity/Message/Email.php
  73. 0 1
      src/Entity/Message/Mail.php
  74. 2 11
      src/Entity/Message/ReportEmail.php
  75. 3 12
      src/Entity/Message/ReportSms.php
  76. 0 1
      src/Entity/Message/Sms.php
  77. 1 1
      src/Entity/Organization/CotisationByYear.php
  78. 2 0
      src/Entity/Organization/OnlineRegistrationOpeningPeriod.php
  79. 2 0
      src/Entity/Organization/OnlineRegistrationSettings.php
  80. 122 50
      src/Entity/Organization/Organization.php
  81. 6 6
      src/Entity/Organization/Parameters.php
  82. 4 3
      src/Entity/Organization/Subdomain.php
  83. 5 31
      src/Entity/Person/Person.php
  84. 2 1
      src/Entity/Place/AbstractPlace.php
  85. 0 1
      src/Entity/Place/Place.php
  86. 0 1
      src/Entity/Place/PlaceControl.php
  87. 0 1
      src/Entity/Place/PlaceRepair.php
  88. 0 1
      src/Entity/Place/PlaceSystem.php
  89. 0 1
      src/Entity/Place/RoomControl.php
  90. 0 1
      src/Entity/Place/RoomRepair.php
  91. 5 1
      src/Entity/Product/AbstractProduct.php
  92. 0 1
      src/Entity/Product/Equipment.php
  93. 0 2
      src/Entity/Product/EquipmentControl.php
  94. 0 1
      src/Entity/Product/EquipmentRepair.php
  95. 0 1
      src/Entity/Product/Intangible.php
  96. 17 1
      src/Entity/Public/FederationStructure.php
  97. 62 0
      src/Entity/Shop/Orders.php
  98. 219 0
      src/Entity/SimulationSession/SimulationSession.php
  99. 17 0
      src/Entity/Token/Token.php
  100. 2 2
      src/Entity/Traits/ActivityYearTrait.php

+ 1 - 1
.gitlab-ci.yml

@@ -57,7 +57,7 @@ code_quality:
   <<: *default_config
   stage: analysis
   script:
-    - php vendor/bin/phpstan analyse -c phpstan.neon.dist --error-format gitlab > phpstan.json  # Display code quality in MR
+    - php vendor/bin/phpstan analyse -c phpstan.neon.dist --error-format gitlab > phpstan.json || true    # Display code quality in MR
     - php vendor/bin/phpstan analyse -c phpstan.neon.dist
   artifacts:
     when: always

+ 2 - 2
composer.json

@@ -14,7 +14,7 @@
     "api-platform/core": "^4.0",
     "beberlei/doctrineextensions": "^1.3",
     "composer/package-versions-deprecated": "^1.11",
-    "damienharper/auditor-bundle": "^5.2",
+    "damienharper/auditor-bundle": "^6.2",
     "doctrine/dbal": "^3.9",
     "doctrine/doctrine-bundle": "2.13",
     "doctrine/doctrine-migrations-bundle": "^3.4",
@@ -81,7 +81,7 @@
     "justinrainbow/json-schema": "^6.1",
     "phpstan/extension-installer": "^1.2",
     "phpstan/phpstan": "^2.1",
-    "phpstan/phpstan-deprecation-rules": "^1.2",
+    "phpstan/phpstan-deprecation-rules": "^2.0",
     "phpstan/phpstan-doctrine": "^2.0",
     "phpstan/phpstan-phpunit": "^2.0",
     "phpstan/phpstan-symfony": "^2.0",

+ 6 - 6
config/packages/docker/messenger.yaml

@@ -1,9 +1,9 @@
 # Désactive le fonctionnement asynchrone de messenger en mode dev
 # > commenter pour tester avec un fonctionnement asynchrone
 #   (dans ce cas, la commande `messenger:consume async` doit être en cours d'exécution)
-framework:
-    messenger:
-        transports:
-            # https://symfony.com/doc/current/messenger.html#transport-configuration
-            async: 'sync://'
-            failed: 'sync://'
+#framework:
+#    messenger:
+#        transports:
+#            # https://symfony.com/doc/current/messenger.html#transport-configuration
+#            async: 'sync://'
+#            failed: 'sync://'

+ 7 - 0
config/services.yaml

@@ -127,3 +127,10 @@ services:
     Symfony\Component\DependencyInjection\ContainerInterface: '@service_container'
     #########################################
 
+    doctrine.schema_update_command:
+        class: App\Commands\Doctrine\SchemaUpdateCommand
+        arguments:
+            - '@doctrine.orm.command.entity_manager_provider'
+        tags: ['console.command']
+
+

+ 4 - 2
phpstan.neon.dist

@@ -8,9 +8,11 @@ parameters:
     # on ignore les erreurs qui proviennent d'un importe d'un attribut PhpStorm
     # on ignore les erreurs qui imposent d'indiquer le type d'un iterable dans la phpDoc (cf: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type)
     ignoreErrors :
-        - '#Attribute class JetBrains\\PhpStorm\\[a-zA-Z]+ does not exist.#'
+        - '#Attribute class JetBrains\\PhpStorm\\[a-zA-Z]+ does not exist\.#'
         - identifier: 'missingType.generics'
-        - '#Property .+::\$id \(int\|null\) is never assigned int so it can be removed from the property type\.$#'
+        - '#Class App\\Repository\\.+Repository has PHPDoc tag @method for method .+\(\) parameter .* with no value type specified in iterable type array\.$#'
+#        - '#Property .+::\$id \(int\|null\) is never assigned int so it can be removed from the property type\.$#'
+        - '#Constructor of ApiPlatform\\Metadata\\[a-zA-Z]+ is invoked with named argument#'
 
     ergebnis:
         # TODO: simplify by using allRules: false (https://github.com/ergebnis/phpstan-rules?tab=readme-ov-file#enabling-rules-one-by-one)

+ 1 - 1
sql/schema-extensions/002-view_federation_structures.sql

@@ -1,6 +1,6 @@
 CREATE OR REPLACE VIEW view_federation_structures AS
     SELECT o.id, o.name, o.logo_id as logoId, o.description, o.image_id as imageId, o.principalType as type,
-           o.portailVisibility,
+           (o.principalType LIKE '%_FEDERATION') as isFederation, o.portailVisibility,
            IF(p.website is not null AND p.website != '', p.website, CONCAT('https://', p.subDomain, '.opentalent.fr')) AS website,
            CONCAT('[', GROUP_CONCAT(COLUMN_JSON(COLUMN_CREATE(
                    'type', oa.type, 'latitude', a.latitude, 'longitude', a.longitude,

+ 2 - 1
sql/schema-extensions/003-view_search_user.sql

@@ -23,5 +23,6 @@ CREATE OR REPLACE VIEW view_search_user AS
         ON
             a.person_id = p.id
     WHERE a.adminAccess IS FALSE
-      AND a.isPseudonymised IS FALSE;
+      AND a.isPseudonymised IS FALSE
+      AND a.newAccess IS FALSE;
 

+ 5 - 4
src/ApiResources/Access/AdminAccess.php

@@ -7,7 +7,7 @@ namespace App\ApiResources\Access;
 use ApiPlatform\Metadata\ApiProperty;
 use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Metadata\Get;
-use ApiPlatform\Metadata\Put;
+use ApiPlatform\Metadata\Patch;
 use App\ApiResources\ApiResourcesInterface;
 use App\State\Processor\Access\AdminAccessProcessor;
 use App\State\Provider\Access\AdminAccessProvider;
@@ -20,12 +20,13 @@ use Symfony\Component\Validator\Constraints as Assert;
     operations: [
         new Get(
             uriTemplate: '/admin-access/{id}',
-            defaults: ['id' => 0]
+            defaults: ['id' => 0],
+            security: 'object.getOrganizationId() == user.getOrganization().getId()'
         ),
-        new Put(
+        new Patch(
             uriTemplate: '/admin-access/{id}',
             defaults: ['id' => 0],
-            security: '(is_granted("ROLE_ADMIN_CORE") and object.getOrganizationId() == user.getOrganization().getId() )'
+            security: '(is_granted("ROLE_ORGANIZATION") and object.getOrganizationId() == user.getOrganization().getId() )'
         ),
     ],
     provider: AdminAccessProvider::class,

+ 1 - 1
src/ApiResources/Dolibarr/DolibarrAccount.php

@@ -65,7 +65,6 @@ class DolibarrAccount implements ApiResourcesInterface
 
     /**
      * Last order of the society.
-     * @var DolibarrOrder|null
      */
     #[Groups('dolibarr_get')]
     private ?DolibarrOrder $order = null;
@@ -150,6 +149,7 @@ class DolibarrAccount implements ApiResourcesInterface
     public function setOrder(?DolibarrOrder $order): self
     {
         $this->order = $order;
+
         return $this;
     }
 

+ 3 - 3
src/ApiResources/Profile/OrganizationProfile.php

@@ -71,7 +71,7 @@ class OrganizationProfile implements ApiResourcesInterface
     private ?PrincipalTypeEnum $principalType = null;
 
     #[Groups('access_profile_read')]
-    private ?bool $trialActive = false;
+    private bool $trialActive = false;
 
     #[Groups('access_profile_read')]
     private ?int $trialCountDown = null;
@@ -256,9 +256,9 @@ class OrganizationProfile implements ApiResourcesInterface
         return $this->trialActive;
     }
 
-    public function setTrialActive(?bool $trialActive): self
+    public function setTrialActive(bool $trialActive): self
     {
-        $this->trialActive = $trialActive ?? false;
+        $this->trialActive = $trialActive;
 
         return $this;
     }

+ 2 - 5
src/Commands/CronCommand.php

@@ -134,10 +134,7 @@ class CronCommand extends Command
         }
 
         if ($action === self::ACTION_RUN_ALL) {
-            $jobs = $this->cronjobIterator->getAll();
-            if (is_iterable($jobs)) {
-                $jobs = iterator_to_array($jobs);
-            }
+            $jobs = iterator_to_array($this->cronjobIterator->getAll());
         }
 
         if ($action === self::ACTION_RUN) {
@@ -226,7 +223,7 @@ class CronCommand extends Command
             $this->output->writeln($formatter->formatSection($job->name(), $msg));
             $this->logger->info($job->name().' - '.$msg);
         } catch (\Throwable $e) {
-            $this->logger->critical((string)$e);
+            $this->logger->critical((string) $e);
             $this->output->write('An error happened while running the process : '.$e);
 
             return Command::FAILURE;

+ 19 - 3
src/Commands/Doctrine/SchemaUpdateCommand.php

@@ -6,9 +6,11 @@ declare(strict_types=1);
 
 namespace App\Commands\Doctrine;
 
-use App\Service\Utils\Path;
+use App\Service\Utils\PathUtils;
 use Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand;
+use Doctrine\ORM\Tools\Console\EntityManagerProvider;
 use Doctrine\ORM\Tools\SchemaTool;
+use Path\Path;
 use Symfony\Component\Console\Input\InputInterface;
 use Symfony\Component\Console\Output\OutputInterface;
 use Symfony\Component\Console\Style\SymfonyStyle;
@@ -18,13 +20,27 @@ use Symfony\Component\Console\Style\SymfonyStyle;
  */
 class SchemaUpdateCommand extends UpdateCommand
 {
+    public static function getDefaultName(): string
+    {
+        return 'doctrine:schema:update';
+    }
+
+    public function __construct(
+        private readonly EntityManagerProvider $entityManagerProvider,
+    ) {
+        parent::__construct($this->entityManagerProvider);
+    }
+
     protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui): int
     {
         $output->writeln('-- Executing pre-update scripts');
 
         // Lists schema extensions scripts in the '/sql/schema-extensions' dir
         $schemaExtensionsDir = PathUtils::join(PathUtils::getProjectDir(), 'sql', 'schema-extensions');
-        $scripts = $this->fileUtils->list($schemaExtensionsDir, '*.sql');
+
+        $schemaExtensionsDir = (new Path(PathUtils::getProjectDir()))->append('sql', 'schema-extensions');
+
+        $scripts = $schemaExtensionsDir->glob('*.sql');
         sort($scripts);
 
         // Execute those scripts in alphabetical order
@@ -32,7 +48,7 @@ class SchemaUpdateCommand extends UpdateCommand
         $conn = $em->getConnection();
 
         foreach ($scripts as $script) {
-            $sql = $this->fileUtils->getFileContent($script);
+            $sql = $script->getContent();
             $conn->executeQuery($sql);
         }
 

+ 3 - 3
src/Commands/PostUpgrade/V0_2/PostUpgradeCommand.php

@@ -156,7 +156,7 @@ class PostUpgradeCommand extends Command
             $this->logger->info('Subdomain table was successfully populated');
         } catch (\Exception $e) {
             $opentalentCnn->rollBack();
-            $this->logger->error((string)$e);
+            $this->logger->error((string) $e);
             $this->logger->critical('Error while populating the subdomains, abort and rollback');
         }
     }
@@ -181,7 +181,7 @@ class PostUpgradeCommand extends Command
             $this->logger->info('Events uuid were successfully generated');
         } catch (\Exception $e) {
             $opentalentCnn->rollBack();
-            $this->logger->error((string)$e);
+            $this->logger->error((string) $e);
             $this->logger->critical('Error while generating events uuids, abort and rollback');
         }
     }
@@ -202,7 +202,7 @@ class PostUpgradeCommand extends Command
             $this->logger->info('Files statuses were successfully updated');
         } catch (\Exception $e) {
             $opentalentCnn->rollBack();
-            $this->logger->error((string)$e);
+            $this->logger->error((string) $e);
             $this->logger->critical('Error while updating file statuses, abort and rollback');
         }
     }

+ 0 - 1
src/Doctrine/Access/CurrentAccessExtension.php

@@ -7,7 +7,6 @@ namespace App\Doctrine\Access;
 use ApiPlatform\Metadata\Operation;
 use App\Doctrine\AbstractExtension;
 use App\Entity\Access\Access;
-use App\Entity\Custom\Search\UserSearchItem;
 use App\Service\ServiceIterator\CurrentAccessExtensionIterator;
 use Doctrine\ORM\QueryBuilder;
 use Symfony\Bundle\SecurityBundle\Security;

+ 2 - 2
src/Doctrine/Custom/Search/RestrictToOrganizationIdExtension.php

@@ -8,7 +8,6 @@ use ApiPlatform\Metadata\Operation;
 use App\Doctrine\AbstractExtension;
 use App\Entity\Access\Access;
 use App\Entity\Custom\Search\UserSearchItem;
-use App\Service\ServiceIterator\CurrentAccessExtensionIterator;
 use Doctrine\ORM\QueryBuilder;
 use Symfony\Bundle\SecurityBundle\Security;
 
@@ -20,7 +19,8 @@ final class RestrictToOrganizationIdExtension extends AbstractExtension
 {
     public function __construct(
         private readonly Security $security,
-    ) {}
+    ) {
+    }
 
     public function supports(string $resourceClass, ?Operation $operation): bool
     {

+ 200 - 92
src/Entity/Access/Access.php

@@ -18,6 +18,7 @@ use App\Entity\Billing\Bill;
 use App\Entity\Billing\BillCredit;
 use App\Entity\Billing\BillLine;
 use App\Entity\Billing\EducationalProjectPayer;
+use App\Entity\Booking\AbstractBooking;
 use App\Entity\Booking\Attendance;
 use App\Entity\Booking\AttendanceBooking;
 use App\Entity\Booking\CalendarSynchro;
@@ -55,6 +56,8 @@ use App\Entity\Product\EquipmentControl;
 use App\Entity\Product\EquipmentLoan;
 use App\Entity\Product\EquipmentRepair;
 use App\Entity\Reward\AccessReward;
+use App\Entity\Shop\Orders;
+use App\Entity\SimulationSession\SimulationSession;
 use App\Entity\Token\Token;
 use App\Entity\Traits\CreatedOnAndByTrait;
 use App\Filter\ApiPlatform\Person\FullNameFilter;
@@ -126,38 +129,42 @@ class Access implements UserInterface, PasswordAuthenticatedUserInterface
     #[ORM\Column(type: 'json', length: 4294967295, nullable: true)]
     private ?array $setting = [];
 
-    #[ORM\OneToOne(mappedBy: 'access', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToOne(mappedBy: 'access', cascade: ['persist', 'remove'])]
     private ?AccessBilling $accessBilling;
 
     /** @var Collection<int, PersonActivity> */
-    #[ORM\OneToMany(targetEntity: PersonActivity::class, mappedBy: 'access', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: PersonActivity::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $personActivity;
 
     /** @var Collection<int, OrganizationFunction> */
-    #[ORM\OneToMany(targetEntity: OrganizationFunction::class, mappedBy: 'access', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: OrganizationFunction::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $organizationFunction;
 
     /** @var Collection<int, OrganizationLicence> */
-    #[ORM\OneToMany(targetEntity: OrganizationLicence::class, mappedBy: 'licensee', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: OrganizationLicence::class, mappedBy: 'licensee', cascade: ['persist', 'remove'])]
     private Collection $organizationLicences;
 
     /** @var Collection<int, PersonalizedList> */
-    #[ORM\OneToMany(targetEntity: PersonalizedList::class, mappedBy: 'access', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: PersonalizedList::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $personalizedLists;
 
     /** @var Collection<int, Notification> */
-    #[ORM\OneToMany(targetEntity: Notification::class, mappedBy: 'recipientAccess', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Notification::class, mappedBy: 'recipientAccess', cascade: ['persist', 'remove'])]
     private Collection $notifications;
 
     /** @var Collection<int, NotificationUser> */
-    #[ORM\OneToMany(targetEntity: NotificationUser::class, mappedBy: 'access', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: NotificationUser::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $notificationUsers;
 
-    /** @var Collection<int, Access> */
+    /**
+     * @var Collection<int, Access>
+     */
     #[ORM\ManyToMany(targetEntity: Access::class, mappedBy: 'children', cascade: ['persist'])]
     private Collection $guardians;
 
-    /** @var Collection<int, Access> */
+    /**
+     * @var Collection<int, Access>
+     */
     #[ORM\ManyToMany(targetEntity: Access::class, inversedBy: 'guardians', cascade: ['persist'])]
     #[ORM\JoinTable(name: 'children_guardians')]
     #[ORM\JoinColumn(name: 'guardians_id', referencedColumnName: 'id')]
@@ -165,54 +172,62 @@ class Access implements UserInterface, PasswordAuthenticatedUserInterface
     private Collection $children;
 
     /** @var Collection<int, AccessPayer> */
-    #[ORM\OneToMany(targetEntity: AccessPayer::class, mappedBy: 'accessPayer', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: AccessPayer::class, mappedBy: 'accessPayer', cascade: ['persist', 'remove'])]
     private Collection $billingPayers;
 
     /** @var Collection<int, AccessPayer> */
-    #[ORM\OneToMany(targetEntity: AccessPayer::class, mappedBy: 'accessReceiver', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: AccessPayer::class, mappedBy: 'accessReceiver', cascade: ['persist', 'remove'])]
     private Collection $billingReceivers;
 
     /** @var Collection<int, AccessIntangible> */
-    #[ORM\OneToMany(targetEntity: AccessIntangible::class, mappedBy: 'access', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: AccessIntangible::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $accessIntangibles;
 
     #[ORM\ManyToOne(inversedBy: 'publicationDirectors')]
-    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: false)]
-    private Parameters $publicationDirector;
+    #[ORM\JoinColumn(referencedColumnName: 'id')]
+    private ?Parameters $publicationDirector;
 
     #[ORM\ManyToOne(inversedBy: 'teachers')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
     private ?EducationNotationConfig $educationNotationConfig;
 
     /** @var Collection<int, CompanyPerson> */
-    #[ORM\OneToMany(targetEntity: CompanyPerson::class, mappedBy: 'company', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: CompanyPerson::class, mappedBy: 'company', cascade: ['persist', 'remove'])]
     private Collection $companyPersonAccesses;
 
     /** @var Collection<int, CompanyPerson> */
-    #[ORM\OneToMany(targetEntity: CompanyPerson::class, mappedBy: 'access', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: CompanyPerson::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $companyPersonCompany;
 
     /** @var Collection<int, EducationStudent> */
-    #[ORM\OneToMany(targetEntity: EducationStudent::class, mappedBy: 'access', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: EducationStudent::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $educationStudent;
 
     /** @var Collection<int, EducationStudent> */
-    #[ORM\ManyToMany(targetEntity: EducationStudent::class, mappedBy: 'teachers', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\ManyToMany(targetEntity: EducationStudent::class, mappedBy: 'teachers', cascade: ['persist'])]
     private Collection $educationStudentByTeacher;
 
     /** @var Collection<int, EducationTeacher> */
-    #[ORM\OneToMany(targetEntity: EducationTeacher::class, mappedBy: 'teacher', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: EducationTeacher::class, mappedBy: 'teacher', cascade: ['persist', 'remove'])]
     private Collection $educationTeachers;
 
     /** @var Collection<int, PersonHoliday> */
-    #[ORM\OneToMany(targetEntity: PersonHoliday::class, mappedBy: 'access', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: PersonHoliday::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $holidays;
 
-    /** @var Collection<int, Course> */
+    /**
+     * TODO: orphanRemoval?
+     *
+     * @var Collection<int, Course>
+     */
     #[ORM\ManyToMany(targetEntity: Course::class, mappedBy: 'students', cascade: ['persist'])]
     private Collection $courses;
 
-    /** @var Collection<int, Course> */
+    /**
+     * TODO: orphanRemoval?
+     *
+     * @var Collection<int, Course>
+     */
     #[ORM\ManyToMany(targetEntity: Course::class, mappedBy: 'organizer', cascade: ['persist'])]
     private Collection $practicalCourses;
 
@@ -220,7 +235,11 @@ class Access implements UserInterface, PasswordAuthenticatedUserInterface
     #[ORM\ManyToMany(targetEntity: Event::class, mappedBy: 'organizer', cascade: ['persist'])]
     private Collection $eventOrganizers;
 
-    /** @var Collection<int, EducationalProject> */
+    /**
+     * TODO: orphanRemoval?
+     *
+     * @var Collection<int, EducationalProject>
+     */
     #[ORM\ManyToMany(targetEntity: EducationalProject::class, mappedBy: 'organizer', cascade: ['persist'])]
     private Collection $educationalProjectOrganizers;
 
@@ -235,183 +254,201 @@ class Access implements UserInterface, PasswordAuthenticatedUserInterface
     private bool $ielEnabled = false;
 
     /** @var Collection<int, EducationalProjectPayer> */
-    #[ORM\OneToMany(targetEntity: EducationalProjectPayer::class, mappedBy: 'educationalProjectPayer', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: EducationalProjectPayer::class, mappedBy: 'educationalProjectPayer', cascade: ['persist', 'remove'])]
     private Collection $billingEducationalProjectPayers;
 
     /** @var Collection<int, Bill> */
-    #[ORM\OneToMany(targetEntity: Bill::class, mappedBy: 'access', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Bill::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $bills;
 
     /** @var Collection<int, BillLine> */
-    #[ORM\OneToMany(targetEntity: BillLine::class, mappedBy: 'access', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: BillLine::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $billLines;
 
     /** @var Collection<int, BillCredit> */
-    #[ORM\OneToMany(targetEntity: BillCredit::class, mappedBy: 'access', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: BillCredit::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $billCredits;
 
     /** @var Collection<int, EducationalProject> */
-    #[ORM\OneToMany(targetEntity: EducationalProject::class, mappedBy: 'silentPartner', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: EducationalProject::class, mappedBy: 'silentPartner', cascade: ['persist', 'remove'])]
     private Collection $silentPartners;
 
     /** @var Collection<int, EducationalProject> */
-    #[ORM\OneToMany(targetEntity: EducationalProject::class, mappedBy: 'operationalPartner', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: EducationalProject::class, mappedBy: 'operationalPartner', cascade: ['persist', 'remove'])]
     private Collection $operationalPartners;
 
     /** @var Collection<int, EventUser> */
-    #[ORM\OneToMany(targetEntity: EventUser::class, mappedBy: 'guest', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: EventUser::class, mappedBy: 'guest', cascade: ['persist', 'remove'])]
     private Collection $eventUsers;
 
     /** @var Collection<int, ExamenConvocation> */
-    #[ORM\OneToMany(targetEntity: ExamenConvocation::class, mappedBy: 'student', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: ExamenConvocation::class, mappedBy: 'student', cascade: ['persist', 'remove'])]
     private Collection $examenConvocations;
 
     /** @var Collection<int, EquipmentRepair> */
-    #[ORM\OneToMany(targetEntity: EquipmentRepair::class, mappedBy: 'provider', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: EquipmentRepair::class, mappedBy: 'provider', cascade: ['persist', 'remove'])]
     private Collection $equipmentRepairProviders;
 
     /** @var Collection<int, Attendance> */
-    #[ORM\OneToMany(targetEntity: Attendance::class, mappedBy: 'access', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Attendance::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $attendances;
 
     /** @var Collection<int, AttendanceBooking> */
-    #[ORM\OneToMany(targetEntity: AttendanceBooking::class, mappedBy: 'access', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: AttendanceBooking::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $attendanceBookings;
 
     /** @var Collection<int, Attendance> */
-    #[ORM\OneToMany(targetEntity: Attendance::class, mappedBy: 'replacement', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Attendance::class, mappedBy: 'replacement', cascade: ['persist', 'remove'])]
     private Collection $attendanceReplacements;
 
     /** @var Collection<int, RoomRepair> */
-    #[ORM\OneToMany(targetEntity: RoomRepair::class, mappedBy: 'provider', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: RoomRepair::class, mappedBy: 'provider', cascade: ['persist', 'remove'])]
     private Collection $roomRepairProviders;
 
     /** @var Collection<int, PlaceRepair> */
-    #[ORM\OneToMany(targetEntity: PlaceRepair::class, mappedBy: 'provider', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: PlaceRepair::class, mappedBy: 'provider', cascade: ['persist', 'remove'])]
     private Collection $placeRepairProviders;
 
     /** @var Collection<int, Email> */
-    #[ORM\OneToMany(targetEntity: Email::class, mappedBy: 'author', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Email::class, mappedBy: 'author', cascade: ['persist', 'remove'])]
     private Collection $emails;
 
     /** @var Collection<int, Mail> */
-    #[ORM\OneToMany(targetEntity: Mail::class, mappedBy: 'author', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Mail::class, mappedBy: 'author', cascade: ['persist', 'remove'])]
     private Collection $mails;
 
     /** @var Collection<int, Sms> */
-    #[ORM\OneToMany(targetEntity: Sms::class, mappedBy: 'author', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Sms::class, mappedBy: 'author', cascade: ['persist', 'remove'])]
     private Collection $sms;
 
     /** @var Collection<int, Jury> */
-    #[ORM\ManyToMany(targetEntity: Jury::class, mappedBy: 'members', orphanRemoval: true)]
+    #[ORM\ManyToMany(targetEntity: Jury::class, mappedBy: 'members', cascade: ['persist'])]
     private Collection $juryMembers;
 
     /** @var Collection<int, Organization> */
-    #[ORM\OneToMany(targetEntity: Organization::class, mappedBy: 'contactPerson', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Organization::class, mappedBy: 'contactPerson', cascade: ['persist', 'remove'])]
     private Collection $organizationContacts;
 
     /** @var Collection<int, CommissionMember> */
-    #[ORM\OneToMany(targetEntity: CommissionMember::class, mappedBy: 'member', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: CommissionMember::class, mappedBy: 'member', cascade: ['persist', 'remove'])]
     private Collection $commissionMembers;
 
     /** @var Collection<int, Equipment> */
-    #[ORM\OneToMany(targetEntity: Equipment::class, mappedBy: 'supplier', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Equipment::class, mappedBy: 'supplier', cascade: ['persist', 'remove'])]
     private Collection $equipmentSuppliers;
 
     /** @var Collection<int, Equipment> */
-    #[ORM\OneToMany(targetEntity: Equipment::class, mappedBy: 'controlManager', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Equipment::class, mappedBy: 'controlManager', cascade: ['persist', 'remove'])]
     private Collection $equipmentControlManagers;
 
     /** @var Collection<int, Equipment> */
-    #[ORM\OneToMany(targetEntity: Equipment::class, mappedBy: 'editor', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Equipment::class, mappedBy: 'editor', cascade: ['persist', 'remove'])]
     private Collection $equipmentEditors;
 
     /** @var Collection<int, EquipmentLoan> */
-    #[ORM\OneToMany(targetEntity: EquipmentLoan::class, mappedBy: 'borrower', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: EquipmentLoan::class, mappedBy: 'borrower', cascade: ['persist', 'remove'])]
     private Collection $equipmentLoans;
 
     /** @var Collection<int, Equipment> */
-    #[ORM\OneToMany(targetEntity: Equipment::class, mappedBy: 'access', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Equipment::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $equipments;
 
     /** @var Collection<int, AccessFictionalIntangible> */
-    #[ORM\OneToMany(targetEntity: AccessFictionalIntangible::class, mappedBy: 'access', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: AccessFictionalIntangible::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $accessFictionalIntangibles;
 
     /** @var Collection<int, Donor> */
-    #[ORM\OneToMany(targetEntity: Donor::class, mappedBy: 'access', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Donor::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $donors;
 
     /** @var Collection<int, AccessReward> */
-    #[ORM\OneToMany(targetEntity: AccessReward::class, mappedBy: 'access', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: AccessReward::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $accessRewards;
 
     /** @var Collection<int, OrganizationResponsability> */
-    #[ORM\OneToMany(targetEntity: OrganizationResponsability::class, mappedBy: 'access', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: OrganizationResponsability::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $organizationResponsabilities;
 
     /** @var Collection<int, AccessWish> */
-    #[ORM\OneToMany(targetEntity: AccessWish::class, mappedBy: 'accessOriginal', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: AccessWish::class, mappedBy: 'accessOriginal', cascade: ['persist', 'remove'])]
     private Collection $accessWishes;
 
     /** @var Collection<int, WorkByUser> */
-    #[ORM\OneToMany(targetEntity: WorkByUser::class, mappedBy: 'student', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: WorkByUser::class, mappedBy: 'student', cascade: ['persist', 'remove'])]
     private Collection $workByUsers;
 
     /** @var Collection<int, Tagg> */
     #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'accesses', cascade: ['persist'])]
+    #[ORM\OrderBy(value: ['label' => 'ASC'])]
     #[ORM\JoinTable(name: 'tag_access')]
     #[ORM\JoinColumn(name: 'access_id', referencedColumnName: 'id')]
     #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
     private Collection $tags;
 
-    // TODO: revoir le mapping, on ne peut pas mapper à une mapped superclass comme abstract booking
-    //    #[ORM\ManyToMany(mappedBy: 'organizer', targetEntity: AbstractBooking::class, cascade: ['persist'], orphanRemoval: false)]
-    //    private Collection $bookingOrganizers;
+    /** @var Collection<int, AbstractBooking> */
+    #[ORM\ManyToMany(targetEntity: AbstractBooking::class, mappedBy: 'organizer', cascade: ['persist'])]
+    private Collection $bookingOrganizers;
 
     /** @var Collection<int, AdvancePayment> */
-    #[ORM\OneToMany(targetEntity: AdvancePayment::class, mappedBy: 'access', cascade: [], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: AdvancePayment::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $advancePayments;
 
     /** @var Collection<int, AbstractMessage> */
-    #[ORM\OneToMany(targetEntity: AbstractMessage::class, mappedBy: 'author', cascade: [], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: AbstractMessage::class, mappedBy: 'author', cascade: ['persist', 'remove'])]
     private Collection $messages;
 
     /** @var Collection<int, Equipment> */
-    #[ORM\OneToMany(targetEntity: Equipment::class, mappedBy: 'managerControl', cascade: [], orphanRemoval: false)]
+    #[ORM\OneToMany(targetEntity: Equipment::class, mappedBy: 'managerControl', cascade: ['persist', 'remove'])]
     private Collection $equipmentManagerControls;
 
     /** @var Collection<int, EquipmentControl> */
-    #[ORM\OneToMany(targetEntity: EquipmentControl::class, mappedBy: 'accompanist', cascade: [], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: EquipmentControl::class, mappedBy: 'accompanist', cascade: ['persist', 'remove'])]
     private Collection $accompanistControl;
 
     /** @var Collection<int, AccessReward> */
-    #[ORM\OneToMany(targetEntity: AccessReward::class, mappedBy: 'access', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: AccessReward::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $rewards;
 
-    #[ORM\OneToOne(targetEntity: AccessSocial::class, mappedBy: 'access', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToOne(targetEntity: AccessSocial::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private ?AccessSocial $accessSocial;
 
-    #[ORM\OneToOne(targetEntity: AccessNetworkSetting::class, mappedBy: 'access', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToOne(targetEntity: AccessNetworkSetting::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private ?AccessNetworkSetting $accessNetworkSetting;
 
-    #[ORM\OneToOne(targetEntity: AccessCommunication::class, mappedBy: 'access', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToOne(targetEntity: AccessCommunication::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private ?AccessCommunication $accessCommunication;
 
-    #[ORM\OneToOne(targetEntity: CalendarSynchro::class, mappedBy: 'access', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToOne(targetEntity: CalendarSynchro::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private ?CalendarSynchro $calendarSynchro;
 
     /** @var Collection<int, Token> */
-    #[ORM\OneToMany(targetEntity: Token::class, mappedBy: 'access', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Token::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $tokens;
 
-    #[ORM\OneToOne(mappedBy: 'access', cascade: ['persist'], fetch: 'EAGER', orphanRemoval: true)]
+    #[ORM\OneToOne(mappedBy: 'access', cascade: ['persist', 'remove'], fetch: 'EAGER')]
     private ?Preferences $preferences;
 
     /** @var Collection<int, AbstractReport> */
-    #[ORM\OneToMany(targetEntity: AbstractReport::class, mappedBy: 'access', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: AbstractReport::class, mappedBy: 'access', cascade: ['persist', 'remove'])]
     private Collection $reports;
 
+    /** @var Collection<int, SimulationSession> */
+    #[ORM\OneToMany(targetEntity: SimulationSession::class, mappedBy: 'accessInitiator', cascade: ['persist', 'remove'])]
+    protected Collection $simulationSessionAccessInitiators;
+
+    /** @var Collection<int, SimulationSession> */
+    #[ORM\OneToMany(
+        targetEntity: SimulationSession::class,
+        mappedBy: 'accessSimulated',
+        cascade: ['persist', 'remove'],
+        orphanRemoval: false,
+    )]
+    protected Collection $simulationSessionAccessSimulateds;
+
+    /** @var Collection<int, Orders> */
+    #[ORM\OneToMany(targetEntity: Orders::class, mappedBy: 'access', cascade: [], orphanRemoval: true)]
+    protected Collection $orders;
+
     #[Pure]
     public function __construct()
     {
@@ -468,6 +505,9 @@ class Access implements UserInterface, PasswordAuthenticatedUserInterface
         $this->emails = new ArrayCollection();
         $this->mails = new ArrayCollection();
         $this->sms = new ArrayCollection();
+        $this->simulationSessionAccessInitiators = new ArrayCollection();
+        $this->simulationSessionAccessSimulateds = new ArrayCollection();
+        $this->orders = new ArrayCollection();
     }
 
     public function getId(): ?int
@@ -2250,29 +2290,29 @@ class Access implements UserInterface, PasswordAuthenticatedUserInterface
         return $this;
     }
 
-    //    public function getBookingOrganizers(): Collection
-    //    {
-    //        return $this->bookingOrganizers;
-    //    }
-    //
-    //    public function addBookingOrganizer(AbstractBooking $bookingOrganizer): self
-    //    {
-    //        if (!$this->bookingOrganizers->contains($bookingOrganizer)) {
-    //            $this->bookingOrganizers[] = $bookingOrganizer;
-    //            $bookingOrganizer->addOrganizer($this);
-    //        }
-    //
-    //        return $this;
-    //    }
-    //
-    //    public function removeBookingOrganizer(AbstractBooking $bookingOrganizer): self
-    //    {
-    //        if ($this->bookingOrganizers->removeElement($bookingOrganizer)) {
-    //            $bookingOrganizer->removeOrganizer($this);
-    //        }
-    //
-    //        return $this;
-    //    }
+    public function getBookingOrganizers(): Collection
+    {
+        return $this->bookingOrganizers;
+    }
+
+    public function addBookingOrganizer(AbstractBooking $bookingOrganizer): self
+    {
+        if (!$this->bookingOrganizers->contains($bookingOrganizer)) {
+            $this->bookingOrganizers[] = $bookingOrganizer;
+            $bookingOrganizer->addOrganizer($this);
+        }
+
+        return $this;
+    }
+
+    public function removeBookingOrganizer(AbstractBooking $bookingOrganizer): self
+    {
+        if ($this->bookingOrganizers->removeElement($bookingOrganizer)) {
+            $bookingOrganizer->removeOrganizer($this);
+        }
+
+        return $this;
+    }
 
     public function getAdvancePayments(): Collection
     {
@@ -2502,4 +2542,72 @@ class Access implements UserInterface, PasswordAuthenticatedUserInterface
 
         return $this;
     }
+
+    public function getSimulationSessionAccessInitiators(): Collection
+    {
+        return $this->simulationSessionAccessInitiators;
+    }
+
+    public function addSimulationSessionAccessInitiator(SimulationSession $simulationSessionAccessInitiator): self
+    {
+        if (!$this->simulationSessionAccessInitiators->contains($simulationSessionAccessInitiator)) {
+            $this->simulationSessionAccessInitiators[] = $simulationSessionAccessInitiator;
+            $simulationSessionAccessInitiator->setAccessInitiator($this);
+        }
+
+        return $this;
+    }
+
+    public function removeSimulationSessionAccessInitiator(SimulationSession $simulationSessionAccessInitiator): self
+    {
+        $this->simulationSessionAccessInitiators->removeElement($simulationSessionAccessInitiator);
+
+        return $this;
+    }
+
+    public function getSimulationSessionAccessSimulateds(): Collection
+    {
+        return $this->simulationSessionAccessSimulateds;
+    }
+
+    public function addSimulationSessionAccessSimulated(SimulationSession $simulationSessionAccessSimulated): self
+    {
+        if (!$this->simulationSessionAccessSimulateds->contains($simulationSessionAccessSimulated)) {
+            $this->simulationSessionAccessSimulateds[] = $simulationSessionAccessSimulated;
+            $simulationSessionAccessSimulated->setAccessSimulated($this);
+        }
+
+        return $this;
+    }
+
+    public function removeSimulationSessionAccessSimulated(SimulationSession $simulationSessionAccessSimulated): self
+    {
+        $this->simulationSessionAccessSimulateds->removeElement($simulationSessionAccessSimulated);
+
+        return $this;
+    }
+
+    public function getOrders(): Collection
+    {
+        return $this->orders;
+    }
+
+    public function addOrder(Orders $order): self
+    {
+        if (!$this->orders->contains($order)) {
+            $this->orders[] = $order;
+            $order->setAccess($this);
+        }
+
+        return $this;
+    }
+
+    public function removeOrder(Orders $order): self
+    {
+        if ($this->orders->removeElement($order)) {
+            $order->setAccess(null);
+        }
+
+        return $this;
+    }
 }

+ 3 - 7
src/Entity/Awin/Product.php

@@ -12,13 +12,9 @@ use Doctrine\ORM\Mapping as ORM;
  */
 #[ApiResource(operations: [])]
 #[ORM\Entity]
-#[ORM\Table(
-    name: 'AwinProduct',
-    indexes: [
-        new ORM\Index(columns: ["name"], name: "name_idx"),
-        new ORM\Index(columns: ["slug"], name: "slug_idx"),
-    ]
-)]
+#[ORM\Table(name: 'AwinProduct')]
+#[ORM\Index(name: 'name_idx', columns: ['name'])]
+#[ORM\Index(name: 'slug_idx', columns: ['slug'])]
 class Product
 {
     #[ORM\Id]

+ 2 - 2
src/Entity/Billing/AbstractBillAccounting.php

@@ -19,8 +19,9 @@ use Doctrine\ORM\Mapping as ORM;
  *
  * @todo : A la suite de la migration, il faut supprimer le nom de la table pour avoir une table BillAccounting, et supprimer l'attribut discr.
  */
-#[ORM\MappedSuperclass]
+#[ORM\Entity]
 #[ORM\Table(name: 'BillAccounting')]
+#[ORM\InheritanceType('SINGLE_TABLE')]
 #[ORM\DiscriminatorColumn(name: 'discr', type: 'string')]
 #[ORM\DiscriminatorMap(
     [
@@ -147,7 +148,6 @@ class AbstractBillAccounting
     {
         if (!$this->billingIntangibleExcludeDates->contains($billingIntangibleExcludeDate)) {
             $this->billingIntangibleExcludeDates[] = $billingIntangibleExcludeDate;
-            /* @phpstan-ignore-next-line */
             $billingIntangibleExcludeDate->setBill($this);
         }
 

+ 2 - 1
src/Entity/Billing/AbstractBillingPayer.php

@@ -11,8 +11,9 @@ use Doctrine\ORM\Mapping as ORM;
  * l'EducationalProject concerné par la facture
  * Classe de base de @see  AccessPayer, EducationalProjectPayer.
  */
-#[ORM\MappedSuperclass]
+#[ORM\Entity]
 #[ORM\Table(name: 'BillingPayer')]
+#[ORM\InheritanceType('SINGLE_TABLE')]
 #[ORM\DiscriminatorColumn(name: 'discr', type: 'string')]
 #[ORM\DiscriminatorMap(
     [

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

@@ -18,7 +18,6 @@ use Doctrine\ORM\Mapping as ORM;
 #[ApiResource(operations: [])]
 // #[Auditable]
 #[ORM\Entity(repositoryClass: AccessIntangibleRepository::class)]
-#[ORM\Table(name: 'BillingIntangible')]
 class AccessIntangible extends AbstractBillingIntangible
 {
     #[ORM\ManyToOne(inversedBy: 'accessIntangibles')]

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

@@ -16,7 +16,6 @@ use Doctrine\ORM\Mapping as ORM;
  * Fais le lien entre l'Access qui règle la facture et l'Access concerné
  */
 #[ApiResource(operations: [])]
-#[ORM\Table(name: 'BillingPayer')]
 // #[Auditable]
 #[ORM\Entity(repositoryClass: AccessPayerRepository::class)]
 class AccessPayer extends AbstractBillingPayer

+ 0 - 1
src/Entity/Billing/AdvancePayment.php

@@ -13,7 +13,6 @@ use Doctrine\ORM\Mapping as ORM;
 #[ApiResource(operations: [])]
 // #[Auditable]
 #[ORM\Entity]
-#[ORM\Table(name: 'BillAccounting')]
 class AdvancePayment extends AbstractBillAccounting
 {
 }

+ 35 - 4
src/Entity/Billing/Bill.php

@@ -15,26 +15,30 @@ use Doctrine\ORM\Mapping as ORM;
 #[ApiResource(operations: [])]
 // #[Auditable]
 #[ORM\Entity]
-#[ORM\Table(name: 'BillAccounting')]
 class Bill extends AbstractBillAccounting
 {
     /** @var Collection<int, BillLine> */
-    #[ORM\OneToMany(targetEntity: BillLine::class, mappedBy: 'bill', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: BillLine::class, mappedBy: 'bill', cascade: ['persist', 'remove'])]
     protected Collection $billLines;
 
     /** @var Collection<int, BillCredit> */
-    #[ORM\OneToMany(targetEntity: BillCredit::class, mappedBy: 'bill', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: BillCredit::class, mappedBy: 'bill', cascade: ['persist', 'remove'])]
     protected Collection $billCredits;
 
     /** @var Collection<int, BillPayment> */
-    #[ORM\OneToMany(targetEntity: BillPayment::class, mappedBy: 'bill', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: BillPayment::class, mappedBy: 'bill', cascade: ['persist', 'remove'])]
     protected Collection $billPayments;
 
+    /** @var Collection<int, PayfipPaymentReturn> */
+    #[ORM\OneToMany(targetEntity: PayfipPaymentReturn::class, mappedBy: 'bill', cascade: ['persist', 'remove'])]
+    protected Collection $payfipPaymentReturns;
+
     public function __construct()
     {
         $this->billLines = new ArrayCollection();
         $this->billCredits = new ArrayCollection();
         $this->billPayments = new ArrayCollection();
+        $this->payfipPaymentReturns = new ArrayCollection();
         parent::__construct();
     }
 
@@ -113,4 +117,31 @@ class Bill extends AbstractBillAccounting
 
         return $this;
     }
+
+    public function getPayfipPaymentReturns(): Collection
+    {
+        return $this->payfipPaymentReturns;
+    }
+
+    public function addPayfipPaymentReturn(PayfipPaymentReturn $payfipPaymentReturn): self
+    {
+        if (!$this->payfipPaymentReturns->contains($payfipPaymentReturn)) {
+            $this->payfipPaymentReturns[] = $payfipPaymentReturn;
+            $payfipPaymentReturn->setBill($this);
+        }
+
+        return $this;
+    }
+
+    public function removePayfipPaymentReturn(PayfipPaymentReturn $payfipPaymentReturn): self
+    {
+        if ($this->payfipPaymentReturns->removeElement($payfipPaymentReturn)) {
+            // set the owning side to null (unless already changed)
+            if ($payfipPaymentReturn->getBill() === $this) {
+                $payfipPaymentReturn->setBill(null);
+            }
+        }
+
+        return $this;
+    }
 }

+ 0 - 2
src/Entity/Billing/BillAccounting.php

@@ -13,8 +13,6 @@ use Doctrine\ORM\Mapping as ORM;
 #[ApiResource(operations: [])]
 // #[Auditable]
 #[ORM\Entity]
-#[ORM\Table(name: 'BillAccounting')]
-#[ORM\InheritanceType('SINGLE_TABLE')]
 class BillAccounting extends AbstractBillAccounting
 {
 }

+ 0 - 1
src/Entity/Billing/BillCredit.php

@@ -13,7 +13,6 @@ use Doctrine\ORM\Mapping as ORM;
 #[ApiResource(operations: [])]
 // #[Auditable]
 #[ORM\Entity]
-#[ORM\Table(name: 'BillAccounting')]
 class BillCredit extends AbstractBillAccounting
 {
 }

+ 3 - 3
src/Entity/Billing/BillingIntangibleExcludeDate.php

@@ -36,7 +36,7 @@ class BillingIntangibleExcludeDate
     private ?EquipmentLoan $equipmentLoan = null;
 
     #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'billingIntangibleExcludeDates')]
-    private ?Bill $bill = null;
+    private ?AbstractBillAccounting $bill = null;
 
     public function getId(): ?int
     {
@@ -91,12 +91,12 @@ class BillingIntangibleExcludeDate
         return $this;
     }
 
-    public function getBill(): ?Bill
+    public function getBill(): ?AbstractBillAccounting
     {
         return $this->bill;
     }
 
-    public function setBill(?Bill $bill): self
+    public function setBill(?AbstractBillAccounting $bill): self
     {
         $this->bill = $bill;
 

+ 1 - 1
src/Entity/Billing/BillingSetting.php

@@ -41,7 +41,7 @@ class BillingSetting
     #[ORM\OneToMany(targetEntity: FamilyQuotient::class, mappedBy: 'billingSetting', cascade: ['persist'], orphanRemoval: true)]
     private Collection $familyQuotients;
 
-    #[ORM\OneToOne(targetEntity: BillingSettingRent::class, mappedBy: 'billingSetting', cascade: ['persist'])]
+    #[ORM\OneToOne(targetEntity: BillingSettingRent::class, mappedBy: 'billingSetting', cascade: ['persist', 'remove'])]
     protected ?BillingSettingRent $billingSettingRent;
 
     #[Pure]

+ 16 - 0
src/Entity/Billing/BillingSettingRent.php

@@ -24,6 +24,10 @@ class BillingSettingRent
     #[ORM\OneToOne(targetEntity: BillingSetting::class, inversedBy: 'billingSettingRent', cascade: [])]
     protected ?BillingSetting $billingSetting;
 
+    #[ORM\ManyToOne(targetEntity: FamilyQuotientModel::class, cascade: [], inversedBy: 'billingSettingRents')]
+    #[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')]
+    protected ?FamilyQuotientModel $familyQuotientModel;
+
     public function getBillingSetting(): ?BillingSetting
     {
         return $this->billingSetting;
@@ -40,4 +44,16 @@ class BillingSettingRent
     {
         return $this->id;
     }
+
+    public function getFamilyQuotientModel(): ?FamilyQuotientModel
+    {
+        return $this->familyQuotientModel;
+    }
+
+    public function setFamilyQuotientModel(?FamilyQuotientModel $familyQuotientModel): self
+    {
+        $this->familyQuotientModel = $familyQuotientModel;
+
+        return $this;
+    }
 }

+ 0 - 1
src/Entity/Billing/EducationalProjectIntangible.php

@@ -17,7 +17,6 @@ use Doctrine\ORM\Mapping as ORM;
 // #[Auditable]
 #[ApiResource(operations: [])]
 #[ORM\Entity]
-#[ORM\Table(name: 'BillingIntangible')]
 class EducationalProjectIntangible extends AbstractBillingIntangible
 {
     #[ORM\ManyToOne(inversedBy: 'educationalProjectIntangibles')]

+ 0 - 1
src/Entity/Billing/EducationalProjectPayer.php

@@ -18,7 +18,6 @@ use Doctrine\ORM\Mapping as ORM;
 #[ApiResource(operations: [])]
 // #[Auditable]
 #[ORM\Entity]
-#[ORM\Table(name: 'BillingPayer')]
 class EducationalProjectPayer extends AbstractBillingPayer
 {
     #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'billingEducationalProjectPayers')]

+ 34 - 0
src/Entity/Billing/FamilyQuotientModel.php

@@ -7,6 +7,7 @@ namespace App\Entity\Billing;
 use ApiPlatform\Metadata\ApiResource;
 use App\Entity\Organization\Organization;
 use App\Entity\Product\IntangiblePriceAndDiscount;
+use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
 
@@ -34,6 +35,15 @@ class FamilyQuotientModel
     #[ORM\OneToMany(targetEntity: IntangiblePriceAndDiscount::class, mappedBy: 'familyQuotientModel', cascade: [], orphanRemoval: false)]
     protected Collection $intangiblePriceAndDiscounts;
 
+    /** @var Collection<int, BillingSettingRent> */
+    #[ORM\OneToMany(targetEntity: BillingSettingRent::class, mappedBy: 'familyQuotientModel', cascade: [], orphanRemoval: false)]
+    protected Collection $billingSettingRents;
+
+    public function __construct()
+    {
+        $this->billingSettingRents = new ArrayCollection();
+    }
+
     public function getId(): int
     {
         return $this->id;
@@ -105,4 +115,28 @@ class FamilyQuotientModel
 
         return $this;
     }
+
+    public function getBillingSettingRents(): Collection
+    {
+        return $this->billingSettingRents;
+    }
+
+    public function addBillingSettingRent(BillingSettingRent $billingSettingRent): self
+    {
+        if (!$this->billingSettingRents->contains($billingSettingRent)) {
+            $this->billingSettingRents[] = $billingSettingRent;
+            $billingSettingRent->setFamilyQuotientModel($this);
+        }
+
+        return $this;
+    }
+
+    public function removeBillingSettingRent(BillingSettingRent $billingSettingRent): self
+    {
+        if ($this->billingSettingRents->removeElement($billingSettingRent)) {
+            $billingSettingRent->setFamilyQuotientModel(null);
+        }
+
+        return $this;
+    }
 }

+ 1 - 1
src/Entity/Billing/PayfipPaymentReturn.php

@@ -21,7 +21,7 @@ class PayfipPaymentReturn
     #[ORM\GeneratedValue]
     private ?int $id = null;
 
-    #[ORM\ManyToOne(cascade: ['persist'])]
+    #[ORM\ManyToOne(targetEntity: Bill::class, inversedBy: 'payfipPaymentReturns', cascade: ['persist', 'remove'])]
     #[ORM\JoinColumn(nullable: false)]
     private Bill $bill;
 

+ 4 - 0
src/Entity/Billing/ResidenceArea.php

@@ -8,6 +8,7 @@ use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Metadata\Delete;
 use ApiPlatform\Metadata\Get;
 use ApiPlatform\Metadata\GetCollection;
+use ApiPlatform\Metadata\Patch;
 use ApiPlatform\Metadata\Post;
 use ApiPlatform\Metadata\Put;
 use App\Attribute\BillingSettingDefaultValue;
@@ -30,6 +31,9 @@ use Doctrine\ORM\Mapping as ORM;
         new Get(
             security: 'is_granted(\'ROLE_ORGANIZATION_VIEW\') and object.getBillingSetting().getOrganization().getId() == user.getOrganization().getId()'
         ),
+        new Patch(
+            security: 'is_granted(\'ROLE_ORGANIZATION\') and object.getBillingSetting().getOrganization().getId() == user.getOrganization().getId()'
+        ),
         new Put(
             security: 'is_granted(\'ROLE_ORGANIZATION\') and object.getBillingSetting().getOrganization().getId() == user.getOrganization().getId()'
         ),

+ 4 - 2
src/Entity/Billing/SddRegie.php

@@ -29,10 +29,12 @@ class SddRegie
     #[ORM\OneToMany(mappedBy: 'sddRegime', targetEntity: BillPayment::class, cascade: [], orphanRemoval: false)]
     protected Collection $billPayments;
 
-    #[ORM\OneToOne(targetEntity: File::class, cascade: ['persist'])]
+    #[ORM\OneToOne(targetEntity: File::class, cascade: ['persist'], inversedBy: 'sddRegieFile')]
+    #[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')]
     protected ?File $file;
 
-    #[ORM\OneToOne(targetEntity: File::class, cascade: ['persist'])]
+    #[ORM\OneToOne(targetEntity: File::class, cascade: ['persist'], inversedBy: 'sddRegieBordereau')]
+    #[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')]
     protected ?File $bordereau;
 
     public function __construct()

+ 2 - 1
src/Entity/Booking/AbstractBooking.php

@@ -21,8 +21,9 @@ use Doctrine\ORM\Mapping as ORM;
  */
 #[ActivityYearConstraintAware(startYearFieldName: 'startYear', endYearFieldName: 'endYear')]
 #[OrganizationDefaultValue(fieldName: 'organization')]
-#[ORM\MappedSuperclass]
+#[ORM\Entity]
 #[ORM\Table(name: 'Booking')]
+#[ORM\InheritanceType('SINGLE_TABLE')]
 #[ORM\DiscriminatorColumn(name: 'discr', type: 'string')]
 #[ORM\DiscriminatorMap(
     [

+ 2 - 1
src/Entity/Booking/AbstractBookingRecur.php

@@ -11,8 +11,9 @@ use Doctrine\ORM\Mapping as ORM;
  *
  * @see EventRecur, CourseRecur, EducationalProjectRecur, ExamenRecur, OrganizationHolidayRecur, PersonHolidayRecur
  */
-#[ORM\MappedSuperclass]
+#[ORM\Entity]
 #[ORM\Table(name: 'BookingRecur')]
+#[ORM\InheritanceType('SINGLE_TABLE')]
 #[ORM\DiscriminatorColumn(name: 'discr', type: 'string')]
 #[ORM\DiscriminatorMap(
     [

+ 1 - 2
src/Entity/Booking/Attendance.php

@@ -35,8 +35,7 @@ class Attendance
     private ?Access $replacement = null;
 
     /** @var Collection<int, AttendanceBooking> */
-    #[ORM\OneToMany(targetEntity: AttendanceBooking::class, mappedBy: 'attendance', cascade: ['persist'], orphanRemoval: true)]
-    #[ORM\JoinColumn(nullable: false)]
+    #[ORM\OneToMany(targetEntity: AttendanceBooking::class, mappedBy: 'attendance', cascade: ['persist', 'remove'])]
     private Collection $attendanceBooking;
 
     public function __construct()

+ 6 - 0
src/Entity/Booking/AttendanceBooking.php

@@ -23,21 +23,27 @@ class AttendanceBooking
     private ?int $id = null;
 
     #[ORM\ManyToOne(inversedBy: 'attendanceBookings')]
+    #[ORM\JoinColumn(nullable: true)]
     private ?Access $access = null;
 
     #[ORM\ManyToOne(inversedBy: 'attendanceBooking')]
+    #[ORM\JoinColumn(nullable: true)]
     private ?Attendance $attendance = null;
 
     #[ORM\ManyToOne(inversedBy: 'attendanceBooking')]
+    #[ORM\JoinColumn(nullable: true)]
     private ?Course $course = null;
 
     #[ORM\ManyToOne(inversedBy: 'attendanceBooking')]
+    #[ORM\JoinColumn(nullable: true)]
     private ?EducationalProject $educationalProject = null;
 
     #[ORM\ManyToOne(inversedBy: 'attendanceBooking')]
+    #[ORM\JoinColumn(nullable: true)]
     private ?Event $event = null;
 
     #[ORM\ManyToOne(inversedBy: 'attendanceBooking')]
+    #[ORM\JoinColumn(nullable: true)]
     private ?Examen $examen = null;
 
     #[ORM\ManyToOne(inversedBy: 'attendanceBookings')]

+ 11 - 3
src/Entity/Booking/AttendanceBookingReason.php

@@ -8,14 +8,15 @@ use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Metadata\Delete;
 use ApiPlatform\Metadata\Get;
 use ApiPlatform\Metadata\GetCollection;
+use ApiPlatform\Metadata\Patch;
 use ApiPlatform\Metadata\Post;
 use ApiPlatform\Metadata\Put;
 use App\Attribute\OrganizationDefaultValue;
 use App\Entity\Organization\Organization;
+use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
-use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
 
 /**
  * Motif d'absence ou de retard.
@@ -32,6 +33,9 @@ use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
         new Put(
             security: 'is_granted(\'ROLE_ORGANIZATION\') and object.getOrganization().getId() == user.getOrganization().getId()'
         ),
+        new Patch(
+            security: 'is_granted(\'ROLE_ORGANIZATION\') and object.getOrganization().getId() == user.getOrganization().getId()'
+        ),
         new Delete(
             security: 'is_granted(\'ROLE_ORGANIZATION\') and object.getOrganization().getId() == user.getOrganization().getId()'
         ),
@@ -60,8 +64,12 @@ class AttendanceBookingReason
     #[ORM\Column(length: 255, nullable: false)]
     private string $reason;
 
-    /** @var Collection<int, AttendanceBooking> */
-    #[ORM\OneToMany(targetEntity: AttendanceBooking::class, mappedBy: 'reason', cascade: ['persist'], orphanRemoval: true)]
+    /**
+     * Pas de cascade remove ici, les absences / présences existent indépendamment de ce motif.
+     *
+     * @var Collection<int, AttendanceBooking>
+     */
+    #[ORM\OneToMany(targetEntity: AttendanceBooking::class, mappedBy: 'reason', cascade: ['persist'])]
     private Collection $attendanceBookings;
 
     public function __construct()

+ 9 - 6
src/Entity/Booking/Course.php

@@ -31,18 +31,18 @@ use Doctrine\ORM\Mapping as ORM;
 #[ApiResource(operations: [])]
 // #[Auditable]
 #[ORM\Entity(repositoryClass: CourseRepository::class)]
-#[ORM\Table(name: 'Booking')]
 class Course extends AbstractBooking
 {
     /** @var Collection<int, CourseRecur> */
-    #[ORM\OneToMany(targetEntity: CourseRecur::class, mappedBy: 'event', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: CourseRecur::class, mappedBy: 'event', cascade: ['persist', 'remove'])]
     protected Collection $eventRecur;
 
     /** @var Collection<int, Course> */
     #[ORM\OneToMany(targetEntity: Course::class, mappedBy: 'parent', orphanRemoval: true)]
     protected Collection $timeline;
 
-    #[ORM\ManyToOne(inversedBy: 'timeline')]
+    #[ORM\ManyToOne(targetEntity: Course::class, cascade: ['persist'], inversedBy: 'timeline')]
+    #[ORM\JoinColumn(nullable: true)]
     protected ?Course $parent;
 
     #[ORM\ManyToOne(inversedBy: 'courses')]
@@ -63,6 +63,9 @@ class Course extends AbstractBooking
 
     /** @var Collection<int, EducationCurriculum> */
     #[ORM\ManyToMany(targetEntity: EducationCurriculum::class, inversedBy: 'courses', cascade: ['persist'])]
+    #[ORM\JoinTable(name: 'course_education_curriculum')]
+    #[ORM\JoinColumn(name: 'course_id', referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
+    #[ORM\InverseJoinColumn(name: 'education_curriculum_id', referencedColumnName: 'id')]
     protected Collection $educationCurriculum;
 
     /** @var Collection<int, Access> */
@@ -73,16 +76,16 @@ class Course extends AbstractBooking
     protected Collection $students;
 
     /** @var Collection<int, Work> */
-    #[ORM\OneToMany(targetEntity: Work::class, mappedBy: 'course', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Work::class, mappedBy: 'course', cascade: ['persist', 'remove'])]
     protected Collection $work;
 
     /** @var Collection<int, AttendanceBooking> */
-    #[ORM\OneToMany(targetEntity: AttendanceBooking::class, mappedBy: 'course', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: AttendanceBooking::class, mappedBy: 'course', cascade: ['persist', 'remove'])]
     #[ORM\JoinColumn(nullable: false)]
     protected Collection $attendanceBooking;
 
     /** @var Collection<int, EducationStudentWish> */
-    #[ORM\OneToMany(targetEntity: EducationStudentWish::class, mappedBy: 'course', cascade: [], orphanRemoval: false)]
+    #[ORM\OneToMany(targetEntity: EducationStudentWish::class, mappedBy: 'course', cascade: [])]
     protected Collection $educationStudentWishes;
 
     public function __construct()

+ 0 - 1
src/Entity/Booking/CourseRecur.php

@@ -16,7 +16,6 @@ use Doctrine\ORM\Mapping as ORM;
 // #[Auditable]
 #[ApiResource(operations: [])]
 #[ORM\Entity]
-#[ORM\Table(name: 'BookingRecur')]
 class CourseRecur extends AbstractBookingRecur
 {
     #[ORM\ManyToOne(inversedBy: 'eventRecur')]

+ 5 - 6
src/Entity/Booking/EducationalProject.php

@@ -26,18 +26,18 @@ use Doctrine\ORM\Mapping as ORM;
 #[ApiResource(operations: [])]
 // #[Auditable]
 #[ORM\Entity]
-#[ORM\Table(name: 'Booking')]
 class EducationalProject extends AbstractBooking
 {
     /** @var Collection<int, EducationalProjectRecur> */
-    #[ORM\OneToMany(targetEntity: EducationalProjectRecur::class, mappedBy: 'event', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: EducationalProjectRecur::class, mappedBy: 'event', cascade: ['persist', 'remove'])]
     protected Collection $eventRecur;
 
     /** @var Collection<int, EducationalProject> */
-    #[ORM\OneToMany(targetEntity: EducationalProject::class, mappedBy: 'parent', orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: EducationalProject::class, mappedBy: 'parent')]
     protected Collection $timeline;
 
-    #[ORM\ManyToOne(inversedBy: 'timeline')]
+    #[ORM\ManyToOne(targetEntity: EducationalProject::class, cascade: ['persist'], inversedBy: 'timeline')]
+    #[ORM\JoinColumn(nullable: true)]
     protected ?EducationalProject $parent = null;
 
     #[ORM\ManyToOne(inversedBy: 'educationalProjects')]
@@ -78,8 +78,7 @@ class EducationalProject extends AbstractBooking
     protected Collection $billLines;
 
     /** @var Collection<int, AttendanceBooking> */
-    #[ORM\OneToMany(targetEntity: AttendanceBooking::class, mappedBy: 'educationalProject', cascade: ['persist'], orphanRemoval: true)]
-    #[ORM\JoinColumn(nullable: false)]
+    #[ORM\OneToMany(targetEntity: AttendanceBooking::class, mappedBy: 'educationalProject', cascade: ['persist', 'remove'])]
     protected Collection $attendanceBooking;
 
     #[ORM\ManyToOne(inversedBy: 'educationalProjects')]

+ 0 - 1
src/Entity/Booking/EducationalProjectRecur.php

@@ -16,7 +16,6 @@ use Doctrine\ORM\Mapping as ORM;
 // #[Auditable]
 #[ApiResource(operations: [])]
 #[ORM\Entity]
-#[ORM\Table(name: 'BookingRecur')]
 class EducationalProjectRecur extends AbstractBookingRecur
 {
     #[ORM\ManyToOne(inversedBy: 'eventRecur')]

+ 7 - 9
src/Entity/Booking/Event.php

@@ -26,7 +26,6 @@ use Symfony\Component\Validator\Constraints as Assert;
 #[ApiResource(operations: [])]
 // #[Auditable]
 #[ORM\Entity]
-#[ORM\Table(name: 'Booking')]
 class Event extends AbstractBooking
 {
     #[ORM\ManyToOne(inversedBy: 'events')]
@@ -42,14 +41,15 @@ class Event extends AbstractBooking
     protected ?Room $room = null;
 
     /** @var Collection<int, EventRecur> */
-    #[ORM\OneToMany(targetEntity: EventRecur::class, mappedBy: 'event', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: EventRecur::class, mappedBy: 'event', cascade: ['persist', 'remove'])]
     protected Collection $eventRecur;
 
     /** @var Collection<int, Event> */
-    #[ORM\OneToMany(targetEntity: Event::class, mappedBy: 'parent', orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Event::class, mappedBy: 'parent', cascade: ['persist'])]
     protected Collection $timeline;
 
-    #[ORM\ManyToOne(inversedBy: 'timeline')]
+    #[ORM\ManyToOne(targetEntity: Event::class, cascade: ['persist'], inversedBy: 'timeline')]
+    #[ORM\JoinColumn(nullable: true)]
     protected ?Event $parent;
 
     #[Assert\Valid]
@@ -62,7 +62,7 @@ class Event extends AbstractBooking
 
     /** @var Collection<int, EventUser> */
     #[Assert\Valid]
-    #[ORM\OneToMany(targetEntity: EventUser::class, mappedBy: 'event', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: EventUser::class, mappedBy: 'event', cascade: ['persist', 'remove'])]
     protected Collection $eventUser;
 
     /** @var Collection<int, Categories> */
@@ -70,7 +70,7 @@ class Event extends AbstractBooking
     protected Collection $categories;
 
     /** @var Collection<int, EventReport> */
-    #[ORM\OneToMany(targetEntity: EventReport::class, mappedBy: 'event', orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: EventReport::class, mappedBy: 'event', cascade: ['persist', 'remove'])]
     protected Collection $eventReports;
 
     /** @var Collection<int, File> */
@@ -85,8 +85,7 @@ class Event extends AbstractBooking
     protected ?PlaceSystem $placeSystem;
 
     /** @var Collection<int, AttendanceBooking> */
-    #[ORM\OneToMany(targetEntity: AttendanceBooking::class, mappedBy: 'event', cascade: ['persist'], orphanRemoval: true)]
-    #[ORM\JoinColumn(nullable: false)]
+    #[ORM\OneToMany(targetEntity: AttendanceBooking::class, mappedBy: 'event', cascade: ['persist', 'remove'])]
     protected Collection $attendanceBooking;
 
     public function __construct()
@@ -376,7 +375,6 @@ class Event extends AbstractBooking
     public function removeAttendanceBooking(AttendanceBooking $attendanceBooking): self
     {
         if ($this->attendanceBooking->removeElement($attendanceBooking)) {
-            // set the owning side to null (unless already changed)
             if ($attendanceBooking->getEvent() === $this) {
                 $attendanceBooking->setEvent(null);
             }

+ 0 - 1
src/Entity/Booking/EventRecur.php

@@ -16,7 +16,6 @@ use Doctrine\ORM\Mapping as ORM;
 // #[Auditable]
 #[ApiResource(operations: [])]
 #[ORM\Entity]
-#[ORM\Table(name: 'BookingRecur')]
 class EventRecur extends AbstractBookingRecur
 {
     #[ORM\ManyToOne(inversedBy: 'eventRecur')]

+ 1 - 1
src/Entity/Booking/EventReport.php

@@ -28,7 +28,7 @@ class EventReport
     private ?Event $event = null;
 
     /** @var Collection<int, File> */
-    #[ORM\OneToMany(targetEntity: File::class, mappedBy: 'eventReport', orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: File::class, mappedBy: 'eventReport', cascade: ['persist', 'remove'])]
     private Collection $files;
 
     public function __construct()

+ 5 - 6
src/Entity/Booking/Examen.php

@@ -26,7 +26,6 @@ use Doctrine\ORM\Mapping as ORM;
 #[ApiResource(operations: [])]
 // #[Auditable]
 #[ORM\Entity]
-#[ORM\Table(name: 'Booking')]
 class Examen extends AbstractBooking
 {
     #[ORM\ManyToOne(inversedBy: 'examens')]
@@ -34,14 +33,15 @@ class Examen extends AbstractBooking
     protected Organization $organization;
 
     /** @var Collection<int, ExamenRecur> */
-    #[ORM\OneToMany(targetEntity: ExamenRecur::class, mappedBy: 'event', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: ExamenRecur::class, mappedBy: 'event', cascade: ['persist', 'remove'])]
     protected Collection $eventRecur;
 
     /** @var Collection<int, Examen> */
-    #[ORM\OneToMany(targetEntity: Examen::class, mappedBy: 'parent', orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Examen::class, mappedBy: 'parent', cascade: ['persist'])]
     protected Collection $timeline;
 
     #[ORM\ManyToOne(inversedBy: 'timeline')]
+    #[ORM\JoinColumn(nullable: true)]
     protected ?Examen $parent;
 
     #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'examens')]
@@ -57,12 +57,11 @@ class Examen extends AbstractBooking
     protected Collection $educationCurriculum;
 
     /** @var Collection<int, ExamenConvocation> */
-    #[ORM\OneToMany(targetEntity: ExamenConvocation::class, mappedBy: 'examen', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: ExamenConvocation::class, mappedBy: 'examen', cascade: ['persist', 'remove'])]
     protected Collection $convocation;
 
     /** @var Collection<int, AttendanceBooking> */
-    #[ORM\OneToMany(targetEntity: AttendanceBooking::class, mappedBy: 'examen', cascade: ['persist'], orphanRemoval: true)]
-    #[ORM\JoinColumn(nullable: false)]
+    #[ORM\OneToMany(targetEntity: AttendanceBooking::class, mappedBy: 'examen', cascade: ['persist', 'remove'])]
     protected Collection $attendanceBooking;
 
     #[ORM\ManyToOne(inversedBy: 'examens')]

+ 0 - 1
src/Entity/Booking/ExamenRecur.php

@@ -16,7 +16,6 @@ use Doctrine\ORM\Mapping as ORM;
 // #[Auditable]
 #[ApiResource(operations: [])]
 #[ORM\Entity]
-#[ORM\Table(name: 'BookingRecur')]
 class ExamenRecur extends AbstractBookingRecur
 {
     #[ORM\ManyToOne(inversedBy: 'eventRecur')]

+ 1 - 2
src/Entity/Booking/OrganizationHoliday.php

@@ -19,11 +19,10 @@ use Doctrine\ORM\Mapping as ORM;
 #[ApiResource(operations: [])]
 // #[Auditable]
 #[ORM\Entity]
-#[ORM\Table(name: 'Booking')]
 class OrganizationHoliday extends AbstractBooking
 {
     /** @var Collection<int, OrganizationHolidayRecur> */
-    #[ORM\OneToMany(targetEntity: OrganizationHolidayRecur::class, mappedBy: 'event', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: OrganizationHolidayRecur::class, mappedBy: 'event', cascade: ['persist', 'remove'])]
     protected Collection $eventRecur;
 
     #[ORM\ManyToOne(inversedBy: 'holidays')]

+ 0 - 1
src/Entity/Booking/OrganizationHolidayRecur.php

@@ -14,7 +14,6 @@ use Doctrine\ORM\Mapping as ORM;
 // #[Auditable]
 #[ApiResource(operations: [])]
 #[ORM\Entity]
-#[ORM\Table(name: 'BookingRecur')]
 class OrganizationHolidayRecur extends AbstractBookingRecur
 {
     #[ORM\ManyToOne(inversedBy: 'eventRecur')]

+ 1 - 2
src/Entity/Booking/PersonHoliday.php

@@ -19,7 +19,6 @@ use Doctrine\ORM\Mapping as ORM;
 #[ApiResource(operations: [])]
 // #[Auditable]
 #[ORM\Entity]
-#[ORM\Table(name: 'Booking')]
 class PersonHoliday extends AbstractBooking
 {
     #[ORM\ManyToOne(inversedBy: 'holidays')]
@@ -30,7 +29,7 @@ class PersonHoliday extends AbstractBooking
     protected Organization $organization;
 
     /** @var Collection<int, PersonHolidayRecur> */
-    #[ORM\OneToMany(targetEntity: PersonHolidayRecur::class, mappedBy: 'event', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: PersonHolidayRecur::class, mappedBy: 'event', cascade: ['persist', 'remove'])]
     protected Collection $eventRecur;
 
     public function getAccess(): ?Access

+ 0 - 1
src/Entity/Booking/PersonHolidayRecur.php

@@ -16,7 +16,6 @@ use Doctrine\ORM\Mapping as ORM;
 // #[Auditable]
 #[ApiResource(operations: [])]
 #[ORM\Entity]
-#[ORM\Table(name: 'BookingRecur')]
 class PersonHolidayRecur extends AbstractBookingRecur
 {
     #[ORM\ManyToOne(inversedBy: 'eventRecur')]

+ 34 - 1
src/Entity/Core/AbstractControl.php

@@ -7,14 +7,16 @@ namespace App\Entity\Core;
 use App\Entity\Place\PlaceControl;
 use App\Entity\Place\RoomControl;
 use App\Entity\Product\EquipmentControl;
+use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
 
 /**
  * Contrôle du bon état des Place, Room et Equipment, effectué ou planifié
  * Classe de base de @see PlaceControl, RoomControl, EquipmentControl.
  */
-#[ORM\MappedSuperclass]
+#[ORM\Entity]
 #[ORM\Table(name: 'Control')]
+#[ORM\InheritanceType('SINGLE_TABLE')]
 #[ORM\DiscriminatorColumn(name: 'discr', type: 'string')]
 #[ORM\DiscriminatorMap(
     [
@@ -30,8 +32,39 @@ abstract class AbstractControl
     #[ORM\GeneratedValue]
     protected ?int $id = null;
 
+    /** @var Collection<int, Tagg> */
+    #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'controls')]
+    #[ORM\JoinTable('tag_control')]
+    #[ORM\JoinColumn(name: 'control_id')]
+    #[ORM\InverseJoinColumn(name: 'tag_id')]
+    protected Collection $tags;
+
     public function getId(): ?int
     {
         return $this->id;
     }
+
+    public function getTags(): Collection
+    {
+        return $this->tags;
+    }
+
+    public function addTag(Tagg $tag): self
+    {
+        if (!$this->tags->contains($tag)) {
+            $this->tags[] = $tag;
+            $tag->addControl($this);
+        }
+
+        return $this;
+    }
+
+    public function removeTag(Tagg $tag): self
+    {
+        if ($this->tags->removeElement($tag)) {
+            $tag->removeControl($this);
+        }
+
+        return $this;
+    }
 }

+ 2 - 1
src/Entity/Core/AbstractRepair.php

@@ -13,8 +13,9 @@ use Doctrine\ORM\Mapping as ORM;
 /**
  * Classe de base de @see PlaceRepair, RoomRepair, EquipmentRepair.
  */
-#[ORM\MappedSuperclass]
+#[ORM\Entity]
 #[ORM\Table(name: 'Repair')]
+#[ORM\InheritanceType('SINGLE_TABLE')]
 #[ORM\DiscriminatorColumn(name: 'discr', type: 'string')]
 #[ORM\DiscriminatorMap(
     [

+ 2 - 2
src/Entity/Core/BankAccount.php

@@ -55,8 +55,8 @@ class BankAccount
     /**
      * 0 => jamais facturé, 1 => facturé 1 fois, 2 => facturé plusieurs fois.
      */
-    #[ORM\Column(columnDefinition: "TINYINT DEFAULT 0 NOT NULL")]
-    private ?int $countInvoiced = 0;
+    #[ORM\Column(columnDefinition: 'TINYINT DEFAULT 0 NOT NULL')]
+    private int $countInvoiced = 0;
 
     #[ORM\Column(length: 255, nullable: true)]
     private ?string $holder = null;

+ 1 - 1
src/Entity/Core/Categories.php

@@ -17,7 +17,7 @@ use Doctrine\ORM\Mapping as ORM;
 class Categories
 {
     #[ORM\Id]
-    #[ORM\Column(type: "mediumint", options: ["unsigned" => true])]
+    #[ORM\Column(type: 'mediumint', options: ['unsigned' => true])]
     #[ORM\GeneratedValue]
     private ?int $id = null;
 

+ 1 - 1
src/Entity/Core/City.php

@@ -18,7 +18,7 @@ use Doctrine\ORM\Mapping as ORM;
 class City
 {
     #[ORM\Id]
-    #[ORM\Column(type: "mediumint", options: ["unsigned" => true])]
+    #[ORM\Column(type: 'mediumint', options: ['unsigned' => true])]
     #[ORM\GeneratedValue]
     private ?int $id = null;
 

+ 2 - 1
src/Entity/Core/Country.php

@@ -23,7 +23,8 @@ use Doctrine\ORM\Mapping as ORM;
 )]
 // #[Auditable]
 #[ORM\Entity(repositoryClass: CountryRepository::class)]
-#[ORM\Table(indexes: [new ORM\Index(name: "name_idx", columns: ["name"])])]
+#[ORM\Table]
+#[ORM\Index(name: 'name_idx', columns: ['name'])]
 class Country
 {
     #[ORM\Id]

+ 35 - 4
src/Entity/Core/File.php

@@ -10,6 +10,7 @@ use ApiPlatform\Metadata\Get;
 use ApiPlatform\Metadata\Post;
 use ApiPlatform\Metadata\Put;
 use App\Entity\AccessWish\DocumentWish;
+use App\Entity\Billing\SddRegie;
 use App\Entity\Booking\CalendarSynchro;
 use App\Entity\Booking\Event;
 use App\Entity\Booking\EventReport;
@@ -74,14 +75,14 @@ class File
     /**
      * Slug du fichier (i.e. le chemin d'accès relatif).
      */
-    #[ORM\Column(length: 255)]
-    private string $slug;
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $slug;
 
     /**
      * Chemin d'accès du fichier.
      */
-    #[ORM\Column(length: 255)]
-    private string $path;
+    #[ORM\Column(length: 255, nullable: true)]
+    private ?string $path;
 
     /**
      * Nom du fichier.
@@ -247,6 +248,12 @@ class File
     #[ORM\OneToOne(targetEntity: CalendarSynchro::class, mappedBy: 'file')]
     private ?CalendarSynchro $calendarSynchro;
 
+    #[ORM\OneToOne(targetEntity: SddRegie::class, mappedBy: 'file')]
+    private ?SddRegie $sddRegieFile = null;
+
+    #[ORM\OneToOne(targetEntity: SddRegie::class, mappedBy: 'bordereau')]
+    private ?SddRegie $sddRegieBordereau = null;
+
     #[Pure]
     public function __construct()
     {
@@ -789,4 +796,28 @@ class File
 
         return $this;
     }
+
+    public function getSddRegieFile(): ?SddRegie
+    {
+        return $this->sddRegieFile;
+    }
+
+    public function setSddRegieFile(?SddRegie $sddRegieFile): self
+    {
+        $this->sddRegieFile = $sddRegieFile;
+
+        return $this;
+    }
+
+    public function getSddRegieBordereau(): ?SddRegie
+    {
+        return $this->sddRegieBordereau;
+    }
+
+    public function setSddRegieBordereau(?SddRegie $sddRegieBordereau): self
+    {
+        $this->sddRegieBordereau = $sddRegieBordereau;
+
+        return $this;
+    }
 }

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

@@ -34,7 +34,6 @@ use Doctrine\ORM\Mapping as ORM;
 )]
 // #[Auditable]
 #[ORM\Entity(repositoryClass: NotificationRepository::class)]
-#[ORM\Table(name: 'Information')]
 class Notification extends AbstractInformation
 {
     #[ORM\ManyToOne(inversedBy: 'notifications')]

+ 34 - 7
src/Entity/Core/Tagg.php

@@ -40,6 +40,7 @@ use App\Entity\Product\Intangible;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
+use Symfony\Component\Validator\Constraints as Assert;
 
 /**
  * Tag, étiquette.
@@ -54,6 +55,10 @@ class Tagg
     #[ORM\GeneratedValue]
     private ?int $id = null;
 
+    #[ORM\Column(length: 50)]
+    #[Assert\Length(min: 3, minMessage: 'Label shall contain at least {{ limit }} characters.')]
+    protected string $label;
+
     #[ORM\ManyToOne]
     #[ORM\JoinColumn(nullable: false)]
     private Organization $organization;
@@ -186,6 +191,10 @@ class Tagg
     #[ORM\ManyToMany(targetEntity: EducationCurriculumPack::class, mappedBy: 'tags', cascade: [], orphanRemoval: false)]
     protected Collection $educationCurriculumPacks;
 
+    /** @var Collection<int, AbstractControl> */
+    #[ORM\OneToMany(targetEntity: AbstractControl::class, mappedBy: 'tags', cascade: [], orphanRemoval: false)]
+    protected Collection $controls;
+
     public function __construct()
     {
         $this->accesses = new ArrayCollection();
@@ -219,8 +228,8 @@ class Tagg
         $this->bookings = new ArrayCollection();
         $this->messages = new ArrayCollection();
         $this->repairs = new ArrayCollection();
-        $this->controls = new ArrayCollection();
         $this->educationCurriculumPacks = new ArrayCollection();
+        $this->controls = new ArrayCollection();
     }
 
     public function getId(): ?int
@@ -1062,12 +1071,6 @@ class Tagg
         return $this;
     }
 
-    public function getControls(): Collection
-    {
-        return $this->controls;
-    }
-
-
     public function getEducationCurriculumPacks(): Collection
     {
         return $this->educationCurriculumPacks;
@@ -1091,4 +1094,28 @@ class Tagg
 
         return $this;
     }
+
+    public function getControls(): Collection
+    {
+        return $this->controls;
+    }
+
+    public function addControl(AbstractControl $control): self
+    {
+        if (!$this->controls->contains($control)) {
+            $this->controls[] = $control;
+            $control->addTag($this);
+        }
+
+        return $this;
+    }
+
+    public function removeControl(AbstractControl $control): self
+    {
+        if ($this->controls->removeElement($control)) {
+            $control->removeTag($this);
+        }
+
+        return $this;
+    }
 }

+ 36 - 1
src/Entity/Core/Tips.php

@@ -6,6 +6,9 @@ namespace App\Entity\Core;
 
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
 use ApiPlatform\Metadata\ApiResource;
+use App\Entity\Organization\Organization;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
 
 /**
@@ -15,7 +18,39 @@ use Doctrine\ORM\Mapping as ORM;
 #[ApiResource(operations: [])]
 // #[Auditable]
 #[ORM\Entity]
-#[ORM\Table(name: 'Information')]
 class Tips extends AbstractInformation
 {
+    /** @var Collection<int, Organization> */
+    #[ORM\ManyToMany(targetEntity: Organization::class, mappedBy: 'tips', cascade: [], orphanRemoval: false)]
+    protected Collection $organizations;
+
+    public function __construct()
+    {
+        $this->organizations = new ArrayCollection();
+        parent::__construct();
+    }
+
+    public function getOrganizations(): Collection
+    {
+        return $this->organizations;
+    }
+
+    public function addOrganization(Organization $organization): self
+    {
+        if (!$this->organizations->contains($organization)) {
+            $this->organizations[] = $organization;
+            $organization->addTip($this);
+        }
+
+        return $this;
+    }
+
+    public function removeOrganization(Organization $organization): self
+    {
+        if ($this->organizations->removeElement($organization)) {
+            $organization->removeTip($this);
+        }
+
+        return $this;
+    }
 }

+ 13 - 6
src/Entity/Custom/Search/UserSearchItem.php

@@ -45,22 +45,22 @@ class UserSearchItem
     #[ORM\Column]
     private int $id;
 
-    #[ORM\Column(type: 'integer')]
+    #[ORM\Column(type: 'integer', nullable: true)]
     private ?int $organizationId = null;
 
-    #[ORM\Column(type: 'integer')]
+    #[ORM\Column(type: 'integer', nullable: true)]
     private ?int $personId = null;
 
-    #[ORM\Column(type: 'string')]
+    #[ORM\Column(type: 'string', nullable: true)]
     private ?string $username = null;
 
-    #[ORM\Column(type: 'string')]
+    #[ORM\Column(type: 'string', nullable: true)]
     private ?string $name = null;
 
-    #[ORM\Column(type: 'string')]
+    #[ORM\Column(type: 'string', nullable: true)]
     private ?string $givenName = null;
 
-    #[ORM\Column(type: 'string')]
+    #[ORM\Column(type: 'string', nullable: true)]
     private ?string $fullName = null;
 
     public function getId(): int
@@ -71,6 +71,7 @@ class UserSearchItem
     public function setId(int $id): self
     {
         $this->id = $id;
+
         return $this;
     }
 
@@ -82,6 +83,7 @@ class UserSearchItem
     public function setOrganizationId(?int $organizationId): self
     {
         $this->organizationId = $organizationId;
+
         return $this;
     }
 
@@ -93,6 +95,7 @@ class UserSearchItem
     public function setPersonId(?int $personId): self
     {
         $this->personId = $personId;
+
         return $this;
     }
 
@@ -104,6 +107,7 @@ class UserSearchItem
     public function setUsername(?string $username): self
     {
         $this->username = $username;
+
         return $this;
     }
 
@@ -115,6 +119,7 @@ class UserSearchItem
     public function setName(?string $name): self
     {
         $this->name = $name;
+
         return $this;
     }
 
@@ -126,6 +131,7 @@ class UserSearchItem
     public function setGivenName(?string $givenName): self
     {
         $this->givenName = $givenName;
+
         return $this;
     }
 
@@ -137,6 +143,7 @@ class UserSearchItem
     public function setFullName(?string $fullName): self
     {
         $this->fullName = $fullName;
+
         return $this;
     }
 }

+ 2 - 2
src/Entity/Education/Cycle.php

@@ -7,7 +7,7 @@ namespace App\Entity\Education;
 use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Metadata\Get;
 use ApiPlatform\Metadata\GetCollection;
-use ApiPlatform\Metadata\Put;
+use ApiPlatform\Metadata\Patch;
 use App\Entity\Organization\Organization;
 use App\Enum\Education\CycleEnum;
 use App\Repository\Education\CycleRepository;
@@ -29,7 +29,7 @@ use Doctrine\ORM\Mapping as ORM;
         new Get(
             security: 'is_granted(\'ROLE_ORGANIZATION_VIEW\') and object.getOrganization().getId() == user.getOrganization().getId()'
         ),
-        new Put(
+        new Patch(
             security: 'is_granted(\'ROLE_ORGANIZATION\') and object.getOrganization().getId() == user.getOrganization().getId()'
         ),
         new GetCollection(

+ 7 - 7
src/Entity/Education/EducationCurriculum.php

@@ -53,15 +53,15 @@ class EducationCurriculum
     protected Collection $educationStudentWish;
 
     /** @var Collection<int, Course> */
-    #[ORM\ManyToMany(targetEntity: Course::class, mappedBy: 'educationCurriculum', cascade: [], orphanRemoval: false)]
+    #[ORM\ManyToMany(targetEntity: Course::class, mappedBy: 'educationCurriculum', cascade: ['persist'])]
     protected Collection $courses;
 
     /** @var Collection<int, Examen> */
-    #[ORM\ManyToMany(targetEntity: Examen::class, mappedBy: 'educationCurriculum', cascade: [], orphanRemoval: false)]
+    #[ORM\ManyToMany(targetEntity: Examen::class, mappedBy: 'educationCurriculum', cascade: ['persist'])]
     protected Collection $examens;
 
     /** @var Collection<int, Intangible> */
-    #[ORM\ManyToMany(targetEntity: Intangible::class, mappedBy: 'educationCurriculums', cascade: [], orphanRemoval: false)]
+    #[ORM\ManyToMany(targetEntity: Intangible::class, mappedBy: 'educationCurriculums', cascade: ['persist'], orphanRemoval: false)]
     protected Collection $intangibles;
 
     /** @var Collection<int, EducationCurriculumPack> */
@@ -73,9 +73,9 @@ class EducationCurriculum
     )]
     protected Collection $requiredEducationCurriculumPacks;
 
-    /** @var Collection<int, EducationCurriculumPack> */
+    /** @var Collection<int, RequiredChoicesBlock> */
     #[ORM\ManyToMany(
-        targetEntity: EducationCurriculumPack::class,
+        targetEntity: RequiredChoicesBlock::class,
         mappedBy: 'requiredChoicesEducationCurriculums',
         cascade: [],
         orphanRemoval: true,
@@ -325,7 +325,7 @@ class EducationCurriculum
     }
 
     public function addRequiredChoicesEducationCurriculumPack(
-        EducationCurriculumPack $requiredChoicesEducationCurriculumPack,
+        RequiredChoicesBlock $requiredChoicesEducationCurriculumPack,
     ): self {
         if (!$this->requiredChoicesEducationCurriculumPacks->contains($requiredChoicesEducationCurriculumPack)) {
             $this->requiredChoicesEducationCurriculumPacks[] = $requiredChoicesEducationCurriculumPack;
@@ -336,7 +336,7 @@ class EducationCurriculum
     }
 
     public function removeRequiredChoicesEducationCurriculumPack(
-        EducationCurriculumPack $requiredChoicesEducationCurriculumPack,
+        RequiredChoicesBlock $requiredChoicesEducationCurriculumPack,
     ): self {
         if ($this->requiredChoicesEducationCurriculumPacks->removeElement($requiredChoicesEducationCurriculumPack)) {
             $requiredChoicesEducationCurriculumPack->removeRequiredChoicesEducationCurriculum($this);

+ 42 - 33
src/Entity/Education/EducationCurriculumPack.php

@@ -8,6 +8,7 @@ use ApiPlatform\Metadata\ApiResource;
 use App\Entity\Core\Tagg;
 use App\Entity\Organization\Organization;
 use App\Entity\Product\Intangible;
+use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
 
@@ -29,6 +30,9 @@ class EducationCurriculumPack
 
     /** @var Collection<int, Tagg> */
     #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'educationCurriculumPacks', cascade: ['persist'], orphanRemoval: false)]
+    #[ORM\JoinTable(name: 'tag_educationCurriculumPack')]
+    #[ORM\JoinColumn(name: 'educationcurriculumpack_id', onDelete: 'CASCADE')]
+    #[ORM\InverseJoinColumn(name: 'tagg_id', onDelete: 'CASCADE')]
     public Collection $tags;
 
     /** @var Collection<int, EducationCurriculum> */
@@ -38,17 +42,9 @@ class EducationCurriculumPack
         cascade: [],
         orphanRemoval: false,
     )]
+    #[ORM\JoinTable(name: 'educationCurriculumPack_requiredEducationCurriculum')]
     public Collection $requiredEducationCurriculums;
 
-    /** @var Collection<int, EducationCurriculum> */
-    #[ORM\ManyToMany(
-        targetEntity: EducationCurriculum::class,
-        inversedBy: 'requiredChoicesEducationCurriculumPacks',
-        cascade: [],
-        orphanRemoval: false,
-    )]
-    public Collection $requiredChoicesEducationCurriculums;
-
     /** @var Collection<int, EducationCurriculum> */
     #[ORM\ManyToMany(
         targetEntity: EducationCurriculum::class,
@@ -56,12 +52,27 @@ class EducationCurriculumPack
         cascade: [],
         orphanRemoval: false,
     )]
+    #[ORM\JoinTable(name: 'educationCurriculumPack_optionnalEducationCurriculum')]
     public Collection $optionnalEducationCurriculums;
 
     /** @var Collection<int, Intangible> */
     #[ORM\ManyToMany(targetEntity: Intangible::class, mappedBy: 'educationCurriculumPacks', cascade: [], orphanRemoval: false)]
     public Collection $intangibles;
 
+    /** @var Collection<int, RequiredChoicesBlock> */
+    #[ORM\OneToMany(
+        targetEntity: RequiredChoicesBlock::class,
+        mappedBy: 'educationCurriculumPacks',
+        cascade: ['persist', 'remove'],
+        orphanRemoval: true,
+    )]
+    protected Collection $requiredChoicesBlocks;
+
+    public function __construct()
+    {
+        $this->requiredChoicesBlocks = new ArrayCollection();
+    }
+
     public function getId(): int
     {
         return $this->id;
@@ -134,30 +145,6 @@ class EducationCurriculumPack
         return $this;
     }
 
-    public function getRequiredChoicesEducationCurriculums(): Collection
-    {
-        return $this->requiredChoicesEducationCurriculums;
-    }
-
-    public function addRequiredChoicesEducationCurriculum(EducationCurriculum $requiredChoicesEducationCurriculum): self
-    {
-        if (!$this->requiredChoicesEducationCurriculums->contains($requiredChoicesEducationCurriculum)) {
-            $this->requiredChoicesEducationCurriculums[] = $requiredChoicesEducationCurriculum;
-            $requiredChoicesEducationCurriculum->addRequiredChoicesEducationCurriculumPack($this);
-        }
-
-        return $this;
-    }
-
-    public function removeRequiredChoicesEducationCurriculum(EducationCurriculum $requiredChoicesEducationCurriculum): self
-    {
-        if ($this->requiredChoicesEducationCurriculums->removeElement($requiredChoicesEducationCurriculum)) {
-            $requiredChoicesEducationCurriculum->removeRequiredChoicesEducationCurriculumPack($this);
-        }
-
-        return $this;
-    }
-
     public function getOptionnalEducationCurriculums(): Collection
     {
         return $this->optionnalEducationCurriculums;
@@ -205,4 +192,26 @@ class EducationCurriculumPack
 
         return $this;
     }
+
+    public function getRequiredChoicesBlocks(): Collection
+    {
+        return $this->requiredChoicesBlocks;
+    }
+
+    public function addRequiredChoicesBlock(RequiredChoicesBlock $requiredChoicesBlock): self
+    {
+        if (!$this->requiredChoicesBlocks->contains($requiredChoicesBlock)) {
+            $this->requiredChoicesBlocks[] = $requiredChoicesBlock;
+            $requiredChoicesBlock->setEducationCurriculumPack($this);
+        }
+
+        return $this;
+    }
+
+    public function removeRequiredChoicesBlock(RequiredChoicesBlock $requiredChoicesBlock): self
+    {
+        $this->requiredChoicesBlocks->removeElement($requiredChoicesBlock);
+
+        return $this;
+    }
 }

+ 1 - 1
src/Entity/Education/EducationNotationConfig.php

@@ -47,7 +47,7 @@ class EducationNotationConfig
     #[ORM\Column(type: 'text', nullable: true)]
     private ?string $description;
 
-    #[ORM\Column(columnDefinition: "TINYINT DEFAULT 1 NOT NULL")]
+    #[ORM\Column(columnDefinition: 'TINYINT DEFAULT 1 NOT NULL')]
     #[Assert\Range(notInRangeMessage: 'between_{{ min }}_and_{{ max }}', min: 1, max: 10)]
     private int $coefficient = 1;
 

+ 5 - 0
src/Entity/Education/EducationTiming.php

@@ -8,6 +8,7 @@ use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Metadata\Delete;
 use ApiPlatform\Metadata\Get;
 use ApiPlatform\Metadata\GetCollection;
+use ApiPlatform\Metadata\Patch;
 use ApiPlatform\Metadata\Post;
 use ApiPlatform\Metadata\Put;
 use App\Attribute\OrganizationDefaultValue;
@@ -35,6 +36,10 @@ use Doctrine\ORM\Mapping as ORM;
             security: 'object.getOrganization().getId() == user.getOrganization().getId()',
             securityMessage: 'You do not have access to this course duration'
         ),
+        new Patch(
+            security: 'object.getOrganization().getId() == user.getOrganization().getId()',
+            securityMessage: 'You do not have access to this course duration'
+        ),
         new Delete(
             security: 'object.getOrganization().getId() == user.getOrganization().getId()',
             securityMessage: 'You do not have access to this course duration'

+ 93 - 0
src/Entity/Education/RequiredChoicesBlock.php

@@ -0,0 +1,93 @@
+<?php
+
+/**
+ * This file is auto-generated.
+ */
+
+declare(strict_types=1);
+
+namespace App\Entity\Education;
+
+use ApiPlatform\Metadata\ApiResource;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ApiResource(operations: [])]
+#[ORM\Entity]
+class RequiredChoicesBlock
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private int $id;
+
+    #[ORM\ManyToOne(targetEntity: EducationCurriculumPack::class, inversedBy: 'requiredChoicesBlocks')]
+    #[ORM\JoinColumn(nullable: false)]
+    protected EducationCurriculumPack $educationCurriculumPack;
+
+    /** @var Collection<int, EducationCurriculum> */
+    #[ORM\ManyToMany(
+        targetEntity: EducationCurriculum::class,
+        inversedBy: 'requiredChoicesEducationCurriculumPacks',
+        cascade: [],
+        orphanRemoval: false,
+    )]
+    #[ORM\JoinTable(name: 'requiredChoicesBlock_educationCurriculum')]
+    #[ORM\JoinColumn(name: 'requiredchoicesblock_id', onDelete: 'CASCADE')]
+    #[ORM\InverseJoinColumn(name: 'educationcurriculum_id', onDelete: 'CASCADE')]
+    protected Collection $requiredChoicesEducationCurriculums;
+
+    public function __construct()
+    {
+        $this->requiredChoicesEducationCurriculums = new ArrayCollection();
+    }
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): self
+    {
+        $this->id = $id;
+
+        return $this;
+    }
+
+    public function getEducationCurriculumPack(): EducationCurriculumPack
+    {
+        return $this->educationCurriculumPack;
+    }
+
+    public function setEducationCurriculumPack(EducationCurriculumPack $educationCurriculumPack): self
+    {
+        $this->educationCurriculumPack = $educationCurriculumPack;
+
+        return $this;
+    }
+
+    public function getRequiredChoicesEducationCurriculum(): Collection
+    {
+        return $this->requiredChoicesEducationCurriculums;
+    }
+
+    public function addRequiredChoicesEducationCurriculum(EducationCurriculum $educationCurriculum): self
+    {
+        if (!$this->requiredChoicesEducationCurriculums->contains($educationCurriculum)) {
+            $this->requiredChoicesEducationCurriculums[] = $educationCurriculum;
+            $educationCurriculum->addRequiredChoicesEducationCurriculumPack($this);
+        }
+
+        return $this;
+    }
+
+    public function removeRequiredChoicesEducationCurriculum(EducationCurriculum $educationCurriculum): self
+    {
+        if ($this->requiredChoicesEducationCurriculums->removeElement($educationCurriculum)) {
+            $educationCurriculum->removeRequiredChoicesEducationCurriculumPack($this);
+        }
+
+        return $this;
+    }
+}

+ 2 - 1
src/Entity/Message/AbstractMessage.php

@@ -20,9 +20,10 @@ use Ramsey\Uuid\UuidInterface;
 /**
  * Classe de base de @see Mail, Sms, Email.
  */
-#[ORM\MappedSuperclass]
+#[ORM\Entity]
 #[OrganizationDefaultValue(fieldName: 'organization')]
 #[ORM\Table(name: 'Message')]
+#[ORM\InheritanceType('SINGLE_TABLE')]
 #[ORM\DiscriminatorColumn(name: 'discr', type: 'string')]
 #[ORM\DiscriminatorMap(
     [

+ 11 - 1
src/Entity/Message/AbstractReport.php

@@ -15,8 +15,13 @@ use Doctrine\ORM\Mapping as ORM;
  */
 #[ORM\MappedSuperclass]
 #[ORM\Table(name: 'ReportMessage')]
-class AbstractReport
+abstract class AbstractReport
 {
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    protected ?int $id = null;
+
     #[ORM\Column(type: 'datetime', nullable: true)]
     protected ?\DatetimeInterface $dateSend;
 
@@ -41,6 +46,11 @@ class AbstractReport
     #[ORM\Column(type: Types::INTEGER)]
     private int $recipientId = 0;
 
+    public function getId(): ?int
+    {
+        return $this->id;
+    }
+
     public function getDateSend(): ?\DatetimeInterface
     {
         return $this->dateSend;

+ 0 - 1
src/Entity/Message/Email.php

@@ -19,7 +19,6 @@ use Doctrine\ORM\Mapping as ORM;
 // #[Auditable]
 #[ApiResource(operations: [])]
 #[ORM\Entity]
-#[ORM\Table(name: 'Message')]
 class Email extends AbstractMessage
 {
     #[ORM\Column(type: 'boolean', options: ['default' => false])]

+ 0 - 1
src/Entity/Message/Mail.php

@@ -17,7 +17,6 @@ use Doctrine\ORM\Mapping as ORM;
 #[ApiResource(operations: [])]
 // #[Auditable]
 #[ORM\Entity]
-#[ORM\Table(name: 'Message')]
 class Mail extends AbstractMessage
 {
 }

+ 2 - 11
src/Entity/Message/ReportEmail.php

@@ -12,15 +12,11 @@ use Doctrine\ORM\Mapping as ORM;
  * TODO: documenter.
  */
 #[ApiResource(operations: [])]
-// #[Auditable]
 #[ORM\Entity]
+#[ORM\Table(name: 'ReportMessage')]
+// #[Auditable]
 class ReportEmail extends AbstractReport
 {
-    #[ORM\Id]
-    #[ORM\Column]
-    #[ORM\GeneratedValue]
-    private ?int $id = null;
-
     #[ORM\ManyToOne(inversedBy: 'reports')]
     #[ORM\JoinColumn('message_id')]
     private ?Email $email = null;
@@ -28,11 +24,6 @@ class ReportEmail extends AbstractReport
     #[ORM\Column(length: 255)]
     private string $addressEmail;
 
-    public function getId(): ?int
-    {
-        return $this->id;
-    }
-
     public function getEmail(): ?Email
     {
         return $this->email;

+ 3 - 12
src/Entity/Message/ReportSms.php

@@ -12,15 +12,11 @@ use Doctrine\ORM\Mapping as ORM;
  * TODO: documenter.
  */
 #[ApiResource(operations: [])]
-// #[Auditable]
+#[ORM\Table(name: 'ReportMessage')]
 #[ORM\Entity]
+// #[Auditable]
 class ReportSms extends AbstractReport
 {
-    #[ORM\Id]
-    #[ORM\Column]
-    #[ORM\GeneratedValue]
-    private ?int $id = null;
-
     #[ORM\ManyToOne(targetEntity: Sms::class, inversedBy: 'reports')]
     #[ORM\JoinColumn('message_id')]
     private ?Sms $sms = null;
@@ -31,11 +27,6 @@ class ReportSms extends AbstractReport
     #[ORM\Column(length: 15, nullable: true)]
     private ?string $smsId;
 
-    public function getId(): ?int
-    {
-        return $this->id;
-    }
-
     public function getSms(): ?Sms
     {
         return $this->sms;
@@ -59,7 +50,7 @@ class ReportSms extends AbstractReport
     //        return $this->mobile;
     //    }
 
-    public function setSmsId(string $smsId): self
+    public function setSmsId(?string $smsId): self
     {
         $this->smsId = $smsId;
 

+ 0 - 1
src/Entity/Message/Sms.php

@@ -17,7 +17,6 @@ use Doctrine\ORM\Mapping as ORM;
 // #[Auditable]
 #[ApiResource(operations: [])]
 #[ORM\Entity]
-#[ORM\Table(name: 'Message')]
 class Sms extends AbstractMessage
 {
 }

+ 1 - 1
src/Entity/Organization/CotisationByYear.php

@@ -25,7 +25,7 @@ class CotisationByYear
     #[ORM\JoinColumn(name: 'organization_id', referencedColumnName: 'id', nullable: false)]
     private Organization $organization;
 
-    #[ORM\OneToOne(targetEntity: CotisationStaffInfos::class, mappedBy: 'cotisationByYear', cascade: ['persist'])]
+    #[ORM\OneToOne(targetEntity: CotisationStaffInfos::class, mappedBy: 'cotisationByYear', cascade: ['persist', 'remove'])]
     protected ?CotisationStaffInfos $cotisationStaffInfos;
 
     public function getId(): ?int

+ 2 - 0
src/Entity/Organization/OnlineRegistrationOpeningPeriod.php

@@ -78,6 +78,7 @@ class OnlineRegistrationOpeningPeriod
     public function setStartDate(\DateTimeInterface $startDate): self
     {
         $this->startDate = $startDate;
+
         return $this;
     }
 
@@ -89,6 +90,7 @@ class OnlineRegistrationOpeningPeriod
     public function setEndDate(\DateTimeInterface $endDate): self
     {
         $this->endDate = $endDate;
+
         return $this;
     }
 }

+ 2 - 0
src/Entity/Organization/OnlineRegistrationSettings.php

@@ -289,6 +289,7 @@ class OnlineRegistrationSettings
     public function setAddNewStudents(bool $addNewStudents): self
     {
         $this->addNewStudents = $addNewStudents;
+
         return $this;
     }
 
@@ -300,6 +301,7 @@ class OnlineRegistrationSettings
     public function setAddNewEducations(bool $addNewEducations): self
     {
         $this->addNewEducations = $addNewEducations;
+
         return $this;
     }
 

+ 122 - 50
src/Entity/Organization/Organization.php

@@ -23,6 +23,7 @@ use App\Entity\Core\ContactPoint;
 use App\Entity\Core\File;
 use App\Entity\Core\Notification;
 use App\Entity\Core\Tagg;
+use App\Entity\Core\Tips;
 use App\Entity\Donor\Donor;
 use App\Entity\Education\CriteriaNotation;
 use App\Entity\Education\Cycle;
@@ -41,6 +42,7 @@ use App\Entity\Place\Place;
 use App\Entity\Product\Equipment;
 use App\Entity\Product\Intangible;
 use App\Entity\Reward\Reward;
+use App\Entity\Shop\Orders;
 use App\Entity\Traits\CreatedOnAndByTrait;
 use App\Enum\Organization\CategoryEnum;
 use App\Enum\Organization\LegalEnum;
@@ -95,7 +97,7 @@ class Organization
     private ?Settings $settings = null;
 
     /** @var Collection<int, Access> */
-    #[ORM\OneToMany(targetEntity: Access::class, mappedBy: 'organization', cascade: ['persist'])]
+    #[ORM\OneToMany(targetEntity: Access::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     private Collection $accesses;
 
     /** @var Collection<int, NetworkOrganization> */
@@ -235,38 +237,46 @@ class Organization
     #[ORM\Column(nullable: true)]
     private ?string $otherPractice = null;
 
-    /** @var Collection<int, ContactPoint> */
+    /**
+     * orphanRemoval: on ne conserve pas un contact point qui n'est plus lié à aucune organisation ou person.
+     *
+     * @var Collection<int, ContactPoint>
+     */
     #[ORM\ManyToMany(targetEntity: ContactPoint::class, mappedBy: 'organization', cascade: ['persist'], orphanRemoval: true)]
     private Collection $contactPoints;
 
-    /** @var Collection<int, BankAccount> */
-    #[ORM\ManyToMany(targetEntity: BankAccount::class, inversedBy: 'organization')]
+    /**
+     * orphanRemoval: on ne conserve pas un contact point qui n'est plus lié à aucune organisation ou person.
+     *
+     * @var Collection<int, BankAccount>
+     */
+    #[ORM\ManyToMany(targetEntity: BankAccount::class, inversedBy: 'organization', cascade: ['persist'], orphanRemoval: true)]
     #[ORM\JoinColumn(name: 'organization_id', referencedColumnName: 'id', unique: true)]
     #[ORM\InverseJoinColumn(name: 'bankAccount_id', referencedColumnName: 'id')]
     private Collection $bankAccounts;
 
     /** @var Collection<int, OrganizationAddressPostal> */
-    #[ORM\OneToMany(targetEntity: OrganizationAddressPostal::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: OrganizationAddressPostal::class, cascade: ['persist', 'remove'])]
     private Collection $organizationAddressPostals;
 
     /** @var Collection<int, OrganizationLicence> */
-    #[ORM\OneToMany(targetEntity: OrganizationLicence::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: OrganizationLicence::class, cascade: ['persist', 'remove'])]
     private Collection $organizationLicences;
 
     /** @var Collection<int, OrganizationArticle> */
-    #[ORM\OneToMany(targetEntity: OrganizationArticle::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: OrganizationArticle::class, cascade: ['persist', 'remove'])]
     private Collection $organizationArticles;
 
     /** @var Collection<int, Cycle> */
-    #[ORM\OneToMany(targetEntity: Cycle::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: Cycle::class, cascade: ['persist', 'remove'])]
     private Collection $cycles;
 
     /** @var Collection<int, EducationTiming> */
-    #[ORM\OneToMany(targetEntity: EducationTiming::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: EducationTiming::class, cascade: ['persist', 'remove'])]
     private Collection $educationTimings;
 
     /** @var Collection<int, Subdomain> */
-    #[ORM\OneToMany(targetEntity: Subdomain::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: Subdomain::class, cascade: ['persist', 'remove'])]
     private Collection $subdomains;
 
     #[ORM\ManyToOne(inversedBy: 'organizationContacts')]
@@ -274,91 +284,91 @@ class Organization
     private ?Access $contactPerson;
 
     /** @var Collection<int, OrganizationHoliday> */
-    #[ORM\OneToMany(targetEntity: OrganizationHoliday::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: OrganizationHoliday::class, cascade: ['persist', 'remove'])]
     private Collection $holidays;
 
     /** @var Collection<int, Course> */
-    #[ORM\OneToMany(targetEntity: Course::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: Course::class, cascade: ['persist', 'remove'])]
     private Collection $courses;
 
     /** @var Collection<int, EducationalProject> */
-    #[ORM\OneToMany(targetEntity: EducationalProject::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: EducationalProject::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     private Collection $educationalProjects;
 
     /** @var Collection<int, Event> */
-    #[ORM\OneToMany(targetEntity: Event::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Event::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     private Collection $events;
 
     /** @var Collection<int, Examen> */
-    #[ORM\OneToMany(targetEntity: Examen::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: Examen::class, cascade: ['persist', 'remove'])]
     private Collection $examens;
 
     /** @var Collection<int, CriteriaNotation> */
-    #[ORM\OneToMany(targetEntity: CriteriaNotation::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: CriteriaNotation::class, cascade: ['persist', 'remove'])]
     private Collection $critereNotations;
 
     /** @var Collection<int, EducationCategory> */
-    #[ORM\OneToMany(targetEntity: EducationCategory::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: EducationCategory::class, cascade: ['persist', 'remove'])]
     private Collection $educationCategories;
 
     /** @var Collection<int, PeriodNotation> */
-    #[ORM\OneToMany(targetEntity: PeriodNotation::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: PeriodNotation::class, cascade: ['persist', 'remove'])]
     private Collection $periodNotations;
 
     /** @var Collection<int, File> */
-    #[ORM\OneToMany(targetEntity: File::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: File::class, cascade: ['persist', 'remove'])]
     private Collection $files;
 
     /** @var Collection<int, Notification> */
-    #[ORM\OneToMany(targetEntity: Notification::class, mappedBy: 'recipientOrganization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(mappedBy: 'recipientOrganization', targetEntity: Notification::class, cascade: ['persist', 'remove'])]
     private Collection $notifications;
 
     /** @var Collection<int, Email> */
-    #[ORM\OneToMany(targetEntity: Email::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Email::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     private Collection $emails;
 
     /** @var Collection<int, Mail> */
-    #[ORM\OneToMany(targetEntity: Mail::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Mail::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     private Collection $mails;
 
     /** @var Collection<int, Sms> */
-    #[ORM\OneToMany(targetEntity: Sms::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Sms::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     private Collection $sms;
 
     /** @var Collection<int, Activity> */
-    #[ORM\OneToMany(targetEntity: Activity::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Activity::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     private Collection $activities;
 
     /** @var Collection<int, Jury> */
-    #[ORM\OneToMany(targetEntity: Jury::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Jury::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     private Collection $juries;
 
     /** @var Collection<int, Commission> */
-    #[ORM\OneToMany(targetEntity: Commission::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Commission::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     private Collection $commissions;
 
     /** @var Collection<int, Place> */
-    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: Place::class, orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Place::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     private Collection $places;
 
     /** @var Collection<int, Attendance> */
-    #[ORM\OneToMany(targetEntity: Attendance::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Attendance::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     private Collection $attendances;
 
     /** @var Collection<int, Equipment> */
-    #[ORM\OneToMany(targetEntity: Equipment::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Equipment::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     private Collection $equipments;
 
     /** @var Collection<int, Intangible> */
-    #[ORM\OneToMany(targetEntity: Intangible::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Intangible::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     private Collection $intangibles;
 
     /** @var Collection<int, Donor> */
-    #[ORM\OneToMany(targetEntity: Donor::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Donor::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     private Collection $donors;
 
     /** @var Collection<int, Reward> */
-    #[ORM\OneToMany(targetEntity: Reward::class, mappedBy: 'organization', cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Reward::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     private Collection $rewards;
 
     //    #[ORM\OneToOne()]
@@ -372,51 +382,65 @@ class Organization
     private Collection $tags;
 
     /** @var Collection<int, NetworkOrganization> */
-    #[ORM\OneToMany(targetEntity: NetworkOrganization::class, mappedBy: 'organization', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: NetworkOrganization::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     protected Collection $network;
 
     /** @var Collection<int, NetworkOrganization> */
-    #[ORM\OneToMany(targetEntity: NetworkOrganization::class, mappedBy: 'parent', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: NetworkOrganization::class, mappedBy: 'parent', cascade: ['persist', 'remove'])]
     protected Collection $networkChild;
 
-    #[ORM\OneToOne(targetEntity: BillingExportSetting::class, mappedBy: 'organization', cascade: ['persist'])]
+    #[ORM\OneToOne(targetEntity: BillingExportSetting::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     protected ?BillingExportSetting $billingExportSetting;
 
     /** @var Collection<int, Access> */
-    #[ORM\OneToMany(targetEntity: Access::class, mappedBy: 'organization', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Access::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     protected Collection $access;
 
     /** @var Collection<int, AbstractMessage> */
-    #[ORM\OneToMany(targetEntity: AbstractMessage::class, mappedBy: 'organization', cascade: [], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: AbstractMessage::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     protected Collection $messages;
 
-    #[ORM\OneToOne(targetEntity: OnlineRegistrationSettings::class, mappedBy: 'organization', cascade: ['persist'])]
+    #[ORM\OneToOne(targetEntity: OnlineRegistrationSettings::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     protected ?OnlineRegistrationSettings $onlineRegistrationSettings;
 
     /** @var Collection<int, CotisationByYear> */
-    #[ORM\OneToMany(targetEntity: CotisationByYear::class, mappedBy: 'organization', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: CotisationByYear::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     protected Collection $cotisationByYears;
 
     /** @var Collection<int, AttendanceBookingReason> */
-    #[ORM\OneToMany(targetEntity: AttendanceBookingReason::class, mappedBy: 'organization', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: AttendanceBookingReason::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     protected Collection $attendanceBookingReasons;
 
     /** @var Collection<int, Cycle> */
-    #[ORM\OneToMany(targetEntity: Cycle::class, mappedBy: 'organization', cascade: [], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: Cycle::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     protected Collection $educationCurriculumPacks;
 
     /** @var Collection<int, FamilyQuotientModel> */
-    #[ORM\OneToMany(targetEntity: FamilyQuotientModel::class, mappedBy: 'organization', cascade: [], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: FamilyQuotientModel::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     protected Collection $familyQuotientModels;
 
     /** @var Collection<int, BillSchedule> */
-    #[ORM\OneToMany(targetEntity: BillSchedule::class, mappedBy: 'organization', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: BillSchedule::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     protected Collection $billSchedules;
 
     /** @var Collection<int, AbstractReport> */
-    #[ORM\OneToMany(targetEntity: AbstractReport::class, mappedBy: 'organization', cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\OneToMany(targetEntity: AbstractReport::class, mappedBy: 'organization', cascade: ['persist', 'remove'])]
     private Collection $reports;
 
+    /** @var Collection<int, Orders> */
+    #[ORM\OneToMany(targetEntity: Orders::class, mappedBy: 'organization', cascade: [], orphanRemoval: true)]
+    protected Collection $orders;
+
+    /**
+     * orphanRemoval: on ne conserve pas un tips qui n'est plus lié à aucune organisation ou access.
+     *
+     * @var Collection<int, Tips>
+     */
+    #[ORM\ManyToMany(targetEntity: Tips::class, inversedBy: 'organizations', cascade: ['persist'], orphanRemoval: false)]
+    #[ORM\JoinTable(name: 'organization_tips')]
+    #[ORM\JoinColumn(name: 'organization_id')]
+    protected Collection $tips;
+
     #[Pure]
     public function __construct()
     {
@@ -465,6 +489,8 @@ class Organization
         $this->educationCurriculumPacks = new ArrayCollection();
         $this->familyQuotientModels = new ArrayCollection();
         $this->billSchedules = new ArrayCollection();
+        $this->orders = new ArrayCollection();
+        $this->tips = new ArrayCollection();
     }
 
     public function getId(): ?int
@@ -527,13 +553,11 @@ class Organization
 
     public function setSettings(Settings $settings): self
     {
-        // set the owning side of the relation if necessary
-        if ($settings->getOrganization() !== $this) {
-            $settings->setOrganization($this);
-        }
-
         $this->settings = $settings;
 
+        // set the owning side of the relation
+        $settings->setOrganization($this);
+
         return $this;
     }
 
@@ -563,7 +587,7 @@ class Organization
 
     public function getNetworkOrganizations(): Collection
     {
-        return new ArrayCollection([]);
+        return $this->networkOrganizations;
     }
 
     public function addNetworkOrganization(NetworkOrganization $networkOrganization): self
@@ -2203,4 +2227,52 @@ class Organization
 
         return $this;
     }
+
+    public function getOrders(): Collection
+    {
+        return $this->orders;
+    }
+
+    public function addOrder(Orders $order): self
+    {
+        if (!$this->orders->contains($order)) {
+            $this->orders[] = $order;
+            $order->setOrganization($this);
+        }
+
+        return $this;
+    }
+
+    public function removeOrder(Orders $order): self
+    {
+        if ($this->orders->removeElement($order)) {
+            $order->setOrganization(null);
+        }
+
+        return $this;
+    }
+
+    public function getTips(): Collection
+    {
+        return $this->tips;
+    }
+
+    public function addTip(Tips $tip): self
+    {
+        if (!$this->tips->contains($tip)) {
+            $this->tips[] = $tip;
+            $tip->addOrganization($this);
+        }
+
+        return $this;
+    }
+
+    public function removeTip(Tips $tip): self
+    {
+        if ($this->tips->removeElement($tip)) {
+            $tip->removeOrganization($this);
+        }
+
+        return $this;
+    }
 }

+ 6 - 6
src/Entity/Organization/Parameters.php

@@ -6,7 +6,7 @@ namespace App\Entity\Organization;
 
 use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Metadata\Get;
-use ApiPlatform\Metadata\Put;
+use ApiPlatform\Metadata\Patch;
 use App\Entity\Access\Access;
 use App\Entity\Core\File;
 use App\Enum\Core\TimeZoneEnum;
@@ -34,7 +34,7 @@ use Symfony\Component\Validator\Constraints as Assert;
         new Get(
             security: 'is_granted("ROLE_ORGANIZATION_VIEW") and object.getOrganization().getId() == user.getOrganization().getId()'
         ),
-        new Put(
+        new Patch(
             security: 'is_granted("ROLE_ORGANIZATION") and object.getOrganization().getId() == user.getOrganization().getId()'
         ),
     ],
@@ -50,7 +50,7 @@ class Parameters
     #[ORM\GeneratedValue]
     private ?int $id = null;
 
-    #[ORM\OneToOne(targetEntity: Organization::class, mappedBy: 'parameters')]
+    #[ORM\OneToOne(targetEntity: Organization::class, mappedBy: 'parameters', cascade: ['persist', 'remove'])]
     private ?Organization $organization = null;
 
     #[ORM\Column(type: 'date', nullable: true)]
@@ -65,7 +65,7 @@ class Parameters
     #[ORM\Column(type: 'date', nullable: true)]
     private ?\DateTimeInterface $endCourseDate = null;
 
-    #[ORM\Column(columnDefinition: "TINYINT DEFAULT 20 NOT NULL")]
+    #[ORM\Column(columnDefinition: 'TINYINT DEFAULT 20 NOT NULL')]
     #[Assert\Range(notInRangeMessage: 'between_{{ min }}_and_{{ max }}', min: 0, max: 100)]
     private int $average = 20;
 
@@ -73,7 +73,7 @@ class Parameters
     private bool $editCriteriaNotationByAdminOnly = true;
 
     #[ORM\Column(length: 11, nullable: true)]
-    #[Assert\Regex('/^\w{3,11}$/i', message: 'smsSenderName_error')]
+    #[Assert\Regex('/^[a-zA-Z0-9_ .]{3,11}$/i', message: 'smsSenderName_error')]
     private ?string $smsSenderName = null;
 
     #[ORM\Column(options: ['default' => false])]
@@ -186,7 +186,7 @@ class Parameters
     #[ORM\Column(type: 'boolean', options: ['default' => false])]
     private bool $notifyAdministrationAbsence = false;
 
-    #[ORM\Column(columnDefinition: "TINYINT DEFAULT 2 NOT NULL")]
+    #[ORM\Column(columnDefinition: 'TINYINT DEFAULT 2 NOT NULL')]
     #[Assert\Range(notInRangeMessage: 'between_{{ min }}_and_{{ max }}', min: 2, max: 100)]
     private int $numberConsecutiveAbsences = 2;
 

+ 4 - 3
src/Entity/Organization/Subdomain.php

@@ -9,8 +9,8 @@ use ApiPlatform\Metadata\ApiFilter;
 use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Metadata\Get;
 use ApiPlatform\Metadata\GetCollection;
+use ApiPlatform\Metadata\Patch;
 use ApiPlatform\Metadata\Post;
-use ApiPlatform\Metadata\Put;
 use App\Attribute\OrganizationDefaultValue;
 use App\Repository\Organization\SubdomainRepository;
 use App\State\Processor\Organization\SubdomainProcessor;
@@ -28,7 +28,7 @@ use Symfony\Component\Validator\Constraints as Assert;
         new Get(
             security: 'is_granted("ROLE_ORGANIZATION_VIEW") and object.getOrganization().getId() == user.getOrganization().getId()'
         ),
-        new Put(
+        new Patch(
             security: 'is_granted("ROLE_ORGANIZATION") and object.getOrganization().getId() == user.getOrganization().getId()'
         ),
         new GetCollection(
@@ -45,7 +45,8 @@ use Symfony\Component\Validator\Constraints as Assert;
 #[OrganizationDefaultValue(fieldName: 'organization')]
 #[UniqueEntity('subdomain')]
 #[ApiFilter(filterClass: SearchFilter::class, properties: ['subdomain' => 'exact'])]
-#[ORM\Table(indexes: [new ORM\Index(name: "subdomain_idx", columns: ["subdomain"])])]
+#[ORM\Table]
+#[ORM\Index(name: 'subdomain_idx', columns: ['subdomain'])]
 class Subdomain
 {
     #[ORM\Id]

+ 5 - 31
src/Entity/Person/Person.php

@@ -29,13 +29,10 @@ use Symfony\Component\Serializer\Annotation\Groups;
 #[ApiResource(operations: [])]
 // #[Auditable]
 #[ORM\Entity(repositoryClass: PersonRepository::class)]
-#[ORM\Table(
-    indexes: [
-        new ORM\Index(columns: ["username"], name: "username_idx"),
-        new ORM\Index(columns: ["name"], name: "name_idx"),
-        new ORM\Index(columns: ["givenName"], name: "givenName_idx"),
-    ]
-)]
+#[ORM\Table]
+#[ORM\Index(name: 'username_idx', columns: ['username'])]
+#[ORM\Index(name: 'name_idx', columns: ['name'])]
+#[ORM\Index(name: 'givenName_idx', columns: ['givenName'])]
 class Person implements UserInterface, PasswordAuthenticatedUserInterface
 {
     use CreatedOnAndByTrait;
@@ -144,10 +141,6 @@ class Person implements UserInterface, PasswordAuthenticatedUserInterface
     #[ORM\OneToMany(targetEntity: AllowedIp::class, mappedBy: 'person', cascade: ['persist'], orphanRemoval: true)]
     private Collection $allowedIps;
 
-    /** @var array<string, string> */
-    #[ORM\Column(type: 'json', nullable: true)]
-    private array $confidentiality = [];
-
     #[Pure]
     public function __construct()
     {
@@ -187,6 +180,7 @@ class Person implements UserInterface, PasswordAuthenticatedUserInterface
     public function setUsernameCanonical(?string $usernameCanonical): self
     {
         $this->usernameCanonical = $usernameCanonical;
+
         return $this;
     }
 
@@ -712,24 +706,4 @@ class Person implements UserInterface, PasswordAuthenticatedUserInterface
 
         return $this;
     }
-
-    /**
-     * @return array<string, string>
-     */
-    public function getConfidentiality(): array
-    {
-        return $this->confidentiality;
-    }
-
-    /**
-     * @param array<string, string> $confidentiality
-     *
-     * @return $this
-     */
-    public function setConfidentiality(array $confidentiality): self
-    {
-        $this->confidentiality = $confidentiality;
-
-        return $this;
-    }
 }

+ 2 - 1
src/Entity/Place/AbstractPlace.php

@@ -16,8 +16,9 @@ use Doctrine\ORM\Mapping as ORM;
  *
  * Classe de base de @see Place, PlaceSystem
  */
-#[ORM\MappedSuperclass]
+#[ORM\Entity]
 #[ORM\Table(name: 'Place')]
+#[ORM\InheritanceType('SINGLE_TABLE')]
 #[ORM\DiscriminatorColumn(name: 'discr', type: 'string')]
 #[ORM\DiscriminatorMap(
     [

+ 0 - 1
src/Entity/Place/Place.php

@@ -23,7 +23,6 @@ use Doctrine\ORM\Mapping as ORM;
 // #[Auditable]
 #[ApiResource(operations: [])]
 #[ORM\Entity]
-#[ORM\Table(name: 'Place')]
 class Place extends AbstractPlace
 {
     /** @var Collection<int, Event> */

+ 0 - 1
src/Entity/Place/PlaceControl.php

@@ -19,7 +19,6 @@ use Doctrine\ORM\Mapping as ORM;
 // #[Auditable]
 #[ApiResource(operations: [])]
 #[ORM\Entity]
-#[ORM\Table(name: 'Control')]
 class PlaceControl extends AbstractControl
 {
     #[ORM\ManyToOne(inversedBy: 'controls')]

+ 0 - 1
src/Entity/Place/PlaceRepair.php

@@ -20,7 +20,6 @@ use Doctrine\ORM\Mapping as ORM;
 // #[Auditable]
 #[ApiResource(operations: [])]
 #[ORM\Entity]
-#[ORM\Table(name: 'Repair')]
 class PlaceRepair extends AbstractRepair
 {
     #[ORM\ManyToOne(inversedBy: 'placeRepairProviders')]

+ 0 - 1
src/Entity/Place/PlaceSystem.php

@@ -15,7 +15,6 @@ use Doctrine\ORM\Mapping as ORM;
 // #[Auditable]
 #[ApiResource(operations: [])]
 #[ORM\Entity]
-#[ORM\Table(name: 'Place')]
 class PlaceSystem extends AbstractPlace
 {
 }

+ 0 - 1
src/Entity/Place/RoomControl.php

@@ -17,7 +17,6 @@ use Doctrine\ORM\Mapping as ORM;
 // #[Auditable]
 #[ApiResource(operations: [])]
 #[ORM\Entity]
-#[ORM\Table(name: 'Control')]
 class RoomControl extends AbstractControl
 {
     #[ORM\ManyToOne(inversedBy: 'controls')]

+ 0 - 1
src/Entity/Place/RoomRepair.php

@@ -19,7 +19,6 @@ use Doctrine\ORM\Mapping as ORM;
 // #[Auditable]
 #[ApiResource(operations: [])]
 #[ORM\Entity]
-#[ORM\Table(name: 'Repair')]
 class RoomRepair extends AbstractRepair
 {
     #[ORM\ManyToOne(inversedBy: 'repairs')]

+ 5 - 1
src/Entity/Product/AbstractProduct.php

@@ -12,8 +12,9 @@ use Doctrine\ORM\Mapping as ORM;
 /**
  * Classe de base de @see Equipment, Intangible.
  */
-#[ORM\MappedSuperclass]
+#[ORM\Entity]
 #[ORM\Table(name: 'Product')]
+#[ORM\InheritanceType('SINGLE_TABLE')]
 #[ORM\DiscriminatorColumn(name: 'discr', type: 'string')]
 #[ORM\DiscriminatorMap(
     [
@@ -30,6 +31,9 @@ abstract class AbstractProduct
 
     /** @var Collection<int, Tagg> */
     #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'products', cascade: ['persist'], orphanRemoval: false)]
+    #[ORM\JoinTable(name: 'tag_product')]
+    #[ORM\JoinColumn(name: 'product_id', referencedColumnName: 'id')]
+    #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
     protected Collection $tags;
 
     public function __construct()

+ 0 - 1
src/Entity/Product/Equipment.php

@@ -24,7 +24,6 @@ use Doctrine\ORM\Mapping as ORM;
 #[ApiResource(operations: [])]
 // #[Auditable]
 #[ORM\Entity]
-#[ORM\Table(name: 'Product')]
 class Equipment extends AbstractProduct
 {
     #[ORM\ManyToOne(inversedBy: 'equipments')]

+ 0 - 2
src/Entity/Product/EquipmentControl.php

@@ -19,7 +19,6 @@ use Doctrine\ORM\Mapping as ORM;
 // #[Auditable]
 #[ApiResource(operations: [])]
 #[ORM\Entity]
-#[ORM\Table(name: 'Control')]
 class EquipmentControl extends AbstractControl
 {
     #[ORM\ManyToOne(inversedBy: 'accompanistControl')]
@@ -57,5 +56,4 @@ class EquipmentControl extends AbstractControl
 
         return $this;
     }
-
 }

+ 0 - 1
src/Entity/Product/EquipmentRepair.php

@@ -20,7 +20,6 @@ use Doctrine\ORM\Mapping as ORM;
 // #[Auditable]
 #[ApiResource(operations: [])]
 #[ORM\Entity]
-#[ORM\Table(name: 'Repair')]
 class EquipmentRepair extends AbstractRepair
 {
     #[ORM\ManyToOne(inversedBy: 'equipmentRepairProviders')]

+ 0 - 1
src/Entity/Product/Intangible.php

@@ -23,7 +23,6 @@ use Doctrine\ORM\Mapping as ORM;
 #[ApiResource(operations: [])]
 // #[Auditable]
 #[ORM\Entity]
-#[ORM\Table(name: 'Product')]
 class Intangible extends AbstractProduct
 {
     #[ORM\ManyToOne(inversedBy: 'intangibles')]

+ 17 - 1
src/Entity/Public/FederationStructure.php

@@ -40,7 +40,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
 #[ApiFilter(filterClass: SearchFilter::class, properties: ['name' => 'partial', 'city' => 'exact'])]
 #[ApiFilter(filterClass: NumericFilter::class, properties: ['id', 'parentId'])]
 #[ApiFilter(filterClass: FindInSetFilter::class, properties: ['parents'])]
-#[ApiFilter(filterClass: BooleanFilter::class, properties: ['portailVisibility'])]
+#[ApiFilter(filterClass: BooleanFilter::class, properties: ['isFederation', 'portailVisibility'])]
 class FederationStructure
 {
     #[ORM\Id]
@@ -68,6 +68,10 @@ class FederationStructure
     #[Groups(['federation_structure_item_get', 'federation_structure_collection_get'])]
     private ?string $type;
 
+    #[ORM\Column(options: ['default' => false])]
+    #[Groups(['federation_structure_item_get', 'federation_structure_collection_get'])]
+    private bool $isFederation = false;
+
     #[ORM\Column(nullable: true)]
     #[Groups(['federation_structure_item_get', 'federation_structure_collection_get'])]
     private ?string $website;
@@ -209,6 +213,18 @@ class FederationStructure
         return $this;
     }
 
+    public function getIsFederation(): bool
+    {
+        return $this->isFederation;
+    }
+
+    public function setIsFederation(bool $isFederation): self
+    {
+        $this->isFederation = $isFederation;
+
+        return $this;
+    }
+
     public function getWebsite(): ?string
     {
         return $this->website;

+ 62 - 0
src/Entity/Shop/Orders.php

@@ -0,0 +1,62 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Shop;
+
+use ApiPlatform\Metadata\ApiResource;
+use App\Entity\Access\Access;
+use App\Entity\Organization\Organization;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ApiResource(operations: [])]
+#[ORM\Entity]
+class Orders
+{
+    #[ORM\Id]
+    #[ORM\Column(length: 100)]
+    protected string $uuid;
+
+    #[ORM\ManyToOne(targetEntity: Organization::class, cascade: [], inversedBy: 'orders')]
+    #[ORM\JoinColumn(nullable: true)]
+    protected ?Organization $organization;
+
+    #[ORM\ManyToOne(targetEntity: Access::class, cascade: [], inversedBy: 'orders')]
+    protected ?Access $access;
+
+    public function getUuid(): mixed
+    {
+        return $this->uuid;
+    }
+
+    public function setUuid(mixed $uuid): self
+    {
+        $this->uuid = $uuid;
+
+        return $this;
+    }
+
+    public function getOrganization(): ?Organization
+    {
+        return $this->organization;
+    }
+
+    public function setOrganization(?Organization $organization): self
+    {
+        $this->organization = $organization;
+
+        return $this;
+    }
+
+    public function getAccess(): ?Access
+    {
+        return $this->access;
+    }
+
+    public function setAccess(?Access $access): self
+    {
+        $this->access = $access;
+
+        return $this;
+    }
+}

+ 219 - 0
src/Entity/SimulationSession/SimulationSession.php

@@ -0,0 +1,219 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\SimulationSession;
+
+use ApiPlatform\Metadata\ApiResource;
+use App\Entity\Access\Access;
+use App\Entity\Token\Token;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ApiResource(operations: [])]
+#[ORM\Entity]
+class SimulationSession
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private int $id;
+
+    /** -- Warning : auto-generated property, checkup the attribute options -- */
+    #[ORM\Column]
+    protected mixed $initiatorIp;
+
+    #[ORM\Column(type: 'datetime', nullable: true)]
+    protected ?\DateTimeInterface $expiryDate;
+
+    #[ORM\Column(options: ['default' => false])]
+    protected bool $alreadyUsed;
+
+    #[ORM\Column(type: 'datetime', nullable: true)]
+    protected ?\DateTimeInterface $createDate;
+
+    #[ORM\Column(type: 'datetime', nullable: true)]
+    protected ?\DateTimeInterface $updateDate;
+
+    /** -- Warning : auto-generated property, checkup the attribute options -- */
+    #[ORM\Column(type: 'integer', options: ['nullable' => true])]
+    protected int $legacyId;
+
+    /** -- Warning : auto-generated property, checkup the attribute options -- */
+    #[ORM\Column(type: 'integer', options: ['nullable' => true])]
+    protected int $createdBy;
+
+    /** -- Warning : auto-generated property, checkup the attribute options -- */
+    #[ORM\Column(type: 'integer', options: ['nullable' => true])]
+    protected int $updatedBy;
+
+    /** -- Warning : auto-generated property, checkup the attribute options -- */
+    #[ORM\Column(options: ['default' => false])]
+    protected bool $draft;
+
+    #[ORM\ManyToOne(targetEntity: Access::class, cascade: [], inversedBy: 'simulationSessionAccessInitiators')]
+    #[ORM\JoinColumn(nullable: false)]
+    protected Access $accessInitiator;
+
+    #[ORM\ManyToOne(targetEntity: Access::class, cascade: [], inversedBy: 'simulationSessionAccessSimulateds')]
+    #[ORM\JoinColumn(nullable: false)]
+    protected Access $accessSimulated;
+
+    #[ORM\OneToOne(mappedBy: 'simulationSession', targetEntity: Token::class, cascade: ['persist'])]
+    protected ?Token $token;
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): self
+    {
+        $this->id = $id;
+
+        return $this;
+    }
+
+    public function getInitiatorIp(): mixed
+    {
+        return $this->initiatorIp;
+    }
+
+    public function setInitiatorIp(mixed $initiatorIp): self
+    {
+        $this->initiatorIp = $initiatorIp;
+
+        return $this;
+    }
+
+    public function getExpiryDate(): ?\DateTimeInterface
+    {
+        return $this->expiryDate;
+    }
+
+    public function setExpiryDate(?\DateTimeInterface $expiryDate): self
+    {
+        $this->expiryDate = $expiryDate;
+
+        return $this;
+    }
+
+    public function getAlreadyUsed(): bool
+    {
+        return $this->alreadyUsed;
+    }
+
+    public function setAlreadyUsed(bool $alreadyUsed): self
+    {
+        $this->alreadyUsed = $alreadyUsed;
+
+        return $this;
+    }
+
+    public function getCreateDate(): ?\DateTimeInterface
+    {
+        return $this->createDate;
+    }
+
+    public function setCreateDate(?\DateTimeInterface $createDate): self
+    {
+        $this->createDate = $createDate;
+
+        return $this;
+    }
+
+    public function getUpdateDate(): ?\DateTimeInterface
+    {
+        return $this->updateDate;
+    }
+
+    public function setUpdateDate(?\DateTimeInterface $updateDate): self
+    {
+        $this->updateDate = $updateDate;
+
+        return $this;
+    }
+
+    public function getLegacyId(): int
+    {
+        return $this->legacyId;
+    }
+
+    public function setLegacyId(int $legacyId): self
+    {
+        $this->legacyId = $legacyId;
+
+        return $this;
+    }
+
+    public function getCreatedBy(): int
+    {
+        return $this->createdBy;
+    }
+
+    public function setCreatedBy(int $createdBy): self
+    {
+        $this->createdBy = $createdBy;
+
+        return $this;
+    }
+
+    public function getUpdatedBy(): int
+    {
+        return $this->updatedBy;
+    }
+
+    public function setUpdatedBy(int $updatedBy): self
+    {
+        $this->updatedBy = $updatedBy;
+
+        return $this;
+    }
+
+    public function getDraft(): bool
+    {
+        return $this->draft;
+    }
+
+    public function setDraft(bool $draft): self
+    {
+        $this->draft = $draft;
+
+        return $this;
+    }
+
+    public function getAccessInitiator(): Access
+    {
+        return $this->accessInitiator;
+    }
+
+    public function setAccessInitiator(Access $accessInitiator): self
+    {
+        $this->accessInitiator = $accessInitiator;
+
+        return $this;
+    }
+
+    public function getAccessSimulated(): Access
+    {
+        return $this->accessSimulated;
+    }
+
+    public function setAccessSimulated(Access $accessSimulated): self
+    {
+        $this->accessSimulated = $accessSimulated;
+
+        return $this;
+    }
+
+    public function getToken(): ?Token
+    {
+        return $this->token;
+    }
+
+    public function setToken(?Token $token): self
+    {
+        $this->token = $token;
+
+        return $this;
+    }
+}

+ 17 - 0
src/Entity/Token/Token.php

@@ -6,6 +6,7 @@ namespace App\Entity\Token;
 
 use ApiPlatform\Metadata\ApiResource;
 use App\Entity\Access\Access;
+use App\Entity\SimulationSession\SimulationSession;
 use Doctrine\ORM\Mapping as ORM;
 
 /**
@@ -24,6 +25,10 @@ class Token
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
     private ?Access $access;
 
+    #[ORM\OneToOne(targetEntity: SimulationSession::class, inversedBy: 'token', cascade: ['persist'])]
+    #[ORM\JoinColumn(unique: true, nullable: true, onDelete: 'CASCADE')]
+    protected ?SimulationSession $simulationSession;
+
     public function getId(): int
     {
         return $this->id;
@@ -47,4 +52,16 @@ class Token
 
         return $this;
     }
+
+    public function getSimulationSession(): ?SimulationSession
+    {
+        return $this->simulationSession;
+    }
+
+    public function setSimulationSession(?SimulationSession $simulationSession): self
+    {
+        $this->simulationSession = $simulationSession;
+
+        return $this;
+    }
 }

+ 2 - 2
src/Entity/Traits/ActivityYearTrait.php

@@ -11,10 +11,10 @@ use Doctrine\ORM\Mapping as ORM;
  */
 trait ActivityYearTrait
 {
-    #[ORM\Column(type: "smallint", nullable: true)]
+    #[ORM\Column(type: 'smallint', nullable: true)]
     private ?int $startYear = null;
 
-    #[ORM\Column(type: "smallint", nullable: true)]
+    #[ORM\Column(type: 'smallint', nullable: true)]
     private ?int $endYear = null;
 
     public function getStartYear(): ?int

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff