浏览代码

Merge branch 'release/2.4.4'

Vincent 7 月之前
父节点
当前提交
298c979778
共有 100 个文件被更改,包括 4900 次插入564 次删除
  1. 1 0
      .gitignore
  2. 3 1
      composer.json
  3. 2 0
      config/opentalent/products.yaml
  4. 1 1
      phpstan.neon.dist
  5. 二进制
      public/fonts/CaviarDreams/CaviarDreams.ttf
  6. 二进制
      public/fonts/CaviarDreams/CaviarDreams_Bold.ttf
  7. 二进制
      public/fonts/CaviarDreams/CaviarDreams_BoldItalic.ttf
  8. 二进制
      public/fonts/CaviarDreams/CaviarDreams_Italic.ttf
  9. 0 25
      rector.php
  10. 26 0
      sql/schema-extensions/003-view_search_user.sql
  11. 18 0
      src/ApiResources/Dolibarr/DolibarrAccount.php
  12. 88 0
      src/ApiResources/Dolibarr/DolibarrDocDownload.php
  13. 77 0
      src/ApiResources/Dolibarr/DolibarrOrder.php
  14. 62 0
      src/ApiResources/Profile/OrganizationProfile.php
  15. 11 4
      src/Commands/Doctrine/SchemaUpdateCommand.php
  16. 80 0
      src/Commands/Doctrine/SchemaValidateCommand.php
  17. 3 3
      src/Commands/SetupEnvCommand.php
  18. 1 0
      src/Doctrine/Access/CurrentAccessExtension.php
  19. 43 0
      src/Doctrine/Custom/Search/RestrictToOrganizationIdExtension.php
  20. 255 0
      src/Entity/Access/Access.php
  21. 15 0
      src/Entity/Access/AccessCommunication.php
  22. 15 0
      src/Entity/Access/AccessNetworkSetting.php
  23. 15 0
      src/Entity/Access/AccessSocial.php
  24. 25 0
      src/Entity/AccessWish/AccessFamilyWish.php
  25. 81 0
      src/Entity/AccessWish/AccessWish.php
  26. 30 0
      src/Entity/AccessWish/DocumentWish.php
  27. 66 0
      src/Entity/AccessWish/EducationStudentWish.php
  28. 441 0
      src/Entity/Awin/Product.php
  29. 444 0
      src/Entity/Billing/AbstractBillAccounting.php
  30. 16 0
      src/Entity/Billing/AccessBilling.php
  31. 18 0
      src/Entity/Billing/AdvancePayment.php
  32. 74 0
      src/Entity/Billing/Afi.php
  33. 16 0
      src/Entity/Billing/BergerLevrault.php
  34. 2 24
      src/Entity/Billing/Bill.php
  35. 3 0
      src/Entity/Billing/BillAccessDetail.php
  36. 2 288
      src/Entity/Billing/BillAccounting.php
  37. 2 25
      src/Entity/Billing/BillCredit.php
  38. 3 3
      src/Entity/Billing/BillLine.php
  39. 35 3
      src/Entity/Billing/BillPayment.php
  40. 130 0
      src/Entity/Billing/BillSchedule.php
  41. 46 0
      src/Entity/Billing/BillScheduleDate.php
  42. 50 0
      src/Entity/Billing/BillingExportSetting.php
  43. 15 0
      src/Entity/Billing/BillingSetting.php
  44. 15 0
      src/Entity/Billing/BillingSettingRent.php
  45. 16 0
      src/Entity/Billing/Ciril.php
  46. 72 0
      src/Entity/Billing/CirilCivil.php
  47. 105 0
      src/Entity/Billing/FamilyQuotientBand.php
  48. 89 0
      src/Entity/Billing/FamilyQuotientBandDetail.php
  49. 103 0
      src/Entity/Billing/FamilyQuotientModel.php
  50. 16 0
      src/Entity/Billing/Jvs.php
  51. 74 0
      src/Entity/Billing/Odyssee.php
  52. 30 0
      src/Entity/Billing/PayboxPaymentReturn.php
  53. 16 0
      src/Entity/Billing/Pes.php
  54. 16 0
      src/Entity/Billing/PesSetting.php
  55. 46 0
      src/Entity/Billing/SddBank.php
  56. 62 0
      src/Entity/Billing/SddRegie.php
  57. 90 1
      src/Entity/Booking/AbstractBooking.php
  58. 32 0
      src/Entity/Booking/CalendarSynchro.php
  59. 43 16
      src/Entity/Booking/Course.php
  60. 1 1
      src/Entity/Booking/CourseRecur.php
  61. 36 19
      src/Entity/Booking/EducationalProject.php
  62. 1 1
      src/Entity/Booking/EducationalProjectRecur.php
  63. 32 18
      src/Entity/Booking/Event.php
  64. 1 1
      src/Entity/Booking/EventRecur.php
  65. 17 14
      src/Entity/Booking/Examen.php
  66. 1 1
      src/Entity/Booking/ExamenRecur.php
  67. 5 1
      src/Entity/Booking/OrganizationHoliday.php
  68. 1 1
      src/Entity/Booking/OrganizationHolidayRecur.php
  69. 22 1
      src/Entity/Booking/PersonHoliday.php
  70. 1 1
      src/Entity/Booking/PersonHolidayRecur.php
  71. 46 0
      src/Entity/Core/AbstractControl.php
  72. 34 0
      src/Entity/Core/AbstractRepair.php
  73. 33 5
      src/Entity/Core/AddressPostal.php
  74. 16 0
      src/Entity/Core/City.php
  75. 5 5
      src/Entity/Core/ContactPoint.php
  76. 16 0
      src/Entity/Core/Department.php
  77. 45 0
      src/Entity/Core/File.php
  78. 120 0
      src/Entity/Core/LoginLog.php
  79. 16 0
      src/Entity/Core/Region.php
  80. 182 10
      src/Entity/Core/Tagg.php
  81. 142 0
      src/Entity/Custom/Search/UserSearchItem.php
  82. 28 0
      src/Entity/Education/Cycle.php
  83. 29 0
      src/Entity/Education/Education.php
  84. 34 0
      src/Entity/Education/EducationComplement.php
  85. 217 0
      src/Entity/Education/EducationCurriculum.php
  86. 200 0
      src/Entity/Education/EducationCurriculumPack.php
  87. 17 0
      src/Entity/Education/EducationStudent.php
  88. 68 0
      src/Entity/Message/AbstractMessage.php
  89. 1 31
      src/Entity/Message/Email.php
  90. 1 31
      src/Entity/Message/Mail.php
  91. 79 0
      src/Entity/Message/ReportMessage.php
  92. 1 0
      src/Entity/Message/Sms.php
  93. 16 0
      src/Entity/Network/Network.php
  94. 15 0
      src/Entity/Organization/Activity.php
  95. 15 0
      src/Entity/Organization/CotisationByYear.php
  96. 15 0
      src/Entity/Organization/CotisationStaffInfos.php
  97. 17 0
      src/Entity/Organization/OnlineRegistrationDocument.php
  98. 45 0
      src/Entity/Organization/OnlineRegistrationSettings.php
  99. 287 27
      src/Entity/Organization/Organization.php
  100. 2 2
      src/Entity/Organization/Parameters.php

+ 1 - 0
.gitignore

@@ -63,3 +63,4 @@ opentalent_test.sql
 ###< fake database for applications tests ###
 
 .php-cs-fixer.cache
+/schema_validation_snippets/

+ 3 - 1
composer.json

@@ -34,7 +34,9 @@
     "lorenzo/pinky": "^1.0",
     "myclabs/php-enum": "^1.7",
     "nelmio/cors-bundle": "^2.1",
+    "nette/php-generator": "^4.1",
     "odolbeau/phone-number-bundle": "^3.1",
+    "olinox14/path-php": "^0.1.8",
     "opentalent/phpdocx": "dev-master",
     "phpdocumentor/reflection-docblock": "^5.2",
     "phpstan/phpdoc-parser": "^1.0",
@@ -87,7 +89,7 @@
     "phpstan/phpstan-phpunit": "^1.3",
     "phpstan/phpstan-symfony": "^1.3",
     "phpunit/phpunit": "^9.6",
-    "rector/rector": "^0.15.13",
+    "rector/rector": "^1.2",
     "symfony/browser-kit": "6.3.*",
     "symfony/css-selector": "6.3.*",
     "symfony/debug-bundle": "6.3.*",

+ 2 - 0
config/opentalent/products.yaml

@@ -18,6 +18,8 @@ parameters:
           - LicenceCmfOrganizationER
           - UploadRequest
           - SubdomainAvailability
+          - UserSearchItem
+          - DolibarrDocDownload
         roles:
           - ROLE_IMPORT
           - ROLE_TAGG

+ 1 - 1
phpstan.neon.dist

@@ -9,5 +9,5 @@ parameters:
     # 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.#'
-        - identifier: 'missingType.generics'
+        - identifier: missingType.generics
 

二进制
public/fonts/CaviarDreams/CaviarDreams.ttf


二进制
public/fonts/CaviarDreams/CaviarDreams_Bold.ttf


二进制
public/fonts/CaviarDreams/CaviarDreams_BoldItalic.ttf


二进制
public/fonts/CaviarDreams/CaviarDreams_Italic.ttf


+ 0 - 25
rector.php

@@ -1,25 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector;
-use Rector\Config\RectorConfig;
-use \Rector\Symfony\Set\SymfonySetList;
-
-return static function (RectorConfig $rectorConfig): void {
-    $rectorConfig->paths([
-        __DIR__ . '/config',
-        __DIR__ . '/public',
-        __DIR__ . '/src',
-    ]);
-
-    // register a single rule
-    $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class);
-    $rectorConfig->symfonyContainerXml(__DIR__ . '/var/cache/docker/App_KernelDockerDebugContainer.xml');
-
-    $rectorConfig->sets([
-        \Rector\Symfony\Set\SymfonyLevelSetList::UP_TO_SYMFONY_60,
-        SymfonySetList::SYMFONY_CODE_QUALITY,
-        SymfonySetList::SYMFONY_CONSTRUCTOR_INJECTION,
-    ]);
-};

+ 26 - 0
sql/schema-extensions/003-view_search_user.sql

@@ -0,0 +1,26 @@
+CREATE OR REPLACE VIEW view_search_user AS
+    SELECT
+        a.id,
+        a.organization_id as organizationId,
+        p.id AS personId,
+        p.username,
+        p.name,
+        p.givenName,
+        CASE
+            WHEN p.givenName IS NOT NULL AND p.name IS NOT NULL
+                AND p.givenName <> '' AND p.name <> ''
+                THEN CONCAT(p.name, ' ', p.givenName)
+            WHEN p.givenName IS NOT NULL AND p.givenName <> ''
+                THEN p.givenName
+            WHEN p.name IS NOT NULL AND p.name <> ''
+                THEN p.name
+            ELSE ''
+        END AS fullName
+    FROM
+        opentalent.Access a
+            INNER JOIN
+        opentalent.Person p
+        ON
+            a.person_id = p.id
+    WHERE adminAccess IS FALSE;
+

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

@@ -63,6 +63,13 @@ class DolibarrAccount implements ApiResourcesInterface
     #[Groups('dolibarr_get')]
     private ?DolibarrContract $contract = null;
 
+    /**
+     * Last order of the society.
+     * @var DolibarrOrder|null
+     */
+    #[Groups('dolibarr_get')]
+    private ?DolibarrOrder $order = null;
+
     /**
      * Last bills.
      */
@@ -135,6 +142,17 @@ class DolibarrAccount implements ApiResourcesInterface
         return $this;
     }
 
+    public function getOrder(): ?DolibarrOrder
+    {
+        return $this->order;
+    }
+
+    public function setOrder(?DolibarrOrder $order): self
+    {
+        $this->order = $order;
+        return $this;
+    }
+
     public function getBills(): Collection
     {
         return $this->bills;

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

@@ -0,0 +1,88 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\ApiResources\Dolibarr;
+
+use ApiPlatform\Metadata\ApiProperty;
+use ApiPlatform\Metadata\ApiResource;
+use ApiPlatform\Metadata\Get;
+use App\Enum\Dolibarr\DolibarrDocTypeEnum;
+use App\State\Provider\Dolibarr\DolibarrDocDownloadProvider;
+use Symfony\Component\Validator\Constraints as Assert;
+
+/**
+ * Demande de téléchargement d'un fichier depuis Dolibarr (facture, bon de commande, etc).
+ */
+#[ApiResource(
+    operations: [
+        new Get(
+            uriTemplate: '/dolibarr/download/{dolibarrDocType}/{ref}',
+            requirements: [
+                'ref' => '[\w-]+',
+            ],
+            security: '(is_granted("ROLE_ADMIN_CORE") or 
+                            is_granted("ROLE_ADMINISTRATIF_MANAGER_CORE") or 
+                            is_granted("ROLE_PEDAGOGICS_MANAGER_CORE") or 
+                            is_granted("ROLE_FINANCIAL_MANAGER_CORE"))',
+            provider: DolibarrDocDownloadProvider::class
+        ),
+    ]
+)]
+class DolibarrDocDownload
+{
+    /**
+     * Id 'bidon' ajouté par défaut pour permettre la construction
+     * de l'IRI par api platform.
+     */
+    #[ApiProperty(identifier: true)]
+    protected int $id = 0;
+
+    /**
+     * Type de fichier à télécharger.
+     */
+    #[Assert\Type(type: DolibarrDocTypeEnum::class)]
+    protected DolibarrDocTypeEnum $dolibarrDocType;
+
+    /**
+     * The dolibarr reference of the document (ex: CO2502-0380, FA2101-02988, ...)
+     * Must be URL Encoded.
+     */
+    protected string $ref;
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): self
+    {
+        $this->id = $id;
+
+        return $this;
+    }
+
+    public function getDolibarrDocType(): DolibarrDocTypeEnum
+    {
+        return $this->dolibarrDocType;
+    }
+
+    public function setDolibarrDocType(DolibarrDocTypeEnum $dolibarrDocType): self
+    {
+        $this->dolibarrDocType = $dolibarrDocType;
+
+        return $this;
+    }
+
+    public function getRef(): string
+    {
+        return $this->ref;
+    }
+
+    public function setRef(string $ref): self
+    {
+        $this->ref = $ref;
+
+        return $this;
+    }
+}

+ 77 - 0
src/ApiResources/Dolibarr/DolibarrOrder.php

@@ -0,0 +1,77 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\ApiResources\Dolibarr;
+
+use ApiPlatform\Metadata\ApiProperty;
+use ApiPlatform\Metadata\ApiResource;
+use ApiPlatform\Metadata\Get;
+use App\ApiResources\ApiResourcesInterface;
+use Symfony\Component\Serializer\Annotation\Groups;
+
+/**
+ * Order of a society, retrieved from dolibarr.
+ */
+#[ApiResource(
+    operations: [
+        new Get(),
+    ]
+)]
+class DolibarrOrder implements ApiResourcesInterface
+{
+    /**
+     * Id of the dolibarr bill ( = invoice).
+     */
+    #[ApiProperty(identifier: true)]
+    #[Groups('dolibarr_get')]
+    private int $id;
+
+    /**
+     * Bill reference.
+     */
+    #[Groups('dolibarr_get')]
+    private string $ref;
+
+    /**
+     * Date of the bill.
+     */
+    #[Groups('dolibarr_get')]
+    private \DateTime $date;
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): self
+    {
+        $this->id = $id;
+
+        return $this;
+    }
+
+    public function getRef(): string
+    {
+        return $this->ref;
+    }
+
+    public function setRef(string $ref): self
+    {
+        $this->ref = $ref;
+
+        return $this;
+    }
+
+    public function getDate(): \DateTime
+    {
+        return $this->date;
+    }
+
+    public function setDate(\DateTime $date): self
+    {
+        $this->date = $date;
+
+        return $this;
+    }
+}

+ 62 - 0
src/ApiResources/Profile/OrganizationProfile.php

@@ -9,6 +9,7 @@ use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Metadata\Get;
 use App\ApiResources\ApiResourcesInterface;
 use App\Enum\Organization\LegalEnum;
+use App\Enum\Organization\PrincipalTypeEnum;
 use App\Enum\Organization\SettingsProductEnum;
 use Symfony\Component\Serializer\Annotation\Groups;
 use Symfony\Component\Validator\Constraints as Assert;
@@ -65,6 +66,19 @@ class OrganizationProfile implements ApiResourcesInterface
     #[Groups('access_profile_read')]
     private ?int $parametersId = null;
 
+    #[Groups('access_profile_read')]
+    #[Assert\Type(type: PrincipalTypeEnum::class)]
+    private ?PrincipalTypeEnum $principalType = null;
+
+    #[Groups('access_profile_read')]
+    private ?bool $trialActive = false;
+
+    #[Groups('access_profile_read')]
+    private ?int $trialCountDown = null;
+
+    #[Groups('access_profile_read')]
+    private ?SettingsProductEnum $productBeforeTrial = null;
+
     public function getId(): ?int
     {
         return $this->id;
@@ -224,4 +238,52 @@ class OrganizationProfile implements ApiResourcesInterface
 
         return $this;
     }
+
+    public function getPrincipalType(): ?PrincipalTypeEnum
+    {
+        return $this->principalType;
+    }
+
+    public function setPrincipalType(?PrincipalTypeEnum $principalType): self
+    {
+        $this->principalType = $principalType;
+
+        return $this;
+    }
+
+    public function isTrialActive(): bool
+    {
+        return $this->trialActive;
+    }
+
+    public function setTrialActive(?bool $trialActive): self
+    {
+        $this->trialActive = $trialActive ?? false;
+
+        return $this;
+    }
+
+    public function getTrialCountDown(): ?int
+    {
+        return $this->trialCountDown;
+    }
+
+    public function setTrialCountDown(?int $trialCountDown): self
+    {
+        $this->trialCountDown = $trialCountDown;
+
+        return $this;
+    }
+
+    public function getProductBeforeTrial(): ?SettingsProductEnum
+    {
+        return $this->productBeforeTrial;
+    }
+
+    public function setProductBeforeTrial(?SettingsProductEnum $productBeforeTrial): self
+    {
+        $this->productBeforeTrial = $productBeforeTrial;
+
+        return $this;
+    }
 }

+ 11 - 4
src/Commands/Doctrine/SchemaUpdateCommand.php

@@ -4,7 +4,8 @@
 
 namespace App\Commands\Doctrine;
 
-use App\Service\Utils\Path;
+use App\Service\Utils\FileUtils;
+use App\Service\Utils\PathUtils;
 use Doctrine\Bundle\DoctrineBundle\Command\Proxy\UpdateSchemaDoctrineCommand;
 use Doctrine\ORM\Tools\SchemaTool;
 use Symfony\Component\Console\Input\InputInterface;
@@ -16,13 +17,19 @@ use Symfony\Component\Console\Style\SymfonyStyle;
  */
 class SchemaUpdateCommand extends UpdateSchemaDoctrineCommand
 {
+    public function __construct(
+        private readonly FileUtils $fileUtils,
+    ) {
+        parent::__construct();
+    }
+
     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 = Path::join(Path::getProjectDir(), 'sql', 'schema-extensions');
-        $scripts = Path::list($schemaExtensionsDir, '*.sql');
+        $schemaExtensionsDir = PathUtils::join(PathUtils::getProjectDir(), 'sql', 'schema-extensions');
+        $scripts = $this->fileUtils->list($schemaExtensionsDir, '*.sql');
         sort($scripts);
 
         // Execute those scripts in alphabetical order
@@ -30,7 +37,7 @@ class SchemaUpdateCommand extends UpdateSchemaDoctrineCommand
         $conn = $em->getConnection();
 
         foreach ($scripts as $script) {
-            $sql = Path::read($script);
+            $sql = $this->fileUtils->getFileContent($script);
             $conn->executeQuery($sql);
         }
 

+ 80 - 0
src/Commands/Doctrine/SchemaValidateCommand.php

@@ -0,0 +1,80 @@
+<?php
+
+/** @noinspection PhpUnused */
+
+namespace App\Commands\Doctrine;
+
+use App\Service\Doctrine\SchemaValidation\DiffTypeEnum;
+use App\Service\Doctrine\SchemaValidation\SchemaSnippetsMaker;
+use App\Service\Doctrine\SchemaValidation\SchemaValidationService;
+use Symfony\Component\Console\Attribute\AsCommand;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+/**
+ * Valide le schéma Doctrine en le comparant à la V1.
+ *
+ * @see https://ressources-opentalent.atlassian.net/wiki/spaces/DEV/pages/240551231/V+rifier+le+sch+ma+Doctrine+de+la+V2+et+g+n+rer+les+entit+s+et+propri+t+s+manquantes
+ */
+#[AsCommand(
+    name: 'ot:schema:validate',
+    description: 'Compare le schema doctrine de la V2 à celui de la V1'
+)]
+class SchemaValidateCommand extends Command
+{
+    public function __construct(
+        private readonly SchemaValidationService $schemaValidationService,
+        private readonly SchemaSnippetsMaker $schemaSnippetsMaker,
+    ) {
+        parent::__construct();
+    }
+
+    /**
+     * Configures the command.
+     */
+    protected function configure(): void
+    {
+        $this->addOption(
+            'filter',
+            null,
+            InputOption::VALUE_OPTIONAL,
+            "Filter the type of difference to display (ex: 'MISSING_PROPERTY')."
+        );
+        $this->addOption(
+            'snippets',
+            null,
+            InputOption::VALUE_NONE,
+            'Make snippets of the missing classes and fields'
+        );
+    }
+
+    protected function execute(InputInterface $input, OutputInterface $output): int
+    {
+        $filter = $input->getOption('filter') ? DiffTypeEnum::from($input->getOption('filter')) : null;
+
+        $diff = $this->schemaValidationService->validateSchema($filter);
+
+        $csv = $this->schemaValidationService->formatToCsv($diff);
+
+        if (empty($csv)) {
+            $output->writeln('No difference found');
+
+            return 0;
+        }
+
+        foreach ($csv as $line) {
+            $output->writeln($line);
+        }
+
+        $output->writeln(count($csv).' differences found');
+
+        if ($input->getOption('snippets')) {
+            $this->schemaSnippetsMaker->makeSnippets($diff);
+            $output->writeln('Snippets generated');
+        }
+
+        return 0;
+    }
+}

+ 3 - 3
src/Commands/SetupEnvCommand.php

@@ -2,7 +2,7 @@
 
 namespace App\Commands;
 
-use App\Service\Utils\Path;
+use App\Service\Utils\PathUtils;
 use Symfony\Component\Console\Attribute\AsCommand;
 use Symfony\Component\Console\Command\Command;
 use Symfony\Component\Console\Input\InputInterface;
@@ -73,8 +73,8 @@ class SetupEnvCommand extends Command
             throw new \RuntimeException('Critical : unknown environment ['.$hostname.']');
         }
 
-        $envFile = Path::join($this->projectDir, 'env', self::ENVIRONMENTS_FILES[$hostname]);
-        $symlinkLocation = Path::join($this->projectDir, '.env.local');
+        $envFile = PathUtils::join($this->projectDir, 'env', self::ENVIRONMENTS_FILES[$hostname]);
+        $symlinkLocation = PathUtils::join($this->projectDir, '.env.local');
 
         if (file_exists($symlinkLocation)) {
             unlink($symlinkLocation);

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

@@ -7,6 +7,7 @@ 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;

+ 43 - 0
src/Doctrine/Custom/Search/RestrictToOrganizationIdExtension.php

@@ -0,0 +1,43 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Doctrine\Custom\Search;
+
+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;
+
+/**
+ * Filtre de sécurité pour les recherches
+ * Restreint les résultats à ceux de l'organization actuelle.
+ */
+final class RestrictToOrganizationIdExtension extends AbstractExtension
+{
+    public function __construct(
+        private readonly Security $security,
+    ) {}
+
+    public function supports(string $resourceClass, ?Operation $operation): bool
+    {
+        return $resourceClass === UserSearchItem::class;
+    }
+
+    protected function addWhere(QueryBuilder $queryBuilder, string $resourceClass, ?Operation $operation): void
+    {
+        /** @var Access $currentUser */
+        $currentUser = $this->security->getUser();
+        if ($currentUser === null || $currentUser->getOrganization() === null) {
+            return;
+        }
+        $rootAlias = $queryBuilder->getRootAliases()[0];
+        $queryBuilder
+            ->andWhere(sprintf('%s.organizationId = :organizationId', $rootAlias))
+            ->setParameter('organizationId', $currentUser->getOrganization()->getId())
+        ;
+    }
+}

+ 255 - 0
src/Entity/Access/Access.php

@@ -13,12 +13,15 @@ use App\Entity\Billing\AccessBilling;
 use App\Entity\Billing\AccessFictionalIntangible;
 use App\Entity\Billing\AccessIntangible;
 use App\Entity\Billing\AccessPayer;
+use App\Entity\Billing\AdvancePayment;
 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;
 use App\Entity\Booking\Course;
 use App\Entity\Booking\EducationalProject;
 use App\Entity\Booking\Event;
@@ -26,6 +29,7 @@ use App\Entity\Booking\EventUser;
 use App\Entity\Booking\ExamenConvocation;
 use App\Entity\Booking\PersonHoliday;
 use App\Entity\Booking\WorkByUser;
+use App\Entity\Core\AbstractControl;
 use App\Entity\Core\Notification;
 use App\Entity\Core\NotificationUser;
 use App\Entity\Core\Tagg;
@@ -33,6 +37,7 @@ use App\Entity\Donor\Donor;
 use App\Entity\Education\EducationNotationConfig;
 use App\Entity\Education\EducationStudent;
 use App\Entity\Education\EducationTeacher;
+use App\Entity\Message\AbstractMessage;
 use App\Entity\Message\Email;
 use App\Entity\Message\Mail;
 use App\Entity\Message\Sms;
@@ -51,6 +56,7 @@ use App\Entity\Product\EquipmentLoan;
 use App\Entity\Product\EquipmentRepair;
 use App\Entity\Reward\AccessReward;
 use App\Entity\Traits\CreatedOnAndByTrait;
+use App\Entity\Token\Token;
 use App\Filter\ApiPlatform\Person\FullNameFilter;
 use App\Filter\ApiPlatform\Utils\InFilter;
 use App\Repository\Access\AccessRepository;
@@ -306,6 +312,39 @@ class Access implements UserInterface, PasswordAuthenticatedUserInterface
     #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
     private Collection $tags;
 
+    #[ORM\ManyToMany(mappedBy: 'organizer', targetEntity: AbstractBooking::class, cascade: ['persist'], orphanRemoval: false)]
+    private Collection $bookingOrganizers;
+
+    #[ORM\OneToMany(mappedBy: 'access', targetEntity: AdvancePayment::class, cascade: [], orphanRemoval: true)]
+    private Collection $advancePayments;
+
+    #[ORM\OneToMany(mappedBy: 'author', targetEntity: AbstractMessage::class, cascade: [], orphanRemoval: true)]
+    private Collection $messages;
+
+    #[ORM\OneToMany(mappedBy: 'managerControl', targetEntity: Equipment::class, cascade: [], orphanRemoval: false)]
+    private Collection $equipmentManagerControls;
+
+    #[ORM\OneToMany(mappedBy: 'accompanist', targetEntity: AbstractControl::class, cascade: [], orphanRemoval: true)]
+    private Collection $accompanistControl;
+
+    #[ORM\OneToMany(mappedBy: 'access', targetEntity: AccessReward::class, cascade: ['persist'], orphanRemoval: true)]
+    private Collection $rewards;
+
+    #[ORM\OneToOne(mappedBy: 'access', targetEntity: AccessSocial::class, cascade: ['persist'], orphanRemoval: true)]
+    private AccessSocial $accessSocial;
+
+    #[ORM\OneToOne(mappedBy: 'access', targetEntity: AccessNetworkSetting::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
+    private AccessNetworkSetting $accessNetworkSetting;
+
+    #[ORM\OneToOne(mappedBy: 'access', targetEntity: AccessCommunication::class, cascade: ['persist'], orphanRemoval: true)]
+    private AccessCommunication $accessCommunication;
+
+    #[ORM\OneToOne(mappedBy: 'access', targetEntity: CalendarSynchro::class, cascade: ['persist'], orphanRemoval: true)]
+    private CalendarSynchro $calendarSynchro;
+
+    #[ORM\OneToMany(mappedBy: 'access', targetEntity: Token::class, cascade: ['persist'], orphanRemoval: true)]
+    private Collection $tokens;
+
     #[ORM\OneToOne(mappedBy: 'access', cascade: ['persist'], fetch: 'EAGER', orphanRemoval: true)]
     private ?Preferences $preferences;
 
@@ -2160,6 +2199,222 @@ 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 getAdvancePayments(): Collection
+    {
+        return $this->advancePayments;
+    }
+
+    public function addAdvancePayment(AdvancePayment $advancePayment): self
+    {
+        if (!$this->advancePayments->contains($advancePayment)) {
+            $this->advancePayments[] = $advancePayment;
+            $advancePayment->setAccess($this);
+        }
+
+        return $this;
+    }
+
+    public function removeAdvancePayment(AdvancePayment $advancePayment): self
+    {
+        if ($this->advancePayments->removeElement($advancePayment)) {
+            $advancePayment->setAccess(null);
+        }
+
+        return $this;
+    }
+
+    public function getMessages(): Collection
+    {
+        return $this->messages;
+    }
+
+    public function addMessage(mixed $message): self
+    {
+        if (!$this->messages->contains($message)) {
+            $this->messages[] = $message;
+            $message->setAuthor($this);
+        }
+
+        return $this;
+    }
+
+    public function removeMessage(mixed $message): self
+    {
+        if ($this->messages->removeElement($message)) {
+            $message->setAuthor(null);
+        }
+
+        return $this;
+    }
+
+    public function getEquipmentManagerControls(): Collection
+    {
+        return $this->equipmentManagerControls;
+    }
+
+    public function addEquipmentManagerControl(Equipment $equipmentManagerControl): self
+    {
+        if (!$this->equipmentManagerControls->contains($equipmentManagerControl)) {
+            $this->equipmentManagerControls[] = $equipmentManagerControl;
+            $equipmentManagerControl->setManagerControl($this);
+        }
+
+        return $this;
+    }
+
+    public function removeEquipmentManagerControl(Equipment $equipmentManagerControl): self
+    {
+        if ($this->equipmentManagerControls->removeElement($equipmentManagerControl)) {
+            $equipmentManagerControl->setManagerControl(null);
+        }
+
+        return $this;
+    }
+
+    public function getAccompanistControl(): Collection
+    {
+        return $this->accompanistControl;
+    }
+
+    public function addAccompanistControl(AbstractControl $accompanistControl): self
+    {
+        if (!$this->accompanistControl->contains($accompanistControl)) {
+            $this->accompanistControl[] = $accompanistControl;
+            $accompanistControl->setAccompanist($this);
+        }
+
+        return $this;
+    }
+
+    public function removeAccompanistControl(AbstractControl $accompanistControl): self
+    {
+        if ($this->accompanistControl->removeElement($accompanistControl)) {
+            //            $accompanistControl->setAccompanist(null);  // TODO: actuellement, pas nullable: conserver?
+        }
+
+        return $this;
+    }
+
+    public function getRewards(): Collection
+    {
+        return $this->rewards;
+    }
+
+    public function addReward(AccessReward $reward): self
+    {
+        if (!$this->rewards->contains($reward)) {
+            $this->rewards[] = $reward;
+            $reward->setAccess($this);
+        }
+
+        return $this;
+    }
+
+    public function removeReward(AccessReward $reward): self
+    {
+        if ($this->rewards->removeElement($reward)) {
+            $reward->setAccess(null);
+        }
+
+        return $this;
+    }
+
+    public function getAccessSocial(): AccessSocial
+    {
+        return $this->accessSocial;
+    }
+
+    public function setAccessSocial(AccessSocial $accessSocial): self
+    {
+        $this->accessSocial = $accessSocial;
+
+        return $this;
+    }
+
+    public function getAccessNetworkSetting(): AccessNetworkSetting
+    {
+        return $this->accessNetworkSetting;
+    }
+
+    public function setAccessNetworkSetting(AccessNetworkSetting $accessNetworkSetting): self
+    {
+        $this->accessNetworkSetting = $accessNetworkSetting;
+
+        return $this;
+    }
+
+    public function getAccessCommunication(): AccessCommunication
+    {
+        return $this->accessCommunication;
+    }
+
+    public function setAccessCommunication(AccessCommunication $accessCommunication): self
+    {
+        $this->accessCommunication = $accessCommunication;
+
+        return $this;
+    }
+
+    public function getCalendarSynchro(): CalendarSynchro
+    {
+        return $this->calendarSynchro;
+    }
+
+    public function setCalendarSynchro(CalendarSynchro $calendarSynchro): self
+    {
+        $this->calendarSynchro = $calendarSynchro;
+
+        return $this;
+    }
+
+    public function getTokens(): Collection
+    {
+        return $this->tokens;
+    }
+
+    public function addToken(Token $token): self
+    {
+        if (!$this->tokens->contains($token)) {
+            $this->tokens[] = $token;
+            $token->setAccess($this);
+        }
+
+        return $this;
+    }
+
+    public function removeToken(Token $token): self
+    {
+        if ($this->tokens->removeElement($token)) {
+            //            $token->setAccess(null);  // TODO: actuellement, pas nullable: conserver?
+        }
+
+        return $this;
+    }
+
     public function setPreferences(?Preferences $preferences = null): self
     {
         if (!is_null($preferences)) {

+ 15 - 0
src/Entity/Access/AccessCommunication.php

@@ -19,8 +19,23 @@ class AccessCommunication
     #[ORM\GeneratedValue]
     private ?int $id = null;
 
+    #[ORM\OneToOne(inversedBy: 'accessCommunication', targetEntity: Access::class, cascade: ['persist'])]
+    protected Access $access;
+
     public function getId(): ?int
     {
         return $this->id;
     }
+
+    public function getAccess(): Access
+    {
+        return $this->access;
+    }
+
+    public function setAccess(Access $access): self
+    {
+        $this->access = $access;
+
+        return $this;
+    }
 }

+ 15 - 0
src/Entity/Access/AccessNetworkSetting.php

@@ -19,8 +19,23 @@ class AccessNetworkSetting
     #[ORM\GeneratedValue]
     private ?int $id = null;
 
+    #[ORM\OneToOne(inversedBy: 'accessNetworkSetting', targetEntity: Access::class, cascade: ['persist'])]
+    protected Access $access;
+
     public function getId(): ?int
     {
         return $this->id;
     }
+
+    public function getAccess(): Access
+    {
+        return $this->access;
+    }
+
+    public function setAccess(Access $access): self
+    {
+        $this->access = $access;
+
+        return $this;
+    }
 }

+ 15 - 0
src/Entity/Access/AccessSocial.php

@@ -19,8 +19,23 @@ class AccessSocial
     #[ORM\GeneratedValue]
     private ?int $id = null;
 
+    #[ORM\OneToOne(inversedBy: 'accessSocial', targetEntity: Access::class, cascade: ['persist'])]
+    protected Access $access;
+
     public function getId(): ?int
     {
         return $this->id;
     }
+
+    public function getAccess(): Access
+    {
+        return $this->access;
+    }
+
+    public function setAccess(Access $access): self
+    {
+        $this->access = $access;
+
+        return $this;
+    }
 }

+ 25 - 0
src/Entity/AccessWish/AccessFamilyWish.php

@@ -36,9 +36,13 @@ class AccessFamilyWish
     #[ORM\Column]
     private bool $closeRegistration = false;
 
+    #[ORM\OneToMany(mappedBy: 'accessFamilyWish', targetEntity: AccessWish::class, cascade: ['remove'], orphanRemoval: false)]
+    protected Collection $accessWishesGuardians;
+
     public function __construct()
     {
         $this->accessWishes = new ArrayCollection();
+        $this->accessWishesGuardians = new ArrayCollection();
     }
 
     public function getId(): ?int
@@ -105,4 +109,25 @@ class AccessFamilyWish
     {
         $this->closeRegistration = $closeRegistration;
     }
+
+    public function getAccessWishesGuardians(): Collection
+    {
+        return $this->accessWishesGuardians;
+    }
+
+    public function addAccessWishesGuardian(AccessWish $accessWishesGuardian): self
+    {
+        if (!$this->accessWishesGuardians->contains($accessWishesGuardian)) {
+            $this->accessWishesGuardians[] = $accessWishesGuardian;
+        }
+
+        return $this;
+    }
+
+    public function removeAccessWishesGuardian(AccessWish $accessWishesGuardian): self
+    {
+        $this->accessWishesGuardians->removeElement($accessWishesGuardian);
+
+        return $this;
+    }
 }

+ 81 - 0
src/Entity/AccessWish/AccessWish.php

@@ -6,11 +6,14 @@ namespace App\Entity\AccessWish;
 
 use ApiPlatform\Metadata\ApiResource;
 use App\Entity\Access\Access;
+use App\Entity\Billing\BillSchedule;
 use App\Entity\Core\Country;
 use App\Entity\Core\File;
 use App\Entity\Core\Tagg;
+use App\Entity\Education\EducationCurriculumPack;
 use App\Entity\Organization\Organization;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
+use App\Entity\Place\Place;
 use App\Enum\OnlineRegistration\ValidationStateEnum;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
@@ -65,6 +68,24 @@ class AccessWish
     #[ORM\Column(length: 50, enumType: ValidationStateEnum::class)]
     private ValidationStateEnum $validationState;
 
+    #[ORM\ManyToOne(targetEntity: BillSchedule::class, cascade: ['persist'], inversedBy: 'accessWishes')]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
+    protected BillSchedule $billSchedule;
+
+    #[ORM\OneToOne(mappedBy: 'accessWishRib', targetEntity: DocumentWish::class, cascade: ['persist'])]
+    protected DocumentWish $documentRib;
+
+    #[ORM\OneToOne(mappedBy: 'accessWishSepa', targetEntity: DocumentWish::class, cascade: ['persist'])]
+    protected DocumentWish $documentSepa;
+
+    #[ORM\ManyToOne(targetEntity: EducationCurriculumPack::class, cascade: [])]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
+    protected EducationCurriculumPack $wishPack;
+
+    #[ORM\ManyToOne(targetEntity: Place::class, cascade: [])]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
+    protected Place $favoritePlace;
+
     /**
      * Date de création dde l'entité.
      *
@@ -297,4 +318,64 @@ class AccessWish
     {
         $this->validationState = $validationState;
     }
+
+    public function getBillSchedule(): BillSchedule
+    {
+        return $this->billSchedule;
+    }
+
+    public function setBillSchedule(BillSchedule $billSchedule): self
+    {
+        $this->billSchedule = $billSchedule;
+
+        return $this;
+    }
+
+    public function getDocumentRib(): DocumentWish
+    {
+        return $this->documentRib;
+    }
+
+    public function setDocumentRib(DocumentWish $documentRib): self
+    {
+        $this->documentRib = $documentRib;
+
+        return $this;
+    }
+
+    public function getDocumentSepa(): DocumentWish
+    {
+        return $this->documentSepa;
+    }
+
+    public function setDocumentSepa(DocumentWish $documentSepa): self
+    {
+        $this->documentSepa = $documentSepa;
+
+        return $this;
+    }
+
+    public function getWishPack(): EducationCurriculumPack
+    {
+        return $this->wishPack;
+    }
+
+    public function setWishPack(EducationCurriculumPack $wishPack): self
+    {
+        $this->wishPack = $wishPack;
+
+        return $this;
+    }
+
+    public function getFavoritePlace(): Place
+    {
+        return $this->favoritePlace;
+    }
+
+    public function setFavoritePlace(Place $favoritePlace): self
+    {
+        $this->favoritePlace = $favoritePlace;
+
+        return $this;
+    }
 }

+ 30 - 0
src/Entity/AccessWish/DocumentWish.php

@@ -34,6 +34,12 @@ class DocumentWish
     #[ORM\OneToMany(mappedBy: 'documentWish', targetEntity: File::class, orphanRemoval: true)]
     private Collection $files;
 
+    #[ORM\OneToOne(inversedBy: 'documentRib', targetEntity: AccessWish::class, cascade: [])]
+    protected AccessWish $accessWishRib;
+
+    #[ORM\OneToOne(inversedBy: 'documentSepa', targetEntity: AccessWish::class, cascade: [])]
+    protected AccessWish $accessWishSepa;
+
     public function __construct()
     {
         $this->files = new ArrayCollection();
@@ -97,4 +103,28 @@ class DocumentWish
 
         return $this;
     }
+
+    public function getAccessWishRib(): AccessWish
+    {
+        return $this->accessWishRib;
+    }
+
+    public function setAccessWishRib(AccessWish $accessWishRib): self
+    {
+        $this->accessWishRib = $accessWishRib;
+
+        return $this;
+    }
+
+    public function getAccessWishSepa(): AccessWish
+    {
+        return $this->accessWishSepa;
+    }
+
+    public function setAccessWishSepa(AccessWish $accessWishSepa): self
+    {
+        $this->accessWishSepa = $accessWishSepa;
+
+        return $this;
+    }
 }

+ 66 - 0
src/Entity/AccessWish/EducationStudentWish.php

@@ -4,13 +4,18 @@ declare(strict_types=1);
 
 namespace App\Entity\AccessWish;
 
+use App\Entity\Access\Access;
+use App\Entity\Booking\Course;
 use App\Entity\Education\Education;
 use App\Entity\Education\EducationCurriculum;
 use App\Entity\Education\EducationStudent;
 use App\Entity\Education\EducationTiming;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
+use App\Entity\Product\EquipmentList;
 use App\Enum\OnlineRegistration\RegistrationStatusEnum;
 use App\Enum\OnlineRegistration\WishRegistrationEnum;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
 
 /**
@@ -53,6 +58,22 @@ class EducationStudentWish
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
     private EducationTiming $educationTiming;
 
+    #[ORM\ManyToMany(targetEntity: Access::class, cascade: [], orphanRemoval: false)]
+    protected Collection $teachers;
+
+    #[ORM\ManyToOne(targetEntity: EquipmentList::class, cascade: [])]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
+    protected EquipmentList $speciality;
+
+    #[ORM\ManyToOne(targetEntity: Course::class, cascade: [], inversedBy: 'educationStudentWishes')]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
+    protected Course $course;
+
+    public function __construct()
+    {
+        $this->teachers = new ArrayCollection();
+    }
+
     public function getId(): ?int
     {
         return $this->id;
@@ -149,4 +170,49 @@ class EducationStudentWish
 
         return $this;
     }
+
+    public function getTeachers(): Collection
+    {
+        return $this->teachers;
+    }
+
+    public function addTeacher(Access $teacher): self
+    {
+        if (!$this->teachers->contains($teacher)) {
+            $this->teachers[] = $teacher;
+        }
+
+        return $this;
+    }
+
+    public function removeTeacher(Access $teacher): self
+    {
+        $this->teachers->removeElement($teacher);
+
+        return $this;
+    }
+
+    public function getSpeciality(): EquipmentList
+    {
+        return $this->speciality;
+    }
+
+    public function setSpeciality(EquipmentList $speciality): self
+    {
+        $this->speciality = $speciality;
+
+        return $this;
+    }
+
+    public function getCourse(): Course
+    {
+        return $this->course;
+    }
+
+    public function setCourse(Course $course): self
+    {
+        $this->course = $course;
+
+        return $this;
+    }
 }

+ 441 - 0
src/Entity/Awin/Product.php

@@ -0,0 +1,441 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Awin;
+
+use ApiPlatform\Metadata\ApiResource;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ApiResource(operations: [])]
+#[ORM\Entity]
+#[ORM\Table(name: 'AwinProduct')]
+class Product
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private int $id;
+
+    #[ORM\Column]
+    protected mixed $slug;
+
+    #[ORM\Column]
+    protected mixed $name;
+
+    #[ORM\Column(length: 255, options: ['nullable' => true])]
+    protected string $description;
+
+    #[ORM\Column]
+    protected mixed $categoryCode;
+
+    #[ORM\Column]
+    protected mixed $subCategory;
+
+    /**
+     * @var array<string>
+     */
+    #[ORM\Column(type: 'json', options: ['nullable' => true])]
+    protected array $categories;
+
+    #[ORM\Column]
+    protected mixed $datetimeStart;
+
+    #[ORM\Column]
+    protected mixed $datetimeEnd;
+
+    /**
+     * @var array<string>
+     */
+    #[ORM\Column(type: 'json', options: ['nullable' => true])]
+    protected array $meetingSchedule;
+
+    #[ORM\Column]
+    protected mixed $placeCode;
+
+    #[ORM\Column]
+    protected mixed $place;
+
+    #[ORM\Column]
+    protected mixed $streetAddress;
+
+    #[ORM\Column]
+    protected mixed $postalCode;
+
+    #[ORM\Column]
+    protected mixed $city;
+
+    #[ORM\Column]
+    protected mixed $country;
+
+    #[ORM\Column]
+    protected mixed $latitude;
+
+    #[ORM\Column]
+    protected mixed $longitude;
+
+    #[ORM\Column]
+    protected mixed $mediumimage;
+
+    #[ORM\Column]
+    protected mixed $largeimage;
+
+    #[ORM\Column(length: 255, options: ['nullable' => true])]
+    protected string $deepLink;
+
+    #[ORM\Column]
+    protected mixed $priceMini;
+
+    #[ORM\Column]
+    protected mixed $priceMaxi;
+
+    #[ORM\Column(length: 255, options: ['nullable' => true])]
+    protected string $artists;
+
+    #[ORM\Column(length: 255, options: ['nullable' => true])]
+    protected string $uuid;
+
+    #[ORM\Column(type: 'date', options: ['nullable' => true])]
+    protected ?\DateTimeInterface $createDate;
+
+    #[ORM\Column(type: 'date', options: ['nullable' => true])]
+    protected ?\DateTimeInterface $updateDate;
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): self
+    {
+        $this->id = $id;
+
+        return $this;
+    }
+
+    public function getSlug(): mixed
+    {
+        return $this->slug;
+    }
+
+    public function setSlug(mixed $slug): self
+    {
+        $this->slug = $slug;
+
+        return $this;
+    }
+
+    public function getName(): mixed
+    {
+        return $this->name;
+    }
+
+    public function setName(mixed $name): self
+    {
+        $this->name = $name;
+
+        return $this;
+    }
+
+    public function getDescription(): string
+    {
+        return $this->description;
+    }
+
+    public function setDescription(string $description): self
+    {
+        $this->description = $description;
+
+        return $this;
+    }
+
+    public function getCategoryCode(): mixed
+    {
+        return $this->categoryCode;
+    }
+
+    public function setCategoryCode(mixed $categoryCode): self
+    {
+        $this->categoryCode = $categoryCode;
+
+        return $this;
+    }
+
+    public function getSubCategory(): mixed
+    {
+        return $this->subCategory;
+    }
+
+    public function setSubCategory(mixed $subCategory): self
+    {
+        $this->subCategory = $subCategory;
+
+        return $this;
+    }
+
+    /**
+     * @return string[]
+     */
+    public function getCategories(): array
+    {
+        return $this->categories;
+    }
+
+    /**
+     * @param string[] $categories
+     */
+    public function setCategories(array $categories): self
+    {
+        $this->categories = $categories;
+
+        return $this;
+    }
+
+    public function getDatetimeStart(): mixed
+    {
+        return $this->datetimeStart;
+    }
+
+    public function setDatetimeStart(mixed $datetimeStart): self
+    {
+        $this->datetimeStart = $datetimeStart;
+
+        return $this;
+    }
+
+    public function getDatetimeEnd(): mixed
+    {
+        return $this->datetimeEnd;
+    }
+
+    public function setDatetimeEnd(mixed $datetimeEnd): self
+    {
+        $this->datetimeEnd = $datetimeEnd;
+
+        return $this;
+    }
+
+    /**
+     * @return string[]
+     */
+    public function getMeetingSchedule(): array
+    {
+        return $this->meetingSchedule;
+    }
+
+    /**
+     * @param array<string> $meetingSchedule
+     *
+     * @return $this
+     */
+    public function setMeetingSchedule(array $meetingSchedule): self
+    {
+        $this->meetingSchedule = $meetingSchedule;
+
+        return $this;
+    }
+
+    public function getPlaceCode(): mixed
+    {
+        return $this->placeCode;
+    }
+
+    public function setPlaceCode(mixed $placeCode): self
+    {
+        $this->placeCode = $placeCode;
+
+        return $this;
+    }
+
+    public function getPlace(): mixed
+    {
+        return $this->place;
+    }
+
+    public function setPlace(mixed $place): self
+    {
+        $this->place = $place;
+
+        return $this;
+    }
+
+    public function getStreetAddress(): mixed
+    {
+        return $this->streetAddress;
+    }
+
+    public function setStreetAddress(mixed $streetAddress): self
+    {
+        $this->streetAddress = $streetAddress;
+
+        return $this;
+    }
+
+    public function getPostalCode(): mixed
+    {
+        return $this->postalCode;
+    }
+
+    public function setPostalCode(mixed $postalCode): self
+    {
+        $this->postalCode = $postalCode;
+
+        return $this;
+    }
+
+    public function getCity(): mixed
+    {
+        return $this->city;
+    }
+
+    public function setCity(mixed $city): self
+    {
+        $this->city = $city;
+
+        return $this;
+    }
+
+    public function getCountry(): mixed
+    {
+        return $this->country;
+    }
+
+    public function setCountry(mixed $country): self
+    {
+        $this->country = $country;
+
+        return $this;
+    }
+
+    public function getLatitude(): mixed
+    {
+        return $this->latitude;
+    }
+
+    public function setLatitude(mixed $latitude): self
+    {
+        $this->latitude = $latitude;
+
+        return $this;
+    }
+
+    public function getLongitude(): mixed
+    {
+        return $this->longitude;
+    }
+
+    public function setLongitude(mixed $longitude): self
+    {
+        $this->longitude = $longitude;
+
+        return $this;
+    }
+
+    public function getMediumimage(): mixed
+    {
+        return $this->mediumimage;
+    }
+
+    public function setMediumimage(mixed $mediumimage): self
+    {
+        $this->mediumimage = $mediumimage;
+
+        return $this;
+    }
+
+    public function getLargeimage(): mixed
+    {
+        return $this->largeimage;
+    }
+
+    public function setLargeimage(mixed $largeimage): self
+    {
+        $this->largeimage = $largeimage;
+
+        return $this;
+    }
+
+    public function getDeepLink(): string
+    {
+        return $this->deepLink;
+    }
+
+    public function setDeepLink(string $deepLink): self
+    {
+        $this->deepLink = $deepLink;
+
+        return $this;
+    }
+
+    public function getPriceMini(): mixed
+    {
+        return $this->priceMini;
+    }
+
+    public function setPriceMini(mixed $priceMini): self
+    {
+        $this->priceMini = $priceMini;
+
+        return $this;
+    }
+
+    public function getPriceMaxi(): mixed
+    {
+        return $this->priceMaxi;
+    }
+
+    public function setPriceMaxi(mixed $priceMaxi): self
+    {
+        $this->priceMaxi = $priceMaxi;
+
+        return $this;
+    }
+
+    public function getArtists(): string
+    {
+        return $this->artists;
+    }
+
+    public function setArtists(string $artists): self
+    {
+        $this->artists = $artists;
+
+        return $this;
+    }
+
+    public function getUuid(): string
+    {
+        return $this->uuid;
+    }
+
+    public function setUuid(string $uuid): self
+    {
+        $this->uuid = $uuid;
+
+        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;
+    }
+}

+ 444 - 0
src/Entity/Billing/AbstractBillAccounting.php

@@ -0,0 +1,444 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use App\Entity\Access\Access;
+use App\Entity\Core\File;
+use App\Entity\Core\Tagg;
+use App\Entity\Organization\Organization;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * Facture ou avoir.
+ *
+ * @see Bill, BillCredit, AdvancePayment
+ *
+ * @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]
+abstract class AbstractBillAccounting
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    protected ?int $id = null;
+
+    #[ORM\Column(length: 255, nullable: false)]
+    protected string $discr;
+
+    #[ORM\ManyToOne(targetEntity: Organization::class)]
+    #[ORM\JoinColumn(nullable: true)]
+    protected Organization $organization;
+
+    #[ORM\OneToMany(mappedBy: 'bill', targetEntity: BillLine::class, cascade: ['persist'], orphanRemoval: true)]
+    protected Collection $billLines;
+
+    #[ORM\OneToMany(mappedBy: 'bill', targetEntity: BillCredit::class, cascade: ['persist'], orphanRemoval: true)]
+    protected Collection $billCredits;
+
+    #[ORM\OneToMany(mappedBy: 'bill', targetEntity: BillPayment::class, cascade: ['persist'], orphanRemoval: true)]
+    protected Collection $billPayments;
+
+    #[ORM\ManyToOne(inversedBy: 'billCredits')]
+    #[ORM\JoinColumn(nullable: true)]
+    protected AbstractBillAccounting $bill;
+
+    #[ORM\OneToMany(mappedBy: 'bill', targetEntity: BillingIntangibleExcludeDate::class, cascade: ['persist'], orphanRemoval: true)]
+    protected Collection $billingIntangibleExcludeDates;
+
+    #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'bills')]
+    #[ORM\JoinColumn(nullable: true)]
+    protected Pes $pes;
+
+    #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'bills')]
+    #[ORM\JoinColumn(nullable: true)]
+    protected BergerLevrault $bergerLevrault;
+
+    #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'bills')]
+    #[ORM\JoinColumn(nullable: true)]
+    protected Ciril $ciril;
+
+    #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'bills')]
+    #[ORM\JoinColumn(nullable: true)]
+    protected Jvs $jvs;
+
+    #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'billAccountings', cascade: ['persist'])]
+    #[ORM\JoinTable(name: 'tag_billAccounting')]
+    #[ORM\JoinColumn(name: 'billAccounting_id', referencedColumnName: 'id')]
+    #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
+    protected Collection $tags;
+
+    #[ORM\ManyToOne(targetEntity: Access::class, cascade: [], inversedBy: 'bills')]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: false, onDelete: 'SET NULL')]
+    protected Access $access;
+
+    #[ORM\OneToOne(targetEntity: BillAccessDetail::class, cascade: ['persist'])]
+    protected BillAccessDetail $accessDetail;
+
+    #[ORM\OneToOne(targetEntity: BillPeriod::class, cascade: ['persist'])]
+    protected BillPeriod $billPeriod;
+
+    #[ORM\OneToOne(targetEntity: BillTotalDetail::class, cascade: ['persist'])]
+    protected BillTotalDetail $totalDetail;
+
+    #[ORM\OneToOne(targetEntity: File::class, cascade: ['persist'])]
+    protected File $file;
+
+    #[ORM\ManyToOne(targetEntity: Odyssee::class, inversedBy: 'bills', cascade: ['persist'])]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: false, onDelete: 'SET NULL')]
+    protected Odyssee $odyssee; // TODO: sûr que c'est pas nullable?
+
+    #[ORM\ManyToOne(targetEntity: Afi::class, inversedBy: 'bills', cascade: ['persist'])]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: false, onDelete: 'SET NULL')]
+    protected Afi $afi;
+
+    #[ORM\ManyToOne(targetEntity: CirilCivil::class, inversedBy: 'bills', cascade: ['persist'])]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: false, onDelete: 'SET NULL')]
+    protected CirilCivil $cirilCivil;
+
+    public function __construct()
+    {
+        $this->billLines = new ArrayCollection();
+        $this->billCredits = new ArrayCollection();
+        $this->billPayments = new ArrayCollection();
+        $this->billingIntangibleExcludeDates = new ArrayCollection();
+        $this->tags = new ArrayCollection();
+    }
+
+    public function getId(): ?int
+    {
+        return $this->id;
+    }
+
+    public function getDiscr(): ?string
+    {
+        return $this->discr;
+    }
+
+    public function setDiscr(string $discr): self
+    {
+        $this->discr = $discr;
+
+        return $this;
+    }
+
+    public function getOrganization(): ?Organization
+    {
+        return $this->organization;
+    }
+
+    public function setOrganization(?Organization $organization): self
+    {
+        $this->organization = $organization;
+
+        return $this;
+    }
+
+    /**
+     * @return Collection<int, BillLine>
+     */
+    public function getBillLines(): Collection
+    {
+        return $this->billLines;
+    }
+
+    public function addBillLine(BillLine $billLine): self
+    {
+        if (!$this->billLines->contains($billLine)) {
+            $this->billLines[] = $billLine;
+            $billLine->setBill($this);
+        }
+
+        return $this;
+    }
+
+    public function removeBillLine(BillLine $billLine): self
+    {
+        if ($this->billLines->removeElement($billLine)) {
+            // set the owning side to null (unless already changed)
+            if ($billLine->getBill() === $this) {
+                $billLine->setBill(null);
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * @return Collection<int, BillCredit>
+     */
+    public function getBillCredits(): Collection
+    {
+        return $this->billCredits;
+    }
+
+    public function addBillCredit(BillCredit $billCredit): self
+    {
+        if (!$this->billCredits->contains($billCredit)) {
+            $this->billCredits[] = $billCredit;
+            $billCredit->setBill($this);
+        }
+
+        return $this;
+    }
+
+    public function removeBillCredit(BillCredit $billCredit): self
+    {
+        if ($this->billCredits->removeElement($billCredit)) {
+            // set the owning side to null (unless already changed)
+            if ($billCredit->getBill() === $this) {
+                $billCredit->setBill(null);
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * @return Collection<int, BillPayment>
+     */
+    public function getBillPayments(): Collection
+    {
+        return $this->billPayments;
+    }
+
+    public function addBillPayment(BillPayment $billPayment): self
+    {
+        if (!$this->billPayments->contains($billPayment)) {
+            $this->billPayments[] = $billPayment;
+            $billPayment->setBill($this);
+        }
+
+        return $this;
+    }
+
+    public function removeBillPayment(BillPayment $billPayment): self
+    {
+        if ($this->billPayments->removeElement($billPayment)) {
+            // set the owning side to null (unless already changed)
+            if ($billPayment->getBill() === $this) {
+                $billPayment->setBill(null);
+            }
+        }
+
+        return $this;
+    }
+
+    public function getBill(): ?self
+    {
+        return $this->bill;
+    }
+
+    public function setBill(?self $bill): self
+    {
+        $this->bill = $bill;
+
+        return $this;
+    }
+
+    /**
+     * @return Collection<int, BillingIntangibleExcludeDate>
+     */
+    public function getBillingIntangibleExcludeDates(): Collection
+    {
+        return $this->billingIntangibleExcludeDates;
+    }
+
+    public function addBillingIntangibleExcludeDate(BillingIntangibleExcludeDate $billingIntangibleExcludeDate): self
+    {
+        if (!$this->billingIntangibleExcludeDates->contains($billingIntangibleExcludeDate)) {
+            $this->billingIntangibleExcludeDates[] = $billingIntangibleExcludeDate;
+            /* @phpstan-ignore-next-line */
+            $billingIntangibleExcludeDate->setBill($this);
+        }
+
+        return $this;
+    }
+
+    public function removeBillingIntangibleExcludeDate(BillingIntangibleExcludeDate $billingIntangibleExcludeDate): self
+    {
+        if ($this->billingIntangibleExcludeDates->removeElement($billingIntangibleExcludeDate)) {
+            // set the owning side to null (unless already changed)
+            if ($billingIntangibleExcludeDate->getBill() === $this) {
+                $billingIntangibleExcludeDate->setBill(null);
+            }
+        }
+
+        return $this;
+    }
+
+    public function getPes(): ?Pes
+    {
+        return $this->pes;
+    }
+
+    public function setPes(?Pes $pes): self
+    {
+        $this->pes = $pes;
+
+        return $this;
+    }
+
+    public function getBergerLevrault(): ?BergerLevrault
+    {
+        return $this->bergerLevrault;
+    }
+
+    public function setBergerLevrault(?BergerLevrault $bergerLevrault): self
+    {
+        $this->bergerLevrault = $bergerLevrault;
+
+        return $this;
+    }
+
+    public function getCiril(): ?Ciril
+    {
+        return $this->ciril;
+    }
+
+    public function setCiril(?Ciril $ciril): self
+    {
+        $this->ciril = $ciril;
+
+        return $this;
+    }
+
+    public function getJvs(): ?Jvs
+    {
+        return $this->jvs;
+    }
+
+    public function setJvs(?Jvs $jvs): self
+    {
+        $this->jvs = $jvs;
+
+        return $this;
+    }
+
+    /**
+     * @return Collection<int, Tagg>
+     */
+    public function getTags(): Collection
+    {
+        return $this->tags;
+    }
+
+    public function addTag(Tagg $tag): self
+    {
+        if (!$this->tags->contains($tag)) {
+            $this->tags[] = $tag;
+            $tag->addBillAccounting($this);
+        }
+
+        return $this;
+    }
+
+    public function removeTag(Tagg $tag): self
+    {
+        if ($this->tags->removeElement($tag)) {
+            $tag->removeBillAccounting($this);
+        }
+
+        return $this;
+    }
+
+    public function getAccess(): Access
+    {
+        return $this->access;
+    }
+
+    public function setAccess(?Access $access): self
+    {
+        $this->access = $access;
+
+        return $this;
+    }
+
+    public function getAccessDetail(): BillAccessDetail
+    {
+        return $this->accessDetail;
+    }
+
+    public function setAccessDetail(BillAccessDetail $accessDetail): self
+    {
+        $this->accessDetail = $accessDetail;
+
+        return $this;
+    }
+
+    public function getBillPeriod(): BillPeriod
+    {
+        return $this->billPeriod;
+    }
+
+    public function setBillPeriod(BillPeriod $billPeriod): self
+    {
+        $this->billPeriod = $billPeriod;
+
+        return $this;
+    }
+
+    public function getTotalDetail(): BillTotalDetail
+    {
+        return $this->totalDetail;
+    }
+
+    public function setTotalDetail(BillTotalDetail $totalDetail): self
+    {
+        $this->totalDetail = $totalDetail;
+
+        return $this;
+    }
+
+    public function getFile(): File
+    {
+        return $this->file;
+    }
+
+    public function setFile(File $file): self
+    {
+        $this->file = $file;
+
+        return $this;
+    }
+
+    public function getOdyssee(): Odyssee
+    {
+        return $this->odyssee;
+    }
+
+    public function setOdyssee(Odyssee $odyssee): self
+    {
+        $this->odyssee = $odyssee;
+
+        return $this;
+    }
+
+    public function getAfi(): Afi
+    {
+        return $this->afi;
+    }
+
+    public function setAfi(Afi $afi): self
+    {
+        $this->afi = $afi;
+
+        return $this;
+    }
+
+    public function getCirilCivil(): CirilCivil
+    {
+        return $this->cirilCivil;
+    }
+
+    public function setCirilCivil(CirilCivil $cirilCivil): self
+    {
+        $this->cirilCivil = $cirilCivil;
+
+        return $this;
+    }
+}

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

@@ -45,6 +45,10 @@ class AccessBilling
     #[ORM\OneToMany(mappedBy: 'accessBillingAccountBalanceReimbursement', targetEntity: BillPayment::class, cascade: ['persist'], orphanRemoval: true)]
     private Collection $accountBalanceReimbursements;
 
+    #[ORM\ManyToOne(targetEntity: BillSchedule::class, cascade: ['persist'], inversedBy: 'accessBilling')]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
+    protected BillSchedule $billSchedule;
+
     public function __construct()
     {
         $this->billDetachedPayments = new ArrayCollection();
@@ -182,4 +186,16 @@ class AccessBilling
 
         return $this;
     }
+
+    public function getBillSchedule(): BillSchedule
+    {
+        return $this->billSchedule;
+    }
+
+    public function setBillSchedule(BillSchedule $billSchedule): self
+    {
+        $this->billSchedule = $billSchedule;
+
+        return $this;
+    }
 }

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

@@ -0,0 +1,18 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use ApiPlatform\Metadata\ApiResource;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ApiResource(operations: [])]
+// #[Auditable]
+#[ORM\Table(name: 'BillAccounting')]
+#[ORM\Entity]
+class AdvancePayment extends AbstractBillAccounting
+{
+    #[ORM\Column(length: 255, nullable: false)]
+    protected string $discr = 'advancepayment';
+}

+ 74 - 0
src/Entity/Billing/Afi.php

@@ -0,0 +1,74 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use ApiPlatform\Metadata\ApiResource;
+use App\Entity\Core\File;
+use Doctrine\Common\Collections\Collection;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ApiResource(operations: [])]
+#[ORM\Entity]
+class Afi
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private int $id;
+
+    #[ORM\OneToMany(mappedBy: 'afi', targetEntity: Bill::class, cascade: ['persist'], orphanRemoval: true)]
+    protected Collection $bills;
+
+    #[ORM\OneToOne(targetEntity: File::class, cascade: ['persist'])]
+    protected File $file;
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): self
+    {
+        $this->id = $id;
+
+        return $this;
+    }
+
+    public function getBills(): Collection
+    {
+        return $this->bills;
+    }
+
+    public function addBill(Bill $bill): self
+    {
+        if (!$this->bills->contains($bill)) {
+            $this->bills[] = $bill;
+            $bill->setAfi($this);
+        }
+
+        return $this;
+    }
+
+    public function removeBill(Bill $bill): self
+    {
+        if ($this->bills->removeElement($bill)) {
+            //            $bill->setAfi(null);   // TODO: actuellement, pas nullable: conserver?
+        }
+
+        return $this;
+    }
+
+    public function getFile(): File
+    {
+        return $this->file;
+    }
+
+    public function setFile(File $file): self
+    {
+        $this->file = $file;
+
+        return $this;
+    }
+}

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

@@ -5,6 +5,7 @@ declare(strict_types=1);
 namespace App\Entity\Billing;
 
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
+use App\Entity\Core\File;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
@@ -24,6 +25,9 @@ class BergerLevrault
     #[ORM\OneToMany(mappedBy: 'bergerLevrault', targetEntity: Bill::class, cascade: ['persist'], orphanRemoval: true)]
     private Collection $bills;
 
+    #[ORM\OneToOne(targetEntity: File::class, cascade: ['persist'])]
+    protected File $file;
+
     public function __construct()
     {
         $this->bills = new ArrayCollection();
@@ -63,4 +67,16 @@ class BergerLevrault
 
         return $this;
     }
+
+    public function getFile(): File
+    {
+        return $this->file;
+    }
+
+    public function setFile(File $file): self
+    {
+        $this->file = $file;
+
+        return $this;
+    }
 }

+ 2 - 24
src/Entity/Billing/Bill.php

@@ -5,36 +5,14 @@ declare(strict_types=1);
 namespace App\Entity\Billing;
 
 use ApiPlatform\Metadata\ApiResource;
-use App\Entity\Access\Access;
-// use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
 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 Bill, et supprimer l'attribut discr.
- * Classe ... qui ...
- */
 #[ApiResource(operations: [])]
 // #[Auditable]
-#[ORM\Entity]
 #[ORM\Table(name: 'BillAccounting')]
-class Bill extends BillAccounting implements BillAccountingInterface
+#[ORM\Entity]
+class Bill extends AbstractBillAccounting
 {
     #[ORM\Column(length: 255, nullable: false)]
     protected string $discr = 'bill';
-
-    #[ORM\ManyToOne(inversedBy: 'bills')]
-    #[ORM\JoinColumn(nullable: false)]
-    public ?Access $access;
-
-    public function getAccess(): ?Access
-    {
-        return $this->access;
-    }
-
-    public function setAccess(?Access $access): self
-    {
-        $this->access = $access;
-
-        return $this;
-    }
 }

+ 3 - 0
src/Entity/Billing/BillAccessDetail.php

@@ -5,12 +5,15 @@ declare(strict_types=1);
 namespace App\Entity\Billing;
 
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
+use ApiPlatform\Metadata\ApiResource;
 use Doctrine\ORM\Mapping as ORM;
 
 /**
  * Classe ... qui ...
  */
 // #[Auditable]
+#[ApiResource(operations: [])]
+#[ORM\Entity]
 class BillAccessDetail
 {
     #[ORM\Id]

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

@@ -5,300 +5,14 @@ declare(strict_types=1);
 namespace App\Entity\Billing;
 
 use ApiPlatform\Metadata\ApiResource;
-use App\Entity\Core\Tagg;
-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;
 
-/**
- * @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.
- * Classe ... qui ...
- */
 #[ApiResource(operations: [])]
+#[ORM\Table(name: 'BillAccounting')]
 // #[Auditable]
 #[ORM\Entity]
-class BillAccounting
+class BillAccounting extends AbstractBillAccounting
 {
-    #[ORM\Id]
-    #[ORM\Column]
-    #[ORM\GeneratedValue]
-    protected ?int $id = null;
-
     #[ORM\Column(length: 255, nullable: false)]
     protected string $discr = 'billaccounting';
-
-    #[ORM\ManyToOne]
-    #[ORM\JoinColumn(nullable: true)]
-    protected Organization $organization;
-
-    #[ORM\OneToMany(mappedBy: 'bill', targetEntity: BillLine::class, cascade: ['persist'], orphanRemoval: true)]
-    protected Collection $billLines;
-
-    #[ORM\OneToMany(mappedBy: 'bill', targetEntity: BillCredit::class, cascade: ['persist'], orphanRemoval: true)]
-    protected Collection $billCredits;
-
-    #[ORM\OneToMany(mappedBy: 'bill', targetEntity: BillPayment::class, cascade: ['persist'], orphanRemoval: true)]
-    protected Collection $billPayments;
-
-    #[ORM\ManyToOne(inversedBy: 'billCredits')]
-    #[ORM\JoinColumn(nullable: true)]
-    protected BillAccounting $bill;
-
-    #[ORM\OneToMany(mappedBy: 'bill', targetEntity: BillingIntangibleExcludeDate::class, cascade: ['persist'], orphanRemoval: true)]
-    protected Collection $billingIntangibleExcludeDates;
-
-    #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'bills')]
-    #[ORM\JoinColumn(nullable: true)]
-    protected Pes $pes;
-
-    #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'bills')]
-    #[ORM\JoinColumn(nullable: true)]
-    protected BergerLevrault $bergerLevrault;
-
-    #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'bills')]
-    #[ORM\JoinColumn(nullable: true)]
-    protected Ciril $ciril;
-
-    #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'bills')]
-    #[ORM\JoinColumn(nullable: true)]
-    protected Jvs $jvs;
-
-    #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'billAccountings', cascade: ['persist'])]
-    #[ORM\JoinTable(name: 'tag_billAccounting')]
-    #[ORM\JoinColumn(name: 'billAccounting_id', referencedColumnName: 'id')]
-    #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
-    protected Collection $tags;
-
-    public function __construct()
-    {
-        $this->billLines = new ArrayCollection();
-        $this->billCredits = new ArrayCollection();
-        $this->billPayments = new ArrayCollection();
-        $this->billingIntangibleExcludeDates = new ArrayCollection();
-        $this->tags = new ArrayCollection();
-    }
-
-    public function getId(): ?int
-    {
-        return $this->id;
-    }
-
-    public function getOrganization(): ?Organization
-    {
-        return $this->organization;
-    }
-
-    public function setOrganization(?Organization $organization): self
-    {
-        $this->organization = $organization;
-
-        return $this;
-    }
-
-    /**
-     * @return Collection<int, BillLine>
-     */
-    public function getBillLines(): Collection
-    {
-        return $this->billLines;
-    }
-
-    public function addBillLine(BillLine $billLine): self
-    {
-        if (!$this->billLines->contains($billLine)) {
-            $this->billLines[] = $billLine;
-            $billLine->setBill($this);
-        }
-
-        return $this;
-    }
-
-    public function removeBillLine(BillLine $billLine): self
-    {
-        if ($this->billLines->removeElement($billLine)) {
-            // set the owning side to null (unless already changed)
-            if ($billLine->getBill() === $this) {
-                $billLine->setBill(null);
-            }
-        }
-
-        return $this;
-    }
-
-    /**
-     * @return Collection<int, BillCredit>
-     */
-    public function getBillCredits(): Collection
-    {
-        return $this->billCredits;
-    }
-
-    public function addBillCredit(BillCredit $billCredit): self
-    {
-        if (!$this->billCredits->contains($billCredit)) {
-            $this->billCredits[] = $billCredit;
-            $billCredit->setBill($this);
-        }
-
-        return $this;
-    }
-
-    public function removeBillCredit(BillCredit $billCredit): self
-    {
-        if ($this->billCredits->removeElement($billCredit)) {
-            // set the owning side to null (unless already changed)
-            if ($billCredit->getBill() === $this) {
-                $billCredit->setBill(null);
-            }
-        }
-
-        return $this;
-    }
-
-    /**
-     * @return Collection<int, BillPayment>
-     */
-    public function getBillPayments(): Collection
-    {
-        return $this->billPayments;
-    }
-
-    public function addBillPayment(BillPayment $billPayment): self
-    {
-        if (!$this->billPayments->contains($billPayment)) {
-            $this->billPayments[] = $billPayment;
-            $billPayment->setBill($this);
-        }
-
-        return $this;
-    }
-
-    public function removeBillPayment(BillPayment $billPayment): self
-    {
-        if ($this->billPayments->removeElement($billPayment)) {
-            // set the owning side to null (unless already changed)
-            if ($billPayment->getBill() === $this) {
-                $billPayment->setBill(null);
-            }
-        }
-
-        return $this;
-    }
-
-    public function getBill(): ?self
-    {
-        return $this->bill;
-    }
-
-    public function setBill(?self $bill): self
-    {
-        $this->bill = $bill;
-
-        return $this;
-    }
-
-    /**
-     * @return Collection<int, BillingIntangibleExcludeDate>
-     */
-    public function getBillingIntangibleExcludeDates(): Collection
-    {
-        return $this->billingIntangibleExcludeDates;
-    }
-
-    public function addBillingIntangibleExcludeDate(BillingIntangibleExcludeDate $billingIntangibleExcludeDate): self
-    {
-        if (!$this->billingIntangibleExcludeDates->contains($billingIntangibleExcludeDate)) {
-            $this->billingIntangibleExcludeDates[] = $billingIntangibleExcludeDate;
-            /* @phpstan-ignore-next-line */
-            $billingIntangibleExcludeDate->setBill($this);
-        }
-
-        return $this;
-    }
-
-    public function removeBillingIntangibleExcludeDate(BillingIntangibleExcludeDate $billingIntangibleExcludeDate): self
-    {
-        if ($this->billingIntangibleExcludeDates->removeElement($billingIntangibleExcludeDate)) {
-            // set the owning side to null (unless already changed)
-            if ($billingIntangibleExcludeDate->getBill() === $this) {
-                $billingIntangibleExcludeDate->setBill(null);
-            }
-        }
-
-        return $this;
-    }
-
-    public function getPes(): ?Pes
-    {
-        return $this->pes;
-    }
-
-    public function setPes(?Pes $pes): self
-    {
-        $this->pes = $pes;
-
-        return $this;
-    }
-
-    public function getBergerLevrault(): ?BergerLevrault
-    {
-        return $this->bergerLevrault;
-    }
-
-    public function setBergerLevrault(?BergerLevrault $bergerLevrault): self
-    {
-        $this->bergerLevrault = $bergerLevrault;
-
-        return $this;
-    }
-
-    public function getCiril(): ?Ciril
-    {
-        return $this->ciril;
-    }
-
-    public function setCiril(?Ciril $ciril): self
-    {
-        $this->ciril = $ciril;
-
-        return $this;
-    }
-
-    public function getJvs(): ?Jvs
-    {
-        return $this->jvs;
-    }
-
-    public function setJvs(?Jvs $jvs): self
-    {
-        $this->jvs = $jvs;
-
-        return $this;
-    }
-
-    /**
-     * @return Collection<int, Tagg>
-     */
-    public function getTags(): Collection
-    {
-        return $this->tags;
-    }
-
-    public function addTag(Tagg $tag): self
-    {
-        if (!$this->tags->contains($tag)) {
-            $this->tags[] = $tag;
-        }
-
-        return $this;
-    }
-
-    public function removeTag(Tagg $tag): self
-    {
-        $this->tags->removeElement($tag);
-
-        return $this;
-    }
 }

+ 2 - 25
src/Entity/Billing/BillCredit.php

@@ -5,37 +5,14 @@ declare(strict_types=1);
 namespace App\Entity\Billing;
 
 use ApiPlatform\Metadata\ApiResource;
-use App\Entity\Access\Access;
-// use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
 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 BillCredit, et supprimer l'attribut discr.
- *
- * Classe ... qui ...
- */
 #[ApiResource(operations: [])]
 // #[Auditable]
-#[ORM\Entity]
 #[ORM\Table(name: 'BillAccounting')]
-class BillCredit extends BillAccounting implements BillAccountingInterface
+#[ORM\Entity]
+class BillCredit extends AbstractBillAccounting
 {
     #[ORM\Column(length: 255, nullable: false)]
     protected string $discr = 'billcredit';
-
-    #[ORM\ManyToOne(inversedBy: 'billCredits')]
-    #[ORM\JoinColumn(nullable: false)]
-    protected Access $access;
-
-    public function getAccess(): ?Access
-    {
-        return $this->access;
-    }
-
-    public function setAccess(?Access $access): self
-    {
-        $this->access = $access;
-
-        return $this;
-    }
 }

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

@@ -26,7 +26,7 @@ class BillLine
 
     #[ORM\ManyToOne(inversedBy: 'billLines')]
     #[ORM\JoinColumn(nullable: false)]
-    private BillAccounting $bill;
+    private AbstractBillAccounting $bill;
 
     #[ORM\ManyToOne(inversedBy: 'billLines')]
     private Access $access;
@@ -42,12 +42,12 @@ class BillLine
         return $this->id;
     }
 
-    public function getBill(): ?BillAccounting
+    public function getBill(): ?AbstractBillAccounting
     {
         return $this->bill;
     }
 
-    public function setBill(?BillAccounting $bill): self
+    public function setBill(?AbstractBillAccounting $bill): self
     {
         $this->bill = $bill;
 

+ 35 - 3
src/Entity/Billing/BillPayment.php

@@ -24,7 +24,7 @@ class BillPayment
 
     #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'billPayments')]
     #[ORM\JoinColumn(nullable: true)]
-    private BillAccounting $bill;
+    private AbstractBillAccounting $bill;
 
     #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'billDetachedPayments')]
     #[ORM\JoinColumn(nullable: true)]
@@ -44,6 +44,14 @@ class BillPayment
     #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
     private Collection $tags;
 
+    #[ORM\ManyToOne(targetEntity: SddBank::class, cascade: ['persist'], inversedBy: 'billPayments')]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
+    protected SddBank $sddBank;
+
+    #[ORM\ManyToOne(targetEntity: SddRegie::class, cascade: ['persist'], inversedBy: 'billPayments')]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
+    protected SddRegie $sddRegie;
+
     public function __construct()
     {
         $this->billDebitBalances = new ArrayCollection();
@@ -55,12 +63,12 @@ class BillPayment
         return $this->id;
     }
 
-    public function getBill(): ?BillAccounting
+    public function getBill(): ?AbstractBillAccounting
     {
         return $this->bill;
     }
 
-    public function setBill(?BillAccounting $bill): self
+    public function setBill(?AbstractBillAccounting $bill): self
     {
         $this->bill = $bill;
 
@@ -144,4 +152,28 @@ class BillPayment
 
         return $this;
     }
+
+    public function getSddBank(): SddBank
+    {
+        return $this->sddBank;
+    }
+
+    public function setSddBank(SddBank $sddBank): self
+    {
+        $this->sddBank = $sddBank;
+
+        return $this;
+    }
+
+    public function getSddRegie(): SddRegie
+    {
+        return $this->sddRegie;
+    }
+
+    public function setSddRegie(SddRegie $sddRegie): self
+    {
+        $this->sddRegie = $sddRegie;
+
+        return $this;
+    }
 }

+ 130 - 0
src/Entity/Billing/BillSchedule.php

@@ -0,0 +1,130 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use ApiPlatform\Metadata\ApiResource;
+use App\Entity\AccessWish\AccessWish;
+use App\Entity\Organization\Organization;
+use Doctrine\Common\Collections\Collection;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ApiResource(operations: [])]
+#[ORM\Entity]
+class BillSchedule
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private int $id;
+
+    #[ORM\ManyToOne(targetEntity: Organization::class, cascade: [], inversedBy: 'billSchedules')]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: false, onDelete: 'SET NULL')]
+    protected Organization $organization;
+
+    #[ORM\OneToMany(mappedBy: 'billSchedule', targetEntity: BillScheduleDate::class, cascade: ['persist'], orphanRemoval: true)]
+    protected Collection $scheduleDates;
+
+    #[ORM\OneToMany(mappedBy: 'billSchedule', targetEntity: AccessBilling::class, cascade: [], orphanRemoval: false)] // TODO: à revoir
+    protected Collection $accessBilling;
+
+    #[ORM\OneToMany(mappedBy: 'billSchedule', targetEntity: AccessWish::class, cascade: [], orphanRemoval: false)] // TODO: à revoir
+    protected Collection $accessWishes;
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): self
+    {
+        $this->id = $id;
+
+        return $this;
+    }
+
+    public function getOrganization(): Organization
+    {
+        return $this->organization;
+    }
+
+    public function setOrganization(Organization $organization): self
+    {
+        $this->organization = $organization;
+
+        return $this;
+    }
+
+    public function getScheduleDates(): Collection
+    {
+        return $this->scheduleDates;
+    }
+
+    public function addScheduleDate(BillScheduleDate $scheduleDate): self
+    {
+        if (!$this->scheduleDates->contains($scheduleDate)) {
+            $this->scheduleDates[] = $scheduleDate;
+            $scheduleDate->setBillSchedule($this);
+        }
+
+        return $this;
+    }
+
+    public function removeScheduleDate(BillScheduleDate $scheduleDate): self
+    {
+        if ($this->scheduleDates->removeElement($scheduleDate)) {
+            $scheduleDate->setBillSchedule(null);
+        }
+
+        return $this;
+    }
+
+    public function getAccessBilling(): Collection
+    {
+        return $this->accessBilling;
+    }
+
+    public function addAccessBilling(AccessBilling $accessBilling): self
+    {
+        if (!$this->accessBilling->contains($accessBilling)) {
+            $this->accessBilling[] = $accessBilling;
+            $accessBilling->setBillSchedule($this);
+        }
+
+        return $this;
+    }
+
+    public function removeAccessBilling(AccessBilling $accessBilling): self
+    {
+        if ($this->accessBilling->removeElement($accessBilling)) {
+            //            $accessBilling->setBillSchedule(null);  // TODO: actuellement, pas nullable: conserver?
+        }
+
+        return $this;
+    }
+
+    public function getAccessWishes(): Collection
+    {
+        return $this->accessWishes;
+    }
+
+    public function addAccessWish(AccessWish $accessWish): self
+    {
+        if (!$this->accessWishes->contains($accessWish)) {
+            $this->accessWishes[] = $accessWish;
+            $accessWish->setBillSchedule($this);
+        }
+
+        return $this;
+    }
+
+    public function removeAccessWish(AccessWish $accessWish): self
+    {
+        if ($this->accessWishes->removeElement($accessWish)) {
+            //            $accessWish->setBillSchedule(null);  // TODO: actuellement, pas nullable: conserver?
+        }
+
+        return $this;
+    }
+}

+ 46 - 0
src/Entity/Billing/BillScheduleDate.php

@@ -0,0 +1,46 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use ApiPlatform\Metadata\ApiResource;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ApiResource(operations: [])]
+#[ORM\Entity]
+class BillScheduleDate
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private int $id;
+
+    #[ORM\ManyToOne(targetEntity: BillSchedule::class, cascade: ['persist'], inversedBy: 'scheduleDates')]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
+    protected mixed $billSchedule;
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): self
+    {
+        $this->id = $id;
+
+        return $this;
+    }
+
+    public function getBillSchedule(): mixed
+    {
+        return $this->billSchedule;
+    }
+
+    public function setBillSchedule(mixed $billSchedule): self
+    {
+        $this->billSchedule = $billSchedule;
+
+        return $this;
+    }
+}

+ 50 - 0
src/Entity/Billing/BillingExportSetting.php

@@ -5,6 +5,10 @@ declare(strict_types=1);
 namespace App\Entity\Billing;
 
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
+use App\Entity\Access\Access;
+use App\Entity\Organization\Organization;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
 
 /**
@@ -23,6 +27,17 @@ class BillingExportSetting
     #[ORM\JoinColumn(nullable: true)]
     private SddTeneur $teneur;
 
+    #[ORM\OneToOne(inversedBy: 'billingExportSetting', targetEntity: Organization::class, cascade: [])]
+    protected Organization $organization;
+
+    #[ORM\ManyToMany(targetEntity: Access::class, cascade: [], orphanRemoval: false)]
+    protected Collection $stageManagers;
+
+    public function __construct()
+    {
+        $this->stageManagers = new ArrayCollection();
+    }
+
     public function getId(): ?int
     {
         return $this->id;
@@ -39,4 +54,39 @@ class BillingExportSetting
 
         return $this;
     }
+
+    public function getOrganization(): Organization
+    {
+        return $this->organization;
+    }
+
+    public function setOrganization(Organization $organization): self
+    {
+        $this->organization = $organization;
+
+        return $this;
+    }
+
+    public function getStageManagers(): Collection
+    {
+        return $this->stageManagers;
+    }
+
+    public function addStageManager(Access $stageManager): self
+    {
+        if (!$this->stageManagers->contains($stageManager)) {
+            $this->stageManagers[] = $stageManager;
+            // TODO: compléter (je n'ai pas le mappedBy)
+        }
+
+        return $this;
+    }
+
+    public function removeStageManager(Access $stageManager): self
+    {
+        $this->stageManagers->removeElement($stageManager);
+
+        // TODO: compléter (je n'ai pas le mappedBy)
+        return $this;
+    }
 }

+ 15 - 0
src/Entity/Billing/BillingSetting.php

@@ -36,6 +36,9 @@ class BillingSetting
     #[ORM\OneToMany(mappedBy: 'billingSetting', targetEntity: FamilyQuotient::class, cascade: ['persist'], orphanRemoval: true)]
     private Collection $familyQuotients;
 
+    #[ORM\OneToOne(mappedBy: 'billingSetting', targetEntity: BillingSettingRent::class, cascade: ['persist'])]
+    protected BillingSettingRent $billingSettingRent;
+
     #[Pure]
     public function __construct()
     {
@@ -128,4 +131,16 @@ class BillingSetting
 
         return $this;
     }
+
+    public function getBillingSettingRent(): BillingSettingRent
+    {
+        return $this->billingSettingRent;
+    }
+
+    public function setBillingSettingRent(BillingSettingRent $billingSettingRent): self
+    {
+        $this->billingSettingRent = $billingSettingRent;
+
+        return $this;
+    }
 }

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

@@ -19,6 +19,21 @@ class BillingSettingRent
     #[ORM\GeneratedValue]
     private ?int $id = null;
 
+    #[ORM\OneToOne(inversedBy: 'billingSettingRent', targetEntity: BillingSetting::class, cascade: [])]
+    protected BillingSetting $billingSetting;
+
+    public function getBillingSetting(): BillingSetting
+    {
+        return $this->billingSetting;
+    }
+
+    public function setBillingSetting(BillingSetting $billingSetting): self
+    {
+        $this->billingSetting = $billingSetting;
+
+        return $this;
+    }
+
     public function getId(): ?int
     {
         return $this->id;

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

@@ -5,6 +5,7 @@ declare(strict_types=1);
 namespace App\Entity\Billing;
 
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
+use App\Entity\Core\File;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
@@ -24,6 +25,9 @@ class Ciril
     #[ORM\OneToMany(mappedBy: 'ciril', targetEntity: Bill::class, cascade: ['persist'], orphanRemoval: true)]
     private Collection $bills;
 
+    #[ORM\OneToOne(targetEntity: File::class, cascade: ['persist'])]
+    protected File $file;
+
     public function __construct()
     {
         $this->bills = new ArrayCollection();
@@ -63,4 +67,16 @@ class Ciril
 
         return $this;
     }
+
+    public function getFile(): File
+    {
+        return $this->file;
+    }
+
+    public function setFile(File $file): self
+    {
+        $this->file = $file;
+
+        return $this;
+    }
 }

+ 72 - 0
src/Entity/Billing/CirilCivil.php

@@ -0,0 +1,72 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use ApiPlatform\Metadata\ApiResource;
+use App\Entity\Core\File;
+use Doctrine\Common\Collections\Collection;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ApiResource(operations: [])]
+#[ORM\Entity]
+class CirilCivil
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private int $id;
+
+    #[ORM\OneToMany(mappedBy: 'cirilCivil', targetEntity: Bill::class, cascade: ['persist'], orphanRemoval: true)]
+    protected Collection $bills;
+
+    #[ORM\OneToOne(targetEntity: File::class, cascade: ['persist'])]
+    protected File $file;
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): self
+    {
+        $this->id = $id;
+
+        return $this;
+    }
+
+    public function getBills(): Collection
+    {
+        return $this->bills;
+    }
+
+    public function addBill(Bill $bill): self
+    {
+        if (!$this->bills->contains($bill)) {
+            $this->bills[] = $bill;
+            $bill->setCirilCivil($this);
+        }
+
+        return $this;
+    }
+
+    public function removeBill(Bill $bill): self
+    {
+        $this->bills->removeElement($bill);
+
+        return $this;
+    }
+
+    public function getFile(): File
+    {
+        return $this->file;
+    }
+
+    public function setFile(File $file): self
+    {
+        $this->file = $file;
+
+        return $this;
+    }
+}

+ 105 - 0
src/Entity/Billing/FamilyQuotientBand.php

@@ -0,0 +1,105 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use ApiPlatform\Metadata\ApiResource;
+use App\Entity\Product\IntangibleDiscountDetail;
+use Doctrine\Common\Collections\Collection;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ApiResource(operations: [])]
+#[ORM\Entity]
+class FamilyQuotientBand
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private int $id;
+
+    #[ORM\ManyToOne(targetEntity: FamilyQuotientModel::class, cascade: [], inversedBy: 'familyQuotientBands')]
+    #[ORM\JoinColumn(nullable: false)]
+    protected mixed $familyQuotientModel;
+
+    #[ORM\OneToMany(
+        mappedBy: 'familyQuotientBand',
+        targetEntity: FamilyQuotientBandDetail::class,
+        cascade: ['persist'],
+        orphanRemoval: true,
+    )]
+    protected Collection $familyQuotientBandDetails;
+
+    #[ORM\OneToMany(mappedBy: 'familyQuotientBand', targetEntity: IntangibleDiscountDetail::class, cascade: [], orphanRemoval: true)]
+    protected Collection $intangibleDiscountDetails;
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): self
+    {
+        $this->id = $id;
+
+        return $this;
+    }
+
+    public function getFamilyQuotientModel(): mixed
+    {
+        return $this->familyQuotientModel;
+    }
+
+    public function setFamilyQuotientModel(mixed $familyQuotientModel): self
+    {
+        $this->familyQuotientModel = $familyQuotientModel;
+
+        return $this;
+    }
+
+    public function getFamilyQuotientBandDetails(): Collection
+    {
+        return $this->familyQuotientBandDetails;
+    }
+
+    public function addFamilyQuotientBandDetail(FamilyQuotientBandDetail $familyQuotientBandDetail): self
+    {
+        if (!$this->familyQuotientBandDetails->contains($familyQuotientBandDetail)) {
+            $this->familyQuotientBandDetails[] = $familyQuotientBandDetail;
+            $familyQuotientBandDetail->setFamilyQuotientBand($this);
+        }
+
+        return $this;
+    }
+
+    public function removeFamilyQuotientBandDetail(FamilyQuotientBandDetail $familyQuotientBandDetail): self
+    {
+        if ($this->familyQuotientBandDetails->removeElement($familyQuotientBandDetail)) {
+            $familyQuotientBandDetail->setFamilyQuotientBand(null);
+        }
+
+        return $this;
+    }
+
+    public function getIntangibleDiscountDetails(): Collection
+    {
+        return $this->intangibleDiscountDetails;
+    }
+
+    public function addIntangibleDiscountDetail(IntangibleDiscountDetail $intangibleDiscountDetail): self
+    {
+        if (!$this->intangibleDiscountDetails->contains($intangibleDiscountDetail)) {
+            $this->intangibleDiscountDetails[] = $intangibleDiscountDetail;
+            $intangibleDiscountDetail->setFamilyQuotientBand($this);
+        }
+
+        return $this;
+    }
+
+    public function removeIntangibleDiscountDetail(IntangibleDiscountDetail $intangibleDiscountDetail): self
+    {
+        $this->intangibleDiscountDetails->removeElement($intangibleDiscountDetail);
+
+        return $this;
+    }
+}

+ 89 - 0
src/Entity/Billing/FamilyQuotientBandDetail.php

@@ -0,0 +1,89 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use ApiPlatform\Metadata\ApiResource;
+use App\Entity\Product\IntangibleDiscountDetail;
+use Doctrine\Common\Collections\Collection;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ApiResource(operations: [])]
+#[ORM\Entity]
+class FamilyQuotientBandDetail
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private int $id;
+
+    #[ORM\ManyToOne(targetEntity: FamilyQuotientBand::class, cascade: [], inversedBy: 'familyQuotientBandDetails')]
+    #[ORM\JoinColumn(nullable: false)]
+    protected mixed $familyQuotientBand;
+
+    #[ORM\ManyToOne(targetEntity: ResidenceArea::class, cascade: [], inversedBy: 'intangibleDiscountDetails')]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
+    protected ResidenceArea $residenceArea;
+
+    #[ORM\OneToMany(mappedBy: 'familyQuotientBandDetail', targetEntity: IntangibleDiscountDetail::class, cascade: [], orphanRemoval: true)]
+    protected Collection $intangibleDiscountDetails;
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): self
+    {
+        $this->id = $id;
+
+        return $this;
+    }
+
+    public function getFamilyQuotientBand(): mixed
+    {
+        return $this->familyQuotientBand;
+    }
+
+    public function setFamilyQuotientBand(mixed $familyQuotientBand): self
+    {
+        $this->familyQuotientBand = $familyQuotientBand;
+
+        return $this;
+    }
+
+    public function getResidenceArea(): ResidenceArea
+    {
+        return $this->residenceArea;
+    }
+
+    public function setResidenceArea(ResidenceArea $residenceArea): self
+    {
+        $this->residenceArea = $residenceArea;
+
+        return $this;
+    }
+
+    public function getIntangibleDiscountDetails(): Collection
+    {
+        return $this->intangibleDiscountDetails;
+    }
+
+    public function addIntangibleDiscountDetail(IntangibleDiscountDetail $intangibleDiscountDetail): self
+    {
+        if (!$this->intangibleDiscountDetails->contains($intangibleDiscountDetail)) {
+            $this->intangibleDiscountDetails[] = $intangibleDiscountDetail;
+            $intangibleDiscountDetail->setFamilyQuotientBandDetail($this);
+        }
+
+        return $this;
+    }
+
+    public function removeIntangibleDiscountDetail(IntangibleDiscountDetail $intangibleDiscountDetail): self
+    {
+        $this->intangibleDiscountDetails->removeElement($intangibleDiscountDetail);
+
+        return $this;
+    }
+}

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

@@ -0,0 +1,103 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use ApiPlatform\Metadata\ApiResource;
+use App\Entity\Organization\Organization;
+use App\Entity\Product\IntangiblePriceAndDiscount;
+use Doctrine\Common\Collections\Collection;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ApiResource(operations: [])]
+#[ORM\Entity]
+class FamilyQuotientModel
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private int $id;
+
+    #[ORM\ManyToOne(targetEntity: Organization::class, cascade: [], inversedBy: 'familyQuotientModels')]
+    #[ORM\JoinColumn(nullable: false)]
+    protected Organization $organization;
+
+    #[ORM\OneToMany(mappedBy: 'familyQuotientModel', targetEntity: FamilyQuotientBand::class, cascade: ['persist'], orphanRemoval: true)]
+    protected Collection $familyQuotientBands;
+
+    #[ORM\OneToMany(mappedBy: 'familyQuotientModel', targetEntity: IntangiblePriceAndDiscount::class, cascade: [], orphanRemoval: false)]
+    protected Collection $intangiblePriceAndDiscounts;
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): self
+    {
+        $this->id = $id;
+
+        return $this;
+    }
+
+    public function getOrganization(): Organization
+    {
+        return $this->organization;
+    }
+
+    public function setOrganization(Organization $organization): self
+    {
+        $this->organization = $organization;
+
+        return $this;
+    }
+
+    public function getFamilyQuotientBands(): Collection
+    {
+        return $this->familyQuotientBands;
+    }
+
+    public function addFamilyQuotientBand(FamilyQuotientBand $familyQuotientBand): self
+    {
+        if (!$this->familyQuotientBands->contains($familyQuotientBand)) {
+            $this->familyQuotientBands[] = $familyQuotientBand;
+            $familyQuotientBand->setFamilyQuotientModel($this);
+        }
+
+        return $this;
+    }
+
+    public function removeFamilyQuotientBand(FamilyQuotientBand $familyQuotientBand): self
+    {
+        if ($this->familyQuotientBands->removeElement($familyQuotientBand)) {
+            $familyQuotientBand->setFamilyQuotientModel(null);
+        }
+
+        return $this;
+    }
+
+    public function getIntangiblePriceAndDiscounts(): Collection
+    {
+        return $this->intangiblePriceAndDiscounts;
+    }
+
+    public function addIntangiblePriceAndDiscount(IntangiblePriceAndDiscount $intangiblePriceAndDiscount): self
+    {
+        if (!$this->intangiblePriceAndDiscounts->contains($intangiblePriceAndDiscount)) {
+            $this->intangiblePriceAndDiscounts[] = $intangiblePriceAndDiscount;
+            $intangiblePriceAndDiscount->setFamilyQuotientModel($this);
+        }
+
+        return $this;
+    }
+
+    public function removeIntangiblePriceAndDiscount(IntangiblePriceAndDiscount $intangiblePriceAndDiscount): self
+    {
+        if ($this->intangiblePriceAndDiscounts->removeElement($intangiblePriceAndDiscount)) {
+            $intangiblePriceAndDiscount->setFamilyQuotientModel(null);
+        }
+
+        return $this;
+    }
+}

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

@@ -5,6 +5,7 @@ declare(strict_types=1);
 namespace App\Entity\Billing;
 
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
+use App\Entity\Core\File;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
@@ -24,6 +25,9 @@ class Jvs
     #[ORM\OneToMany(mappedBy: 'jvs', targetEntity: Bill::class, cascade: ['persist'], orphanRemoval: true)]
     private Collection $bills;
 
+    #[ORM\OneToOne(targetEntity: File::class, cascade: ['persist'])]
+    protected File $file;
+
     public function __construct()
     {
         $this->bills = new ArrayCollection();
@@ -63,4 +67,16 @@ class Jvs
 
         return $this;
     }
+
+    public function getFile(): File
+    {
+        return $this->file;
+    }
+
+    public function setFile(File $file): self
+    {
+        $this->file = $file;
+
+        return $this;
+    }
 }

+ 74 - 0
src/Entity/Billing/Odyssee.php

@@ -0,0 +1,74 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use ApiPlatform\Metadata\ApiResource;
+use App\Entity\Core\File;
+use Doctrine\Common\Collections\Collection;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ApiResource(operations: [])]
+#[ORM\Entity]
+class Odyssee
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private int $id;
+
+    #[ORM\OneToMany(mappedBy: 'odyssee', targetEntity: Bill::class, cascade: ['persist'], orphanRemoval: true)]
+    protected Collection $bills;
+
+    #[ORM\OneToOne(targetEntity: File::class, cascade: ['persist'])]
+    protected File $file;
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): self
+    {
+        $this->id = $id;
+
+        return $this;
+    }
+
+    public function getBills(): Collection
+    {
+        return $this->bills;
+    }
+
+    public function addBill(Bill $bill): self
+    {
+        if (!$this->bills->contains($bill)) {
+            $this->bills[] = $bill;
+            $bill->setOdyssee($this);
+        }
+
+        return $this;
+    }
+
+    public function removeBill(Bill $bill): self
+    {
+        if ($this->bills->removeElement($bill)) {
+            //            $bill->setOdyssee(null); // TODO: actuellement, pas nullable: conserver?
+        }
+
+        return $this;
+    }
+
+    public function getFile(): File
+    {
+        return $this->file;
+    }
+
+    public function setFile(File $file): self
+    {
+        $this->file = $file;
+
+        return $this;
+    }
+}

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

@@ -0,0 +1,30 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use ApiPlatform\Metadata\ApiResource;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ApiResource(operations: [])]
+#[ORM\Entity]
+class PayboxPaymentReturn
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private int $id;
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): self
+    {
+        $this->id = $id;
+
+        return $this;
+    }
+}

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

@@ -5,6 +5,7 @@ declare(strict_types=1);
 namespace App\Entity\Billing;
 
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
+use App\Entity\Core\File;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
@@ -24,6 +25,9 @@ class Pes
     #[ORM\OneToMany(mappedBy: 'pes', targetEntity: Bill::class, cascade: ['persist'], orphanRemoval: true)]
     private Collection $bills;
 
+    #[ORM\OneToOne(targetEntity: File::class, cascade: ['persist'])]
+    protected File $file;
+
     public function __construct()
     {
         $this->bills = new ArrayCollection();
@@ -63,4 +67,16 @@ class Pes
 
         return $this;
     }
+
+    public function getFile(): File
+    {
+        return $this->file;
+    }
+
+    public function setFile(File $file): self
+    {
+        $this->file = $file;
+
+        return $this;
+    }
 }

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

@@ -5,6 +5,7 @@ declare(strict_types=1);
 namespace App\Entity\Billing;
 
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
+use App\Entity\Organization\Organization;
 use Doctrine\ORM\Mapping as ORM;
 
 /**
@@ -19,8 +20,23 @@ class PesSetting
     #[ORM\GeneratedValue]
     private ?int $id = null;
 
+    #[ORM\OneToOne(targetEntity: Organization::class, inversedBy: 'pesSetting', cascade: [])]
+    protected Organization $organization;
+
     public function getId(): ?int
     {
         return $this->id;
     }
+
+    public function getOrganization(): Organization
+    {
+        return $this->organization;
+    }
+
+    public function setOrganization(Organization $organization): self
+    {
+        $this->organization = $organization;
+
+        return $this;
+    }
 }

+ 46 - 0
src/Entity/Billing/SddBank.php

@@ -5,6 +5,9 @@ declare(strict_types=1);
 namespace App\Entity\Billing;
 
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
+use App\Entity\Core\File;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
 
 /**
@@ -19,12 +22,55 @@ class SddBank
     #[ORM\GeneratedValue]
     private ?int $id = null;
 
+    #[ORM\OneToMany(mappedBy: 'sddBank', targetEntity: BillPayment::class, cascade: [], orphanRemoval: false)]
+    protected Collection $billPayments;
+
+    #[ORM\OneToOne(targetEntity: File::class, cascade: ['persist'])]
+    protected File $file;
+
     public function __construct()
     {
+        $this->billPayments = new ArrayCollection();
     }
 
     public function getId(): ?int
     {
         return $this->id;
     }
+
+    public function getBillPayments(): Collection
+    {
+        return $this->billPayments;
+    }
+
+    public function addBillPayment(BillPayment $billPayment): self
+    {
+        if (!$this->billPayments->contains($billPayment)) {
+            $this->billPayments[] = $billPayment;
+            $billPayment->setSddBank($this);
+        }
+
+        return $this;
+    }
+
+    public function removeBillPayment(BillPayment $billPayment): self
+    {
+        if ($this->billPayments->removeElement($billPayment)) {
+            //            $billPayment->setSddBank(null); // TODO: actuellement, pas nullable: conserver?
+        }
+
+        return $this;
+    }
+
+    public function getFile(): File
+    {
+        return $this->file;
+    }
+
+    public function setFile(File $file): self
+    {
+        $this->file = $file;
+
+        return $this;
+    }
 }

+ 62 - 0
src/Entity/Billing/SddRegie.php

@@ -5,10 +5,14 @@ declare(strict_types=1);
 namespace App\Entity\Billing;
 
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
+use App\Entity\Core\File;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
 
 /**
  * Classe ... qui ...
+ * // TODO: possible factoriser avec SddBank?
  */
 // #[Auditable]
 #[ORM\Entity]
@@ -19,12 +23,70 @@ class SddRegie
     #[ORM\GeneratedValue]
     private ?int $id = null;
 
+    #[ORM\OneToMany(mappedBy: 'sddRegie', targetEntity: BillPayment::class, cascade: [], orphanRemoval: false)]
+    protected Collection $billPayments;
+
+    #[ORM\OneToOne(targetEntity: File::class, cascade: ['persist'])]
+    protected File $file;
+
+    #[ORM\OneToOne(targetEntity: File::class, cascade: ['persist'])]
+    protected File $bordereau;
+
     public function __construct()
     {
+        $this->billPayments = new ArrayCollection();
     }
 
     public function getId(): ?int
     {
         return $this->id;
     }
+
+    public function getBillPayments(): Collection
+    {
+        return $this->billPayments;
+    }
+
+    public function addBillPayment(BillPayment $billPayment): self
+    {
+        if (!$this->billPayments->contains($billPayment)) {
+            $this->billPayments[] = $billPayment;
+            $billPayment->setSddRegie($this);
+        }
+
+        return $this;
+    }
+
+    public function removeBillPayment(BillPayment $billPayment): self
+    {
+        if ($this->billPayments->removeElement($billPayment)) {
+            //            $billPayment->setSddBank(null); // TODO: actuellement, pas nullable: conserver?
+        }
+
+        return $this;
+    }
+
+    public function getFile(): File
+    {
+        return $this->file;
+    }
+
+    public function setFile(File $file): self
+    {
+        $this->file = $file;
+
+        return $this;
+    }
+
+    public function getBordereau(): File
+    {
+        return $this->bordereau;
+    }
+
+    public function setBordereau(File $bordereau): self
+    {
+        $this->bordereau = $bordereau;
+
+        return $this;
+    }
 }

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

@@ -6,12 +6,19 @@ namespace App\Entity\Booking;
 
 use App\Attribute\ActivityYearConstraintAware;
 use App\Attribute\OrganizationDefaultValue;
+use App\Entity\Access\Access;
+use App\Entity\Core\Tagg;
+use App\Entity\Product\Equipment;
 use App\Entity\Traits\ActivityYearTrait;
 use App\Enum\Booking\VisibilityEnum;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
 
 /**
- * Classe ... qui ...
+ * Données d'un évènement générique, classe de base des évènements.
+ *
+ * @see Event, Course, EducationalProject, Examen, OrganizationHoliday, PersonHoliday
  */
 #[ActivityYearConstraintAware(startYearFieldName: 'startYear', endYearFieldName: 'endYear')]
 #[OrganizationDefaultValue(fieldName: 'organization')]
@@ -25,6 +32,9 @@ abstract class AbstractBooking
     #[ORM\GeneratedValue]
     protected ?int $id = null;
 
+    #[ORM\Column(length: 255, nullable: false)]
+    protected string $discr;
+
     #[ORM\Column]
     protected string $name;
 
@@ -40,6 +50,22 @@ abstract class AbstractBooking
     #[ORM\Column(unique: true)]
     protected string $uuid;
 
+    #[ORM\ManyToMany(targetEntity: Access::class, inversedBy: 'practicalCourses', cascade: [], orphanRemoval: false)]
+    protected Collection $organizer;
+
+    #[ORM\ManyToMany(targetEntity: Equipment::class, cascade: [], orphanRemoval: false)]
+    protected Collection $equipments;
+
+    #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'bookings', cascade: ['persist'], orphanRemoval: false)]
+    protected Collection $tags;
+
+    public function __construct()
+    {
+        $this->organizer = new ArrayCollection();
+        $this->equipments = new ArrayCollection();
+        $this->tags = new ArrayCollection();
+    }
+
     public function getId(): ?int
     {
         return $this->id;
@@ -104,4 +130,67 @@ abstract class AbstractBooking
 
         return $this;
     }
+
+    public function getOrganizer(): Collection
+    {
+        return $this->organizer;
+    }
+
+    public function addOrganizer(Access $organizer): self
+    {
+        if (!$this->organizer->contains($organizer)) {
+            $this->organizer[] = $organizer;
+        }
+
+        return $this;
+    }
+
+    public function removeOrganizer(Access $organizer): self
+    {
+        $this->organizer->removeElement($organizer);
+
+        return $this;
+    }
+
+    public function getEquipments(): Collection
+    {
+        return $this->equipments;
+    }
+
+    public function addEquipment(Equipment $equipment): self
+    {
+        if (!$this->equipments->contains($equipment)) {
+            $this->equipments[] = $equipment;
+        }
+
+        return $this;
+    }
+
+    public function removeEquipment(Equipment $equipment): self
+    {
+        $this->equipments->removeElement($equipment);
+
+        return $this;
+    }
+
+    public function getTags(): Collection
+    {
+        return $this->tags;
+    }
+
+    public function addTag(Tagg $tag): self
+    {
+        if (!$this->tags->contains($tag)) {
+            $this->tags[] = $tag;
+        }
+
+        return $this;
+    }
+
+    public function removeTag(Tagg $tag): self
+    {
+        $this->tags->removeElement($tag);
+
+        return $this;
+    }
 }

+ 32 - 0
src/Entity/Booking/CalendarSynchro.php

@@ -5,6 +5,8 @@ declare(strict_types=1);
 namespace App\Entity\Booking;
 
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
+use App\Entity\Access\Access;
+use App\Entity\Core\File;
 use Doctrine\ORM\Mapping as ORM;
 
 /**
@@ -19,8 +21,38 @@ class CalendarSynchro
     #[ORM\GeneratedValue]
     private ?int $id = null;
 
+    #[ORM\OneToOne(inversedBy: 'calendarSynchro', targetEntity: Access::class, cascade: ['persist'])]
+    protected Access $access;
+
+    #[ORM\OneToOne(inversedBy: 'calendarSynchro', targetEntity: File::class, cascade: ['persist'])]
+    protected File $file;
+
     public function getId(): ?int
     {
         return $this->id;
     }
+
+    public function getAccess(): Access
+    {
+        return $this->access;
+    }
+
+    public function setAccess(Access $access): self
+    {
+        $this->access = $access;
+
+        return $this;
+    }
+
+    public function getFile(): File
+    {
+        return $this->file;
+    }
+
+    public function setFile(File $file): self
+    {
+        $this->file = $file;
+
+        return $this;
+    }
 }

+ 43 - 16
src/Entity/Booking/Course.php

@@ -6,11 +6,12 @@ namespace App\Entity\Booking;
 
 use ApiPlatform\Metadata\ApiResource;
 use App\Entity\Access\Access;
+use App\Entity\AccessWish\EducationStudentWish;
 use App\Entity\Core\Tagg;
 use App\Entity\Education\Education;
 use App\Entity\Education\EducationCurriculum;
 use App\Entity\Organization\Organization;
-use App\Entity\Place\Place;
+use App\Entity\Place\AbstractPlace;
 use App\Entity\Place\Room;
 use App\Entity\Product\Equipment;
 use App\Repository\Booking\CourseRepository;
@@ -36,20 +37,20 @@ use Doctrine\ORM\Mapping as ORM;
 class Course extends AbstractBooking
 {
     #[ORM\Column(length: 255, nullable: false)]
-    private string $discr = 'course';
+    protected string $discr = 'course';
 
     #[ORM\OneToMany(mappedBy: 'event', targetEntity: CourseRecur::class, cascade: ['persist'], orphanRemoval: true)]
-    private Collection $eventRecur;
+    protected Collection $eventRecur;
 
     #[ORM\OneToMany(mappedBy: 'parent', targetEntity: Course::class, orphanRemoval: true)]
-    private Collection $timeline;
+    protected Collection $timeline;
 
     #[ORM\ManyToOne(inversedBy: 'timeline')]
-    private Course $parent;
+    protected Course $parent;
 
     #[ORM\ManyToOne(inversedBy: 'courses')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
-    protected Place $place;
+    protected AbstractPlace $place;
 
     #[ORM\ManyToOne(inversedBy: 'courses')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
@@ -59,7 +60,7 @@ class Course extends AbstractBooking
     #[ORM\JoinTable(name: 'booking_organizer')]
     #[ORM\JoinColumn(name: 'booking_id', referencedColumnName: 'id')]
     #[ORM\InverseJoinColumn(name: 'organizer_id', referencedColumnName: 'id')]
-    private Collection $organizer;
+    protected Collection $organizer;
 
     #[ORM\ManyToOne(inversedBy: 'courses')]
     #[ORM\JoinColumn(nullable: false)]
@@ -67,35 +68,38 @@ class Course extends AbstractBooking
 
     #[ORM\ManyToOne(inversedBy: 'courses')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
-    private Education $education;
+    protected Education $education;
 
     #[ORM\ManyToMany(targetEntity: EducationCurriculum::class)]
-    private Collection $educationCurriculum;
+    protected Collection $educationCurriculum;
 
     #[ORM\ManyToMany(targetEntity: Access::class, inversedBy: 'courses')]
     #[ORM\JoinTable(name: 'course_student')]
     #[ORM\JoinColumn(name: 'course_id', referencedColumnName: 'id')]
     #[ORM\InverseJoinColumn(name: 'student_id', referencedColumnName: 'id')]
-    private Collection $students;
+    protected Collection $students;
 
     #[ORM\OneToMany(mappedBy: 'course', targetEntity: Work::class, cascade: ['persist'], orphanRemoval: true)]
-    private Collection $work;
+    protected Collection $work;
 
     #[ORM\ManyToMany(targetEntity: Equipment::class)]
     #[ORM\JoinTable(name: 'booking_equipment')]
     #[ORM\JoinColumn(name: 'booking_id', referencedColumnName: 'id')]
     #[ORM\InverseJoinColumn(name: 'equipment_id', referencedColumnName: 'id')]
-    private Collection $equipments;
+    protected Collection $equipments;
 
     #[ORM\OneToMany(mappedBy: 'course', targetEntity: AttendanceBooking::class, cascade: ['persist'], orphanRemoval: true)]
     #[ORM\JoinColumn(nullable: false)]
-    private Collection $attendanceBooking;
+    protected Collection $attendanceBooking;
 
     #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'courses', cascade: ['persist'])]
     #[ORM\JoinTable(name: 'tag_booking')]
     #[ORM\JoinColumn(name: 'booking_id', referencedColumnName: 'id')]
     #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
-    private Collection $tags;
+    protected Collection $tags;
+
+    #[ORM\OneToMany(mappedBy: 'course', targetEntity: EducationStudentWish::class, cascade: [], orphanRemoval: false)]
+    protected Collection $educationStudentWishes;
 
     public function __construct()
     {
@@ -108,6 +112,8 @@ class Course extends AbstractBooking
         $this->equipments = new ArrayCollection();
         $this->attendanceBooking = new ArrayCollection();
         $this->tags = new ArrayCollection();
+        $this->educationStudentWishes = new ArrayCollection();
+        parent::__construct();
     }
 
     public function getDiscr(): ?string
@@ -194,12 +200,12 @@ class Course extends AbstractBooking
         return $this;
     }
 
-    public function getPlace(): ?Place
+    public function getPlace(): ?AbstractPlace
     {
         return $this->place;
     }
 
-    public function setPlace(?Place $place): self
+    public function setPlace(?AbstractPlace $place): self
     {
         $this->place = $place;
 
@@ -421,4 +427,25 @@ class Course extends AbstractBooking
 
         return $this;
     }
+
+    public function getEducationStudentWishes(): Collection
+    {
+        return $this->educationStudentWishes;
+    }
+
+    public function addEducationStudentWish(EducationStudentWish $educationStudentWish): self
+    {
+        if (!$this->educationStudentWishes->contains($educationStudentWish)) {
+            $this->educationStudentWishes[] = $educationStudentWish;
+        }
+
+        return $this;
+    }
+
+    public function removeEducationStudentWish(EducationStudentWish $educationStudentWish): self
+    {
+        $this->educationStudentWishes->removeElement($educationStudentWish);
+
+        return $this;
+    }
 }

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

@@ -18,7 +18,7 @@ use Doctrine\ORM\Mapping as ORM;
 class CourseRecur extends AbstractBookingRecur
 {
     #[ORM\Column(length: 255, nullable: false)]
-    private string $discr = 'course';
+    protected string $discr = 'course';
 
     #[ORM\ManyToOne(inversedBy: 'eventRecur')]
     private Course $event;

+ 36 - 19
src/Entity/Booking/EducationalProject.php

@@ -12,7 +12,7 @@ use App\Entity\Billing\EducationalProjectPayer;
 use App\Entity\Core\File;
 use App\Entity\Core\Tagg;
 use App\Entity\Organization\Organization;
-use App\Entity\Place\Place;
+use App\Entity\Place\AbstractPlace;
 use App\Entity\Place\Room;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
 use Doctrine\Common\Collections\ArrayCollection;
@@ -31,16 +31,16 @@ use Doctrine\ORM\Mapping as ORM;
 class EducationalProject extends AbstractBooking
 {
     #[ORM\Column(length: 255, nullable: false)]
-    private string $discr = 'educationalproject';
+    protected string $discr = 'educationalproject';
 
     #[ORM\OneToMany(mappedBy: 'event', targetEntity: EducationalProjectRecur::class, cascade: ['persist'], orphanRemoval: true)]
-    private Collection $eventRecur;
+    protected Collection $eventRecur;
 
     #[ORM\OneToMany(mappedBy: 'parent', targetEntity: EducationalProject::class, orphanRemoval: true)]
-    private Collection $timeline;
+    protected Collection $timeline;
 
     #[ORM\ManyToOne(inversedBy: 'timeline')]
-    private EducationalProject $parent;
+    protected EducationalProject $parent;
 
     #[ORM\ManyToOne(inversedBy: 'educationalProjects')]
     #[ORM\JoinColumn(nullable: false)]
@@ -48,39 +48,39 @@ class EducationalProject extends AbstractBooking
 
     #[ORM\ManyToOne(inversedBy: 'silentPartners')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
-    private Access $silentPartner;
+    protected Access $silentPartner;
 
     #[ORM\ManyToOne(inversedBy: 'educationalProjects')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
-    private EducationalProjectPublic $public;
+    protected EducationalProjectPublic $public;
 
     #[ORM\ManyToOne(inversedBy: 'operationalPartners')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
-    private Access $operationalPartner;
+    protected Access $operationalPartner;
 
     #[ORM\ManyToMany(targetEntity: Access::class)]
     #[ORM\JoinTable(name: 'educationalproject_financier')]
-    private Collection $financiers;
+    protected Collection $financiers;
 
     #[ORM\ManyToMany(targetEntity: File::class)]
-    private Collection $files;
+    protected Collection $files;
 
     #[ORM\OneToMany(mappedBy: 'educationalProject', targetEntity: EducationalProjectIntangible::class, cascade: ['persist'], orphanRemoval: true)]
-    private Collection $educationalProjectIntangibles;
+    protected Collection $educationalProjectIntangibles;
 
     #[ORM\OneToMany(mappedBy: 'educationalProjectReceiver', targetEntity: EducationalProjectPayer::class, cascade: ['persist'], orphanRemoval: true)]
-    private Collection $billingReceivers;
+    protected Collection $billingReceivers;
 
     #[ORM\OneToMany(mappedBy: 'educationalProject', targetEntity: BillLine::class, orphanRemoval: true)]
-    private Collection $billLines;
+    protected Collection $billLines;
 
     #[ORM\OneToMany(mappedBy: 'educationalProject', targetEntity: AttendanceBooking::class, cascade: ['persist'], orphanRemoval: true)]
     #[ORM\JoinColumn(nullable: false)]
-    private Collection $attendanceBooking;
+    protected Collection $attendanceBooking;
 
     #[ORM\ManyToOne(inversedBy: 'educationalProjects')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
-    protected Place $place;
+    protected AbstractPlace $place;
 
     #[ORM\ManyToOne(inversedBy: 'educationalProjects')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
@@ -90,13 +90,16 @@ class EducationalProject extends AbstractBooking
     #[ORM\JoinTable(name: 'booking_organizer')]
     #[ORM\JoinColumn(name: 'booking_id', referencedColumnName: 'id')]
     #[ORM\InverseJoinColumn(name: 'organizer_id', referencedColumnName: 'id')]
-    private Collection $organizer;
+    protected Collection $organizer;
 
     #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'educationalProjects', cascade: ['persist'])]
     #[ORM\JoinTable(name: 'tag_booking')]
     #[ORM\JoinColumn(name: 'booking_id', referencedColumnName: 'id')]
     #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
-    private Collection $tags;
+    protected Collection $tags;
+
+    #[ORM\OneToOne(targetEntity: EducationalProjectAge::class, cascade: ['persist'])]
+    protected EducationalProjectAge $ageDistribution;
 
     public function __construct()
     {
@@ -110,6 +113,8 @@ class EducationalProject extends AbstractBooking
         $this->attendanceBooking = new ArrayCollection();
         $this->organizer = new ArrayCollection();
         $this->tags = new ArrayCollection();
+        $this->equipments = new ArrayCollection();
+        parent::__construct();
     }
 
     public function getDiscr(): ?string
@@ -412,12 +417,12 @@ class EducationalProject extends AbstractBooking
         return $this;
     }
 
-    public function getPlace(): ?Place
+    public function getPlace(): ?AbstractPlace
     {
         return $this->place;
     }
 
-    public function setPlace(?Place $place): self
+    public function setPlace(?AbstractPlace $place): self
     {
         $this->place = $place;
 
@@ -483,4 +488,16 @@ class EducationalProject extends AbstractBooking
 
         return $this;
     }
+
+    public function getAgeDistribution(): EducationalProjectAge
+    {
+        return $this->ageDistribution;
+    }
+
+    public function setAgeDistribution(EducationalProjectAge $ageDistribution): self
+    {
+        $this->ageDistribution = $ageDistribution;
+
+        return $this;
+    }
 }

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

@@ -16,7 +16,7 @@ use Doctrine\ORM\Mapping as ORM;
 class EducationalProjectRecur extends AbstractBookingRecur
 {
     #[ORM\Column(length: 255, nullable: false)]
-    private string $discr = 'educationalproject';
+    protected string $discr = 'educationalproject';
 
     #[ORM\ManyToOne(inversedBy: 'eventRecur')]
     private EducationalProject $event;

+ 32 - 18
src/Entity/Booking/Event.php

@@ -10,7 +10,7 @@ use App\Entity\Core\Categories;
 use App\Entity\Core\File;
 use App\Entity\Core\Tagg;
 use App\Entity\Organization\Organization;
-use App\Entity\Place\Place;
+use App\Entity\Place\AbstractPlace;
 use App\Entity\Place\PlaceSystem;
 use App\Entity\Place\Room;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
@@ -30,7 +30,7 @@ use Symfony\Component\Validator\Constraints as Assert;
 class Event extends AbstractBooking
 {
     #[ORM\Column(length: 255, nullable: false)]
-    private string $discr = 'event';
+    protected string $discr = 'event';
 
     #[ORM\ManyToOne(inversedBy: 'events')]
     #[ORM\JoinColumn(nullable: false)]
@@ -38,64 +38,64 @@ class Event extends AbstractBooking
 
     #[ORM\ManyToOne(inversedBy: 'events')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
-    protected Place $place;
+    protected AbstractPlace $place;
 
     #[ORM\ManyToOne(inversedBy: 'events')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
     protected Room $room;
 
     #[ORM\OneToMany(mappedBy: 'event', targetEntity: EventRecur::class, cascade: ['persist'], orphanRemoval: true)]
-    private Collection $eventRecur;
+    protected Collection $eventRecur;
 
     #[ORM\OneToMany(mappedBy: 'parent', targetEntity: Event::class, orphanRemoval: true)]
-    private Collection $timeline;
+    protected Collection $timeline;
 
     #[ORM\ManyToOne(inversedBy: 'timeline')]
-    private Event $parent;
+    protected Event $parent;
 
     #[Assert\Valid]
     #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'events')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
-    private File $image;
+    protected File $image;
 
     #[ORM\ManyToOne]
-    private EventGender $gender;
+    protected EventGender $gender;
 
     #[Assert\Valid]
     #[ORM\OneToMany(mappedBy: 'event', targetEntity: EventUser::class, cascade: ['persist'], orphanRemoval: true)]
-    private Collection $eventUser;
+    protected Collection $eventUser;
 
     #[ORM\ManyToMany(targetEntity: Categories::class, cascade: ['persist'])]
-    private Collection $categories;
+    protected Collection $categories;
 
     #[ORM\OneToMany(mappedBy: 'event', targetEntity: EventReport::class, orphanRemoval: true)]
-    private Collection $eventReports;
+    protected Collection $eventReports;
 
     #[ORM\ManyToMany(targetEntity: File::class, cascade: ['persist'], orphanRemoval: true)]
     #[ORM\JoinTable(name: 'event_files')]
     #[ORM\JoinColumn(name: 'event_id', referencedColumnName: 'id', onDelete: 'cascade')]
     #[ORM\InverseJoinColumn(name: 'file_id', referencedColumnName: 'id', onDelete: 'cascade')]
-    private Collection $files;
+    protected Collection $files;
 
     #[ORM\ManyToOne]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
-    private PlaceSystem $placeSystem;
+    protected PlaceSystem $placeSystem;
 
     #[ORM\OneToMany(mappedBy: 'event', targetEntity: AttendanceBooking::class, cascade: ['persist'], orphanRemoval: true)]
     #[ORM\JoinColumn(nullable: false)]
-    private Collection $attendanceBooking;
+    protected Collection $attendanceBooking;
 
     #[ORM\ManyToMany(targetEntity: Access::class, inversedBy: 'eventOrganizers')]
     #[ORM\JoinTable(name: 'booking_organizer')]
     #[ORM\JoinColumn(name: 'booking_id', referencedColumnName: 'id')]
     #[ORM\InverseJoinColumn(name: 'organizer_id', referencedColumnName: 'id')]
-    private Collection $organizer;
+    protected Collection $organizer;
 
     #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'events', cascade: ['persist'])]
     #[ORM\JoinTable(name: 'tag_booking')]
     #[ORM\JoinColumn(name: 'booking_id', referencedColumnName: 'id')]
     #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
-    private Collection $tags;
+    protected Collection $tags;
 
     public function __construct()
     {
@@ -108,6 +108,8 @@ class Event extends AbstractBooking
         $this->attendanceBooking = new ArrayCollection();
         $this->organizer = new ArrayCollection();
         $this->tags = new ArrayCollection();
+        $this->equipments = new ArrayCollection();
+        parent::__construct();
     }
 
     public function getDiscr(): ?string
@@ -134,12 +136,12 @@ class Event extends AbstractBooking
         return $this;
     }
 
-    public function getPlace(): ?Place
+    public function getPlace(): ?AbstractPlace
     {
         return $this->place;
     }
 
-    public function setPlace(?Place $place): self
+    public function setPlace(?AbstractPlace $place): self
     {
         $this->place = $place;
 
@@ -451,4 +453,16 @@ class Event extends AbstractBooking
 
         return $this;
     }
+
+    public function getEquipments(): Collection
+    {
+        return $this->equipments;
+    }
+
+    public function setEquipments(Collection $equipments): self
+    {
+        $this->equipments = $equipments;
+
+        return $this;
+    }
 }

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

@@ -16,7 +16,7 @@ use Doctrine\ORM\Mapping as ORM;
 class EventRecur extends AbstractBookingRecur
 {
     #[ORM\Column(length: 255, nullable: false)]
-    private string $discr = 'event';
+    protected string $discr = 'event';
 
     #[ORM\ManyToOne(inversedBy: 'eventRecur')]
     private Event $event;

+ 17 - 14
src/Entity/Booking/Examen.php

@@ -10,7 +10,7 @@ use App\Entity\Education\Education;
 use App\Entity\Education\EducationCurriculum;
 use App\Entity\Organization\Jury;
 use App\Entity\Organization\Organization;
-use App\Entity\Place\Place;
+use App\Entity\Place\AbstractPlace;
 use App\Entity\Place\Room;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
 use Doctrine\Common\Collections\ArrayCollection;
@@ -29,42 +29,42 @@ use Doctrine\ORM\Mapping as ORM;
 class Examen extends AbstractBooking
 {
     #[ORM\Column(length: 255, nullable: false)]
-    private string $discr = 'examen';
+    protected string $discr = 'examen';
 
     #[ORM\ManyToOne(inversedBy: 'examens')]
     #[ORM\JoinColumn(nullable: false)]
     protected Organization $organization;
 
     #[ORM\OneToMany(mappedBy: 'event', targetEntity: ExamenRecur::class, cascade: ['persist'], orphanRemoval: true)]
-    private Collection $eventRecur;
+    protected Collection $eventRecur;
 
     #[ORM\OneToMany(mappedBy: 'parent', targetEntity: Examen::class, orphanRemoval: true)]
-    private Collection $timeline;
+    protected Collection $timeline;
 
     #[ORM\ManyToOne(inversedBy: 'timeline')]
-    private Examen $parent;
+    protected Examen $parent;
 
     #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'examens')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
-    private Jury $jury;
+    protected Jury $jury;
 
     #[ORM\ManyToOne(inversedBy: 'examens')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
-    private Education $education;
+    protected Education $education;
 
     #[ORM\ManyToMany(targetEntity: EducationCurriculum::class)]
-    private Collection $educationCurriculum;
+    protected Collection $educationCurriculum;
 
     #[ORM\OneToMany(mappedBy: 'examen', targetEntity: ExamenConvocation::class, cascade: ['persist'], orphanRemoval: true)]
-    private Collection $convocation;
+    protected Collection $convocation;
 
     #[ORM\OneToMany(mappedBy: 'examen', targetEntity: AttendanceBooking::class, cascade: ['persist'], orphanRemoval: true)]
     #[ORM\JoinColumn(nullable: false)]
-    private Collection $attendanceBooking;
+    protected Collection $attendanceBooking;
 
     #[ORM\ManyToOne(inversedBy: 'examens')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
-    protected Place $place;
+    protected AbstractPlace $place;
 
     #[ORM\ManyToOne(inversedBy: 'examens')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
@@ -74,7 +74,7 @@ class Examen extends AbstractBooking
     #[ORM\JoinTable(name: 'tag_booking')]
     #[ORM\JoinColumn(name: 'booking_id', referencedColumnName: 'id')]
     #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
-    private Collection $tags;
+    protected Collection $tags;
 
     public function __construct()
     {
@@ -84,6 +84,9 @@ class Examen extends AbstractBooking
         $this->convocation = new ArrayCollection();
         $this->attendanceBooking = new ArrayCollection();
         $this->tags = new ArrayCollection();
+        $this->organizer = new ArrayCollection();
+        $this->equipments = new ArrayCollection();
+        parent::__construct();
     }
 
     public function getDiscr(): ?string
@@ -290,12 +293,12 @@ class Examen extends AbstractBooking
         return $this;
     }
 
-    public function getPlace(): ?Place
+    public function getPlace(): ?AbstractPlace
     {
         return $this->place;
     }
 
-    public function setPlace(?Place $place): self
+    public function setPlace(?AbstractPlace $place): self
     {
         $this->place = $place;
 

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

@@ -18,7 +18,7 @@ use Doctrine\ORM\Mapping as ORM;
 class ExamenRecur extends AbstractBookingRecur
 {
     #[ORM\Column(length: 255, nullable: false)]
-    private string $discr = 'examen';
+    protected string $discr = 'examen';
 
     #[ORM\ManyToOne(inversedBy: 'eventRecur')]
     private Examen $event;

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

@@ -23,7 +23,7 @@ use Doctrine\ORM\Mapping as ORM;
 class OrganizationHoliday extends AbstractBooking
 {
     #[ORM\Column(length: 255, nullable: false)]
-    private string $discr = 'organizationholiday';
+    protected string $discr = 'organizationholiday';
 
     #[ORM\OneToMany(mappedBy: 'event', targetEntity: OrganizationHolidayRecur::class, cascade: ['persist'], orphanRemoval: true)]
     private Collection $eventRecur;
@@ -35,6 +35,10 @@ class OrganizationHoliday extends AbstractBooking
     public function __construct()
     {
         $this->eventRecur = new ArrayCollection();
+        $this->organizer = new ArrayCollection();
+        $this->equipments = new ArrayCollection();
+        $this->tags = new ArrayCollection();
+        parent::__construct();
     }
 
     public function getDiscr(): ?string

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

@@ -16,7 +16,7 @@ use Doctrine\ORM\Mapping as ORM;
 class OrganizationHolidayRecur extends AbstractBookingRecur
 {
     #[ORM\Column(length: 255, nullable: false)]
-    private string $discr = 'organizationholiday';
+    protected string $discr = 'organizationholiday';
 
     #[ORM\ManyToOne(inversedBy: 'eventRecur')]
     private OrganizationHoliday $event;

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

@@ -7,6 +7,7 @@ namespace App\Entity\Booking;
 use ApiPlatform\Metadata\ApiResource;
 use App\Entity\Access\Access;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
+use App\Entity\Organization\Organization;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
@@ -23,7 +24,7 @@ use Doctrine\ORM\Mapping as ORM;
 class PersonHoliday extends AbstractBooking
 {
     #[ORM\Column(length: 255, nullable: false)]
-    private string $discr = 'personholiday';
+    protected string $discr = 'personholiday';
 
     #[ORM\OneToMany(mappedBy: 'event', targetEntity: PersonHolidayRecur::class, cascade: ['persist'], orphanRemoval: true)]
     protected Collection $eventRecur;
@@ -31,9 +32,17 @@ class PersonHoliday extends AbstractBooking
     #[ORM\ManyToOne(inversedBy: 'holidays')]
     private Access $access;
 
+    #[ORM\ManyToOne(targetEntity: Organization::class, cascade: [])]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: false, onDelete: 'SET NULL')]
+    protected Organization $organization;
+
     public function __construct()
     {
         $this->eventRecur = new ArrayCollection();
+        $this->organizer = new ArrayCollection();
+        $this->equipments = new ArrayCollection();
+        $this->tags = new ArrayCollection();
+        parent::__construct();
     }
 
     public function getDiscr(): ?string
@@ -89,4 +98,16 @@ class PersonHoliday extends AbstractBooking
 
         return $this;
     }
+
+    public function getOrganization(): Organization
+    {
+        return $this->organization;
+    }
+
+    public function setOrganization(Organization $organization): self
+    {
+        $this->organization = $organization;
+
+        return $this;
+    }
 }

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

@@ -18,7 +18,7 @@ use Doctrine\ORM\Mapping as ORM;
 class PersonHolidayRecur extends AbstractBookingRecur
 {
     #[ORM\Column(length: 255, nullable: false)]
-    private string $discr = 'personholiday';
+    protected string $discr = 'personholiday';
 
     #[ORM\ManyToOne(inversedBy: 'eventRecur')]
     private PersonHoliday $event;

+ 46 - 0
src/Entity/Core/AbstractControl.php

@@ -5,6 +5,8 @@ declare(strict_types=1);
 namespace App\Entity\Core;
 
 use App\Entity\Access\Access;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
 
 #[ORM\MappedSuperclass]
@@ -19,8 +21,52 @@ abstract class AbstractControl
     #[ORM\JoinColumn(nullable: true)]
     protected Access $accompanist;
 
+    #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'controls', cascade: ['persist'], orphanRemoval: false)]
+    protected Collection $tags;
+
+    public function __construct()
+    {
+        $this->tags = new ArrayCollection();
+    }
+
     public function getId(): ?int
     {
         return $this->id;
     }
+
+    public function getAccompanist(): Access
+    {
+        return $this->accompanist;
+    }
+
+    public function setAccompanist(Access $accompanist): self
+    {
+        $this->accompanist = $accompanist;
+
+        return $this;
+    }
+
+    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->addControl($this);
+        }
+
+        return $this;
+    }
 }

+ 34 - 0
src/Entity/Core/AbstractRepair.php

@@ -4,6 +4,8 @@ declare(strict_types=1);
 
 namespace App\Entity\Core;
 
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
 
 #[ORM\MappedSuperclass]
@@ -14,8 +16,40 @@ abstract class AbstractRepair
     #[ORM\GeneratedValue]
     protected ?int $id = null;
 
+    #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'repairs', cascade: ['persist'], orphanRemoval: false)]
+    protected Collection $tags;
+
+    public function __construct()
+    {
+        $this->tags = new ArrayCollection();
+    }
+
     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->addRepair($this);
+        }
+
+        return $this;
+    }
+
+    public function removeTag(Tagg $tag): self
+    {
+        if ($this->tags->removeElement($tag)) {
+            $tag->removeRepair($this);
+        }
+
+        return $this;
+    }
 }

+ 33 - 5
src/Entity/Core/AddressPostal.php

@@ -7,7 +7,7 @@ namespace App\Entity\Core;
 use ApiPlatform\Metadata\ApiResource;
 use App\Entity\Organization\OrganizationAddressPostal;
 use App\Entity\Person\PersonAddressPostal;
-use App\Entity\Place\Place;
+use App\Entity\Place\AbstractPlace;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
 use App\Entity\Traits\CreatedOnAndByTrait;
 use App\Repository\Core\AddressPostalRepository;
@@ -78,12 +78,16 @@ class AddressPostal
     #[ORM\OneToOne(mappedBy: 'addressPostal')]
     private PersonAddressPostal $personAddressPostal;
 
-    #[ORM\OneToMany(mappedBy: 'addressPostal', targetEntity: Place::class)]
+    #[ORM\OneToMany(mappedBy: 'addressPostal', targetEntity: AbstractPlace::class)]
     private Collection $places;
 
+    #[ORM\OneToMany(mappedBy: 'addressPostal', targetEntity: OrganizationAddressPostal::class, cascade: [], orphanRemoval: false)]
+    protected Collection $organizationAddressPostals;
+
     public function __construct()
     {
         $this->places = new ArrayCollection();
+        $this->organizationAddressPostals = new ArrayCollection();
     }
 
     public function getId(): ?int
@@ -224,14 +228,14 @@ class AddressPostal
     }
 
     /**
-     * @return Collection<int, Place>
+     * @return Collection<int, AbstractPlace>
      */
     public function getPlaces(): Collection
     {
         return $this->places;
     }
 
-    public function addPlace(Place $place): self
+    public function addPlace(AbstractPlace $place): self
     {
         if (!$this->places->contains($place)) {
             $this->places[] = $place;
@@ -241,7 +245,7 @@ class AddressPostal
         return $this;
     }
 
-    public function removePlace(Place $place): self
+    public function removePlace(AbstractPlace $place): self
     {
         if ($this->places->removeElement($place)) {
             // set the owning side to null (unless already changed)
@@ -252,4 +256,28 @@ class AddressPostal
 
         return $this;
     }
+
+    public function getOrganizationAddressPostals(): Collection
+    {
+        return $this->organizationAddressPostals;
+    }
+
+    public function addOrganizationAddressPostal(OrganizationAddressPostal $organizationAddressPostal): self
+    {
+        if (!$this->organizationAddressPostals->contains($organizationAddressPostal)) {
+            $this->organizationAddressPostals[] = $organizationAddressPostal;
+            $organizationAddressPostal->setAddressPostal($this);
+        }
+
+        return $this;
+    }
+
+    public function removeOrganizationAddressPostal(OrganizationAddressPostal $organizationAddressPostal): self
+    {
+        if ($this->organizationAddressPostals->removeElement($organizationAddressPostal)) {
+            //            $organizationAddressPostal->setAddressPostal(null); // TODO: actuellement, pas nullable: conserver?
+        }
+
+        return $this;
+    }
 }

+ 16 - 0
src/Entity/Core/City.php

@@ -19,8 +19,24 @@ class City
     #[ORM\GeneratedValue]
     private ?int $id = null;
 
+    #[ORM\ManyToOne(targetEntity: Department::class, cascade: [])]
+    #[ORM\JoinColumn(nullable: false)]
+    protected Department $department;
+
     public function getId(): ?int
     {
         return $this->id;
     }
+
+    public function getDepartment(): Department
+    {
+        return $this->department;
+    }
+
+    public function setDepartment(Department $department): self
+    {
+        $this->department = $department;
+
+        return $this;
+    }
 }

+ 5 - 5
src/Entity/Core/ContactPoint.php

@@ -7,7 +7,7 @@ namespace App\Entity\Core;
 use ApiPlatform\Metadata\ApiResource;
 use App\Entity\Organization\Organization;
 use App\Entity\Person\Person;
-use App\Entity\Place\Place;
+use App\Entity\Place\AbstractPlace;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
 use App\Entity\Traits\CreatedOnAndByTrait;
 use App\Enum\Core\ContactPointTypeEnum;
@@ -80,7 +80,7 @@ class ContactPoint
     #[ORM\InverseJoinColumn(name: 'person_id', referencedColumnName: 'id')]
     private Collection $person;
 
-    #[ORM\ManyToMany(targetEntity: Place::class, mappedBy: 'contactpoint')]
+    #[ORM\ManyToMany(targetEntity: AbstractPlace::class, mappedBy: 'contactpoint')]
     #[ORM\JoinTable(name: 'place_contactpoint')]
     #[ORM\JoinColumn(name: 'contactPoint_id', referencedColumnName: 'id', unique: true)]
     #[ORM\InverseJoinColumn(name: 'place_id', referencedColumnName: 'id')]
@@ -268,14 +268,14 @@ class ContactPoint
     }
 
     /**
-     * @return Collection<int, Place>
+     * @return Collection<int, AbstractPlace>
      */
     public function getPlace(): Collection
     {
         return $this->place;
     }
 
-    public function addPlace(Place $place): self
+    public function addPlace(AbstractPlace $place): self
     {
         if (!$this->place->contains($place)) {
             $this->place[] = $place;
@@ -285,7 +285,7 @@ class ContactPoint
         return $this;
     }
 
-    public function removePlace(Place $place): self
+    public function removePlace(AbstractPlace $place): self
     {
         if ($this->place->removeElement($place)) {
             $place->removeContactpoint($this);

+ 16 - 0
src/Entity/Core/Department.php

@@ -19,8 +19,24 @@ class Department
     #[ORM\GeneratedValue]
     private ?int $id = null;
 
+    #[ORM\ManyToOne(targetEntity: Region::class, cascade: [])]
+    #[ORM\JoinColumn(nullable: false)]
+    protected Region $region;
+
     public function getId(): ?int
     {
         return $this->id;
     }
+
+    public function getRegion(): Region
+    {
+        return $this->region;
+    }
+
+    public function setRegion(Region $region): self
+    {
+        $this->region = $region;
+
+        return $this;
+    }
 }

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

@@ -10,10 +10,12 @@ use ApiPlatform\Metadata\Get;
 use ApiPlatform\Metadata\Post;
 use ApiPlatform\Metadata\Put;
 use App\Entity\AccessWish\DocumentWish;
+use App\Entity\Booking\CalendarSynchro;
 use App\Entity\Booking\Event;
 use App\Entity\Booking\EventReport;
 use App\Entity\Booking\Work;
 use App\Entity\Message\TemplateSystem;
+use App\Entity\Network\Network;
 use App\Entity\Organization\Activity;
 use App\Entity\Organization\OnlineRegistrationSettings;
 use App\Entity\Organization\Organization;
@@ -231,6 +233,12 @@ class File
     #[ORM\JoinColumn(onDelete: 'CASCADE')]
     private TemplateSystem $templateSystem;
 
+    #[ORM\OneToMany(mappedBy: 'image', targetEntity: Network::class)]
+    private Collection $networks;
+
+    #[ORM\OneToOne(targetEntity: CalendarSynchro::class, mappedBy: 'file')]
+    private CalendarSynchro $calendarSynchro;
+
     #[Pure]
     public function __construct()
     {
@@ -241,6 +249,7 @@ class File
         $this->events = new ArrayCollection();
         $this->activityLogos = new ArrayCollection();
         $this->activityImages = new ArrayCollection();
+        $this->networks = new ArrayCollection();
     }
 
     public function getId(): ?int
@@ -738,4 +747,40 @@ class File
 
         return $this;
     }
+
+    public function getNetworks(): Collection
+    {
+        return $this->networks;
+    }
+
+    public function addNetwork(Network $network): self
+    {
+        if (!$this->networks->contains($network)) {
+            $this->networks[] = $network;
+            $network->setImage($this);
+        }
+
+        return $this;
+    }
+
+    public function removeNetwork(Network $network): self
+    {
+        if ($this->networks->removeElement($network)) {
+            //            $network->setImage(null);  // TODO: actuellement, pas nullable: conserver?
+        }
+
+        return $this;
+    }
+
+    public function getCalendarSynchro(): CalendarSynchro
+    {
+        return $this->calendarSynchro;
+    }
+
+    public function setCalendarSynchro(CalendarSynchro $calendarSynchro): self
+    {
+        $this->calendarSynchro = $calendarSynchro;
+
+        return $this;
+    }
 }

+ 120 - 0
src/Entity/Core/LoginLog.php

@@ -0,0 +1,120 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Core;
+
+use ApiPlatform\Metadata\ApiResource;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ApiResource(operations: [])]
+#[ORM\Entity]
+class LoginLog
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private int $id;
+
+    #[ORM\Column]
+    protected mixed $login;
+
+    #[ORM\Column(type: 'integer', options: ['nullable' => true])]
+    protected int $organizationId;
+
+    #[ORM\Column]
+    protected mixed $navigateur;
+
+    #[ORM\Column]
+    protected mixed $ip;
+
+    #[ORM\Column(type: 'date', options: ['nullable' => true])]
+    protected ?\DateTimeInterface $date;
+
+    #[ORM\Column]
+    protected mixed $type;
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): self
+    {
+        $this->id = $id;
+
+        return $this;
+    }
+
+    public function getLogin(): mixed
+    {
+        return $this->login;
+    }
+
+    public function setLogin(mixed $login): self
+    {
+        $this->login = $login;
+
+        return $this;
+    }
+
+    public function getOrganizationId(): int
+    {
+        return $this->organizationId;
+    }
+
+    public function setOrganizationId(int $organizationId): self
+    {
+        $this->organizationId = $organizationId;
+
+        return $this;
+    }
+
+    public function getNavigateur(): mixed
+    {
+        return $this->navigateur;
+    }
+
+    public function setNavigateur(mixed $navigateur): self
+    {
+        $this->navigateur = $navigateur;
+
+        return $this;
+    }
+
+    public function getIp(): mixed
+    {
+        return $this->ip;
+    }
+
+    public function setIp(mixed $ip): self
+    {
+        $this->ip = $ip;
+
+        return $this;
+    }
+
+    public function getDate(): \DateTimeInterface
+    {
+        return $this->date;
+    }
+
+    public function setDate(\DateTimeInterface $date): self
+    {
+        $this->date = $date;
+
+        return $this;
+    }
+
+    public function getType(): mixed
+    {
+        return $this->type;
+    }
+
+    public function setType(mixed $type): self
+    {
+        $this->type = $type;
+
+        return $this;
+    }
+}

+ 16 - 0
src/Entity/Core/Region.php

@@ -19,8 +19,24 @@ class Region
     #[ORM\GeneratedValue]
     private ?int $id = null;
 
+    #[ORM\ManyToOne(targetEntity: Country::class, cascade: [])]
+    #[ORM\JoinColumn(nullable: false)]
+    protected Country $country;
+
     public function getId(): ?int
     {
         return $this->id;
     }
+
+    public function getCountry(): Country
+    {
+        return $this->country;
+    }
+
+    public function setCountry(Country $country): self
+    {
+        $this->country = $country;
+
+        return $this;
+    }
 }

+ 182 - 10
src/Entity/Core/Tagg.php

@@ -7,16 +7,19 @@ namespace App\Entity\Core;
 use ApiPlatform\Metadata\ApiResource;
 use App\Entity\Access\Access;
 use App\Entity\AccessWish\AccessWish;
+use App\Entity\Billing\AbstractBillAccounting;
 use App\Entity\Billing\AbstractBillingIntangible;
-use App\Entity\Billing\BillAccounting;
 use App\Entity\Billing\BillPayment;
+use App\Entity\Booking\AbstractBooking;
 use App\Entity\Booking\Course;
 use App\Entity\Booking\EducationalProject;
 use App\Entity\Booking\Event;
 use App\Entity\Booking\Examen;
 use App\Entity\Education\Education;
+use App\Entity\Education\EducationCurriculumPack;
 use App\Entity\Education\EducationNotation;
 use App\Entity\Education\EducationStudent;
+use App\Entity\Message\AbstractMessage;
 use App\Entity\Message\Email;
 use App\Entity\Message\Mail;
 use App\Entity\Message\Sms;
@@ -24,9 +27,10 @@ use App\Entity\Organization\Activity;
 use App\Entity\Organization\Jury;
 use App\Entity\Organization\Organization;
 use App\Entity\Person\Commission;
-use App\Entity\Place\Place;
+use App\Entity\Place\AbstractPlace;
 use App\Entity\Place\PlaceControl;
 use App\Entity\Place\PlaceRepair;
+use App\Entity\Product\AbstractProduct;
 use App\Entity\Product\Equipment;
 use App\Entity\Product\EquipmentControl;
 use App\Entity\Product\EquipmentLoan;
@@ -60,7 +64,7 @@ class Tagg
     #[ORM\ManyToMany(targetEntity: Organization::class, mappedBy: 'tags')]
     protected Collection $organizations;
 
-    #[ORM\ManyToMany(targetEntity: BillAccounting::class, mappedBy: 'tags')]
+    #[ORM\ManyToMany(targetEntity: AbstractBillAccounting::class, mappedBy: 'tags')]
     protected Collection $billAccountings;
 
     #[ORM\ManyToMany(targetEntity: Equipment::class, mappedBy: 'tags')]
@@ -123,7 +127,7 @@ class Tagg
     #[ORM\ManyToMany(targetEntity: EquipmentLoan::class, mappedBy: 'tags')]
     protected Collection $equipmentLoans;
 
-    #[ORM\ManyToMany(targetEntity: Place::class, mappedBy: 'tags')]
+    #[ORM\ManyToMany(targetEntity: AbstractPlace::class, mappedBy: 'tags')]
     protected Collection $places;
 
     #[ORM\ManyToMany(targetEntity: Email::class, mappedBy: 'tags')]
@@ -135,6 +139,24 @@ class Tagg
     #[ORM\ManyToMany(targetEntity: Sms::class, mappedBy: 'tags')]
     protected Collection $sms;
 
+    #[ORM\ManyToMany(targetEntity: AbstractProduct::class, mappedBy: 'tags', cascade: [], orphanRemoval: false)]
+    protected Collection $products;
+
+    #[ORM\ManyToMany(targetEntity: AbstractBooking::class, mappedBy: 'tags', cascade: [], orphanRemoval: false)]
+    protected Collection $bookings;
+
+    #[ORM\ManyToMany(targetEntity: AbstractMessage::class, mappedBy: 'tags', cascade: [], orphanRemoval: false)]
+    protected Collection $messages;
+
+    #[ORM\ManyToMany(targetEntity: AbstractRepair::class, mappedBy: 'tags', cascade: [], orphanRemoval: false)]
+    protected Collection $repairs;
+
+    #[ORM\ManyToMany(targetEntity: AbstractControl::class, mappedBy: 'tags', cascade: [], orphanRemoval: false)]
+    protected Collection $controls;
+
+    #[ORM\ManyToMany(targetEntity: EducationCurriculumPack::class, mappedBy: 'tags', cascade: [], orphanRemoval: false)]
+    protected Collection $educationCurriculumPacks;
+
     public function __construct()
     {
         $this->accesses = new ArrayCollection();
@@ -164,6 +186,12 @@ class Tagg
         $this->emails = new ArrayCollection();
         $this->mails = new ArrayCollection();
         $this->sms = new ArrayCollection();
+        $this->products = new ArrayCollection();
+        $this->bookings = new ArrayCollection();
+        $this->messages = new ArrayCollection();
+        $this->repairs = new ArrayCollection();
+        $this->controls = new ArrayCollection();
+        $this->educationCurriculumPacks = new ArrayCollection();
     }
 
     public function getId(): ?int
@@ -238,14 +266,14 @@ class Tagg
     }
 
     /**
-     * @return Collection<int, BillAccounting>
+     * @return Collection<int, AbstractBillAccounting>
      */
     public function getBillAccountings(): Collection
     {
         return $this->billAccountings;
     }
 
-    public function addBillAccounting(BillAccounting $billAccounting): self
+    public function addBillAccounting(AbstractBillAccounting $billAccounting): self
     {
         if (!$this->billAccountings->contains($billAccounting)) {
             $this->billAccountings[] = $billAccounting;
@@ -255,7 +283,7 @@ class Tagg
         return $this;
     }
 
-    public function removeBillAccounting(BillAccounting $billAccounting): self
+    public function removeBillAccounting(AbstractBillAccounting $billAccounting): self
     {
         if ($this->billAccountings->removeElement($billAccounting)) {
             $billAccounting->removeTag($this);
@@ -805,14 +833,14 @@ class Tagg
     }
 
     /**
-     * @return Collection<int, Place>
+     * @return Collection<int, AbstractPlace>
      */
     public function getPlaces(): Collection
     {
         return $this->places;
     }
 
-    public function addPlace(Place $place): self
+    public function addPlace(AbstractPlace $place): self
     {
         if (!$this->places->contains($place)) {
             $this->places[] = $place;
@@ -822,7 +850,7 @@ class Tagg
         return $this;
     }
 
-    public function removePlace(Place $place): self
+    public function removePlace(AbstractPlace $place): self
     {
         if ($this->places->removeElement($place)) {
             $place->removeTag($this);
@@ -911,4 +939,148 @@ class Tagg
 
         return $this;
     }
+
+    public function getProducts(): Collection
+    {
+        return $this->products;
+    }
+
+    public function addProduct(AbstractProduct $product): self
+    {
+        if (!$this->products->contains($product)) {
+            $this->products[] = $product;
+            $product->addTag($this);
+        }
+
+        return $this;
+    }
+
+    public function removeProduct(AbstractProduct $product): self
+    {
+        if ($this->products->removeElement($product)) {
+            $product->removeTag($this);
+        }
+
+        return $this;
+    }
+
+    public function getBookings(): Collection
+    {
+        return $this->bookings;
+    }
+
+    public function addBooking(AbstractBooking $booking): self
+    {
+        if (!$this->bookings->contains($booking)) {
+            $this->bookings[] = $booking;
+            $booking->addTag($this);
+        }
+
+        return $this;
+    }
+
+    public function removeBooking(AbstractBooking $booking): self
+    {
+        if ($this->bookings->removeElement($booking)) {
+            $booking->removeTag($this);
+        }
+
+        return $this;
+    }
+
+    public function getMessages(): Collection
+    {
+        return $this->messages;
+    }
+
+    public function addMessage(mixed $message): self
+    {
+        if (!$this->messages->contains($message)) {
+            $this->messages[] = $message;
+            $message->addTag($this);
+        }
+
+        return $this;
+    }
+
+    public function removeMessage(mixed $message): self
+    {
+        if ($this->messages->removeElement($message)) {
+            $message->removeTag($this);
+        }
+
+        return $this;
+    }
+
+    public function getRepairs(): Collection
+    {
+        return $this->repairs;
+    }
+
+    public function addRepair(AbstractRepair $repair): self
+    {
+        if (!$this->repairs->contains($repair)) {
+            $this->repairs[] = $repair;
+            $repair->addTag($this);
+        }
+
+        return $this;
+    }
+
+    public function removeRepair(AbstractRepair $repair): self
+    {
+        if ($this->repairs->removeElement($repair)) {
+            $repair->removeTag($this);
+        }
+
+        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;
+    }
+
+    public function getEducationCurriculumPacks(): Collection
+    {
+        return $this->educationCurriculumPacks;
+    }
+
+    public function addEducationCurriculumPack(EducationCurriculumPack $educationCurriculumPack): self
+    {
+        if (!$this->educationCurriculumPacks->contains($educationCurriculumPack)) {
+            $this->educationCurriculumPacks[] = $educationCurriculumPack;
+            $educationCurriculumPack->addTag($this);
+        }
+
+        return $this;
+    }
+
+    public function removeEducationCurriculumPack(EducationCurriculumPack $educationCurriculumPack): self
+    {
+        if ($this->educationCurriculumPacks->removeElement($educationCurriculumPack)) {
+            $educationCurriculumPack->removeTag($this);
+        }
+
+        return $this;
+    }
 }

+ 142 - 0
src/Entity/Custom/Search/UserSearchItem.php

@@ -0,0 +1,142 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Custom\Search;
+
+use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
+use ApiPlatform\Metadata\ApiFilter;
+use ApiPlatform\Metadata\ApiResource;
+use ApiPlatform\Metadata\Get;
+use ApiPlatform\Metadata\GetCollection;
+use App\Filter\ApiPlatform\Utils\InFilter;
+use App\Repository\Custom\Search\UserSearchItemRepository;
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * Données réduites d'identification d'un utilisateur (ids, noms)
+ * Utilisées entre autres pour les listes déroulantes de recherche.
+ *
+ * Fichier source de la view : ./sql/schema-extensions/003-view_search_user.sql
+ *
+ * @see App\Doctrine\Custom\Search\RestrictToOrganizationIdExtension.php
+ */
+#[ApiResource(
+    operations: [
+        new Get(
+            uriTemplate: '/search/users/{id}',
+            security: 'object.getOrganizationId() == user.getOrganization().getId()'
+        ),
+        new GetCollection(
+            uriTemplate: '/search/users',
+            paginationMaximumItemsPerPage: 10,
+            paginationClientItemsPerPage: true,
+            order: ['fullName' => 'ASC']
+        ),
+    ]
+)]
+#[ORM\Table(name: 'view_search_user')]
+#[ORM\Entity(repositoryClass: UserSearchItemRepository::class, readOnly: true)]
+#[ApiFilter(filterClass: InFilter::class, properties: ['id'])]
+#[ApiFilter(filterClass: SearchFilter::class, properties: ['fullName' => 'ipartial'])]
+class UserSearchItem
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    private int $id;
+
+    #[ORM\Column(type: 'integer')]
+    private ?int $organizationId = null;
+
+    #[ORM\Column(type: 'integer')]
+    private ?int $personId = null;
+
+    #[ORM\Column(type: 'string')]
+    private ?string $username = null;
+
+    #[ORM\Column(type: 'string')]
+    private ?string $name = null;
+
+    #[ORM\Column(type: 'string')]
+    private ?string $givenName = null;
+
+    #[ORM\Column(type: 'string')]
+    private ?string $fullName = null;
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): self
+    {
+        $this->id = $id;
+        return $this;
+    }
+
+    public function getOrganizationId(): ?int
+    {
+        return $this->organizationId;
+    }
+
+    public function setOrganizationId(?int $organizationId): self
+    {
+        $this->organizationId = $organizationId;
+        return $this;
+    }
+
+    public function getPersonId(): ?int
+    {
+        return $this->personId;
+    }
+
+    public function setPersonId(?int $personId): self
+    {
+        $this->personId = $personId;
+        return $this;
+    }
+
+    public function getUsername(): ?string
+    {
+        return $this->username;
+    }
+
+    public function setUsername(?string $username): self
+    {
+        $this->username = $username;
+        return $this;
+    }
+
+    public function getName(): ?string
+    {
+        return $this->name;
+    }
+
+    public function setName(?string $name): self
+    {
+        $this->name = $name;
+        return $this;
+    }
+
+    public function getGivenName(): ?string
+    {
+        return $this->givenName;
+    }
+
+    public function setGivenName(?string $givenName): self
+    {
+        $this->givenName = $givenName;
+        return $this;
+    }
+
+    public function getFullName(): ?string
+    {
+        return $this->fullName;
+    }
+
+    public function setFullName(?string $fullName): self
+    {
+        $this->fullName = $fullName;
+        return $this;
+    }
+}

+ 28 - 0
src/Entity/Education/Cycle.php

@@ -65,9 +65,13 @@ class Cycle
     #[ORM\OneToMany(mappedBy: 'cycle', targetEntity: CycleByEducation::class, orphanRemoval: true)]
     private Collection $cycleByEducations;
 
+    #[ORM\OneToMany(mappedBy: 'cycle', targetEntity: EducationCurriculum::class, cascade: [], orphanRemoval: false)]
+    protected Collection $educationCurriculums;
+
     public function __construct()
     {
         $this->cycleByEducations = new ArrayCollection();
+        $this->educationCurriculums = new ArrayCollection();
     }
 
     public function getId(): ?int
@@ -164,4 +168,28 @@ class Cycle
 
         return $this;
     }
+
+    public function getEducationCurriculums(): Collection
+    {
+        return $this->educationCurriculums;
+    }
+
+    public function addEducationCurriculum(EducationCurriculum $educationCurriculum): self
+    {
+        if (!$this->educationCurriculums->contains($educationCurriculum)) {
+            $this->educationCurriculums[] = $educationCurriculum;
+            $educationCurriculum->setCycle($this);
+        }
+
+        return $this;
+    }
+
+    public function removeEducationCurriculum(EducationCurriculum $educationCurriculum): self
+    {
+        if ($this->educationCurriculums->removeElement($educationCurriculum)) {
+            $educationCurriculum->setCycle(null);
+        }
+
+        return $this;
+    }
 }

+ 29 - 0
src/Entity/Education/Education.php

@@ -5,6 +5,7 @@ declare(strict_types=1);
 namespace App\Entity\Education;
 
 use ApiPlatform\Metadata\ApiResource;
+use App\Entity\AccessWish\EducationStudentWish;
 use App\Entity\Booking\Course;
 use App\Entity\Booking\Examen;
 use App\Entity\Core\Tagg;
@@ -59,6 +60,9 @@ class Education
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
     private EducationNotationConfig $educationNotationConfig;
 
+    #[ORM\OneToMany(mappedBy: 'educationWish', targetEntity: EducationStudentWish::class, cascade: [], orphanRemoval: true)]
+    protected Collection $educationWishes;
+
     public function __construct()
     {
         $this->educationCurriculums = new ArrayCollection();
@@ -67,6 +71,7 @@ class Education
         $this->examens = new ArrayCollection();
         $this->educationTeachers = new ArrayCollection();
         $this->tags = new ArrayCollection();
+        $this->educationWishes = new ArrayCollection();
     }
 
     public function getId(): ?int
@@ -283,4 +288,28 @@ class Education
 
         return $this;
     }
+
+    public function getEducationWishes(): Collection
+    {
+        return $this->educationWishes;
+    }
+
+    public function addEducationWish(EducationStudentWish $educationWish): self
+    {
+        if (!$this->educationWishes->contains($educationWish)) {
+            $this->educationWishes[] = $educationWish;
+            $educationWish->setEducationWish($this);
+        }
+
+        return $this;
+    }
+
+    public function removeEducationWish(EducationStudentWish $educationWish): self
+    {
+        if ($this->educationWishes->removeElement($educationWish)) {
+            $educationWish->setEducationWish(null);
+        }
+
+        return $this;
+    }
 }

+ 34 - 0
src/Entity/Education/EducationComplement.php

@@ -5,6 +5,8 @@ declare(strict_types=1);
 namespace App\Entity\Education;
 
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
 
 /**
@@ -19,8 +21,40 @@ class EducationComplement
     #[ORM\GeneratedValue]
     private ?int $id = null;
 
+    #[ORM\OneToMany(mappedBy: 'educationComplement', targetEntity: Education::class, cascade: [], orphanRemoval: true)]
+    protected Collection $educations;
+
+    public function __construct()
+    {
+        $this->educations = new ArrayCollection();
+    }
+
     public function getId(): ?int
     {
         return $this->id;
     }
+
+    public function getEducations(): Collection
+    {
+        return $this->educations;
+    }
+
+    public function addEducation(Education $education): self
+    {
+        if (!$this->educations->contains($education)) {
+            $this->educations[] = $education;
+            $education->setEducationComplement($this);
+        }
+
+        return $this;
+    }
+
+    public function removeEducation(Education $education): self
+    {
+        if ($this->educations->removeElement($education)) {
+            $education->setEducationComplement(null);
+        }
+
+        return $this;
+    }
 }

+ 217 - 0
src/Entity/Education/EducationCurriculum.php

@@ -5,6 +5,10 @@ declare(strict_types=1);
 namespace App\Entity\Education;
 
 use ApiPlatform\Metadata\ApiResource;
+use App\Entity\AccessWish\EducationStudentWish;
+use App\Entity\Booking\Course;
+use App\Entity\Booking\Examen;
+use App\Entity\Product\Intangible;
 use App\Repository\Education\EducationCurriculumRepository;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
 use Doctrine\Common\Collections\ArrayCollection;
@@ -42,10 +46,53 @@ class EducationCurriculum
     #[ORM\InverseJoinColumn(name: 'educationTiming_id', referencedColumnName: 'id')]
     private Collection $educationTimings;
 
+    #[ORM\OneToMany(mappedBy: 'educationCurriculum', targetEntity: EducationStudentWish::class, cascade: [], orphanRemoval: false)]
+    protected Collection $educationStudentWish;
+
+    #[ORM\ManyToMany(targetEntity: Course::class, mappedBy: 'educationCurriculum', cascade: [], orphanRemoval: false)]
+    protected Collection $courses;
+
+    #[ORM\ManyToMany(targetEntity: Examen::class, mappedBy: 'educationCurriculum', cascade: [], orphanRemoval: false)]
+    protected Collection $examens;
+
+    #[ORM\ManyToMany(targetEntity: Intangible::class, mappedBy: 'educationCurriculums', cascade: [], orphanRemoval: false)]
+    protected Collection $intangibles;
+
+    #[ORM\ManyToMany(
+        targetEntity: EducationCurriculumPack::class,
+        mappedBy: 'requiredEducationCurriculums',
+        cascade: [],
+        orphanRemoval: true,
+    )]
+    protected Collection $requiredEducationCurriculumPacks;
+
+    #[ORM\ManyToMany(
+        targetEntity: EducationCurriculumPack::class,
+        mappedBy: 'requiredChoicesEducationCurriculums',
+        cascade: [],
+        orphanRemoval: true,
+    )]
+    protected Collection $requiredChoicesEducationCurriculumPacks;
+
+    #[ORM\ManyToMany(
+        targetEntity: EducationCurriculumPack::class,
+        mappedBy: 'optionnalEducationCurriculums',
+        cascade: [],
+        orphanRemoval: true,
+    )]
+    protected Collection $optionnalEducationCurriculumPacks;
+
     public function __construct()
     {
         $this->educationStudent = new ArrayCollection();
         $this->educationTimings = new ArrayCollection();
+        $this->educationStudentWish = new ArrayCollection();
+        $this->courses = new ArrayCollection();
+        $this->examens = new ArrayCollection();
+        $this->intangibles = new ArrayCollection();
+        $this->requiredEducationCurriculumPacks = new ArrayCollection();
+        $this->requiredChoicesEducationCurriculumPacks = new ArrayCollection();
+        $this->optionnalEducationCurriculumPacks = new ArrayCollection();
     }
 
     public function getId(): ?int
@@ -142,4 +189,174 @@ class EducationCurriculum
 
         return $this;
     }
+
+    public function getEducationStudentWish(): Collection
+    {
+        return $this->educationStudentWish;
+    }
+
+    public function addEducationStudentWish(EducationStudentWish $educationStudentWish): self
+    {
+        if (!$this->educationStudentWish->contains($educationStudentWish)) {
+            $this->educationStudentWish[] = $educationStudentWish;
+            $educationStudentWish->setEducationCurriculum($this);
+        }
+
+        return $this;
+    }
+
+    public function removeEducationStudentWish(EducationStudentWish $educationStudentWish): self
+    {
+        if ($this->educationStudentWish->removeElement($educationStudentWish)) {
+            $educationStudentWish->setEducationCurriculum(null);
+        }
+
+        return $this;
+    }
+
+    public function getCourses(): Collection
+    {
+        return $this->courses;
+    }
+
+    public function addCourse(Course $course): self
+    {
+        if (!$this->courses->contains($course)) {
+            $this->courses[] = $course;
+            $course->addEducationCurriculum($this);
+        }
+
+        return $this;
+    }
+
+    public function removeCourse(Course $course): self
+    {
+        if ($this->courses->removeElement($course)) {
+            $course->removeEducationCurriculum($this);
+        }
+
+        return $this;
+    }
+
+    public function getExamens(): Collection
+    {
+        return $this->examens;
+    }
+
+    public function addExamen(Examen $examen): self
+    {
+        if (!$this->examens->contains($examen)) {
+            $this->examens[] = $examen;
+            $examen->addEducationCurriculum($this);
+        }
+
+        return $this;
+    }
+
+    public function removeExamen(Examen $examen): self
+    {
+        if ($this->examens->removeElement($examen)) {
+            $examen->removeEducationCurriculum($this);
+        }
+
+        return $this;
+    }
+
+    public function getIntangibles(): Collection
+    {
+        return $this->intangibles;
+    }
+
+    public function addIntangible(Intangible $intangible): self
+    {
+        if (!$this->intangibles->contains($intangible)) {
+            $this->intangibles[] = $intangible;
+            $intangible->addEducationCurriculum($this);
+        }
+
+        return $this;
+    }
+
+    public function removeIntangible(Intangible $intangible): self
+    {
+        if ($this->intangibles->removeElement($intangible)) {
+            $intangible->removeEducationCurriculum($this);
+        }
+
+        return $this;
+    }
+
+    public function getRequiredEducationCurriculumPacks(): Collection
+    {
+        return $this->requiredEducationCurriculumPacks;
+    }
+
+    public function addRequiredEducationCurriculumPack(EducationCurriculumPack $requiredEducationCurriculumPack): self
+    {
+        if (!$this->requiredEducationCurriculumPacks->contains($requiredEducationCurriculumPack)) {
+            $this->requiredEducationCurriculumPacks[] = $requiredEducationCurriculumPack;
+            $requiredEducationCurriculumPack->addRequiredEducationCurriculum($this);
+        }
+
+        return $this;
+    }
+
+    public function removeRequiredEducationCurriculumPack(EducationCurriculumPack $requiredEducationCurriculumPack): self
+    {
+        if ($this->requiredEducationCurriculumPacks->removeElement($requiredEducationCurriculumPack)) {
+            $requiredEducationCurriculumPack->removeRequiredEducationCurriculum($this);
+        }
+
+        return $this;
+    }
+
+    public function getRequiredChoicesEducationCurriculumPacks(): Collection
+    {
+        return $this->requiredChoicesEducationCurriculumPacks;
+    }
+
+    public function addRequiredChoicesEducationCurriculumPack(
+        EducationCurriculumPack $requiredChoicesEducationCurriculumPack,
+    ): self {
+        if (!$this->requiredChoicesEducationCurriculumPacks->contains($requiredChoicesEducationCurriculumPack)) {
+            $this->requiredChoicesEducationCurriculumPacks[] = $requiredChoicesEducationCurriculumPack;
+            $requiredChoicesEducationCurriculumPack->addRequiredChoicesEducationCurriculum($this);
+        }
+
+        return $this;
+    }
+
+    public function removeRequiredChoicesEducationCurriculumPack(
+        EducationCurriculumPack $requiredChoicesEducationCurriculumPack,
+    ): self {
+        if ($this->requiredChoicesEducationCurriculumPacks->removeElement($requiredChoicesEducationCurriculumPack)) {
+            $requiredChoicesEducationCurriculumPack->removeRequiredChoicesEducationCurriculum($this);
+        }
+
+        return $this;
+    }
+
+    public function getOptionnalEducationCurriculumPacks(): Collection
+    {
+        return $this->optionnalEducationCurriculumPacks;
+    }
+
+    public function addOptionnalEducationCurriculumPack(EducationCurriculumPack $optionnalEducationCurriculumPack): self
+    {
+        if (!$this->optionnalEducationCurriculumPacks->contains($optionnalEducationCurriculumPack)) {
+            $this->optionnalEducationCurriculumPacks[] = $optionnalEducationCurriculumPack;
+            $optionnalEducationCurriculumPack->addOptionnalEducationCurriculum($this);
+        }
+
+        return $this;
+    }
+
+    public function removeOptionnalEducationCurriculumPack(EducationCurriculumPack $optionnalEducationCurriculumPack): self
+    {
+        if ($this->optionnalEducationCurriculumPacks->removeElement($optionnalEducationCurriculumPack)) {
+            $optionnalEducationCurriculumPack->removeOptionnalEducationCurriculum($this);
+        }
+
+        return $this;
+    }
 }

+ 200 - 0
src/Entity/Education/EducationCurriculumPack.php

@@ -0,0 +1,200 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Education;
+
+use ApiPlatform\Metadata\ApiResource;
+use App\Entity\Core\Tagg;
+use App\Entity\Organization\Organization;
+use App\Entity\Product\Intangible;
+use Doctrine\Common\Collections\Collection;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ApiResource(operations: [])]
+#[ORM\Entity]
+class EducationCurriculumPack
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private int $id;
+
+    #[ORM\ManyToOne(targetEntity: Organization::class, cascade: [], inversedBy: 'educationCurriculumPacks')]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: false, onDelete: 'SET NULL')]
+    public Organization $organization;
+
+    #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'educationCurriculumPacks', cascade: ['persist'], orphanRemoval: false)]
+    public Collection $tags;
+
+    #[ORM\ManyToMany(
+        targetEntity: EducationCurriculum::class,
+        inversedBy: 'requiredEducationCurriculumPacks',
+        cascade: [],
+        orphanRemoval: false,
+    )]
+    public Collection $requiredEducationCurriculums;
+
+    #[ORM\ManyToMany(
+        targetEntity: EducationCurriculum::class,
+        inversedBy: 'requiredChoicesEducationCurriculumPacks',
+        cascade: [],
+        orphanRemoval: false,
+    )]
+    public Collection $requiredChoicesEducationCurriculums;
+
+    #[ORM\ManyToMany(
+        targetEntity: EducationCurriculum::class,
+        inversedBy: 'optionnalEducationCurriculumPacks',
+        cascade: [],
+        orphanRemoval: false,
+    )]
+    public Collection $optionnalEducationCurriculums;
+
+    #[ORM\ManyToMany(targetEntity: Intangible::class, mappedBy: 'educationCurriculumPacks', cascade: [], orphanRemoval: false)]
+    public Collection $intangibles;
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): self
+    {
+        $this->id = $id;
+
+        return $this;
+    }
+
+    public function getOrganization(): Organization
+    {
+        return $this->organization;
+    }
+
+    public function setOrganization(Organization $organization): self
+    {
+        $this->organization = $organization;
+
+        return $this;
+    }
+
+    public function getTags(): Collection
+    {
+        return $this->tags;
+    }
+
+    public function addTag(Tagg $tag): self
+    {
+        if (!$this->tags->contains($tag)) {
+            $this->tags[] = $tag;
+            $tag->addEducationCurriculumPack($this);
+        }
+
+        return $this;
+    }
+
+    public function removeTag(Tagg $tag): self
+    {
+        if ($this->tags->removeElement($tag)) {
+            $tag->removeEducationCurriculumPack($this);
+        }
+
+        return $this;
+    }
+
+    public function getRequiredEducationCurriculums(): Collection
+    {
+        return $this->requiredEducationCurriculums;
+    }
+
+    public function addRequiredEducationCurriculum(EducationCurriculum $requiredEducationCurriculum): self
+    {
+        if (!$this->requiredEducationCurriculums->contains($requiredEducationCurriculum)) {
+            $this->requiredEducationCurriculums[] = $requiredEducationCurriculum;
+            $requiredEducationCurriculum->addRequiredEducationCurriculumPack($this);
+        }
+
+        return $this;
+    }
+
+    public function removeRequiredEducationCurriculum(EducationCurriculum $requiredEducationCurriculum): self
+    {
+        if ($this->requiredEducationCurriculums->removeElement($requiredEducationCurriculum)) {
+            $requiredEducationCurriculum->removeRequiredEducationCurriculumPack($this);
+        }
+
+        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;
+    }
+
+    public function addOptionnalEducationCurriculum(EducationCurriculum $optionnalEducationCurriculum): self
+    {
+        if (!$this->optionnalEducationCurriculums->contains($optionnalEducationCurriculum)) {
+            $this->optionnalEducationCurriculums[] = $optionnalEducationCurriculum;
+            $optionnalEducationCurriculum->addOptionnalEducationCurriculumPack($this);
+        }
+
+        return $this;
+    }
+
+    public function removeOptionnalEducationCurriculum(EducationCurriculum $optionnalEducationCurriculum): self
+    {
+        if ($this->optionnalEducationCurriculums->removeElement($optionnalEducationCurriculum)) {
+            $optionnalEducationCurriculum->removeOptionnalEducationCurriculumPack($this);
+        }
+
+        return $this;
+    }
+
+    public function getIntangibles(): Collection
+    {
+        return $this->intangibles;
+    }
+
+    public function addIntangible(Intangible $intangible): self
+    {
+        if (!$this->intangibles->contains($intangible)) {
+            $this->intangibles[] = $intangible;
+            $intangible->addEducationCurriculumPack($this);
+        }
+
+        return $this;
+    }
+
+    public function removeIntangible(Intangible $intangible): self
+    {
+        if ($this->intangibles->removeElement($intangible)) {
+            $intangible->removeEducationCurriculumPack($this);
+        }
+
+        return $this;
+    }
+}

+ 17 - 0
src/Entity/Education/EducationStudent.php

@@ -8,6 +8,7 @@ use ApiPlatform\Metadata\ApiResource;
 use App\Entity\Access\Access;
 use App\Entity\Core\Tagg;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
+use App\Entity\Product\EquipmentList;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
@@ -57,6 +58,10 @@ class EducationStudent
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
     private EducationTiming $educationTiming;
 
+    #[ORM\ManyToOne(targetEntity: EquipmentList::class, cascade: [])]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
+    protected EquipmentList $speciality;
+
     public function __construct()
     {
         $this->teachers = new ArrayCollection();
@@ -225,4 +230,16 @@ class EducationStudent
 
         return $this;
     }
+
+    public function getSpeciality(): EquipmentList
+    {
+        return $this->speciality;
+    }
+
+    public function setSpeciality(EquipmentList $speciality): self
+    {
+        $this->speciality = $speciality;
+
+        return $this;
+    }
 }

+ 68 - 0
src/Entity/Message/AbstractMessage.php

@@ -5,8 +5,11 @@ declare(strict_types=1);
 namespace App\Entity\Message;
 
 use App\Attribute\OrganizationDefaultValue;
+use App\Entity\Core\File;
 use App\Entity\Organization\Organization;
 use App\Enum\Message\MessageStatusEnum;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
 use Ramsey\Uuid\Doctrine\UuidGenerator;
 use Ramsey\Uuid\UuidInterface;
@@ -53,6 +56,20 @@ abstract class AbstractMessage
     #[ORM\Column(type: 'text', nullable: true)]
     protected string $text;
 
+    #[ORM\ManyToMany(targetEntity: File::class, cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\JoinTable(name: 'messages_files')]
+    #[ORM\JoinColumn(name: 'message_id', referencedColumnName: 'id', onDelete: 'cascade')]
+    #[ORM\InverseJoinColumn(name: 'file_id', referencedColumnName: 'id', onDelete: 'cascade')]
+    protected Collection $files;
+
+    #[ORM\OneToMany(mappedBy: 'message', targetEntity: ReportMessage::class, cascade: ['persist'], orphanRemoval: true)]
+    protected Collection $reportMessage;
+
+    public function __construct()
+    {
+        $this->reportMessage = new ArrayCollection();
+    }
+
     public function getId(): ?int
     {
         return $this->id;
@@ -122,4 +139,55 @@ abstract class AbstractMessage
     {
         return $this->dateSent;
     }
+
+    /**
+     * @return Collection<int, File>
+     */
+    public function getFiles(): Collection
+    {
+        return $this->files;
+    }
+
+    public function addFile(File $file): self
+    {
+        if (!$this->files->contains($file)) {
+            $this->files[] = $file;
+            //            $file->addXXXX($this);  // TODO: quel méthode?
+        }
+
+        return $this;
+    }
+
+    public function removeFile(File $file): self
+    {
+        if ($this->files->removeElement($file)) {
+            //            $file->removeXXX($this);  // TODO: quel méthode?
+        }
+
+        return $this;
+    }
+
+    public function getReportMessage(): Collection
+    {
+        return $this->reportMessage;
+    }
+
+    public function addReportMessage(ReportMessage $reportMessage): self
+    {
+        if (!$this->reportMessage->contains($reportMessage)) {
+            $this->reportMessage[] = $reportMessage;
+            $reportMessage->setMessage($this);
+        }
+
+        return $this;
+    }
+
+    public function removeReportMessage(ReportMessage $reportMessage): self
+    {
+        if ($this->reportMessage->removeElement($reportMessage)) {
+            $reportMessage->setMessage(null);
+        }
+
+        return $this;
+    }
 }

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

@@ -6,7 +6,6 @@ namespace App\Entity\Message;
 
 use ApiPlatform\Metadata\ApiResource;
 use App\Entity\Access\Access;
-use App\Entity\Core\File;
 use App\Entity\Core\Tagg;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
 use Doctrine\Common\Collections\ArrayCollection;
@@ -44,12 +43,6 @@ class Email extends AbstractMessage
     #[ORM\JoinColumn(nullable: true)]
     private Mail $mailAttached;
 
-    #[ORM\ManyToMany(targetEntity: File::class, cascade: ['persist'], orphanRemoval: true)]
-    #[ORM\JoinTable(name: 'messages_files')]
-    #[ORM\JoinColumn(name: 'message_id', referencedColumnName: 'id', onDelete: 'cascade')]
-    #[ORM\InverseJoinColumn(name: 'file_id', referencedColumnName: 'id', onDelete: 'cascade')]
-    private Collection $files;
-
     #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'emails', cascade: ['persist'])]
     #[ORM\JoinTable(name: 'tag_message')]
     #[ORM\JoinColumn(name: 'message_id', referencedColumnName: 'id', onDelete: 'cascade')]
@@ -62,6 +55,7 @@ class Email extends AbstractMessage
         $this->reports = new ArrayCollection();
         $this->files = new ArrayCollection();
         $this->tags = new ArrayCollection();
+        parent::__construct();
     }
 
     public function getDiscr(): ?string
@@ -142,30 +136,6 @@ class Email extends AbstractMessage
         return $this;
     }
 
-    /**
-     * @return Collection<int, File>
-     */
-    public function getFiles(): Collection
-    {
-        return $this->files;
-    }
-
-    public function addFile(File $file): self
-    {
-        if (!$this->files->contains($file)) {
-            $this->files[] = $file;
-        }
-
-        return $this;
-    }
-
-    public function removeFile(File $file): self
-    {
-        $this->files->removeElement($file);
-
-        return $this;
-    }
-
     /**
      * @return Collection<int, Tagg>
      */

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

@@ -6,7 +6,6 @@ namespace App\Entity\Message;
 
 use ApiPlatform\Metadata\ApiResource;
 use App\Entity\Access\Access;
-use App\Entity\Core\File;
 use App\Entity\Core\Tagg;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
 use Doctrine\Common\Collections\ArrayCollection;
@@ -33,12 +32,6 @@ class Mail extends AbstractMessage
     #[ORM\JoinColumn(nullable: true)]
     private Access $author;
 
-    #[ORM\ManyToMany(targetEntity: File::class, cascade: ['persist'], orphanRemoval: true)]
-    #[ORM\JoinTable(name: 'messages_files')]
-    #[ORM\JoinColumn(name: 'message_id', referencedColumnName: 'id', onDelete: 'cascade')]
-    #[ORM\InverseJoinColumn(name: 'file_id', referencedColumnName: 'id', onDelete: 'cascade')]
-    private Collection $files;
-
     #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'mails', cascade: ['persist'])]
     #[ORM\JoinTable(name: 'tag_message')]
     #[ORM\JoinColumn(name: 'message_id', referencedColumnName: 'id')]
@@ -50,6 +43,7 @@ class Mail extends AbstractMessage
         $this->uuid = Uuid::uuid4();
         $this->files = new ArrayCollection();
         $this->tags = new ArrayCollection();
+        parent::__construct();
     }
 
     public function getDiscr(): ?string
@@ -76,30 +70,6 @@ class Mail extends AbstractMessage
         return $this;
     }
 
-    /**
-     * @return Collection<int, File>
-     */
-    public function getFiles(): Collection
-    {
-        return $this->files;
-    }
-
-    public function addFile(File $file): self
-    {
-        if (!$this->files->contains($file)) {
-            $this->files[] = $file;
-        }
-
-        return $this;
-    }
-
-    public function removeFile(File $file): self
-    {
-        $this->files->removeElement($file);
-
-        return $this;
-    }
-
     /**
      * @return Collection<int, Tagg>
      */

+ 79 - 0
src/Entity/Message/ReportMessage.php

@@ -0,0 +1,79 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Message;
+
+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 ReportMessage
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private int $id;
+
+    #[ORM\ManyToOne(targetEntity: AbstractMessage::class, cascade: [], inversedBy: 'reportMessage')]
+    public mixed $message;
+
+    #[ORM\ManyToOne(targetEntity: Access::class, cascade: [])]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
+    public Access $access;
+
+    #[ORM\ManyToOne(targetEntity: Organization::class, cascade: [])]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
+    public Organization $organization;
+
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    public function setId(int $id): self
+    {
+        $this->id = $id;
+
+        return $this;
+    }
+
+    public function getMessage(): mixed
+    {
+        return $this->message;
+    }
+
+    public function setMessage(mixed $message): self
+    {
+        $this->message = $message;
+
+        return $this;
+    }
+
+    public function getAccess(): Access
+    {
+        return $this->access;
+    }
+
+    public function setAccess(Access $access): self
+    {
+        $this->access = $access;
+
+        return $this;
+    }
+
+    public function getOrganization(): Organization
+    {
+        return $this->organization;
+    }
+
+    public function setOrganization(Organization $organization): self
+    {
+        $this->organization = $organization;
+
+        return $this;
+    }
+}

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

@@ -46,6 +46,7 @@ class Sms extends AbstractMessage
         $this->uuid = Uuid::uuid4();
         $this->reports = new ArrayCollection();
         $this->tags = new ArrayCollection();
+        parent::__construct();
     }
 
     public function getDiscr(): ?string

+ 16 - 0
src/Entity/Network/Network.php

@@ -5,6 +5,7 @@ declare(strict_types=1);
 namespace App\Entity\Network;
 
 use ApiPlatform\Metadata\ApiResource;
+use App\Entity\Core\File;
 use App\Repository\Network\NetworkRepository;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
 use Doctrine\Common\Collections\ArrayCollection;
@@ -40,6 +41,9 @@ class Network
     #[ORM\OneToMany(mappedBy: 'network', targetEntity: NetworkOrganization::class, orphanRemoval: true)]
     private Collection $organizations;
 
+    #[ORM\ManyToOne(targetEntity: File::class, cascade: [], inversedBy: 'networks')]
+    protected File $image;
+
     #[Pure]
     public function __construct()
     {
@@ -123,4 +127,16 @@ class Network
 
         return $this;
     }
+
+    public function getImage(): File
+    {
+        return $this->image;
+    }
+
+    public function setImage(File $image): self
+    {
+        $this->image = $image;
+
+        return $this;
+    }
 }

+ 15 - 0
src/Entity/Organization/Activity.php

@@ -54,6 +54,9 @@ class Activity
     #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
     private Collection $tags;
 
+    #[ORM\ManyToOne(targetEntity: TypeOfPractice::class, cascade: [])]
+    protected TypeOfPractice $typeOfSection;
+
     public function __construct()
     {
         $this->categories = new ArrayCollection();
@@ -191,4 +194,16 @@ class Activity
 
         return $this;
     }
+
+    public function getTypeOfSection(): TypeOfPractice
+    {
+        return $this->typeOfSection;
+    }
+
+    public function setTypeOfSection(TypeOfPractice $typeOfSection): self
+    {
+        $this->typeOfSection = $typeOfSection;
+
+        return $this;
+    }
 }

+ 15 - 0
src/Entity/Organization/CotisationByYear.php

@@ -23,6 +23,9 @@ class CotisationByYear
     #[ORM\JoinColumn(name: 'organization_id', referencedColumnName: 'id', nullable: false)]
     private Organization $organization;
 
+    #[ORM\OneToOne(mappedBy: 'cotisationByYear', targetEntity: CotisationStaffInfos::class, cascade: ['persist'])]
+    protected CotisationStaffInfos $cotisationStaffInfos;
+
     public function getId(): ?int
     {
         return $this->id;
@@ -39,4 +42,16 @@ class CotisationByYear
 
         return $this;
     }
+
+    public function getCotisationStaffInfos(): CotisationStaffInfos
+    {
+        return $this->cotisationStaffInfos;
+    }
+
+    public function setCotisationStaffInfos(CotisationStaffInfos $cotisationStaffInfos): self
+    {
+        $this->cotisationStaffInfos = $cotisationStaffInfos;
+
+        return $this;
+    }
 }

+ 15 - 0
src/Entity/Organization/CotisationStaffInfos.php

@@ -19,8 +19,23 @@ class CotisationStaffInfos
     #[ORM\GeneratedValue]
     private ?int $id = null;
 
+    #[ORM\OneToOne(targetEntity: CotisationByYear::class, inversedBy: 'cotisationStaffInfos', cascade: [])]
+    protected CotisationByYear $cotisationByYear;
+
     public function getId(): ?int
     {
         return $this->id;
     }
+
+    public function getCotisationByYear(): CotisationByYear
+    {
+        return $this->cotisationByYear;
+    }
+
+    public function setCotisationByYear(CotisationByYear $cotisationByYear): self
+    {
+        $this->cotisationByYear = $cotisationByYear;
+
+        return $this;
+    }
 }

+ 17 - 0
src/Entity/Organization/OnlineRegistrationDocument.php

@@ -27,6 +27,10 @@ class OnlineRegistrationDocument
     #[ORM\JoinColumn(nullable: true)]
     private OnlineRegistrationSettings $guardiansOnlineRegistrationSettings;
 
+    #[ORM\ManyToOne(targetEntity: OnlineRegistrationSettings::class, cascade: [], inversedBy: 'adultStudentDocuments')]
+    #[ORM\JoinColumn(nullable: true)]
+    protected OnlineRegistrationSettings $adultStudentOnlineRegistrationSettings;
+
     public function getId(): ?int
     {
         return $this->id;
@@ -55,4 +59,17 @@ class OnlineRegistrationDocument
 
         return $this;
     }
+
+    public function getAdultStudentOnlineRegistrationSettings(): OnlineRegistrationSettings
+    {
+        return $this->adultStudentOnlineRegistrationSettings;
+    }
+
+    public function setAdultStudentOnlineRegistrationSettings(
+        OnlineRegistrationSettings $adultStudentOnlineRegistrationSettings,
+    ): self {
+        $this->adultStudentOnlineRegistrationSettings = $adultStudentOnlineRegistrationSettings;
+
+        return $this;
+    }
 }

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

@@ -40,6 +40,17 @@ class OnlineRegistrationSettings
     #[ORM\OneToMany(mappedBy: 'onlineRegistrationSettingsNewEnrolments', targetEntity: OnlineRegistrationOpeningPeriod::class, cascade: ['persist'], orphanRemoval: true)]
     private Collection $openingPeriodsNewEnrolments;
 
+    #[ORM\OneToOne(inversedBy: 'onlineRegistrationSettings', targetEntity: Organization::class, cascade: [])]
+    protected Organization $organization;
+
+    #[ORM\OneToMany(
+        mappedBy: 'adultStudentOnlineRegistrationSettings',
+        targetEntity: OnlineRegistrationDocument::class,
+        cascade: ['persist'],
+        orphanRemoval: true,
+    )]
+    protected Collection $adultStudentDocuments;
+
     public function __construct()
     {
         $this->openingPeriods = new ArrayCollection();
@@ -48,6 +59,7 @@ class OnlineRegistrationSettings
         $this->introductionFiles = new ArrayCollection();
         $this->introductionFilesNewEnrolments = new ArrayCollection();
         $this->openingPeriodsNewEnrolments = new ArrayCollection();
+        $this->adultStudentDocuments = new ArrayCollection();
     }
 
     public function getId(): ?int
@@ -234,4 +246,37 @@ class OnlineRegistrationSettings
 
         return $this;
     }
+
+    public function getOrganization(): Organization
+    {
+        return $this->organization;
+    }
+
+    public function setOrganization(Organization $organization): self
+    {
+        $this->organization = $organization;
+
+        return $this;
+    }
+
+    public function getAdultStudentDocuments(): Collection
+    {
+        return $this->adultStudentDocuments;
+    }
+
+    public function addAdultStudentDocument(OnlineRegistrationDocument $adultStudentDocument): self
+    {
+        if (!$this->adultStudentDocuments->contains($adultStudentDocument)) {
+            $this->adultStudentDocuments[] = $adultStudentDocument;
+        }
+
+        return $this;
+    }
+
+    public function removeAdultStudentDocument(OnlineRegistrationDocument $adultStudentDocument): self
+    {
+        $this->adultStudentDocuments->removeElement($adultStudentDocument);
+
+        return $this;
+    }
 }

+ 287 - 27
src/Entity/Organization/Organization.php

@@ -7,8 +7,12 @@ namespace App\Entity\Organization;
 use ApiPlatform\Metadata\ApiResource;
 use ApiPlatform\Metadata\Get;
 use App\Entity\Access\Access;
+use App\Entity\Billing\BillingExportSetting;
 use App\Entity\Billing\BillingSetting;
+use App\Entity\Billing\BillSchedule;
+use App\Entity\Billing\FamilyQuotientModel;
 use App\Entity\Booking\Attendance;
+use App\Entity\Booking\AttendanceBookingReason;
 use App\Entity\Booking\Course;
 use App\Entity\Booking\EducationalProject;
 use App\Entity\Booking\Event;
@@ -26,12 +30,13 @@ use App\Entity\Education\EducationCategory;
 use App\Entity\Education\EducationNotationConfig;
 use App\Entity\Education\EducationTiming;
 use App\Entity\Education\PeriodNotation;
+use App\Entity\Message\AbstractMessage;
 use App\Entity\Message\Email;
 use App\Entity\Message\Mail;
 use App\Entity\Message\Sms;
 use App\Entity\Network\NetworkOrganization;
 use App\Entity\Person\Commission;
-use App\Entity\Place\Place;
+use App\Entity\Place\AbstractPlace;
 use App\Entity\Product\Equipment;
 use App\Entity\Product\Intangible;
 use App\Entity\Reward\Reward;
@@ -300,7 +305,7 @@ class Organization
     #[ORM\OneToMany(mappedBy: 'organization', targetEntity: Commission::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
     private Collection $commissions;
 
-    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: Place::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: AbstractPlace::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
     private Collection $places;
 
     #[ORM\OneToMany(mappedBy: 'organization', targetEntity: Attendance::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
@@ -327,6 +332,39 @@ class Organization
     #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
     private Collection $tags;
 
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: NetworkOrganization::class, cascade: ['persist'], orphanRemoval: true)]
+    protected Collection $network;
+
+    #[ORM\OneToMany(mappedBy: 'parent', targetEntity: NetworkOrganization::class, cascade: ['persist'], orphanRemoval: true)]
+    protected Collection $networkChild;
+
+    #[ORM\OneToOne(mappedBy: 'organization', targetEntity: BillingExportSetting::class, cascade: ['persist'])]
+    protected BillingExportSetting $billingExportSetting;
+
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: Access::class, cascade: ['persist'], orphanRemoval: true)]
+    protected Collection $access;
+
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: AbstractMessage::class, cascade: [], orphanRemoval: true)]
+    protected Collection $messages;
+
+    #[ORM\OneToOne(mappedBy: 'organization', targetEntity: OnlineRegistrationSettings::class, cascade: ['persist'])]
+    protected OnlineRegistrationSettings $onlineRegistrationSettings;
+
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: CotisationByYear::class, cascade: ['persist'], orphanRemoval: true)]
+    protected Collection $cotisationByYears;
+
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: AttendanceBookingReason::class, cascade: ['persist'], orphanRemoval: true)]
+    protected Collection $attendanceBookingReasons;
+
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: Cycle::class, cascade: [], orphanRemoval: true)]
+    protected Collection $educationCurriculumPacks;
+
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: FamilyQuotientModel::class, cascade: [], orphanRemoval: true)]
+    protected Collection $familyQuotientModels;
+
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: BillSchedule::class, cascade: ['persist'], orphanRemoval: true)]
+    protected Collection $billSchedules;
+
     #[Pure]
     public function __construct()
     {
@@ -366,6 +404,15 @@ class Organization
         $this->donors = new ArrayCollection();
         $this->tags = new ArrayCollection();
         $this->rewards = new ArrayCollection();
+        $this->network = new ArrayCollection();
+        $this->networkChild = new ArrayCollection();
+        $this->access = new ArrayCollection();
+        $this->messages = new ArrayCollection();
+        $this->cotisationByYears = new ArrayCollection();
+        $this->attendanceBookingReasons = new ArrayCollection();
+        $this->educationCurriculumPacks = new ArrayCollection();
+        $this->familyQuotientModels = new ArrayCollection();
+        $this->billSchedules = new ArrayCollection();
     }
 
     public function getId(): ?int
@@ -443,6 +490,25 @@ class Organization
         return $this->accesses;
     }
 
+    public function addAccess(Access $access): self
+    {
+        if (!$this->access->contains($access)) {
+            $this->access[] = $access;
+            $access->setOrganization($this);
+        }
+
+        return $this;
+    }
+
+    public function removeAccess(Access $access): self
+    {
+        if ($this->access->removeElement($access)) {
+            $access->setOrganization(null);
+        }
+
+        return $this;
+    }
+
     public function getNetworkOrganizations(): Collection
     {
         return $this->networkOrganizations;
@@ -1212,28 +1278,6 @@ class Organization
         return $this;
     }
 
-    public function addAccess(Access $access): self
-    {
-        if (!$this->accesses->contains($access)) {
-            $this->accesses[] = $access;
-            $access->setOrganization($this);
-        }
-
-        return $this;
-    }
-
-    public function removeAccess(Access $access): self
-    {
-        if ($this->accesses->removeElement($access)) {
-            // set the owning side to null (unless already changed)
-            if ($access->getOrganization() === $this) {
-                $access->setOrganization(null);
-            }
-        }
-
-        return $this;
-    }
-
     public function getContactPerson(): ?Access
     {
         return $this->contactPerson;
@@ -1661,14 +1705,14 @@ class Organization
     }
 
     /**
-     * @return Collection<int, Place>
+     * @return Collection<int, AbstractPlace>
      */
     public function getPlaces(): Collection
     {
         return $this->places;
     }
 
-    public function addPlace(Place $place): self
+    public function addPlace(AbstractPlace $place): self
     {
         if (!$this->places->contains($place)) {
             $this->places[] = $place;
@@ -1678,7 +1722,7 @@ class Organization
         return $this;
     }
 
-    public function removePlace(Place $place): self
+    public function removePlace(AbstractPlace $place): self
     {
         if ($this->places->removeElement($place)) {
             // set the owning side to null (unless already changed)
@@ -1870,4 +1914,220 @@ class Organization
 
         return $this;
     }
+
+    public function getNetwork(): Collection
+    {
+        return $this->network;
+    }
+
+    public function addNetwork(NetworkOrganization $network): self
+    {
+        if (!$this->network->contains($network)) {
+            $this->network[] = $network;
+            $network->setOrganization($this);
+        }
+
+        return $this;
+    }
+
+    public function removeNetwork(NetworkOrganization $network): self
+    {
+        if ($this->network->removeElement($network)) {
+            $network->setOrganization(null);
+        }
+
+        return $this;
+    }
+
+    public function getNetworkChild(): Collection
+    {
+        return $this->networkChild;
+    }
+
+    public function addNetworkChild(NetworkOrganization $networkChild): self
+    {
+        if (!$this->networkChild->contains($networkChild)) {
+            $this->networkChild[] = $networkChild;
+            $networkChild->setParent($this);
+        }
+
+        return $this;
+    }
+
+    public function removeNetworkChild(NetworkOrganization $networkChild): self
+    {
+        if ($this->networkChild->removeElement($networkChild)) {
+            $networkChild->setParent(null);
+        }
+
+        return $this;
+    }
+
+    public function getBillingExportSetting(): BillingExportSetting
+    {
+        return $this->billingExportSetting;
+    }
+
+    public function setBillingExportSetting(BillingExportSetting $billingExportSetting): self
+    {
+        $this->billingExportSetting = $billingExportSetting;
+
+        return $this;
+    }
+
+    public function getMessages(): Collection
+    {
+        return $this->messages;
+    }
+
+    public function addMessage(mixed $message): self
+    {
+        if (!$this->messages->contains($message)) {
+            $this->messages[] = $message;
+            $message->setOrganization($this);
+        }
+
+        return $this;
+    }
+
+    public function removeMessage(mixed $message): self
+    {
+        if ($this->messages->removeElement($message)) {
+            $message->setOrganization(null);
+        }
+
+        return $this;
+    }
+
+    public function getOnlineRegistrationSettings(): OnlineRegistrationSettings
+    {
+        return $this->onlineRegistrationSettings;
+    }
+
+    public function setOnlineRegistrationSettings(OnlineRegistrationSettings $onlineRegistrationSettings): self
+    {
+        $this->onlineRegistrationSettings = $onlineRegistrationSettings;
+
+        return $this;
+    }
+
+    public function getCotisationByYears(): Collection
+    {
+        return $this->cotisationByYears;
+    }
+
+    public function addCotisationByYear(CotisationByYear $cotisationByYear): self
+    {
+        if (!$this->cotisationByYears->contains($cotisationByYear)) {
+            $this->cotisationByYears[] = $cotisationByYear;
+            $cotisationByYear->setOrganization($this);
+        }
+
+        return $this;
+    }
+
+    public function removeCotisationByYear(CotisationByYear $cotisationByYear): self
+    {
+        if ($this->cotisationByYears->removeElement($cotisationByYear)) {
+            $cotisationByYear->setOrganization(null);
+        }
+
+        return $this;
+    }
+
+    public function getAttendanceBookingReasons(): Collection
+    {
+        return $this->attendanceBookingReasons;
+    }
+
+    public function addAttendanceBookingReason(AttendanceBookingReason $attendanceBookingReason): self
+    {
+        if (!$this->attendanceBookingReasons->contains($attendanceBookingReason)) {
+            $this->attendanceBookingReasons[] = $attendanceBookingReason;
+            $attendanceBookingReason->setOrganization($this);
+        }
+
+        return $this;
+    }
+
+    public function removeAttendanceBookingReason(AttendanceBookingReason $attendanceBookingReason): self
+    {
+        if ($this->attendanceBookingReasons->removeElement($attendanceBookingReason)) {
+            $attendanceBookingReason->setOrganization(null);
+        }
+
+        return $this;
+    }
+
+    public function getEducationCurriculumPacks(): Collection
+    {
+        return $this->educationCurriculumPacks;
+    }
+
+    public function addEducationCurriculumPack(Cycle $educationCurriculumPack): self
+    {
+        if (!$this->educationCurriculumPacks->contains($educationCurriculumPack)) {
+            $this->educationCurriculumPacks[] = $educationCurriculumPack;
+            $educationCurriculumPack->setOrganization($this);
+        }
+
+        return $this;
+    }
+
+    public function removeEducationCurriculumPack(Cycle $educationCurriculumPack): self
+    {
+        if ($this->educationCurriculumPacks->removeElement($educationCurriculumPack)) {
+            $educationCurriculumPack->setOrganization(null);
+        }
+
+        return $this;
+    }
+
+    public function getFamilyQuotientModels(): Collection
+    {
+        return $this->familyQuotientModels;
+    }
+
+    public function addFamilyQuotientModel(FamilyQuotientModel $familyQuotientModel): self
+    {
+        if (!$this->familyQuotientModels->contains($familyQuotientModel)) {
+            $this->familyQuotientModels[] = $familyQuotientModel;
+            $familyQuotientModel->setOrganization($this);
+        }
+
+        return $this;
+    }
+
+    public function removeFamilyQuotientModel(FamilyQuotientModel $familyQuotientModel): self
+    {
+        if ($this->familyQuotientModels->removeElement($familyQuotientModel)) {
+            //            $familyQuotientModel->setOrganization(null); // TODO: actuellement, pas nullable: conserver?
+        }
+
+        return $this;
+    }
+
+    public function getBillSchedules(): Collection
+    {
+        return $this->billSchedules;
+    }
+
+    public function addBillSchedule(BillSchedule $billSchedule): self
+    {
+        if (!$this->billSchedules->contains($billSchedule)) {
+            $this->billSchedules[] = $billSchedule;
+            $billSchedule->setOrganization($this);
+        }
+
+        return $this;
+    }
+
+    public function removeBillSchedule(BillSchedule $billSchedule): self
+    {
+        if ($this->billSchedules->removeElement($billSchedule)) {
+            //            $billSchedule->setOrganization(null);  // TODO: actuellement, pas nullable: conserver?
+        }
+
+        return $this;
+    }
 }

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

@@ -69,8 +69,8 @@ class Parameters
     #[ORM\Column(options: ['default' => true])]
     private bool $editCriteriaNotationByAdminOnly = true;
 
-    #[ORM\Column(length: 255, nullable: true)]
-    #[Assert\Regex('/^[a-z0-9]+$/i', message: 'smsSenderName_error')]
+    #[ORM\Column(length: 11, nullable: true)]
+    #[Assert\Regex('/^\w{3,11}$/i', message: 'smsSenderName_error')]
     private ?string $smsSenderName = null;
 
     #[ORM\Column(options: ['default' => false])]

部分文件因为文件数量过多而无法显示