Forráskód Böngészése

Merge branch 'V8-6941_complete_entities' into feature/V8-6941-complter-les-entits-avec-les-pro

Olivier Massot 1 éve
szülő
commit
a757b8e2db
100 módosított fájl, 5113 hozzáadás és 1059 törlés
  1. 1 1
      phpstan.neon.dist
  2. 9 2
      src/Commands/Doctrine/SchemaValidateCommand.php
  3. 164 0
      src/Entity/Access/Access.php
  4. 14 0
      src/Entity/Access/AccessCommunication.php
  5. 14 0
      src/Entity/Access/AccessNetworkSetting.php
  6. 14 0
      src/Entity/Access/AccessSocial.php
  7. 25 0
      src/Entity/AccessWish/AccessFamilyWish.php
  8. 76 0
      src/Entity/AccessWish/AccessWish.php
  9. 28 0
      src/Entity/AccessWish/DocumentWish.php
  10. 64 0
      src/Entity/AccessWish/EducationStudentWish.php
  11. 417 0
      src/Entity/Awin/Product.php
  12. 433 0
      src/Entity/Billing/AbstractBillAccounting.php
  13. 15 0
      src/Entity/Billing/AccessBilling.php
  14. 17 0
      src/Entity/Billing/AdvancePayment.php
  15. 61 0
      src/Entity/Billing/Afi.php
  16. 15 0
      src/Entity/Billing/BergerLevrault.php
  17. 2 25
      src/Entity/Billing/Bill.php
  18. 3 0
      src/Entity/Billing/BillAccessDetail.php
  19. 2 289
      src/Entity/Billing/BillAccounting.php
  20. 2 26
      src/Entity/Billing/BillCredit.php
  21. 3 3
      src/Entity/Billing/BillLine.php
  22. 33 3
      src/Entity/Billing/BillPayment.php
  23. 91 0
      src/Entity/Billing/BillSchedule.php
  24. 45 0
      src/Entity/Billing/BillScheduleDate.php
  25. 46 0
      src/Entity/Billing/BillingExportSetting.php
  26. 14 0
      src/Entity/Billing/BillingSetting.php
  27. 13 0
      src/Entity/Billing/BillingSettingRent.php
  28. 15 0
      src/Entity/Billing/Ciril.php
  29. 61 0
      src/Entity/Billing/CirilCivil.php
  30. 80 0
      src/Entity/Billing/FamilyQuotientBand.php
  31. 87 0
      src/Entity/Billing/FamilyQuotientBandDetail.php
  32. 97 0
      src/Entity/Billing/FamilyQuotientModel.php
  33. 15 0
      src/Entity/Billing/Jvs.php
  34. 71 0
      src/Entity/Billing/Odyssee.php
  35. 32 0
      src/Entity/Billing/PayboxPaymentReturn.php
  36. 15 0
      src/Entity/Billing/Pes.php
  37. 15 0
      src/Entity/Billing/PesSetting.php
  38. 42 0
      src/Entity/Billing/SddBank.php
  39. 57 0
      src/Entity/Billing/SddRegie.php
  40. 90 1
      src/Entity/Booking/AbstractBooking.php
  41. 30 0
      src/Entity/Booking/CalendarSynchro.php
  42. 43 16
      src/Entity/Booking/Course.php
  43. 1 1
      src/Entity/Booking/CourseRecur.php
  44. 36 19
      src/Entity/Booking/EducationalProject.php
  45. 1 1
      src/Entity/Booking/EducationalProjectRecur.php
  46. 32 18
      src/Entity/Booking/Event.php
  47. 1 1
      src/Entity/Booking/EventRecur.php
  48. 19 14
      src/Entity/Booking/Examen.php
  49. 1 1
      src/Entity/Booking/ExamenRecur.php
  50. 8 1
      src/Entity/Booking/OrganizationHoliday.php
  51. 1 1
      src/Entity/Booking/OrganizationHolidayRecur.php
  52. 23 1
      src/Entity/Booking/PersonHoliday.php
  53. 1 1
      src/Entity/Booking/PersonHolidayRecur.php
  54. 42 0
      src/Entity/Core/AbstractControl.php
  55. 31 0
      src/Entity/Core/AbstractRepair.php
  56. 30 5
      src/Entity/Core/AddressPostal.php
  57. 15 0
      src/Entity/Core/City.php
  58. 5 5
      src/Entity/Core/ContactPoint.php
  59. 15 0
      src/Entity/Core/Department.php
  60. 116 0
      src/Entity/Core/LoginLog.php
  61. 15 0
      src/Entity/Core/Region.php
  62. 165 10
      src/Entity/Core/Tagg.php
  63. 25 0
      src/Entity/Education/Cycle.php
  64. 26 0
      src/Entity/Education/Education.php
  65. 31 0
      src/Entity/Education/EducationComplement.php
  66. 175 0
      src/Entity/Education/EducationCurriculum.php
  67. 186 0
      src/Entity/Education/EducationCurriculumPack.php
  68. 16 0
      src/Entity/Education/EducationStudent.php
  69. 62 0
      src/Entity/Message/AbstractMessage.php
  70. 1 30
      src/Entity/Message/Email.php
  71. 1 30
      src/Entity/Message/Mail.php
  72. 77 0
      src/Entity/Message/ReportMessage.php
  73. 1 0
      src/Entity/Message/Sms.php
  74. 15 0
      src/Entity/Network/Network.php
  75. 14 0
      src/Entity/Organization/Activity.php
  76. 14 0
      src/Entity/Organization/CotisationByYear.php
  77. 14 0
      src/Entity/Organization/CotisationStaffInfos.php
  78. 16 0
      src/Entity/Organization/OnlineRegistrationDocument.php
  79. 44 0
      src/Entity/Organization/OnlineRegistrationSettings.php
  80. 253 27
      src/Entity/Organization/Organization.php
  81. 1 1
      src/Entity/Person/AllowedIp.php
  82. 456 0
      src/Entity/Place/AbstractPlace.php
  83. 5 434
      src/Entity/Place/Place.php
  84. 6 5
      src/Entity/Place/PlaceControl.php
  85. 7 6
      src/Entity/Place/PlaceRepair.php
  86. 6 1
      src/Entity/Place/PlaceSystem.php
  87. 4 4
      src/Entity/Place/Room.php
  88. 32 0
      src/Entity/Product/AbstractProduct.php
  89. 102 28
      src/Entity/Product/Equipment.php
  90. 4 3
      src/Entity/Product/EquipmentControl.php
  91. 4 4
      src/Entity/Product/EquipmentRepair.php
  92. 46 4
      src/Entity/Product/Intangible.php
  93. 32 0
      src/Entity/Product/IntangibleDiscountDetail.php
  94. 31 0
      src/Entity/Product/IntangiblePriceAndDiscount.php
  95. 47 0
      src/Entity/Token/Token.php
  96. 16 0
      src/Service/Doctrine/SchemaValidation/Difference.php
  97. 208 22
      src/Service/Doctrine/SchemaValidation/SchemaSnippetsMaker.php
  98. 11 5
      src/Service/Utils/EntityUtils.php
  99. 1 1
      tests/Unit/Service/Dolibarr/DolibarrAccountCreatorTest.php
  100. 194 9
      tests/Unit/Service/Utils/EntityUtilsTest.php

+ 1 - 1
phpstan.neon.dist

@@ -2,7 +2,6 @@
 parameters:
     level: 6
     treatPhpDocTypesAsCertain: false
-    checkGenericClassInNonGenericObjectType: false
     paths:
         - src
 
@@ -10,4 +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
 

+ 9 - 2
src/Commands/Doctrine/SchemaValidateCommand.php

@@ -15,7 +15,9 @@ use Symfony\Component\Console\Input\InputOption;
 use Symfony\Component\Console\Output\OutputInterface;
 
 /**
- * Overrides the default doctrine:schema:update command.
+ * 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',
@@ -74,7 +76,12 @@ class SchemaValidateCommand extends Command
         }
 
         if ($diff) {
-            $output->writeln(count($diff) . " differences found");
+            $count = 0;
+            foreach ($diff as $entity => $value) {
+                $count += (is_array($value) ? count($value) : 1);
+            }
+
+            $output->writeln($count . " differences found");
         } else {
             $output->writeln("No difference found");
         }

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

@@ -13,6 +13,7 @@ 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;
@@ -33,6 +34,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;
@@ -50,6 +52,13 @@ use App\Entity\Product\Equipment;
 use App\Entity\Product\EquipmentLoan;
 use App\Entity\Product\EquipmentRepair;
 use App\Entity\Reward\AccessReward;
+use App\Entity\Access\AccessCommunication;
+use App\Entity\Access\AccessNetworkSetting;
+use App\Entity\Access\AccessSocial;
+use App\Entity\Booking\AbstractBooking;
+use App\Entity\Booking\CalendarSynchro;
+use App\Entity\Core\AbstractControl;
+use App\Entity\Token\Token;
 use App\Filter\ApiPlatform\Person\FullNameFilter;
 use App\Filter\ApiPlatform\Utils\InFilter;
 use App\Repository\Access\AccessRepository;
@@ -300,6 +309,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;
+
     #[Pure]
     public function __construct()
     {
@@ -2138,4 +2180,126 @@ class Access implements UserInterface, PasswordAuthenticatedUserInterface
 
         return $this;
     }
+
+
+    function getBookingOrganizers(): Collection
+    {
+        return $this->bookingOrganizers;
+    }
+
+    function setBookingOrganizers(Collection $bookingOrganizers): self
+    {
+        $this->bookingOrganizers = $bookingOrganizers;
+        return $this;
+    }
+
+    function getAdvancePayments(): Collection
+    {
+        return $this->advancePayments;
+    }
+
+    function setAdvancePayments(Collection $advancePayments): self
+    {
+        $this->advancePayments = $advancePayments;
+        return $this;
+    }
+
+    function getMessages(): Collection
+    {
+        return $this->messages;
+    }
+
+    function setMessages(Collection $messages): self
+    {
+        $this->messages = $messages;
+        return $this;
+    }
+
+    function getEquipmentManagerControls(): Collection
+    {
+        return $this->equipmentManagerControls;
+    }
+
+    function setEquipmentManagerControls(Collection $equipmentManagerControls): self
+    {
+        $this->equipmentManagerControls = $equipmentManagerControls;
+        return $this;
+    }
+
+    function getAccompanistControl(): Collection
+    {
+        return $this->accompanistControl;
+    }
+
+    function setAccompanistControl(Collection $accompanistControl): self
+    {
+        $this->accompanistControl = $accompanistControl;
+        return $this;
+    }
+
+    function getRewards(): Collection
+    {
+        return $this->rewards;
+    }
+
+    function setRewards(Collection $rewards): self
+    {
+        $this->rewards = $rewards;
+        return $this;
+    }
+
+    function getAccessSocial(): AccessSocial
+    {
+        return $this->accessSocial;
+    }
+
+    function setAccessSocial(AccessSocial $accessSocial): self
+    {
+        $this->accessSocial = $accessSocial;
+        return $this;
+    }
+
+    function getAccessNetworkSetting(): AccessNetworkSetting
+    {
+        return $this->accessNetworkSetting;
+    }
+
+    function setAccessNetworkSetting(AccessNetworkSetting $accessNetworkSetting): self
+    {
+        $this->accessNetworkSetting = $accessNetworkSetting;
+        return $this;
+    }
+
+    function getAccessCommunication(): AccessCommunication
+    {
+        return $this->accessCommunication;
+    }
+
+    function setAccessCommunication(AccessCommunication $accessCommunication): self
+    {
+        $this->accessCommunication = $accessCommunication;
+        return $this;
+    }
+
+    function getCalendarSynchro(): CalendarSynchro
+    {
+        return $this->calendarSynchro;
+    }
+
+    function setCalendarSynchro(CalendarSynchro $calendarSynchro): self
+    {
+        $this->calendarSynchro = $calendarSynchro;
+        return $this;
+    }
+
+    function getTokens(): Collection
+    {
+        return $this->tokens;
+    }
+
+    function setTokens(Collection $tokens): self
+    {
+        $this->tokens = $tokens;
+        return $this;
+    }
 }

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

@@ -19,8 +19,22 @@ 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;
     }
+
+    function getAccess(): Access
+    {
+        return $this->access;
+    }
+
+    function setAccess(Access $access): self
+    {
+        $this->access = $access;
+        return $this;
+    }
 }

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

@@ -19,8 +19,22 @@ 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;
     }
+
+    function getAccess(): Access
+    {
+        return $this->access;
+    }
+
+    function setAccess(Access $access): self
+    {
+        $this->access = $access;
+        return $this;
+    }
 }

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

@@ -19,8 +19,22 @@ 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;
     }
+
+    function getAccess(): Access
+    {
+        return $this->access;
+    }
+
+    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;
     }
+
+    function getAccessWishesGuardians(): Collection
+    {
+        return $this->accessWishesGuardians;
+    }
+
+    function addAccessWishesGuardian(AccessWish $accessWishesGuardian): self
+    {
+        if (!$this->accessWishesGuardians->contains($accessWishesGuardian)) {
+            $this->accessWishesGuardians[] = $accessWishesGuardian;
+        }
+
+        return $this;
+    }
+
+    function removeAccessWishesGuardian(AccessWish $accessWishesGuardian): self
+    {
+        $this->accessWishesGuardians->removeElement($accessWishesGuardian);
+
+        return $this;
+    }
 }

+ 76 - 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,59 @@ class AccessWish
     {
         $this->validationState = $validationState;
     }
+
+    function getBillSchedule(): BillSchedule
+    {
+        return $this->billSchedule;
+    }
+
+    function setBillSchedule(BillSchedule $billSchedule): self
+    {
+        $this->billSchedule = $billSchedule;
+        return $this;
+    }
+
+    function getDocumentRib(): DocumentWish
+    {
+        return $this->documentRib;
+    }
+
+    function setDocumentRib(DocumentWish $documentRib): self
+    {
+        $this->documentRib = $documentRib;
+        return $this;
+    }
+
+    function getDocumentSepa(): DocumentWish
+    {
+        return $this->documentSepa;
+    }
+
+    function setDocumentSepa(DocumentWish $documentSepa): self
+    {
+        $this->documentSepa = $documentSepa;
+        return $this;
+    }
+
+    function getWishPack(): EducationCurriculumPack
+    {
+        return $this->wishPack;
+    }
+
+    function setWishPack(EducationCurriculumPack $wishPack): self
+    {
+        $this->wishPack = $wishPack;
+        return $this;
+    }
+
+    function getFavoritePlace(): Place
+    {
+        return $this->favoritePlace;
+    }
+
+    function setFavoritePlace(Place $favoritePlace): self
+    {
+        $this->favoritePlace = $favoritePlace;
+        return $this;
+    }
 }

+ 28 - 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,26 @@ class DocumentWish
 
         return $this;
     }
+
+    function getAccessWishRib(): AccessWish
+    {
+        return $this->accessWishRib;
+    }
+
+    function setAccessWishRib(AccessWish $accessWishRib): self
+    {
+        $this->accessWishRib = $accessWishRib;
+        return $this;
+    }
+
+    function getAccessWishSepa(): AccessWish
+    {
+        return $this->accessWishSepa;
+    }
+
+    function setAccessWishSepa(AccessWish $accessWishSepa): self
+    {
+        $this->accessWishSepa = $accessWishSepa;
+        return $this;
+    }
 }

+ 64 - 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,47 @@ class EducationStudentWish
 
         return $this;
     }
+
+    function getTeachers(): Collection
+    {
+        return $this->teachers;
+    }
+
+    function addTeacher(Access $teacher): self
+    {
+        if (!$this->teachers->contains($teacher)) {
+            $this->teachers[] = $teacher;
+        }
+
+        return $this;
+    }
+
+    function removeTeacher(Access $teacher): self
+    {
+        $this->teachers->removeElement($teacher);
+
+        return $this;
+    }
+
+    function getSpeciality(): EquipmentList
+    {
+        return $this->speciality;
+    }
+
+    function setSpeciality(EquipmentList $speciality): self
+    {
+        $this->speciality = $speciality;
+        return $this;
+    }
+
+    function getCourse(): Course
+    {
+        return $this->course;
+    }
+
+    function setCourse(Course $course): self
+    {
+        $this->course = $course;
+        return $this;
+    }
 }

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

@@ -0,0 +1,417 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Awin;
+
+use ApiPlatform\Metadata\ApiResource;
+use DateTimeInterface;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
+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;
+
+    function getId(): int
+    {
+        return $this->id;
+    }
+
+    function setId(int $id): self
+    {
+        $this->id = $id;
+        return $this;
+    }
+
+    function getSlug(): mixed
+    {
+        return $this->slug;
+    }
+
+    function setSlug(mixed $slug): self
+    {
+        $this->slug = $slug;
+        return $this;
+    }
+
+    function getName(): mixed
+    {
+        return $this->name;
+    }
+
+    function setName(mixed $name): self
+    {
+        $this->name = $name;
+        return $this;
+    }
+
+    function getDescription(): string
+    {
+        return $this->description;
+    }
+
+    function setDescription(string $description): self
+    {
+        $this->description = $description;
+        return $this;
+    }
+
+    function getCategoryCode(): mixed
+    {
+        return $this->categoryCode;
+    }
+
+    function setCategoryCode(mixed $categoryCode): self
+    {
+        $this->categoryCode = $categoryCode;
+        return $this;
+    }
+
+    function getSubCategory(): mixed
+    {
+        return $this->subCategory;
+    }
+
+    function setSubCategory(mixed $subCategory): self
+    {
+        $this->subCategory = $subCategory;
+        return $this;
+    }
+
+    /**
+     * @return string[]
+     */
+    function getCategories(): array
+    {
+        return $this->categories;
+    }
+
+    /**
+     * @param string[] $categories
+     * @return self
+     */
+    function setCategories(array $categories): self
+    {
+        $this->categories = $categories;
+        return $this;
+    }
+
+    function getDatetimeStart(): mixed
+    {
+        return $this->datetimeStart;
+    }
+
+    function setDatetimeStart(mixed $datetimeStart): self
+    {
+        $this->datetimeStart = $datetimeStart;
+        return $this;
+    }
+
+    function getDatetimeEnd(): mixed
+    {
+        return $this->datetimeEnd;
+    }
+
+    function setDatetimeEnd(mixed $datetimeEnd): self
+    {
+        $this->datetimeEnd = $datetimeEnd;
+        return $this;
+    }
+
+    /**
+     * @return string[]
+     */
+    function getMeetingSchedule(): array
+    {
+        return $this->meetingSchedule;
+    }
+
+    /**
+     * @param array<string> $meetingSchedule
+     * @return $this
+     */
+    function setMeetingSchedule(array $meetingSchedule): self
+    {
+        $this->meetingSchedule = $meetingSchedule;
+        return $this;
+    }
+
+    function getPlaceCode(): mixed
+    {
+        return $this->placeCode;
+    }
+
+    function setPlaceCode(mixed $placeCode): self
+    {
+        $this->placeCode = $placeCode;
+        return $this;
+    }
+
+    function getPlace(): mixed
+    {
+        return $this->place;
+    }
+
+    function setPlace(mixed $place): self
+    {
+        $this->place = $place;
+        return $this;
+    }
+
+    function getStreetAddress(): mixed
+    {
+        return $this->streetAddress;
+    }
+
+    function setStreetAddress(mixed $streetAddress): self
+    {
+        $this->streetAddress = $streetAddress;
+        return $this;
+    }
+
+    function getPostalCode(): mixed
+    {
+        return $this->postalCode;
+    }
+
+    function setPostalCode(mixed $postalCode): self
+    {
+        $this->postalCode = $postalCode;
+        return $this;
+    }
+
+    function getCity(): mixed
+    {
+        return $this->city;
+    }
+
+    function setCity(mixed $city): self
+    {
+        $this->city = $city;
+        return $this;
+    }
+
+    function getCountry(): mixed
+    {
+        return $this->country;
+    }
+
+    function setCountry(mixed $country): self
+    {
+        $this->country = $country;
+        return $this;
+    }
+
+    function getLatitude(): mixed
+    {
+        return $this->latitude;
+    }
+
+    function setLatitude(mixed $latitude): self
+    {
+        $this->latitude = $latitude;
+        return $this;
+    }
+
+    function getLongitude(): mixed
+    {
+        return $this->longitude;
+    }
+
+    function setLongitude(mixed $longitude): self
+    {
+        $this->longitude = $longitude;
+        return $this;
+    }
+
+    function getMediumimage(): mixed
+    {
+        return $this->mediumimage;
+    }
+
+    function setMediumimage(mixed $mediumimage): self
+    {
+        $this->mediumimage = $mediumimage;
+        return $this;
+    }
+
+    function getLargeimage(): mixed
+    {
+        return $this->largeimage;
+    }
+
+    function setLargeimage(mixed $largeimage): self
+    {
+        $this->largeimage = $largeimage;
+        return $this;
+    }
+
+    function getDeepLink(): string
+    {
+        return $this->deepLink;
+    }
+
+    function setDeepLink(string $deepLink): self
+    {
+        $this->deepLink = $deepLink;
+        return $this;
+    }
+
+    function getPriceMini(): mixed
+    {
+        return $this->priceMini;
+    }
+
+    function setPriceMini(mixed $priceMini): self
+    {
+        $this->priceMini = $priceMini;
+        return $this;
+    }
+
+    function getPriceMaxi(): mixed
+    {
+        return $this->priceMaxi;
+    }
+
+    function setPriceMaxi(mixed $priceMaxi): self
+    {
+        $this->priceMaxi = $priceMaxi;
+        return $this;
+    }
+
+    function getArtists(): string
+    {
+        return $this->artists;
+    }
+
+    function setArtists(string $artists): self
+    {
+        $this->artists = $artists;
+        return $this;
+    }
+
+    function getUuid(): string
+    {
+        return $this->uuid;
+    }
+
+    function setUuid(string $uuid): self
+    {
+        $this->uuid = $uuid;
+        return $this;
+    }
+
+    function getCreateDate(): DateTimeInterface
+    {
+        return $this->createDate;
+    }
+
+    function setCreateDate(DateTimeInterface $createDate): self
+    {
+        $this->createDate = $createDate;
+        return $this;
+    }
+
+    function getUpdateDate(): DateTimeInterface
+    {
+        return $this->updateDate;
+    }
+
+    function setUpdateDate(DateTimeInterface $updateDate): self
+    {
+        $this->updateDate = $updateDate;
+        return $this;
+    }
+}

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

@@ -0,0 +1,433 @@
+<?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;
+
+    #[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;
+        }
+
+        return $this;
+    }
+
+    public function removeTag(Tagg $tag): self
+    {
+        $this->tags->removeElement($tag);
+
+        return $this;
+    }
+
+    function getAccess(): Access
+    {
+        return $this->access;
+    }
+
+    function setAccess(?Access $access): self
+    {
+        $this->access = $access;
+        return $this;
+    }
+
+    function getAccessDetail(): BillAccessDetail
+    {
+        return $this->accessDetail;
+    }
+
+    function setAccessDetail(BillAccessDetail $accessDetail): self
+    {
+        $this->accessDetail = $accessDetail;
+        return $this;
+    }
+
+    function getBillPeriod(): BillPeriod
+    {
+        return $this->billPeriod;
+    }
+
+    function setBillPeriod(BillPeriod $billPeriod): self
+    {
+        $this->billPeriod = $billPeriod;
+        return $this;
+    }
+
+    function getTotalDetail(): BillTotalDetail
+    {
+        return $this->totalDetail;
+    }
+
+    function setTotalDetail(BillTotalDetail $totalDetail): self
+    {
+        $this->totalDetail = $totalDetail;
+        return $this;
+    }
+
+    function getFile(): File
+    {
+        return $this->file;
+    }
+
+    function setFile(File $file): self
+    {
+        $this->file = $file;
+        return $this;
+    }
+
+    function getOdyssee(): Odyssee
+    {
+        return $this->odyssee;
+    }
+
+    function setOdyssee(Odyssee $odyssee): self
+    {
+        $this->odyssee = $odyssee;
+        return $this;
+    }
+
+    function getAfi(): Afi
+    {
+        return $this->afi;
+    }
+
+    function setAfi(Afi $afi): self
+    {
+        $this->afi = $afi;
+        return $this;
+    }
+
+    function getCirilCivil(): CirilCivil
+    {
+        return $this->cirilCivil;
+    }
+
+    function setCirilCivil(CirilCivil $cirilCivil): self
+    {
+        $this->cirilCivil = $cirilCivil;
+        return $this;
+    }
+}

+ 15 - 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,15 @@ class AccessBilling
 
         return $this;
     }
+
+    function getBillSchedule(): BillSchedule
+    {
+        return $this->billSchedule;
+    }
+
+    function setBillSchedule(BillSchedule $billSchedule): self
+    {
+        $this->billSchedule = $billSchedule;
+        return $this;
+    }
 }

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

@@ -0,0 +1,17 @@
+<?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';
+}

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

@@ -0,0 +1,61 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use ApiPlatform\Metadata\ApiResource;
+use App;
+use App\Entity\Core\File;
+use DateTimeInterface;
+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 App\Entity\Core\File $file;
+
+    function getId(): int
+    {
+        return $this->id;
+    }
+
+    function setId(int $id): self
+    {
+        $this->id = $id;
+        return $this;
+    }
+
+    function getBills(): Collection
+    {
+        return $this->bills;
+    }
+
+    function setBills(Collection $bills): self
+    {
+        $this->bills = $bills;
+        return $this;
+    }
+
+    function getFile(): App\Entity\Core\File
+    {
+        return $this->file;
+    }
+
+    function setFile(App\Entity\Core\File $file): self
+    {
+        $this->file = $file;
+        return $this;
+    }
+}

+ 15 - 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,15 @@ class BergerLevrault
 
         return $this;
     }
+
+    function getFile(): File
+    {
+        return $this->file;
+    }
+
+    function setFile(File $file): self
+    {
+        $this->file = $file;
+        return $this;
+    }
 }

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

@@ -1,40 +1,17 @@
 <?php
-
 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 - 289
src/Entity/Billing/BillAccounting.php

@@ -1,304 +1,17 @@
 <?php
-
 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 - 26
src/Entity/Billing/BillCredit.php

@@ -1,41 +1,17 @@
 <?php
-
 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;
 

+ 33 - 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,26 @@ class BillPayment
 
         return $this;
     }
+
+    function getSddBank(): SddBank
+    {
+        return $this->sddBank;
+    }
+
+    function setSddBank(SddBank $sddBank): self
+    {
+        $this->sddBank = $sddBank;
+        return $this;
+    }
+
+    function getSddRegie(): SddRegie
+    {
+        return $this->sddRegie;
+    }
+
+    function setSddRegie(SddRegie $sddRegie): self
+    {
+        $this->sddRegie = $sddRegie;
+        return $this;
+    }
 }

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

@@ -0,0 +1,91 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use ApiPlatform\Metadata\ApiResource;
+use App;
+use App\Entity\AccessWish\AccessWish;
+use App\Entity\Organization\Organization;
+use DateTimeInterface;
+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 App\Entity\Organization\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)]
+    protected Collection $accessBilling;
+
+    #[ORM\OneToMany(mappedBy: 'billSchedule', targetEntity: AccessWish::class, cascade: [], orphanRemoval: false)]
+    protected Collection $accessWishes;
+
+    function getId(): int
+    {
+        return $this->id;
+    }
+
+    function setId(int $id): self
+    {
+        $this->id = $id;
+        return $this;
+    }
+
+    function getOrganization(): App\Entity\Organization\Organization
+    {
+        return $this->organization;
+    }
+
+    function setOrganization(App\Entity\Organization\Organization $organization): self
+    {
+        $this->organization = $organization;
+        return $this;
+    }
+
+    function getScheduleDates(): Collection
+    {
+        return $this->scheduleDates;
+    }
+
+    function setScheduleDates(Collection $scheduleDates): self
+    {
+        $this->scheduleDates = $scheduleDates;
+        return $this;
+    }
+
+    function getAccessBilling(): Collection
+    {
+        return $this->accessBilling;
+    }
+
+    function setAccessBilling(Collection $accessBilling): self
+    {
+        $this->accessBilling = $accessBilling;
+        return $this;
+    }
+
+    function getAccessWishes(): Collection
+    {
+        return $this->accessWishes;
+    }
+
+    function setAccessWishes(Collection $accessWishes): self
+    {
+        $this->accessWishes = $accessWishes;
+        return $this;
+    }
+}

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

@@ -0,0 +1,45 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use ApiPlatform\Metadata\ApiResource;
+use DateTimeInterface;
+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;
+
+    function getId(): int
+    {
+        return $this->id;
+    }
+
+    function setId(int $id): self
+    {
+        $this->id = $id;
+        return $this;
+    }
+
+    function getBillSchedule(): mixed
+    {
+        return $this->billSchedule;
+    }
+
+    function setBillSchedule(mixed $billSchedule): self
+    {
+        $this->billSchedule = $billSchedule;
+        return $this;
+    }
+}

+ 46 - 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,35 @@ class BillingExportSetting
 
         return $this;
     }
+
+    function getOrganization(): Organization
+    {
+        return $this->organization;
+    }
+
+    function setOrganization(Organization $organization): self
+    {
+        $this->organization = $organization;
+        return $this;
+    }
+    function getStageManagers(): Collection
+    {
+        return $this->stageManagers;
+    }
+
+    function addStageManager(Access $stageManager): self
+    {
+        if (!$this->stageManagers->contains($stageManager)) {
+            $this->stageManagers[] = $stageManager;
+        }
+
+        return $this;
+    }
+
+    function removeStageManager(Access $stageManager): self
+    {
+        $this->stageManagers->removeElement($stageManager);
+
+        return $this;
+    }
 }

+ 14 - 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,15 @@ class BillingSetting
 
         return $this;
     }
+
+    function getBillingSettingRent(): BillingSettingRent
+    {
+        return $this->billingSettingRent;
+    }
+
+    function setBillingSettingRent(BillingSettingRent $billingSettingRent): self
+    {
+        $this->billingSettingRent = $billingSettingRent;
+        return $this;
+    }
 }

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

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

+ 15 - 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,15 @@ class Ciril
 
         return $this;
     }
+
+    function getFile(): File
+    {
+        return $this->file;
+    }
+
+    function setFile(File $file): self
+    {
+        $this->file = $file;
+        return $this;
+    }
 }

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

@@ -0,0 +1,61 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use ApiPlatform\Metadata\ApiResource;
+use App;
+use App\Entity\Core\File;
+use DateTimeInterface;
+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 App\Entity\Core\File $file;
+
+    function getId(): int
+    {
+        return $this->id;
+    }
+
+    function setId(int $id): self
+    {
+        $this->id = $id;
+        return $this;
+    }
+
+    function getBills(): Collection
+    {
+        return $this->bills;
+    }
+
+    function setBills(Collection $bills): self
+    {
+        $this->bills = $bills;
+        return $this;
+    }
+
+    function getFile(): App\Entity\Core\File
+    {
+        return $this->file;
+    }
+
+    function setFile(App\Entity\Core\File $file): self
+    {
+        $this->file = $file;
+        return $this;
+    }
+}

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

@@ -0,0 +1,80 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use ApiPlatform\Metadata\ApiResource;
+use App\Entity\Product\IntangibleDiscountDetail;
+use DateTimeInterface;
+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;
+
+    function getId(): int
+    {
+        return $this->id;
+    }
+
+    function setId(int $id): self
+    {
+        $this->id = $id;
+        return $this;
+    }
+
+    function getFamilyQuotientModel(): mixed
+    {
+        return $this->familyQuotientModel;
+    }
+
+    function setFamilyQuotientModel(mixed $familyQuotientModel): self
+    {
+        $this->familyQuotientModel = $familyQuotientModel;
+        return $this;
+    }
+
+    function getFamilyQuotientBandDetails(): Collection
+    {
+        return $this->familyQuotientBandDetails;
+    }
+
+    function setFamilyQuotientBandDetails(Collection $familyQuotientBandDetails): self
+    {
+        $this->familyQuotientBandDetails = $familyQuotientBandDetails;
+        return $this;
+    }
+
+    function getIntangibleDiscountDetails(): Collection
+    {
+        return $this->intangibleDiscountDetails;
+    }
+
+    function setIntangibleDiscountDetails(Collection $intangibleDiscountDetails): self
+    {
+        $this->intangibleDiscountDetails = $intangibleDiscountDetails;
+        return $this;
+    }
+}

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

@@ -0,0 +1,87 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use ApiPlatform\Metadata\ApiResource;
+use App;
+use App\Entity\Product\IntangibleDiscountDetail;
+use DateTimeInterface;
+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 App\Entity\Billing\ResidenceArea $residenceArea;
+
+    #[ORM\OneToMany(mappedBy: 'familyQuotientBandDetail', targetEntity: IntangibleDiscountDetail::class, cascade: [], orphanRemoval: true)]
+    protected Collection $intangibleDiscountDetails;
+
+    function getId(): int
+    {
+        return $this->id;
+    }
+
+    function setId(int $id): self
+    {
+        $this->id = $id;
+        return $this;
+    }
+
+    function getFamilyQuotientBand(): mixed
+    {
+        return $this->familyQuotientBand;
+    }
+
+    function setFamilyQuotientBand(mixed $familyQuotientBand): self
+    {
+        $this->familyQuotientBand = $familyQuotientBand;
+        return $this;
+    }
+
+    function getResidenceArea(): App\Entity\Billing\ResidenceArea
+    {
+        return $this->residenceArea;
+    }
+
+    function setResidenceArea(App\Entity\Billing\ResidenceArea $residenceArea): self
+    {
+        $this->residenceArea = $residenceArea;
+        return $this;
+    }
+
+    function getIntangibleDiscountDetails(): Collection
+    {
+        return $this->intangibleDiscountDetails;
+    }
+
+    function addIntangibleDiscountDetail(IntangibleDiscountDetail $intangibleDiscountDetail): self
+    {
+        if (!$this->intangibleDiscountDetails->contains($intangibleDiscountDetail)) {
+            $this->intangibleDiscountDetails[] = $intangibleDiscountDetail;
+        }
+
+        return $this;
+    }
+
+    function removeIntangibleDiscountDetail(IntangibleDiscountDetail $intangibleDiscountDetail): self
+    {
+        $this->intangibleDiscountDetails->removeElement($intangibleDiscountDetail);
+
+        return $this;
+    }
+}

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

@@ -0,0 +1,97 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use ApiPlatform\Metadata\ApiResource;
+use App;
+use App\Entity\Organization\Organization;
+use App\Entity\Product\IntangiblePriceAndDiscount;
+use DateTimeInterface;
+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 App\Entity\Organization\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;
+
+    function getId(): int
+    {
+        return $this->id;
+    }
+
+    function setId(int $id): self
+    {
+        $this->id = $id;
+        return $this;
+    }
+
+    function getOrganization(): App\Entity\Organization\Organization
+    {
+        return $this->organization;
+    }
+
+    function setOrganization(App\Entity\Organization\Organization $organization): self
+    {
+        $this->organization = $organization;
+        return $this;
+    }
+
+    function getFamilyQuotientBands(): Collection
+    {
+        return $this->familyQuotientBands;
+    }
+
+    function addFamilyQuotientBand(FamilyQuotientBand $familyQuotientBand): self
+    {
+        if (!$this->familyQuotientBands->contains($familyQuotientBand)) {
+            $this->familyQuotientBands[] = $familyQuotientBand;
+        }
+
+        return $this;
+    }
+
+    function removeFamilyQuotientBand(FamilyQuotientBand $familyQuotientBand): self
+    {
+        $this->familyQuotientBands->removeElement($familyQuotientBand);
+
+        return $this;
+    }
+
+    function getIntangiblePriceAndDiscounts(): Collection
+    {
+        return $this->intangiblePriceAndDiscounts;
+    }
+
+    function addIntangiblePriceAndDiscount(IntangiblePriceAndDiscount $intangiblePriceAndDiscount): self
+    {
+        if (!$this->intangiblePriceAndDiscounts->contains($intangiblePriceAndDiscount)) {
+            $this->intangiblePriceAndDiscounts[] = $intangiblePriceAndDiscount;
+        }
+
+        return $this;
+    }
+
+    function removeIntangiblePriceAndDiscount(IntangiblePriceAndDiscount $intangiblePriceAndDiscount): self
+    {
+        $this->intangiblePriceAndDiscounts->removeElement($intangiblePriceAndDiscount);
+
+        return $this;
+    }
+}

+ 15 - 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,15 @@ class Jvs
 
         return $this;
     }
+
+    function getFile(): File
+    {
+        return $this->file;
+    }
+
+    function setFile(File $file): self
+    {
+        $this->file = $file;
+        return $this;
+    }
 }

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

@@ -0,0 +1,71 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Billing;
+
+use ApiPlatform\Metadata\ApiResource;
+use App;
+use App\Entity\Core\File;
+use DateTimeInterface;
+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 App\Entity\Core\File $file;
+
+    function getId(): int
+    {
+        return $this->id;
+    }
+
+    function setId(int $id): self
+    {
+        $this->id = $id;
+        return $this;
+    }
+
+    function getBills(): Collection
+    {
+        return $this->bills;
+    }
+
+    function addBill(Bill $bill): self
+    {
+        if (!$this->bills->contains($bill)) {
+            $this->bills[] = $bill;
+        }
+
+        return $this;
+    }
+
+    function removeBill(Bill $bill): self
+    {
+        $this->bills->removeElement($bill);
+
+        return $this;
+    }
+
+    function getFile(): App\Entity\Core\File
+    {
+        return $this->file;
+    }
+
+    function setFile(App\Entity\Core\File $file): self
+    {
+        $this->file = $file;
+        return $this;
+    }
+}

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

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

+ 15 - 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,15 @@ class Pes
 
         return $this;
     }
+
+    function getFile(): File
+    {
+        return $this->file;
+    }
+
+    function setFile(File $file): self
+    {
+        $this->file = $file;
+        return $this;
+    }
 }

+ 15 - 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,22 @@ 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;
     }
+
+    function getOrganization(): Organization
+    {
+        return $this->organization;
+    }
+
+    function setOrganization(Organization $organization): self
+    {
+        $this->organization = $organization;
+        return $this;
+    }
 }

+ 42 - 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,51 @@ 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;
     }
+
+    function getBillPayments(): Collection
+    {
+        return $this->billPayments;
+    }
+
+    function addBillPayment(BillPayment $billPayment): self
+    {
+        if (!$this->billPayments->contains($billPayment)) {
+            $this->billPayments[] = $billPayment;
+        }
+
+        return $this;
+    }
+
+    function removeBillPayment(BillPayment $billPayment): self
+    {
+        $this->billPayments->removeElement($billPayment);
+
+        return $this;
+    }
+
+    function getFile(): File
+    {
+        return $this->file;
+    }
+
+    function setFile(File $file): self
+    {
+        $this->file = $file;
+        return $this;
+    }
 }

+ 57 - 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,65 @@ 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;
     }
+
+    function getBillPayments(): Collection
+    {
+        return $this->billPayments;
+    }
+
+    function addBillPayment(BillPayment $billPayment): self
+    {
+        if (!$this->billPayments->contains($billPayment)) {
+            $this->billPayments[] = $billPayment;
+        }
+
+        return $this;
+    }
+
+    function removeBillPayment(BillPayment $billPayment): self
+    {
+        $this->billPayments->removeElement($billPayment);
+
+        return $this;
+    }
+
+    function getFile(): File
+    {
+        return $this->file;
+    }
+
+    function setFile(File $file): self
+    {
+        $this->file = $file;
+        return $this;
+    }
+
+    function getBordereau(): File
+    {
+        return $this->bordereau;
+    }
+
+    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;
     }
+
+    function getOrganizer(): Collection
+    {
+        return $this->organizer;
+    }
+
+    function addOrganizer(Access $organizer): self
+    {
+        if (!$this->organizer->contains($organizer)) {
+            $this->organizer[] = $organizer;
+        }
+
+        return $this;
+    }
+
+    function removeOrganizer(Access $organizer): self
+    {
+        $this->organizer->removeElement($organizer);
+
+        return $this;
+    }
+
+    function getEquipments(): Collection
+    {
+        return $this->equipments;
+    }
+
+    function addEquipment(Equipment $equipment): self
+    {
+        if (!$this->equipments->contains($equipment)) {
+            $this->equipments[] = $equipment;
+        }
+
+        return $this;
+    }
+
+    function removeEquipment(Equipment $equipment): self
+    {
+        $this->equipments->removeElement($equipment);
+
+        return $this;
+    }
+
+    function getTags(): Collection
+    {
+        return $this->tags;
+    }
+
+    function addTag(Tagg $tag): self
+    {
+        if (!$this->tags->contains($tag)) {
+            $this->tags[] = $tag;
+        }
+
+        return $this;
+    }
+
+    function removeTag(Tagg $tag): self
+    {
+        $this->tags->removeElement($tag);
+
+        return $this;
+    }
 }

+ 30 - 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,36 @@ 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;
     }
+
+    function getAccess(): Access
+    {
+        return $this->access;
+    }
+
+    function setAccess(Access $access): self
+    {
+        $this->access = $access;
+        return $this;
+    }
+
+    function getFile(): File
+    {
+        return $this->file;
+    }
+
+    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;
     }
+
+    function getEducationStudentWishes(): Collection
+    {
+        return $this->educationStudentWishes;
+    }
+
+    function addEducationStudentWish(EducationStudentWish $educationStudentWish): self
+    {
+        if (!$this->educationStudentWishes->contains($educationStudentWish)) {
+            $this->educationStudentWishes[] = $educationStudentWish;
+        }
+
+        return $this;
+    }
+
+    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,9 +12,10 @@ 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 App\Entity\Product\Equipment;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
@@ -31,16 +32,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 +49,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 +91,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 +114,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 +418,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 +489,15 @@ class EducationalProject extends AbstractBooking
 
         return $this;
     }
+
+    function getAgeDistribution(): EducationalProjectAge
+    {
+        return $this->ageDistribution;
+    }
+
+    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,10 +10,11 @@ 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;
+use App\Entity\Product\Equipment;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
@@ -30,7 +31,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 +39,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 +109,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 +137,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 +454,15 @@ class Event extends AbstractBooking
 
         return $this;
     }
+
+    function getEquipments(): Collection
+    {
+        return $this->equipments;
+    }
+
+    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;

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

@@ -5,14 +5,16 @@ declare(strict_types=1);
 namespace App\Entity\Booking;
 
 use ApiPlatform\Metadata\ApiResource;
+use App\Entity\Access\Access;
 use App\Entity\Core\Tagg;
 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 App\Entity\Product\Equipment;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
@@ -29,42 +31,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 +76,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 +86,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 +295,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;

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

@@ -5,8 +5,11 @@ declare(strict_types=1);
 namespace App\Entity\Booking;
 
 use ApiPlatform\Metadata\ApiResource;
+use App\Entity\Access\Access;
+use App\Entity\Core\Tagg;
 use App\Entity\Organization\Organization;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
+use App\Entity\Product\Equipment;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
@@ -23,7 +26,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 +38,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;

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

@@ -7,6 +7,9 @@ namespace App\Entity\Booking;
 use ApiPlatform\Metadata\ApiResource;
 use App\Entity\Access\Access;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
+use App\Entity\Core\Tagg;
+use App\Entity\Organization\Organization;
+use App\Entity\Product\Equipment;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
@@ -23,7 +26,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 +34,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 +100,15 @@ class PersonHoliday extends AbstractBooking
 
         return $this;
     }
+
+    function getOrganization(): Organization
+    {
+        return $this->organization;
+    }
+
+    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;

+ 42 - 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,48 @@ 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;
     }
+
+    function getAccompanist(): Access
+    {
+        return $this->accompanist;
+    }
+
+    function setAccompanist(Access $accompanist): self
+    {
+        $this->accompanist = $accompanist;
+        return $this;
+    }
+
+    function getTags(): Collection
+    {
+        return $this->tags;
+    }
+
+    function addTag(Tagg $tag): self
+    {
+        if (!$this->tags->contains($tag)) {
+            $this->tags[] = $tag;
+        }
+
+        return $this;
+    }
+
+    function removeTag(Tagg $tag): self
+    {
+        $this->tags->removeElement($tag);
+
+        return $this;
+    }
 }

+ 31 - 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,37 @@ 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;
     }
+
+    function getTags(): Collection
+    {
+        return $this->tags;
+    }
+
+    function addTag(Tagg $tag): self
+    {
+        if (!$this->tags->contains($tag)) {
+            $this->tags[] = $tag;
+        }
+
+        return $this;
+    }
+
+    function removeTag(Tagg $tag): self
+    {
+        $this->tags->removeElement($tag);
+
+        return $this;
+    }
 }

+ 30 - 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\Repository\Core\AddressPostalRepository;
 use Doctrine\Common\Collections\ArrayCollection;
@@ -75,12 +75,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
@@ -221,14 +225,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;
@@ -238,7 +242,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)
@@ -249,4 +253,25 @@ class AddressPostal
 
         return $this;
     }
+
+    function getOrganizationAddressPostals(): Collection
+    {
+        return $this->organizationAddressPostals;
+    }
+
+    function addOrganizationAddressPostal(OrganizationAddressPostal $organizationAddressPostal): self
+    {
+        if (!$this->organizationAddressPostals->contains($organizationAddressPostal)) {
+            $this->organizationAddressPostals[] = $organizationAddressPostal;
+        }
+
+        return $this;
+    }
+
+    function removeOrganizationAddressPostal(OrganizationAddressPostal $organizationAddressPostal): self
+    {
+        $this->organizationAddressPostals->removeElement($organizationAddressPostal);
+
+        return $this;
+    }
 }

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

@@ -19,8 +19,23 @@ 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;
     }
+
+    function getDepartment(): Department
+    {
+        return $this->department;
+    }
+
+    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\Enum\Core\ContactPointTypeEnum;
 use App\Repository\Core\ContactPointRepository;
@@ -77,7 +77,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')]
@@ -265,14 +265,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;
@@ -282,7 +282,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);

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

@@ -19,8 +19,23 @@ 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;
     }
+
+    function getRegion(): Region
+    {
+        return $this->region;
+    }
+
+    function setRegion(Region $region): self
+    {
+        $this->region = $region;
+        return $this;
+    }
 }

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

@@ -0,0 +1,116 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Core;
+
+use ApiPlatform\Metadata\ApiResource;
+use DateTimeInterface;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
+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;
+
+    function getId(): int
+    {
+        return $this->id;
+    }
+
+    function setId(int $id): self
+    {
+        $this->id = $id;
+        return $this;
+    }
+
+    function getLogin(): mixed
+    {
+        return $this->login;
+    }
+
+    function setLogin(mixed $login): self
+    {
+        $this->login = $login;
+        return $this;
+    }
+
+    function getOrganizationId(): int
+    {
+        return $this->organizationId;
+    }
+
+    function setOrganizationId(int $organizationId): self
+    {
+        $this->organizationId = $organizationId;
+        return $this;
+    }
+
+    function getNavigateur(): mixed
+    {
+        return $this->navigateur;
+    }
+
+    function setNavigateur(mixed $navigateur): self
+    {
+        $this->navigateur = $navigateur;
+        return $this;
+    }
+
+    function getIp(): mixed
+    {
+        return $this->ip;
+    }
+
+    function setIp(mixed $ip): self
+    {
+        $this->ip = $ip;
+        return $this;
+    }
+
+    function getDate(): DateTimeInterface
+    {
+        return $this->date;
+    }
+
+    function setDate(DateTimeInterface $date): self
+    {
+        $this->date = $date;
+        return $this;
+    }
+
+    function getType(): mixed
+    {
+        return $this->type;
+    }
+
+    function setType(mixed $type): self
+    {
+        $this->type = $type;
+        return $this;
+    }
+}

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

@@ -19,8 +19,23 @@ 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;
     }
+
+    function getCountry(): Country
+    {
+        return $this->country;
+    }
+
+    function setCountry(Country $country): self
+    {
+        $this->country = $country;
+        return $this;
+    }
 }

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

@@ -8,15 +8,18 @@ use ApiPlatform\Metadata\ApiResource;
 use App\Entity\Access\Access;
 use App\Entity\AccessWish\AccessWish;
 use App\Entity\Billing\AbstractBillingIntangible;
-use App\Entity\Billing\BillAccounting;
+use App\Entity\Billing\AbstractBillAccounting;
 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,13 @@ 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 +267,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 +284,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 +834,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 +851,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 +940,130 @@ class Tagg
 
         return $this;
     }
+
+    function getProducts(): Collection
+    {
+        return $this->products;
+    }
+
+    function addProduct(AbstractProduct $product): self
+    {
+        if (!$this->products->contains($product)) {
+            $this->products[] = $product;
+        }
+
+        return $this;
+    }
+
+    function removeProduct(AbstractProduct $product): self
+    {
+        $this->products->removeElement($product);
+
+        return $this;
+    }
+
+    function getBookings(): Collection
+    {
+        return $this->bookings;
+    }
+
+    function addBooking(AbstractBooking $booking): self
+    {
+        if (!$this->bookings->contains($booking)) {
+            $this->bookings[] = $booking;
+        }
+
+        return $this;
+    }
+
+    function removeBooking(AbstractBooking $booking): self
+    {
+        $this->bookings->removeElement($booking);
+
+        return $this;
+    }
+
+    function getMessages(): Collection
+    {
+        return $this->messages;
+    }
+
+    function addMessage(AbstractMessage $message): self
+    {
+        if (!$this->messages->contains($message)) {
+            $this->messages[] = $message;
+        }
+
+        return $this;
+    }
+
+    function removeMessage(AbstractMessage $message): self
+    {
+        $this->messages->removeElement($message);
+
+        return $this;
+    }
+
+    function getRepairs(): Collection
+    {
+        return $this->repairs;
+    }
+
+    function addRepair(AbstractRepair $repair): self
+    {
+        if (!$this->repairs->contains($repair)) {
+            $this->repairs[] = $repair;
+        }
+
+        return $this;
+    }
+
+    function removeRepair(AbstractRepair $repair): self
+    {
+        $this->repairs->removeElement($repair);
+
+        return $this;
+    }
+
+    function getControls(): Collection
+    {
+        return $this->controls;
+    }
+
+    function addControl(AbstractControl $control): self
+    {
+        if (!$this->controls->contains($control)) {
+            $this->controls[] = $control;
+        }
+
+        return $this;
+    }
+
+    function removeControl(AbstractControl $control): self
+    {
+        $this->controls->removeElement($control);
+
+        return $this;
+    }
+
+    function getEducationCurriculumPacks(): Collection
+    {
+        return $this->educationCurriculumPacks;
+    }
+
+    function addEducationCurriculumPack(EducationCurriculumPack $educationCurriculumPack): self
+    {
+        if (!$this->educationCurriculumPacks->contains($educationCurriculumPack)) {
+            $this->educationCurriculumPacks[] = $educationCurriculumPack;
+        }
+
+        return $this;
+    }
+
+    function removeEducationCurriculumPack(EducationCurriculumPack $educationCurriculumPack): self
+    {
+        $this->educationCurriculumPacks->removeElement($educationCurriculumPack);
+
+        return $this;
+    }
 }

+ 25 - 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,25 @@ class Cycle
 
         return $this;
     }
+
+    function getEducationCurriculums(): Collection
+    {
+        return $this->educationCurriculums;
+    }
+
+    function addEducationCurriculum(EducationCurriculum $educationCurriculum): self
+    {
+        if (!$this->educationCurriculums->contains($educationCurriculum)) {
+            $this->educationCurriculums[] = $educationCurriculum;
+        }
+
+        return $this;
+    }
+
+    function removeEducationCurriculum(EducationCurriculum $educationCurriculum): self
+    {
+        $this->educationCurriculums->removeElement($educationCurriculum);
+
+        return $this;
+    }
 }

+ 26 - 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,25 @@ class Education
 
         return $this;
     }
+
+    function getEducationWishes(): Collection
+    {
+        return $this->educationWishes;
+    }
+
+    function addEducationWishe(EducationStudentWish $educationWishe): self
+    {
+        if (!$this->educationWishes->contains($educationWishe)) {
+            $this->educationWishes[] = $educationWishe;
+        }
+
+        return $this;
+    }
+
+    function removeEducationWishe(EducationStudentWish $educationWishe): self
+    {
+        $this->educationWishes->removeElement($educationWishe);
+
+        return $this;
+    }
 }

+ 31 - 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,37 @@ 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;
     }
+
+    function getEducations(): Collection
+    {
+        return $this->educations;
+    }
+
+    function addEducation(Education $education): self
+    {
+        if (!$this->educations->contains($education)) {
+            $this->educations[] = $education;
+        }
+
+        return $this;
+    }
+
+    function removeEducation(Education $education): self
+    {
+        $this->educations->removeElement($education);
+
+        return $this;
+    }
 }

+ 175 - 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,132 @@ class EducationCurriculum
 
         return $this;
     }
+
+    function getEducationStudentWish(): Collection
+    {
+        return $this->educationStudentWish;
+    }
+
+    function addEducationStudentWish(EducationStudentWish $educationStudentWish): self
+    {
+        if (!$this->educationStudentWish->contains($educationStudentWish)) {
+            $this->educationStudentWish[] = $educationStudentWish;
+        }
+
+        return $this;
+    }
+
+    function removeEducationStudentWish(EducationStudentWish $educationStudentWish): self
+    {
+        $this->educationStudentWish->removeElement($educationStudentWish);
+
+        return $this;
+    }
+
+    function getCourses(): Collection
+    {
+        return $this->courses;
+    }
+
+    function addCourse(Course $course): self
+    {
+        if (!$this->courses->contains($course)) {
+            $this->courses[] = $course;
+        }
+
+        return $this;
+    }
+
+    function removeCourse(Course $course): self
+    {
+        $this->courses->removeElement($course);
+
+        return $this;
+    }
+
+    function getExamens(): Collection
+    {
+        return $this->examens;
+    }
+
+    function addExamen(Examen $examen): self
+    {
+        if (!$this->examens->contains($examen)) {
+            $this->examens[] = $examen;
+        }
+
+        return $this;
+    }
+
+    function removeExamen(Examen $examen): self
+    {
+        $this->examens->removeElement($examen);
+
+        return $this;
+    }
+
+    function getIntangibles(): Collection
+    {
+        return $this->intangibles;
+    }
+
+    function addIntangible(Intangible $intangible): self
+    {
+        if (!$this->intangibles->contains($intangible)) {
+            $this->intangibles[] = $intangible;
+        }
+
+        return $this;
+    }
+
+    function removeIntangible(Intangible $intangible): self
+    {
+        $this->intangibles->removeElement($intangible);
+
+        return $this;
+    }
+
+    function getRequiredChoicesEducationCurriculumPacks(): Collection
+    {
+        return $this->requiredChoicesEducationCurriculumPacks;
+    }
+
+    function addRequiredChoicesEducationCurriculumPack(
+        EducationCurriculumPack $requiredChoicesEducationCurriculumPack,
+    ): self {
+        if (!$this->requiredChoicesEducationCurriculumPacks->contains($requiredChoicesEducationCurriculumPack)) {
+            $this->requiredChoicesEducationCurriculumPacks[] = $requiredChoicesEducationCurriculumPack;
+        }
+
+        return $this;
+    }
+
+    function removeRequiredChoicesEducationCurriculumPack(
+        EducationCurriculumPack $requiredChoicesEducationCurriculumPack,
+    ): self {
+        $this->requiredChoicesEducationCurriculumPacks->removeElement($requiredChoicesEducationCurriculumPack);
+
+        return $this;
+    }
+
+    function getOptionnalEducationCurriculumPacks(): Collection
+    {
+        return $this->optionnalEducationCurriculumPacks;
+    }
+
+    function addOptionnalEducationCurriculumPack(EducationCurriculumPack $optionnalEducationCurriculumPack): self
+    {
+        if (!$this->optionnalEducationCurriculumPacks->contains($optionnalEducationCurriculumPack)) {
+            $this->optionnalEducationCurriculumPacks[] = $optionnalEducationCurriculumPack;
+        }
+
+        return $this;
+    }
+
+    function removeOptionnalEducationCurriculumPack(EducationCurriculumPack $optionnalEducationCurriculumPack): self
+    {
+        $this->optionnalEducationCurriculumPacks->removeElement($optionnalEducationCurriculumPack);
+
+        return $this;
+    }
 }

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

@@ -0,0 +1,186 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Education;
+
+use ApiPlatform\Metadata\ApiResource;
+use App;
+use App\Entity\Core\Tagg;
+use App\Entity\Organization\Organization;
+use App\Entity\Product\Intangible;
+use DateTimeInterface;
+use Doctrine\Common\Collections\ArrayCollection;
+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 App\Entity\Organization\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;
+
+    function getId(): int
+    {
+        return $this->id;
+    }
+
+    function setId(int $id): self
+    {
+        $this->id = $id;
+        return $this;
+    }
+
+    function getOrganization(): App\Entity\Organization\Organization
+    {
+        return $this->organization;
+    }
+
+    function setOrganization(App\Entity\Organization\Organization $organization): self
+    {
+        $this->organization = $organization;
+        return $this;
+    }
+
+    function getTags(): Collection
+    {
+        return $this->tags;
+    }
+
+    function addTag(Tagg $tag): self
+    {
+        if (!$this->tags->contains($tag)) {
+            $this->tags[] = $tag;
+        }
+
+        return $this;
+    }
+
+    function removeTag(Tagg $tag): self
+    {
+        $this->tags->removeElement($tag);
+
+        return $this;
+    }
+
+    function getRequiredEducationCurriculums(): Collection
+    {
+        return $this->requiredEducationCurriculums;
+    }
+
+    function addRequiredEducationCurriculum(EducationCurriculum $requiredEducationCurriculum): self
+    {
+        if (!$this->requiredEducationCurriculums->contains($requiredEducationCurriculum)) {
+            $this->requiredEducationCurriculums[] = $requiredEducationCurriculum;
+        }
+
+        return $this;
+    }
+
+    function removeRequiredEducationCurriculum(EducationCurriculum $requiredEducationCurriculum): self
+    {
+        $this->requiredEducationCurriculums->removeElement($requiredEducationCurriculum);
+
+        return $this;
+    }
+
+    function getRequiredChoicesEducationCurriculums(): Collection
+    {
+        return $this->requiredChoicesEducationCurriculums;
+    }
+
+    function addRequiredChoicesEducationCurriculum(EducationCurriculum $requiredChoicesEducationCurriculum): self
+    {
+        if (!$this->requiredChoicesEducationCurriculums->contains($requiredChoicesEducationCurriculum)) {
+            $this->requiredChoicesEducationCurriculums[] = $requiredChoicesEducationCurriculum;
+        }
+
+        return $this;
+    }
+
+    function removeRequiredChoicesEducationCurriculum(EducationCurriculum $requiredChoicesEducationCurriculum): self
+    {
+        $this->requiredChoicesEducationCurriculums->removeElement($requiredChoicesEducationCurriculum);
+
+        return $this;
+    }
+
+    function getOptionnalEducationCurriculums(): Collection
+    {
+        return $this->optionnalEducationCurriculums;
+    }
+
+    function addOptionnalEducationCurriculum(EducationCurriculum $optionnalEducationCurriculum): self
+    {
+        if (!$this->optionnalEducationCurriculums->contains($optionnalEducationCurriculum)) {
+            $this->optionnalEducationCurriculums[] = $optionnalEducationCurriculum;
+        }
+
+        return $this;
+    }
+
+    function removeOptionnalEducationCurriculum(EducationCurriculum $optionnalEducationCurriculum): self
+    {
+        $this->optionnalEducationCurriculums->removeElement($optionnalEducationCurriculum);
+
+        return $this;
+    }
+
+    function getIntangibles(): Collection
+    {
+        return $this->intangibles;
+    }
+
+    function addIntangible(Intangible $intangible): self
+    {
+        if (!$this->intangibles->contains($intangible)) {
+            $this->intangibles[] = $intangible;
+        }
+
+        return $this;
+    }
+
+    function removeIntangible(Intangible $intangible): self
+    {
+        $this->intangibles->removeElement($intangible);
+
+        return $this;
+    }
+}

+ 16 - 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,15 @@ class EducationStudent
 
         return $this;
     }
+
+    function getSpeciality(): EquipmentList
+    {
+        return $this->speciality;
+    }
+
+    function setSpeciality(EquipmentList $speciality): self
+    {
+        $this->speciality = $speciality;
+        return $this;
+    }
 }

+ 62 - 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,49 @@ 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;
+        }
+
+        return $this;
+    }
+
+    public function removeFile(File $file): self
+    {
+        $this->files->removeElement($file);
+
+        return $this;
+    }
+
+    function getReportMessage(): Collection
+    {
+        return $this->reportMessage;
+    }
+
+    function addReportMessage(ReportMessage $reportMessage): self
+    {
+        if (!$this->reportMessage->contains($reportMessage)) {
+            $this->reportMessage[] = $reportMessage;
+        }
+
+        return $this;
+    }
+
+    function removeReportMessage(ReportMessage $reportMessage): self
+    {
+        $this->reportMessage->removeElement($reportMessage);
+
+        return $this;
+    }
 }

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

@@ -44,12 +44,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 +56,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 +137,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 - 30
src/Entity/Message/Mail.php

@@ -33,12 +33,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 +44,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 +71,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>
      */

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

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

+ 15 - 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,15 @@ class Network
 
         return $this;
     }
+
+    function getImage(): File
+    {
+        return $this->image;
+    }
+
+    function setImage(File $image): self
+    {
+        $this->image = $image;
+        return $this;
+    }
 }

+ 14 - 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,15 @@ class Activity
 
         return $this;
     }
+
+    function getTypeOfSection(): TypeOfPractice
+    {
+        return $this->typeOfSection;
+    }
+
+    function setTypeOfSection(TypeOfPractice $typeOfSection): self
+    {
+        $this->typeOfSection = $typeOfSection;
+        return $this;
+    }
 }

+ 14 - 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,15 @@ class CotisationByYear
 
         return $this;
     }
+
+    function getCotisationStaffInfos(): CotisationStaffInfos
+    {
+        return $this->cotisationStaffInfos;
+    }
+
+    function setCotisationStaffInfos(CotisationStaffInfos $cotisationStaffInfos): self
+    {
+        $this->cotisationStaffInfos = $cotisationStaffInfos;
+        return $this;
+    }
 }

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

@@ -19,8 +19,22 @@ 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;
     }
+
+    function getCotisationByYear(): CotisationByYear
+    {
+        return $this->cotisationByYear;
+    }
+
+    function setCotisationByYear(CotisationByYear $cotisationByYear): self
+    {
+        $this->cotisationByYear = $cotisationByYear;
+        return $this;
+    }
 }

+ 16 - 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,16 @@ class OnlineRegistrationDocument
 
         return $this;
     }
+
+    function getAdultStudentOnlineRegistrationSettings(): OnlineRegistrationSettings
+    {
+        return $this->adultStudentOnlineRegistrationSettings;
+    }
+
+    function setAdultStudentOnlineRegistrationSettings(
+        OnlineRegistrationSettings $adultStudentOnlineRegistrationSettings,
+    ): self {
+        $this->adultStudentOnlineRegistrationSettings = $adultStudentOnlineRegistrationSettings;
+        return $this;
+    }
 }

+ 44 - 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,36 @@ class OnlineRegistrationSettings
 
         return $this;
     }
+
+    function getOrganization(): Organization
+    {
+        return $this->organization;
+    }
+
+    function setOrganization(Organization $organization): self
+    {
+        $this->organization = $organization;
+        return $this;
+    }
+
+    function getAdultStudentDocuments(): Collection
+    {
+        return $this->adultStudentDocuments;
+    }
+
+    function addAdultStudentDocument(OnlineRegistrationDocument $adultStudentDocument): self
+    {
+        if (!$this->adultStudentDocuments->contains($adultStudentDocument)) {
+            $this->adultStudentDocuments[] = $adultStudentDocument;
+        }
+
+        return $this;
+    }
+
+    function removeAdultStudentDocument(OnlineRegistrationDocument $adultStudentDocument): self
+    {
+        $this->adultStudentDocuments->removeElement($adultStudentDocument);
+
+        return $this;
+    }
 }

+ 253 - 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;
@@ -296,7 +301,7 @@ class Organization
     #[ORM\OneToMany(mappedBy: 'organization', targetEntity: Commission::class, orphanRemoval: true)]
     private Collection $commissions;
 
-    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: Place::class, orphanRemoval: true)]
+    #[ORM\OneToMany(mappedBy: 'organization', targetEntity: AbstractPlace::class, orphanRemoval: true)]
     private Collection $places;
 
     #[ORM\OneToMany(mappedBy: 'organization', targetEntity: Attendance::class, orphanRemoval: true)]
@@ -323,6 +328,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()
     {
@@ -362,6 +400,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
@@ -438,6 +485,22 @@ class Organization
         return $this->accesses;
     }
 
+    function addAccess(Access $access): self
+    {
+        if (!$this->access->contains($access)) {
+            $this->access[] = $access;
+        }
+
+        return $this;
+    }
+
+    function removeAccess(Access $access): self
+    {
+        $this->access->removeElement($access);
+
+        return $this;
+    }
+
     public function getNetworkOrganizations(): Collection
     {
         return $this->networkOrganizations;
@@ -1197,28 +1260,6 @@ class Organization
         return $this->subdomains;
     }
 
-    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;
@@ -1646,14 +1687,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;
@@ -1663,7 +1704,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)
@@ -1855,4 +1896,189 @@ class Organization
 
         return $this;
     }
+
+    function getNetwork(): Collection
+    {
+        return $this->network;
+    }
+
+    function addNetwork(NetworkOrganization $network): self
+    {
+        if (!$this->network->contains($network)) {
+            $this->network[] = $network;
+        }
+
+        return $this;
+    }
+
+    function removeNetwork(NetworkOrganization $network): self
+    {
+        $this->network->removeElement($network);
+
+        return $this;
+    }
+
+    function getNetworkChild(): Collection
+    {
+        return $this->networkChild;
+    }
+
+    function addNetworkChild(NetworkOrganization $networkChild): self
+    {
+        if (!$this->networkChild->contains($networkChild)) {
+            $this->networkChild[] = $networkChild;
+        }
+
+        return $this;
+    }
+
+    function removeNetworkChild(NetworkOrganization $networkChild): self
+    {
+        $this->networkChild->removeElement($networkChild);
+
+        return $this;
+    }
+
+    function getBillingExportSetting(): BillingExportSetting
+    {
+        return $this->billingExportSetting;
+    }
+
+    function setBillingExportSetting(BillingExportSetting $billingExportSetting): self
+    {
+        $this->billingExportSetting = $billingExportSetting;
+        return $this;
+    }
+
+    function getMessages(): Collection
+    {
+        return $this->messages;
+    }
+
+    function addMessage(mixed $message): self
+    {
+        if (!$this->messages->contains($message)) {
+            $this->messages[] = $message;
+        }
+
+        return $this;
+    }
+
+    function removeMessage(mixed $message): self
+    {
+        $this->messages->removeElement($message);
+
+        return $this;
+    }
+
+    function getOnlineRegistrationSettings(): OnlineRegistrationSettings
+    {
+        return $this->onlineRegistrationSettings;
+    }
+
+    function setOnlineRegistrationSettings(OnlineRegistrationSettings $onlineRegistrationSettings): self
+    {
+        $this->onlineRegistrationSettings = $onlineRegistrationSettings;
+        return $this;
+    }
+
+    function getCotisationByYears(): Collection
+    {
+        return $this->cotisationByYears;
+    }
+
+    function addCotisationByYear(CotisationByYear $cotisationByYear): self
+    {
+        if (!$this->cotisationByYears->contains($cotisationByYear)) {
+            $this->cotisationByYears[] = $cotisationByYear;
+        }
+
+        return $this;
+    }
+
+    function removeCotisationByYear(CotisationByYear $cotisationByYear): self
+    {
+        $this->cotisationByYears->removeElement($cotisationByYear);
+
+        return $this;
+    }
+
+    function getAttendanceBookingReasons(): Collection
+    {
+        return $this->attendanceBookingReasons;
+    }
+
+    function addAttendanceBookingReason(AttendanceBookingReason $attendanceBookingReason): self
+    {
+        if (!$this->attendanceBookingReasons->contains($attendanceBookingReason)) {
+            $this->attendanceBookingReasons[] = $attendanceBookingReason;
+        }
+
+        return $this;
+    }
+
+    function removeAttendanceBookingReason(AttendanceBookingReason $attendanceBookingReason): self
+    {
+        $this->attendanceBookingReasons->removeElement($attendanceBookingReason);
+
+        return $this;
+    }
+
+    function getEducationCurriculumPacks(): Collection
+    {
+        return $this->educationCurriculumPacks;
+    }
+
+    function addEducationCurriculumPack(Cycle $educationCurriculumPack): self
+    {
+        if (!$this->educationCurriculumPacks->contains($educationCurriculumPack)) {
+            $this->educationCurriculumPacks[] = $educationCurriculumPack;
+        }
+
+        return $this;
+    }
+
+    function removeEducationCurriculumPack(Cycle $educationCurriculumPack): self
+    {
+        $this->educationCurriculumPacks->removeElement($educationCurriculumPack);
+
+        return $this;
+    }
+
+    function getFamilyQuotientModels(): Collection
+    {
+        return $this->familyQuotientModels;
+    }
+
+    function addFamilyQuotientModel(FamilyQuotientModel $familyQuotientModel): self
+    {
+        if (!$this->familyQuotientModels->contains($familyQuotientModel)) {
+            $this->familyQuotientModels[] = $familyQuotientModel;
+        }
+
+        return $this;
+    }
+
+    function removeFamilyQuotientModel(FamilyQuotientModel $familyQuotientModel): self
+    {
+        $this->familyQuotientModels->removeElement($familyQuotientModel);
+
+        return $this;
+    }
+
+    function addBillSchedule(BillSchedule $billSchedule): self
+    {
+        if (!$this->billSchedules->contains($billSchedule)) {
+            $this->billSchedules[] = $billSchedule;
+        }
+
+        return $this;
+    }
+
+    function removeBillSchedule(BillSchedule $billSchedule): self
+    {
+        $this->billSchedules->removeElement($billSchedule);
+
+        return $this;
+    }
 }

+ 1 - 1
src/Entity/Person/AllowedIp.php

@@ -51,7 +51,7 @@ class AllowedIp
         return $this->ipOrRange;
     }
 
-    public function setIpOrRange(string $ipOrRange)
+    public function setIpOrRange(string $ipOrRange): self
     {
         $this->ipOrRange = $ipOrRange;
         return $this;

+ 456 - 0
src/Entity/Place/AbstractPlace.php

@@ -0,0 +1,456 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Place;
+
+use ApiPlatform\Metadata\ApiResource;
+use App\Entity\Booking\Course;
+use App\Entity\Booking\EducationalProject;
+use App\Entity\Booking\Event;
+use App\Entity\Booking\Examen;
+use App\Entity\Core\AddressPostal;
+use App\Entity\Core\ContactPoint;
+use App\Entity\Core\Tagg;
+use App\Entity\Organization\Organization;
+use App\Entity\Product\Equipment;
+// 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 Place, et supprimer l'attribut discr.
+ *
+ * Classe ... qui ...
+ */
+#[ORM\MappedSuperclass]
+abstract class AbstractPlace
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private ?int $id = null;
+
+    #[ORM\Column(length: 255, nullable: false)]
+    protected string $discr;
+
+    #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'places')]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
+    private AddressPostal $addressPostal;
+
+    #[ORM\OneToMany(mappedBy: 'place', targetEntity: Event::class)]
+    private Collection $events;
+
+    #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'places', cascade: ['persist'])]
+    #[ORM\JoinTable(name: 'tag_place')]
+    #[ORM\JoinColumn(name: 'place_id', referencedColumnName: 'id')]
+    #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
+    private Collection $tags;
+
+    #[ORM\ManyToOne(inversedBy: 'places')]
+    private Organization $organization;
+
+    #[ORM\ManyToMany(targetEntity: ContactPoint::class, inversedBy: 'place', cascade: ['persist'])]
+    private Collection $contactpoint;
+
+    #[ORM\OneToMany(mappedBy: 'place', targetEntity: Room::class, cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\JoinColumn(nullable: false)]
+    private Collection $rooms;
+
+    #[ORM\OneToMany(mappedBy: 'place', targetEntity: PlaceControl::class, cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\JoinColumn(nullable: false)]
+    private Collection $controls;
+
+    #[ORM\OneToMany(mappedBy: 'place', targetEntity: PlaceRepair::class, cascade: ['persist'], orphanRemoval: true)]
+    #[ORM\JoinColumn(nullable: false)]
+    private Collection $repairs;
+
+    #[ORM\OneToMany(mappedBy: 'place', targetEntity: Course::class)]
+    private Collection $courses;
+
+    #[ORM\OneToMany(mappedBy: 'place', targetEntity: EducationalProject::class)]
+    private Collection $educationalProjects;
+
+    #[ORM\OneToMany(mappedBy: 'place', targetEntity: Examen::class)]
+    private Collection $examens;
+
+    #[ORM\OneToMany(mappedBy: 'placeStorage', targetEntity: Equipment::class)]
+    private Collection $equipmentStorages;
+
+    #[ORM\OneToMany(mappedBy: 'placeWhereIsUsed', targetEntity: Equipment::class)]
+    private Collection $equipmentUseds;
+
+    public function __construct()
+    {
+        $this->events = new ArrayCollection();
+        $this->tags = new ArrayCollection();
+        $this->contactpoint = new ArrayCollection();
+        $this->rooms = new ArrayCollection();
+        $this->controls = new ArrayCollection();
+        $this->repairs = new ArrayCollection();
+        $this->courses = new ArrayCollection();
+        $this->educationalProjects = new ArrayCollection();
+        $this->examens = new ArrayCollection();
+        $this->equipmentStorages = new ArrayCollection();
+        $this->equipmentUseds = 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 getAddressPostal(): ?AddressPostal
+    {
+        return $this->addressPostal;
+    }
+
+    public function setAddressPostal(?AddressPostal $addressPostal): self
+    {
+        $this->addressPostal = $addressPostal;
+
+        return $this;
+    }
+
+    /**
+     * @return Collection<int, Event>
+     */
+    public function getEvents(): Collection
+    {
+        return $this->events;
+    }
+
+    public function addEvent(Event $event): self
+    {
+        if (!$this->events->contains($event)) {
+            $this->events[] = $event;
+            $event->setPlace($this);
+        }
+
+        return $this;
+    }
+
+    public function removeEvent(Event $event): self
+    {
+        if ($this->events->removeElement($event)) {
+            // set the owning side to null (unless already changed)
+            if ($event->getPlace() === $this) {
+                $event->setPlace(null);
+            }
+        }
+
+        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;
+    }
+
+    public function getOrganization(): ?Organization
+    {
+        return $this->organization;
+    }
+
+    public function setOrganization(?Organization $organization): self
+    {
+        $this->organization = $organization;
+
+        return $this;
+    }
+
+    /**
+     * @return Collection<int, ContactPoint>
+     */
+    public function getContactpoint(): Collection
+    {
+        return $this->contactpoint;
+    }
+
+    public function addContactpoint(ContactPoint $contactpoint): self
+    {
+        if (!$this->contactpoint->contains($contactpoint)) {
+            $this->contactpoint[] = $contactpoint;
+        }
+
+        return $this;
+    }
+
+    public function removeContactpoint(ContactPoint $contactpoint): self
+    {
+        $this->contactpoint->removeElement($contactpoint);
+
+        return $this;
+    }
+
+    /**
+     * @return Collection<int, Room>
+     */
+    public function getRooms(): Collection
+    {
+        return $this->rooms;
+    }
+
+    public function addRoom(Room $room): self
+    {
+        if (!$this->rooms->contains($room)) {
+            $this->rooms[] = $room;
+            $room->setPlace($this);
+        }
+
+        return $this;
+    }
+
+    public function removeRoom(Room $room): self
+    {
+        if ($this->rooms->removeElement($room)) {
+            // set the owning side to null (unless already changed)
+            if ($room->getPlace() === $this) {
+                $room->setPlace(null);
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * @return Collection<int, PlaceControl>
+     */
+    public function getControls(): Collection
+    {
+        return $this->controls;
+    }
+
+    public function addControl(PlaceControl $control): self
+    {
+        if (!$this->controls->contains($control)) {
+            $this->controls[] = $control;
+            $control->setPlace($this);
+        }
+
+        return $this;
+    }
+
+    public function removeControl(PlaceControl $control): self
+    {
+        if ($this->controls->removeElement($control)) {
+            // set the owning side to null (unless already changed)
+            if ($control->getPlace() === $this) {
+                $control->setPlace(null);
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * @return Collection<int, PlaceRepair>
+     */
+    public function getRepairs(): Collection
+    {
+        return $this->repairs;
+    }
+
+    public function addRepair(PlaceRepair $repair): self
+    {
+        if (!$this->repairs->contains($repair)) {
+            $this->repairs[] = $repair;
+            $repair->setPlace($this);
+        }
+
+        return $this;
+    }
+
+    public function removeRepair(PlaceRepair $repair): self
+    {
+        if ($this->repairs->removeElement($repair)) {
+            // set the owning side to null (unless already changed)
+            if ($repair->getPlace() === $this) {
+                $repair->setPlace(null);
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * @return Collection<int, Course>
+     */
+    public function getCourses(): Collection
+    {
+        return $this->courses;
+    }
+
+    public function addCourse(Course $course): self
+    {
+        if (!$this->courses->contains($course)) {
+            $this->courses[] = $course;
+            $course->setPlace($this);
+        }
+
+        return $this;
+    }
+
+    public function removeCourse(Course $course): self
+    {
+        if ($this->courses->removeElement($course)) {
+            // set the owning side to null (unless already changed)
+            if ($course->getPlace() === $this) {
+                $course->setPlace(null);
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * @return Collection<int, EducationalProject>
+     */
+    public function getEducationalProjects(): Collection
+    {
+        return $this->educationalProjects;
+    }
+
+    public function addEducationalProject(EducationalProject $educationalProject): self
+    {
+        if (!$this->educationalProjects->contains($educationalProject)) {
+            $this->educationalProjects[] = $educationalProject;
+            $educationalProject->setPlace($this);
+        }
+
+        return $this;
+    }
+
+    public function removeEducationalProject(EducationalProject $educationalProject): self
+    {
+        if ($this->educationalProjects->removeElement($educationalProject)) {
+            // set the owning side to null (unless already changed)
+            if ($educationalProject->getPlace() === $this) {
+                $educationalProject->setPlace(null);
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * @return Collection<int, Examen>
+     */
+    public function getExamens(): Collection
+    {
+        return $this->examens;
+    }
+
+    public function addExamen(Examen $examen): self
+    {
+        if (!$this->examens->contains($examen)) {
+            $this->examens[] = $examen;
+            $examen->setPlace($this);
+        }
+
+        return $this;
+    }
+
+    public function removeExamen(Examen $examen): self
+    {
+        if ($this->examens->removeElement($examen)) {
+            // set the owning side to null (unless already changed)
+            if ($examen->getPlace() === $this) {
+                $examen->setPlace(null);
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * @return Collection<int, Equipment>
+     */
+    public function getEquipmentStorages(): Collection
+    {
+        return $this->equipmentStorages;
+    }
+
+    public function addEquipmentStorage(Equipment $equipmentStorage): self
+    {
+        if (!$this->equipmentStorages->contains($equipmentStorage)) {
+            $this->equipmentStorages[] = $equipmentStorage;
+            $equipmentStorage->setPlaceStorage($this);
+        }
+
+        return $this;
+    }
+
+    public function removeEquipmentStorage(Equipment $equipmentStorage): self
+    {
+        if ($this->equipmentStorages->removeElement($equipmentStorage)) {
+            // set the owning side to null (unless already changed)
+            if ($equipmentStorage->getPlaceStorage() === $this) {
+                $equipmentStorage->setPlaceStorage(null);
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * @return Collection<int, Equipment>
+     */
+    public function getEquipmentUseds(): Collection
+    {
+        return $this->equipmentUseds;
+    }
+
+    public function addEquipmentUsed(Equipment $equipmentUsed): self
+    {
+        if (!$this->equipmentUseds->contains($equipmentUsed)) {
+            $this->equipmentUseds[] = $equipmentUsed;
+            $equipmentUsed->setPlaceWhereIsUsed($this);
+        }
+
+        return $this;
+    }
+
+    public function removeEquipmentUsed(Equipment $equipmentUsed): self
+    {
+        if ($this->equipmentUseds->removeElement($equipmentUsed)) {
+            // set the owning side to null (unless already changed)
+            if ($equipmentUsed->getPlaceWhereIsUsed() === $this) {
+                $equipmentUsed->setPlaceWhereIsUsed(null);
+            }
+        }
+
+        return $this;
+    }
+}

+ 5 - 434
src/Entity/Place/Place.php

@@ -4,448 +4,19 @@ declare(strict_types=1);
 
 namespace App\Entity\Place;
 
-use ApiPlatform\Metadata\ApiResource;
-use App\Entity\Booking\Course;
-use App\Entity\Booking\EducationalProject;
-use App\Entity\Booking\Event;
-use App\Entity\Booking\Examen;
-use App\Entity\Core\AddressPostal;
-use App\Entity\Core\ContactPoint;
-use App\Entity\Core\Tagg;
-use App\Entity\Organization\Organization;
-use App\Entity\Product\Equipment;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
-use Doctrine\Common\Collections\ArrayCollection;
-use Doctrine\Common\Collections\Collection;
+use ApiPlatform\Metadata\ApiResource;
 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 Place, et supprimer l'attribut discr.
- *
  * Classe ... qui ...
  */
-#[ApiResource(operations: [])]
 // #[Auditable]
+#[ApiResource(operations: [])]
 #[ORM\Entity]
 #[ORM\Table(name: 'Place')]
-#[ORM\InheritanceType('SINGLE_TABLE')]
-#[ORM\DiscriminatorColumn(name: 'discr', type: 'string')]
-#[ORM\DiscriminatorMap([
-    'place' => 'Place',
-    'place_system' => 'PlaceSystem',
-])]
-class Place
+class Place extends AbstractPlace
 {
-    #[ORM\Id]
-    #[ORM\Column]
-    #[ORM\GeneratedValue]
-    private ?int $id = null;
-
-    #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'places')]
-    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
-    private AddressPostal $addressPostal;
-
-    #[ORM\OneToMany(mappedBy: 'place', targetEntity: Event::class)]
-    private Collection $events;
-
-    #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'places', cascade: ['persist'])]
-    #[ORM\JoinTable(name: 'tag_place')]
-    #[ORM\JoinColumn(name: 'place_id', referencedColumnName: 'id')]
-    #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
-    private Collection $tags;
-
-    #[ORM\ManyToOne(inversedBy: 'places')]
-    private Organization $organization;
-
-    #[ORM\ManyToMany(targetEntity: ContactPoint::class, inversedBy: 'place', cascade: ['persist'])]
-    private Collection $contactpoint;
-
-    #[ORM\OneToMany(mappedBy: 'place', targetEntity: Room::class, cascade: ['persist'], orphanRemoval: true)]
-    #[ORM\JoinColumn(nullable: false)]
-    private Collection $rooms;
-
-    #[ORM\OneToMany(mappedBy: 'place', targetEntity: PlaceControl::class, cascade: ['persist'], orphanRemoval: true)]
-    #[ORM\JoinColumn(nullable: false)]
-    private Collection $controls;
-
-    #[ORM\OneToMany(mappedBy: 'place', targetEntity: PlaceRepair::class, cascade: ['persist'], orphanRemoval: true)]
-    #[ORM\JoinColumn(nullable: false)]
-    private Collection $repairs;
-
-    #[ORM\OneToMany(mappedBy: 'place', targetEntity: Course::class)]
-    private Collection $courses;
-
-    #[ORM\OneToMany(mappedBy: 'place', targetEntity: EducationalProject::class)]
-    private Collection $educationalProjects;
-
-    #[ORM\OneToMany(mappedBy: 'place', targetEntity: Examen::class)]
-    private Collection $examens;
-
-    #[ORM\OneToMany(mappedBy: 'placeStorage', targetEntity: Equipment::class)]
-    private Collection $equipmentStorages;
-
-    #[ORM\OneToMany(mappedBy: 'placeWhereIsUsed', targetEntity: Equipment::class)]
-    private Collection $equipmentUseds;
-
-    public function __construct()
-    {
-        $this->events = new ArrayCollection();
-        $this->tags = new ArrayCollection();
-        $this->contactpoint = new ArrayCollection();
-        $this->rooms = new ArrayCollection();
-        $this->controls = new ArrayCollection();
-        $this->repairs = new ArrayCollection();
-        $this->courses = new ArrayCollection();
-        $this->educationalProjects = new ArrayCollection();
-        $this->examens = new ArrayCollection();
-        $this->equipmentStorages = new ArrayCollection();
-        $this->equipmentUseds = new ArrayCollection();
-    }
-
-    public function getId(): ?int
-    {
-        return $this->id;
-    }
-
-    public function getAddressPostal(): ?AddressPostal
-    {
-        return $this->addressPostal;
-    }
-
-    public function setAddressPostal(?AddressPostal $addressPostal): self
-    {
-        $this->addressPostal = $addressPostal;
-
-        return $this;
-    }
-
-    /**
-     * @return Collection<int, Event>
-     */
-    public function getEvents(): Collection
-    {
-        return $this->events;
-    }
-
-    public function addEvent(Event $event): self
-    {
-        if (!$this->events->contains($event)) {
-            $this->events[] = $event;
-            $event->setPlace($this);
-        }
-
-        return $this;
-    }
-
-    public function removeEvent(Event $event): self
-    {
-        if ($this->events->removeElement($event)) {
-            // set the owning side to null (unless already changed)
-            if ($event->getPlace() === $this) {
-                $event->setPlace(null);
-            }
-        }
-
-        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;
-    }
-
-    public function getOrganization(): ?Organization
-    {
-        return $this->organization;
-    }
-
-    public function setOrganization(?Organization $organization): self
-    {
-        $this->organization = $organization;
-
-        return $this;
-    }
-
-    /**
-     * @return Collection<int, ContactPoint>
-     */
-    public function getContactpoint(): Collection
-    {
-        return $this->contactpoint;
-    }
-
-    public function addContactpoint(ContactPoint $contactpoint): self
-    {
-        if (!$this->contactpoint->contains($contactpoint)) {
-            $this->contactpoint[] = $contactpoint;
-        }
-
-        return $this;
-    }
-
-    public function removeContactpoint(ContactPoint $contactpoint): self
-    {
-        $this->contactpoint->removeElement($contactpoint);
-
-        return $this;
-    }
-
-    /**
-     * @return Collection<int, Room>
-     */
-    public function getRooms(): Collection
-    {
-        return $this->rooms;
-    }
-
-    public function addRoom(Room $room): self
-    {
-        if (!$this->rooms->contains($room)) {
-            $this->rooms[] = $room;
-            $room->setPlace($this);
-        }
-
-        return $this;
-    }
-
-    public function removeRoom(Room $room): self
-    {
-        if ($this->rooms->removeElement($room)) {
-            // set the owning side to null (unless already changed)
-            if ($room->getPlace() === $this) {
-                $room->setPlace(null);
-            }
-        }
-
-        return $this;
-    }
-
-    /**
-     * @return Collection<int, PlaceControl>
-     */
-    public function getControls(): Collection
-    {
-        return $this->controls;
-    }
-
-    public function addControl(PlaceControl $control): self
-    {
-        if (!$this->controls->contains($control)) {
-            $this->controls[] = $control;
-            $control->setPlace($this);
-        }
-
-        return $this;
-    }
-
-    public function removeControl(PlaceControl $control): self
-    {
-        if ($this->controls->removeElement($control)) {
-            // set the owning side to null (unless already changed)
-            if ($control->getPlace() === $this) {
-                $control->setPlace(null);
-            }
-        }
-
-        return $this;
-    }
-
-    /**
-     * @return Collection<int, PlaceRepair>
-     */
-    public function getRepairs(): Collection
-    {
-        return $this->repairs;
-    }
-
-    public function addRepair(PlaceRepair $repair): self
-    {
-        if (!$this->repairs->contains($repair)) {
-            $this->repairs[] = $repair;
-            $repair->setPlace($this);
-        }
-
-        return $this;
-    }
-
-    public function removeRepair(PlaceRepair $repair): self
-    {
-        if ($this->repairs->removeElement($repair)) {
-            // set the owning side to null (unless already changed)
-            if ($repair->getPlace() === $this) {
-                $repair->setPlace(null);
-            }
-        }
-
-        return $this;
-    }
-
-    /**
-     * @return Collection<int, Course>
-     */
-    public function getCourses(): Collection
-    {
-        return $this->courses;
-    }
-
-    public function addCourse(Course $course): self
-    {
-        if (!$this->courses->contains($course)) {
-            $this->courses[] = $course;
-            $course->setPlace($this);
-        }
-
-        return $this;
-    }
-
-    public function removeCourse(Course $course): self
-    {
-        if ($this->courses->removeElement($course)) {
-            // set the owning side to null (unless already changed)
-            if ($course->getPlace() === $this) {
-                $course->setPlace(null);
-            }
-        }
-
-        return $this;
-    }
-
-    /**
-     * @return Collection<int, EducationalProject>
-     */
-    public function getEducationalProjects(): Collection
-    {
-        return $this->educationalProjects;
-    }
-
-    public function addEducationalProject(EducationalProject $educationalProject): self
-    {
-        if (!$this->educationalProjects->contains($educationalProject)) {
-            $this->educationalProjects[] = $educationalProject;
-            $educationalProject->setPlace($this);
-        }
-
-        return $this;
-    }
-
-    public function removeEducationalProject(EducationalProject $educationalProject): self
-    {
-        if ($this->educationalProjects->removeElement($educationalProject)) {
-            // set the owning side to null (unless already changed)
-            if ($educationalProject->getPlace() === $this) {
-                $educationalProject->setPlace(null);
-            }
-        }
-
-        return $this;
-    }
-
-    /**
-     * @return Collection<int, Examen>
-     */
-    public function getExamens(): Collection
-    {
-        return $this->examens;
-    }
-
-    public function addExamen(Examen $examen): self
-    {
-        if (!$this->examens->contains($examen)) {
-            $this->examens[] = $examen;
-            $examen->setPlace($this);
-        }
-
-        return $this;
-    }
-
-    public function removeExamen(Examen $examen): self
-    {
-        if ($this->examens->removeElement($examen)) {
-            // set the owning side to null (unless already changed)
-            if ($examen->getPlace() === $this) {
-                $examen->setPlace(null);
-            }
-        }
-
-        return $this;
-    }
-
-    /**
-     * @return Collection<int, Equipment>
-     */
-    public function getEquipmentStorages(): Collection
-    {
-        return $this->equipmentStorages;
-    }
-
-    public function addEquipmentStorage(Equipment $equipmentStorage): self
-    {
-        if (!$this->equipmentStorages->contains($equipmentStorage)) {
-            $this->equipmentStorages[] = $equipmentStorage;
-            $equipmentStorage->setPlaceStorage($this);
-        }
-
-        return $this;
-    }
-
-    public function removeEquipmentStorage(Equipment $equipmentStorage): self
-    {
-        if ($this->equipmentStorages->removeElement($equipmentStorage)) {
-            // set the owning side to null (unless already changed)
-            if ($equipmentStorage->getPlaceStorage() === $this) {
-                $equipmentStorage->setPlaceStorage(null);
-            }
-        }
-
-        return $this;
-    }
-
-    /**
-     * @return Collection<int, Equipment>
-     */
-    public function getEquipmentUseds(): Collection
-    {
-        return $this->equipmentUseds;
-    }
-
-    public function addEquipmentUsed(Equipment $equipmentUsed): self
-    {
-        if (!$this->equipmentUseds->contains($equipmentUsed)) {
-            $this->equipmentUseds[] = $equipmentUsed;
-            $equipmentUsed->setPlaceWhereIsUsed($this);
-        }
-
-        return $this;
-    }
-
-    public function removeEquipmentUsed(Equipment $equipmentUsed): self
-    {
-        if ($this->equipmentUseds->removeElement($equipmentUsed)) {
-            // set the owning side to null (unless already changed)
-            if ($equipmentUsed->getPlaceWhereIsUsed() === $this) {
-                $equipmentUsed->setPlaceWhereIsUsed(null);
-            }
-        }
-
-        return $this;
-    }
+    #[ORM\Column(length: 255, nullable: false)]
+    protected string $discr = 'place';
 }

+ 6 - 5
src/Entity/Place/PlaceControl.php

@@ -22,20 +22,21 @@ use Doctrine\ORM\Mapping as ORM;
 class PlaceControl extends AbstractControl
 {
     #[ORM\Column(length: 255, nullable: false)]
-    private string $discr = 'place';
+    protected string $discr = 'place';
 
     #[ORM\ManyToOne(inversedBy: 'controls')]
-    private Place $place;
+    protected AbstractPlace $place;
 
     #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'placeControls', cascade: ['persist'])]
     #[ORM\JoinTable(name: 'tag_control')]
     #[ORM\JoinColumn(name: 'control_id', referencedColumnName: 'id')]
     #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
-    private Collection $tags;
+    protected Collection $tags;
 
     public function __construct()
     {
         $this->tags = new ArrayCollection();
+        parent::__construct();
     }
 
     public function getDiscr(): ?string
@@ -50,12 +51,12 @@ class PlaceControl extends AbstractControl
         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;
 

+ 7 - 6
src/Entity/Place/PlaceRepair.php

@@ -23,24 +23,25 @@ use Doctrine\ORM\Mapping as ORM;
 class PlaceRepair extends AbstractRepair
 {
     #[ORM\Column(length: 255, nullable: false)]
-    private string $discr = 'place';
+    protected string $discr = 'place';
 
     #[ORM\ManyToOne(inversedBy: 'placeRepairProviders')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
-    private Access $provider;
+    protected Access $provider;
 
     #[ORM\ManyToOne(inversedBy: 'repairs')]
-    private Place $place;
+    protected AbstractPlace $place;
 
     #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'placeRepairs', cascade: ['persist'])]
     #[ORM\JoinTable(name: 'tag_repair')]
     #[ORM\JoinColumn(name: 'repair_id', referencedColumnName: 'id')]
     #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
-    private Collection $tags;
+    protected Collection $tags;
 
     public function __construct()
     {
         $this->tags = new ArrayCollection();
+        parent::__construct();
     }
 
     public function getDiscr(): ?string
@@ -67,12 +68,12 @@ class PlaceRepair extends AbstractRepair
         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;
 

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

@@ -5,13 +5,18 @@ declare(strict_types=1);
 namespace App\Entity\Place;
 
 // 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 PlaceSystem extends Place
+#[ORM\Table(name: 'Place')]
+class PlaceSystem extends AbstractPlace
 {
+    #[ORM\Column(length: 255, nullable: false)]
+    protected string $discr = 'place_system';
 }

+ 4 - 4
src/Entity/Place/Room.php

@@ -28,8 +28,8 @@ class Room
     #[ORM\GeneratedValue]
     private ?int $id = null;
 
-    #[ORM\ManyToOne(targetEntity: Place::class, inversedBy: 'rooms')]
-    private Place $place;
+    #[ORM\ManyToOne(targetEntity: AbstractPlace::class, inversedBy: 'rooms')]
+    private AbstractPlace $place;
 
     #[ORM\OneToMany(mappedBy: 'room', targetEntity: RoomControl::class, cascade: ['persist'], orphanRemoval: true)]
     #[ORM\JoinColumn(nullable: false)]
@@ -74,12 +74,12 @@ class Room
         return $this->id;
     }
 
-    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;
 

+ 32 - 0
src/Entity/Product/AbstractProduct.php

@@ -4,7 +4,10 @@ declare(strict_types=1);
 
 namespace App\Entity\Product;
 
+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;
 
 /**
@@ -18,11 +21,40 @@ abstract class AbstractProduct
     #[ORM\GeneratedValue]
     protected ?int $id = null;
 
+    #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'products', cascade: ['persist'], orphanRemoval: false)]
+    protected Collection $tags;
+
     #[ORM\ManyToOne]
     protected Organization $organization;
 
+    public function __construct()
+    {
+        $this->tags = new ArrayCollection();
+    }
+
     public function getId(): ?int
     {
         return $this->id;
     }
+
+    function getTags(): Collection
+    {
+        return $this->tags;
+    }
+
+    function addTag(Tagg $tag): self
+    {
+        if (!$this->tags->contains($tag)) {
+            $this->tags[] = $tag;
+        }
+
+        return $this;
+    }
+
+    function removeTag(Tagg $tag): self
+    {
+        $this->tags->removeElement($tag);
+
+        return $this;
+    }
 }

+ 102 - 28
src/Entity/Product/Equipment.php

@@ -6,9 +6,10 @@ namespace App\Entity\Product;
 
 use ApiPlatform\Metadata\ApiResource;
 use App\Entity\Access\Access;
+use App\Entity\Booking\ExamenConvocation;
 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;
@@ -27,72 +28,81 @@ use Doctrine\ORM\Mapping as ORM;
 class Equipment extends AbstractProduct
 {
     #[ORM\Column(length: 255, nullable: false)]
-    private string $discr = 'equipment';
+    protected string $discr = 'equipment';
 
     #[ORM\ManyToOne(inversedBy: 'equipments')]
     protected Organization $organization;
 
     #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'equipments')]
-    private Access $access;
+    protected Access $access;
 
     #[ORM\ManyToOne(inversedBy: 'equipmentStorages')]
     #[ORM\JoinColumn(name: 'place_storage_id', nullable: true, onDelete: 'SET NULL')]
-    private Place $placeStorage;
+    protected AbstractPlace $placeStorage;
 
     #[ORM\ManyToOne(inversedBy: 'equipmentStorages')]
     #[ORM\JoinColumn(name: 'room_storage_id', nullable: true, onDelete: 'SET NULL')]
-    private Room $roomStorage;
+    protected Room $roomStorage;
 
     #[ORM\ManyToOne(inversedBy: 'equipmentUseds')]
     #[ORM\JoinColumn(name: 'place_used_id', nullable: true, onDelete: 'SET NULL')]
-    private Place $placeWhereIsUsed;
+    protected AbstractPlace $placeWhereIsUsed;
 
     #[ORM\ManyToOne(inversedBy: 'equipmentUseds')]
     #[ORM\JoinColumn(name: 'room_used_id', nullable: true, onDelete: 'SET NULL')]
-    private Room $roomWhereIsUsed;
+    protected Room $roomWhereIsUsed;
 
     #[ORM\ManyToOne]
     #[ORM\JoinColumn(nullable: true)]
-    private EquipmentList $equipmentList;
+    protected EquipmentList $equipmentList;
 
     #[ORM\OneToMany(mappedBy: 'parent', targetEntity: EquipmentComposition::class, orphanRemoval: true)]
-    private Collection $equipmentComposition;
+    protected Collection $equipmentComposition;
 
     #[ORM\OneToMany(mappedBy: 'equipment', targetEntity: EquipmentRepair::class, orphanRemoval: true)]
-    private Collection $equipmentRepair;
+    protected Collection $equipmentRepair;
 
     #[ORM\OneToMany(mappedBy: 'equipment', targetEntity: EquipmentControl::class, cascade: ['persist'], orphanRemoval: true)]
-    private Collection $equipmentControl;
+    protected Collection $equipmentControl;
 
     #[ORM\OneToMany(mappedBy: 'equipment', targetEntity: EquipmentLoan::class, cascade: ['persist'], orphanRemoval: true)]
-    private Collection $equipmentLoan;
+    protected Collection $equipmentLoan;
 
     #[ORM\ManyToOne(inversedBy: 'equipmentSuppliers')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
-    private Access $supplier;
+    protected Access $supplier;
 
     #[ORM\ManyToOne(inversedBy: 'equipmentControlManagers')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
-    private Access $controlManager;
+    protected Access $controlManager;
 
     #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'equipmentEditors')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
-    private Access $editor;
+    protected Access $editor;
 
     #[ORM\ManyToMany(targetEntity: EquipmentList::class)]
     #[ORM\JoinColumn(name: 'equipment_id', referencedColumnName: 'id')]
     #[ORM\InverseJoinColumn(name: 'equipmentlist_id', referencedColumnName: 'id')]
-    private Collection $instrumentOrVoice;
+    protected Collection $instrumentOrVoice;
 
     #[ORM\ManyToOne]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
-    private Access $managerControl;
+    protected Access $managerControl;
 
     #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'equipments', cascade: ['persist'])]
     #[ORM\JoinTable(name: 'tag_product')]
     #[ORM\JoinColumn(name: 'product_id', referencedColumnName: 'id')]
     #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
-    private Collection $tags;
+    protected Collection $tags;
+
+    #[ORM\OneToMany(mappedBy: 'children', targetEntity: EquipmentComposition::class, cascade: [], orphanRemoval: true)]
+    protected Collection $equipmentCompositionChildren;
+
+    #[ORM\OneToMany(mappedBy: 'equipment', targetEntity: EquipmentLoan::class, cascade: [], orphanRemoval: true)]
+    protected Collection $equipmentLoanFiltered;
+
+    #[ORM\ManyToMany(targetEntity: ExamenConvocation::class, mappedBy: 'equipments', cascade: [], orphanRemoval: false)]
+    protected Collection $examenConvocations;
 
     public function __construct()
     {
@@ -102,6 +112,10 @@ class Equipment extends AbstractProduct
         $this->equipmentLoan = new ArrayCollection();
         $this->instrumentOrVoice = new ArrayCollection();
         $this->tags = new ArrayCollection();
+        $this->equipmentCompositionChildren = new ArrayCollection();
+        $this->equipmentLoanFiltered = new ArrayCollection();
+        $this->examenConvocations = new ArrayCollection();
+        parent::__construct();
     }
 
     public function getDiscr(): ?string
@@ -140,12 +154,12 @@ class Equipment extends AbstractProduct
         return $this;
     }
 
-    public function getPlaceStorage(): ?Place
+    public function getPlaceStorage(): ?AbstractPlace
     {
         return $this->placeStorage;
     }
 
-    public function setPlaceStorage(?Place $placeStorage): self
+    public function setPlaceStorage(?AbstractPlace $placeStorage): self
     {
         $this->placeStorage = $placeStorage;
 
@@ -164,12 +178,12 @@ class Equipment extends AbstractProduct
         return $this;
     }
 
-    public function getPlaceWhereIsUsed(): ?Place
+    public function getPlaceWhereIsUsed(): ?AbstractPlace
     {
         return $this->placeWhereIsUsed;
     }
 
-    public function setPlaceWhereIsUsed(?Place $placeWhereIsUsed): self
+    public function setPlaceWhereIsUsed(?AbstractPlace $placeWhereIsUsed): self
     {
         $this->placeWhereIsUsed = $placeWhereIsUsed;
 
@@ -392,15 +406,12 @@ class Equipment extends AbstractProduct
         return $this;
     }
 
-    /**
-     * @return Collection<int, Tagg>
-     */
-    public function getTags(): Collection
+    function getTags(): Collection
     {
         return $this->tags;
     }
 
-    public function addTag(Tagg $tag): self
+    function addTag(Tagg $tag): self
     {
         if (!$this->tags->contains($tag)) {
             $this->tags[] = $tag;
@@ -409,10 +420,73 @@ class Equipment extends AbstractProduct
         return $this;
     }
 
-    public function removeTag(Tagg $tag): self
+    function removeTag(Tagg $tag): self
     {
         $this->tags->removeElement($tag);
 
         return $this;
     }
+
+    function getEquipmentCompositionChildren(): Collection
+    {
+        return $this->equipmentCompositionChildren;
+    }
+
+    function addEquipmentCompositionChildren(EquipmentComposition $equipmentCompositionChildren): self
+    {
+        if (!$this->equipmentCompositionChildren->contains($equipmentCompositionChildren)) {
+            $this->equipmentCompositionChildren[] = $equipmentCompositionChildren;
+        }
+
+        return $this;
+    }
+
+    function removeEquipmentCompositionChildren(EquipmentComposition $equipmentCompositionChildren): self
+    {
+        $this->equipmentCompositionChildren->removeElement($equipmentCompositionChildren);
+
+        return $this;
+    }
+
+    function getEquipmentLoanFiltered(): Collection
+    {
+        return $this->equipmentLoanFiltered;
+    }
+
+    function addEquipmentLoanFiltered(EquipmentLoan $equipmentLoanFiltered): self
+    {
+        if (!$this->equipmentLoanFiltered->contains($equipmentLoanFiltered)) {
+            $this->equipmentLoanFiltered[] = $equipmentLoanFiltered;
+        }
+
+        return $this;
+    }
+
+    function removeEquipmentLoanFiltered(EquipmentLoan $equipmentLoanFiltered): self
+    {
+        $this->equipmentLoanFiltered->removeElement($equipmentLoanFiltered);
+
+        return $this;
+    }
+
+    function getExamenConvocations(): Collection
+    {
+        return $this->examenConvocations;
+    }
+
+    function addExamenConvocation(ExamenConvocation $examenConvocation): self
+    {
+        if (!$this->examenConvocations->contains($examenConvocation)) {
+            $this->examenConvocations[] = $examenConvocation;
+        }
+
+        return $this;
+    }
+
+    function removeExamenConvocation(ExamenConvocation $examenConvocation): self
+    {
+        $this->examenConvocations->removeElement($examenConvocation);
+
+        return $this;
+    }
 }

+ 4 - 3
src/Entity/Product/EquipmentControl.php

@@ -22,20 +22,21 @@ use Doctrine\ORM\Mapping as ORM;
 class EquipmentControl extends AbstractControl
 {
     #[ORM\Column(length: 255, nullable: false)]
-    private string $discr = 'equipment';
+    protected string $discr = 'equipment';
 
     #[ORM\ManyToOne(inversedBy: 'equipmentControl')]
-    private Equipment $equipment;
+    protected Equipment $equipment;
 
     #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'equipmentControls', cascade: ['persist'])]
     #[ORM\JoinTable(name: 'tag_control')]
     #[ORM\JoinColumn(name: 'control_id', referencedColumnName: 'id')]
     #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
-    private Collection $tags;
+    protected Collection $tags;
 
     public function __construct()
     {
         $this->tags = new ArrayCollection();
+        parent::__construct();
     }
 
     public function getDiscr(): ?string

+ 4 - 4
src/Entity/Product/EquipmentRepair.php

@@ -24,20 +24,20 @@ use Doctrine\ORM\Mapping as ORM;
 class EquipmentRepair extends AbstractRepair
 {
     #[ORM\Column(length: 255, nullable: false)]
-    private string $discr = 'equipment';
+    protected string $discr = 'equipment';
 
     #[ORM\ManyToOne(inversedBy: 'equipmentRepairProviders')]
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
-    private Access $provider;
+    protected Access $provider;
 
     #[ORM\ManyToOne(inversedBy: 'equipmentRepair')]
-    private Equipment $equipment;
+    protected Equipment $equipment;
 
     #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'equipmentRepairs', cascade: ['persist'])]
     #[ORM\JoinTable(name: 'tag_repair')]
     #[ORM\JoinColumn(name: 'repair_id', referencedColumnName: 'id')]
     #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
-    private Collection $tags;
+    protected Collection $tags;
 
     public function __construct()
     {

+ 46 - 4
src/Entity/Product/Intangible.php

@@ -9,6 +9,7 @@ use App\Entity\Billing\AccessIntangible;
 use App\Entity\Core\Tagg;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
 use App\Entity\Education\EducationCurriculum;
+use App\Entity\Education\EducationCurriculumPack;
 use App\Entity\Organization\Organization;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
@@ -26,28 +27,37 @@ use Doctrine\ORM\Mapping as ORM;
 class Intangible extends AbstractProduct
 {
     #[ORM\Column(length: 255, nullable: false)]
-    private string $discr = 'intangible';
+    protected string $discr = 'intangible';
 
     #[ORM\ManyToOne(inversedBy: 'intangibles')]
     protected Organization $organization;
 
     #[ORM\ManyToMany(targetEntity: EducationCurriculum::class)]
-    private Collection $educationCurriculums;
+    protected Collection $educationCurriculums;
 
     #[ORM\OneToMany(mappedBy: 'intangible', targetEntity: AccessIntangible::class, cascade: ['persist'], orphanRemoval: true)]
-    private Collection $accessIntangibles;
+    protected Collection $accessIntangibles;
 
     #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'intangibles', cascade: ['persist'])]
     #[ORM\JoinTable(name: 'tag_product')]
     #[ORM\JoinColumn(name: 'product_id', referencedColumnName: 'id')]
     #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
-    private Collection $tags;
+    protected Collection $tags;
+
+    #[ORM\ManyToMany(targetEntity: EducationCurriculumPack::class, inversedBy: 'intangibles', cascade: [], orphanRemoval: false)]
+    protected Collection $educationCurriculumPacks;
+
+    #[ORM\OneToOne(inversedBy: 'intangible', targetEntity: IntangiblePriceAndDiscount::class, cascade: ['persist'])]
+    protected IntangiblePriceAndDiscount $intangiblePriceAndDiscount;
 
     public function __construct()
     {
         $this->educationCurriculums = new ArrayCollection();
         $this->accessIntangibles = new ArrayCollection();
         $this->tags = new ArrayCollection();
+        $this->educationCurriculumPacks = new ArrayCollection();
+        $this->intangiblePriceAndDiscount = new IntangiblePriceAndDiscount();
+        parent::__construct();
     }
 
     public function getDiscr(): ?string
@@ -151,4 +161,36 @@ class Intangible extends AbstractProduct
 
         return $this;
     }
+
+    function getEducationCurriculumPacks(): Collection
+    {
+        return $this->educationCurriculumPacks;
+    }
+
+    function setEducationCurriculumPacks(Collection $educationCurriculumPacks): self
+    {
+        $this->educationCurriculumPacks = $educationCurriculumPacks;
+        return $this;
+    }
+
+    function getIntangiblePriceAndDiscount(): IntangiblePriceAndDiscount
+    {
+        return $this->intangiblePriceAndDiscount;
+    }
+
+    function addEducationCurriculumPack(EducationCurriculumPack $educationCurriculumPack): self
+    {
+        if (!$this->educationCurriculumPacks->contains($educationCurriculumPack)) {
+            $this->educationCurriculumPacks[] = $educationCurriculumPack;
+        }
+
+        return $this;
+    }
+
+    function removeEducationCurriculumPack(EducationCurriculumPack $educationCurriculumPack): self
+    {
+        $this->educationCurriculumPacks->removeElement($educationCurriculumPack);
+
+        return $this;
+    }
 }

+ 32 - 0
src/Entity/Product/IntangibleDiscountDetail.php

@@ -6,6 +6,8 @@ namespace App\Entity\Product;
 
 use ApiPlatform\Metadata\ApiResource;
 use App\Entity\Billing\FamilyQuotient;
+use App\Entity\Billing\FamilyQuotientBand;
+use App\Entity\Billing\FamilyQuotientBandDetail;
 use App\Entity\Billing\ResidenceArea;
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
 use Doctrine\ORM\Mapping as ORM;
@@ -35,6 +37,14 @@ class IntangibleDiscountDetail
     #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
     private FamilyQuotient $familyQuotient;
 
+    #[ORM\ManyToOne(targetEntity: FamilyQuotientBandDetail::class, cascade: [], inversedBy: 'intangibleDiscountDetails')]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
+    protected FamilyQuotientBandDetail $familyQuotientBandDetail;
+
+    #[ORM\ManyToOne(targetEntity: FamilyQuotientBand::class, cascade: [], inversedBy: 'intangibleDiscountDetails')]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
+    protected FamilyQuotientBand $familyQuotientBand;
+
     public function getId(): ?int
     {
         return $this->id;
@@ -75,4 +85,26 @@ class IntangibleDiscountDetail
 
         return $this;
     }
+
+    function getFamilyQuotientBandDetail(): FamilyQuotientBandDetail
+    {
+        return $this->familyQuotientBandDetail;
+    }
+
+    function setFamilyQuotientBandDetail(FamilyQuotientBandDetail $familyQuotientBandDetail): self
+    {
+        $this->familyQuotientBandDetail = $familyQuotientBandDetail;
+        return $this;
+    }
+
+    function getFamilyQuotientBand(): FamilyQuotientBand
+    {
+        return $this->familyQuotientBand;
+    }
+
+    function setFamilyQuotientBand(FamilyQuotientBand $familyQuotientBand): self
+    {
+        $this->familyQuotientBand = $familyQuotientBand;
+        return $this;
+    }
 }

+ 31 - 0
src/Entity/Product/IntangiblePriceAndDiscount.php

@@ -5,6 +5,7 @@ declare(strict_types=1);
 namespace App\Entity\Product;
 
 // use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
+use App\Entity\Billing\FamilyQuotientModel;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
@@ -26,6 +27,13 @@ class IntangiblePriceAndDiscount
     #[ORM\OneToMany(mappedBy: 'intangiblePriceAndDiscount', targetEntity: IntangibleDiscountDetail::class, cascade: ['persist'], orphanRemoval: true)]
     private Collection $intangibleDiscountDetails;
 
+    #[ORM\OneToOne(mappedBy: 'intangiblePriceAndDiscount', targetEntity: Intangible::class, cascade: [])]
+    protected Intangible $intangible;
+
+    #[ORM\ManyToOne(targetEntity: FamilyQuotientModel::class, cascade: [], inversedBy: 'intangiblePriceAndDiscounts')]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
+    protected FamilyQuotientModel $familyQuotientModel;
+
     public function __construct()
     {
         $this->intangibleDiscountDetails = new ArrayCollection();
@@ -65,4 +73,27 @@ class IntangiblePriceAndDiscount
 
         return $this;
     }
+
+
+    function getIntangible(): Intangible
+    {
+        return $this->intangible;
+    }
+
+    function setIntangible(Intangible $intangible): self
+    {
+        $this->intangible = $intangible;
+        return $this;
+    }
+
+    function getFamilyQuotientModel(): FamilyQuotientModel
+    {
+        return $this->familyQuotientModel;
+    }
+
+    function setFamilyQuotientModel(FamilyQuotientModel $familyQuotientModel): self
+    {
+        $this->familyQuotientModel = $familyQuotientModel;
+        return $this;
+    }
 }

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

@@ -0,0 +1,47 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Entity\Token;
+
+use ApiPlatform\Metadata\ApiResource;
+use App;
+use App\Entity\Access\Access;
+use DateTimeInterface;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ApiResource(operations: [])]
+#[ORM\Entity]
+class Token
+{
+    #[ORM\Id]
+    #[ORM\Column]
+    #[ORM\GeneratedValue]
+    private int $id;
+
+    #[ORM\ManyToOne(targetEntity: Access::class, cascade: [], inversedBy: 'tokens')]
+    #[ORM\JoinColumn(referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
+    private App\Entity\Access\Access $access;
+
+    function getId(): int
+    {
+        return $this->id;
+    }
+
+    function setId(int $id): self
+    {
+        $this->id = $id;
+        return $this;
+    }
+
+    function getAccess(): App\Entity\Access\Access
+    {
+        return $this->access;
+    }
+
+    function setAccess(App\Entity\Access\Access $access): self
+    {
+        $this->access = $access;
+        return $this;
+    }
+}

+ 16 - 0
src/Service/Doctrine/SchemaValidation/Difference.php

@@ -11,8 +11,17 @@ class Difference
 
     protected string $entity;
     protected string $property;
+
+    /**
+     * @var string|array<string, string|array<string>>
+     */
     protected string | array $expectedType;
 
+    /**
+     * @param DiffTypeEnum $type
+     * @param string|null $message
+     * @param string|array<string, string|array<string>> $expectedType
+     */
     public function __construct(DiffTypeEnum $type, ?string $message, string | array $expectedType = []) {
         $this->type = $type;
         $this->message = $message;
@@ -41,11 +50,18 @@ class Difference
         return $this;
     }
 
+    /**
+     * @return string|array<string, string|array<string>>
+     */
     public function getExpectedType(): string | array
     {
         return $this->expectedType;
     }
 
+    /**
+     * @param string|array<string, string|array<string>> $expectedType
+     * @return $this
+     */
     public function setExpectedType(string | array $expectedType): self
     {
         $this->expectedType = $expectedType;

+ 208 - 22
src/Service/Doctrine/SchemaValidation/SchemaSnippetsMaker.php

@@ -11,11 +11,14 @@ use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping\ClassMetadataInfo;
 use Doctrine\ORM\Mapping\Column;
 use Doctrine\ORM\Mapping\Entity;
+use Doctrine\ORM\Mapping\InverseJoinColumn;
 use Doctrine\ORM\Mapping\JoinColumn;
+use Doctrine\ORM\Mapping\JoinTable;
 use Doctrine\ORM\Mapping\ManyToMany;
 use Doctrine\ORM\Mapping\ManyToOne;
 use Doctrine\ORM\Mapping\OneToMany;
 use Doctrine\ORM\Mapping\OneToOne;
+use Nette\InvalidStateException;
 use Nette\PhpGenerator\Attribute;
 use Nette\PhpGenerator\ClassType;
 use Nette\PhpGenerator\Method;
@@ -60,6 +63,7 @@ class SchemaSnippetsMaker
             $class = $this->makeSnippetEntityClass($entity);
 
             $methods = [];
+            $collections = [];
 
             $expectedFields = [];
             if (!is_array($differences)) {
@@ -81,9 +85,19 @@ class SchemaSnippetsMaker
 
                 $class->addMember($prop);
 
+                if ($prop->getType() === Collection::class) {
+                    $collections[] = $prop;
+                }
+
                 $methods = [...$methods, ...$this->makeMethodsSnippetForProp($prop)];
             }
 
+            if ($collections) {
+                $class->addMember(
+                    $this->makeSnippetConstructor($collections)
+                );
+            }
+
             foreach ($methods as $method) {
                 $class->addMember($method);
             }
@@ -98,7 +112,12 @@ class SchemaSnippetsMaker
                 }
             }
 
-            $namespace->add($class);
+            try {
+                $namespace->add($class);
+            } catch (InvalidStateException $e) {
+                var_dump($e->getMessage());
+                continue;
+            }
 
             $file->addNamespace($namespace);
 
@@ -117,7 +136,7 @@ class SchemaSnippetsMaker
     protected function makeMethodsSnippetForProp(Property $prop): array {
         $methods = [];
 
-        if ($prop->getType() !== 'Collection') {
+        if ($prop->getType() !== Collection::class) {
             $methods[] = $this->makeSnippetGetterForProp($prop);
             $methods[] = $this->makeSnippetSetterForProp($prop);
         } else {
@@ -260,7 +279,29 @@ class SchemaSnippetsMaker
      */
     protected function getNamespaceValue(string $entity): string
     {
-        return $this->entityUtils->getNamespaceFromName($entity) ?? ('App\\Entity\\' . $entity);
+        try {
+            $fullQualifiedName = str_contains($entity, "\\") ?
+                $entity :
+                $this->entityUtils->getFullNameFromEntityName($entity);
+
+            return $this->entityUtils->getNamespaceFromName($fullQualifiedName);
+        } catch (\LogicException) {
+            return 'App\\Entity';
+        }
+    }
+
+    /**
+     * @param array<string, string|array<string>> $type
+     * @return string
+     */
+    protected function getRelationTargetEntityName(array $type): string
+    {
+        $targetEntityName = $this->entityUtils->getEntityNameFromFullName($type['targetEntity']);
+        try {
+            return $this->entityUtils->getFullNameFromEntityName($targetEntityName);
+        } catch (\LogicException) {
+            return 'mixed';
+        }
     }
 
     /**
@@ -337,10 +378,14 @@ class SchemaSnippetsMaker
      */
     protected function makeSnippetEntitySimpleProp(string $name, string $type): Property
     {
+        if ($name === 'id') {
+            return $this->makeIdPropertySnippet();
+        }
+
         $php_type = $this->getPhpTypeFromDoctrineType($type);
 
         $prop = new Property($name);
-        $prop->setPrivate();
+        $prop->setProtected();
         $prop->setType($php_type);
 
         if ($type === 'text') {
@@ -371,24 +416,45 @@ class SchemaSnippetsMaker
     protected function makeSnippetEntityCollectionProp(string $name, array $type): Property
     {
         $prop = new Property($name);
+        $prop->setProtected();
         $prop->setType('Collection');
 
         if (
             isset($type['type']) &&
             $type['type'] === ClassMetadataInfo::ONE_TO_ONE || $type['type'] === ClassMetadataInfo::MANY_TO_ONE
         ) {
-            $targetEntityName = $this->entityUtils->getEntityNameFromFullName($type['targetEntity']);
-            try {
-                $newType = $this->entityUtils->getFullNameFromEntityName($targetEntityName);
-            } catch (\LogicException) {
-                $newType = 'mixed';
-            }
-            $prop->setType($newType);
+            $targetEntityName = $this->getRelationTargetEntityName($type);
+            $prop->setType($targetEntityName);
 
         } else {
             $prop->setType(Collection::class);
         }
 
+        $attributes = [];
+        $attributes[] = $this->makeRelationAttribute($type);
+
+        $joinTable = $this->makeJoinTableAttributes($type);
+        if ($joinTable) {
+            $attributes[] = $joinTable;
+        }
+
+        $attributes = array_merge($attributes, $this->makeJoinColumnAttributes($type));
+
+        $attributes = array_merge($attributes, $this->makeJoinColumnAttributes($type, true));
+
+        $prop->setAttributes($attributes);
+
+        return $prop;
+    }
+
+    /**
+     * Make the attribute defining the relation (ex: #[ORM\ManyToMany(...)])
+     *
+     * @param array<string | array<string | array<string>>> $type
+     * @return Attribute
+     */
+    protected function makeRelationAttribute(array $type): Attribute
+    {
         $options = [];
         if (isset($type['mappedBy'])) {
             $options['mappedBy'] = $type['mappedBy'];
@@ -398,17 +464,17 @@ class SchemaSnippetsMaker
             $options['targetEntity'] = $this->entityUtils->getEntityNameFromFullName($type['targetEntity']) . '::class';
         }
 
-        if (isset($type['inversedBy'])) {
-            $options['inversedBy'] = $type['inversedBy'];
-        }
-
         if (isset($type['cascade'])) {
             $options['cascade'] = $type['cascade'];
         } else {
             $options['cascade'] = ['persist'];
         }
 
-        if (isset($type['orphanRemoval'])) {
+        if (isset($type['inversedBy'])) {
+            $options['inversedBy'] = $type['inversedBy'];
+        }
+
+        if (isset($type['orphanRemoval']) && ($type['type'] === ClassMetadataInfo::ONE_TO_MANY || $type['type'] === ClassMetadataInfo::MANY_TO_MANY)) {
             $options['orphanRemoval'] = $type['orphanRemoval'];
         }
 
@@ -419,13 +485,97 @@ class SchemaSnippetsMaker
             ClassMetadataInfo::ONE_TO_ONE => OneToOne::class,
         ];
 
-        $prop->addAttribute($relationClassNames[$type['type']], $options);
+        return new Attribute($relationClassNames[$type['type']], $options);
+    }
 
-        if ($type['type'] === ClassMetadataInfo::MANY_TO_ONE) {
-            $prop->addAttribute(JoinColumn::class, ['referencedColumnName' => 'id', 'nullable' => false, 'onDelete' => 'SET NULL']);
+    /**
+     * Make the #[ORM\JoinTable] attribute (if a definition exists)
+     *
+     * @param array<string | array<string | array<string>>> $type
+     * @return Attribute|null
+     */
+    protected function makeJoinTableAttributes(array $type): ?Attribute {
+        if (!isset($type['joinTable'])) {
+            return null;
         }
 
-        return $prop;
+        $options = [];
+        if ($type['joinTable']['name']) {
+            $options['name'] = $type['joinTable']['name'];
+        }
+
+        return new Attribute(JoinTable::class, $options);
+    }
+
+    /**
+     * Make the #[JoinColumn] attributes, if definitions exists.
+     *
+     * Is `$inverse` is true, make the #[InverseJoinColumn] instead.
+     *
+     * @param array<string | array<string | array<string>>> $type
+     * @param bool $inverse
+     * @return array<Attribute>
+     */
+    protected function makeJoinColumnAttributes(array $type, bool $inverse = false): array {
+        $key = $inverse ? 'inverseJoinColumns' : 'joinColumns';
+
+        $definition = $type[$key] ?? $type['joinTable'][$key] ?? [];
+        if (empty($definition)) {
+            return [];
+        }
+
+        $attributes = [];
+
+        foreach ($definition as $joinColDefinition) {
+            $options = [];
+
+            if (isset($joinColDefinition['name']) && $joinColDefinition['name'] !== $type['fieldName'] . '_id') {
+                $options['name'] = $joinColDefinition['name'];
+            }
+            if (($joinColDefinition['unique'] ?? false) === true) {
+                $options['unique'] = true;
+            }
+            if (($joinColDefinition['nullable'] ?? true) === false) {
+                $options['nullable'] = false;
+            }
+            if (($joinColDefinition['onDelete'] ?? null) !== null) {
+                $options['onDelete'] = $joinColDefinition['onDelete'];
+            }
+            if (($joinColDefinition['columnDefinition'] ?? null) !== null) {
+                $options['columnDefinition'] = $joinColDefinition['columnDefinition'];
+            }
+            if (($joinColDefinition['referencedColumnName'] ?? 'id') !== 'id') {
+                $options['referencedColumnName'] = $joinColDefinition['referencedColumnName'];
+            }
+
+            if (empty($options)) {
+                // Useless attribute
+                continue;
+            }
+
+            $attributes[] = new Attribute(
+                $inverse ? InverseJoinColumn::class : JoinColumn::class,
+                $options
+            );
+        }
+
+        return $attributes;
+    }
+
+    /**
+     * Make the '__construct' method with collections initialization
+     * @param array<Property> $collections
+     * @return Method
+     */
+    protected function makeSnippetConstructor(array $collections): Method {
+        $constructor = new Method('__construct');
+        $constructor->setPublic();
+
+        foreach ($collections as $collection) {
+            $constructor->addBody('$this->' . $collection->getName() . ' = new ArrayCollection();');
+        }
+
+        return $constructor;
     }
 
     /**
@@ -467,6 +617,38 @@ class SchemaSnippetsMaker
         return $method;
     }
 
+    protected function getTargetEntityNameFromCollectionProp(Property $prop): ?string
+    {
+        if ($prop->getType() !== Collection::class) {
+            throw new \LogicException('The property must be a collection');
+        }
+
+        foreach ($prop->getAttributes() as $attribute) {
+            if (
+                $attribute instanceof Attribute &&
+                ($attribute->getName() === OneToMany::class || $attribute->getName() === ManyToMany::class)
+            ) {
+                $targetEntityName = $attribute->getArguments()['targetEntity'];
+                if (!$targetEntityName) {
+                    return null;
+                }
+
+                // Normalize result (it could be a FQN, or a '::class' notation)
+                $targetEntityName = str_replace('::class', '', $targetEntityName);
+
+                if (!str_contains($targetEntityName, '\\')) {
+                    try {
+                        $targetEntityName = $this->entityUtils->getFullNameFromEntityName($targetEntityName);
+                    } catch (\LogicException) {
+                        return null;
+                    }
+                }
+                return $targetEntityName;
+            }
+        }
+        return null;
+    }
+
     /**
      * Make an 'adder' method for the given property
      *
@@ -479,8 +661,10 @@ class SchemaSnippetsMaker
 
         $method = new Method('add' . ucfirst($singularPropName));
 
+        $targetEntityName = $this->getTargetEntityNameFromCollectionProp($prop);
+
         $parameter = new Parameter($singularPropName);
-        $parameter->setType($prop->getType());
+        $parameter->setType($targetEntityName ?? 'mixed');
         $method->setParameters([$parameter]);
 
         $method->setReturnType('self');
@@ -510,8 +694,10 @@ class SchemaSnippetsMaker
 
         $method = new Method('remove' . ucfirst($singularPropName));
 
+        $targetEntityName = $this->getTargetEntityNameFromCollectionProp($prop);
+
         $parameter = new Parameter($singularPropName);
-        $parameter->setType($prop->getType());
+        $parameter->setType($targetEntityName ?? 'mixed');
         $method->setParameters([$parameter]);
 
         $method->setReturnType('self');

+ 11 - 5
src/Service/Utils/EntityUtils.php

@@ -14,6 +14,11 @@ use Doctrine\ORM\EntityManagerInterface;
  */
 class EntityUtils
 {
+    /**
+     * Cache of the mapping between entity names and fully qualified names
+     *
+     * @var array<string, string>
+     */
     protected array $entityNamesMappingCache = [];
 
     public function __construct(
@@ -36,8 +41,8 @@ class EntityUtils
     protected function organizationDefaultValue(mixed $entity, Access $access): void
     {
         $reflection = new \ReflectionClass($entity::class);
-        $organizationFaultValue = $reflection->getAttributes(OrganizationDefaultValue::class)[0] ?? null;
-        $fieldName = $organizationFaultValue?->getArguments()['fieldName'] ?? null;
+        $organizationDefaultValue = $reflection->getAttributes(OrganizationDefaultValue::class)[0] ?? null;
+        $fieldName = $organizationDefaultValue?->getArguments()['fieldName'] ?? null;
         if ($fieldName) {
             $entity->{sprintf('set%s', ucfirst($fieldName))}(...[$access->getOrganization()]);
         }
@@ -84,7 +89,7 @@ class EntityUtils
             $this->populateEntityNamesMappingCache();
         }
         if (!isset($this->entityNamesMappingCache[$entityName])) {
-            throw new \LogicException('No entity found for name '.$entityName);
+            throw new \LogicException('No entity found for name `'.$entityName.'`');
         }
         return $this->entityNamesMappingCache[$entityName];
 
@@ -96,6 +101,7 @@ class EntityUtils
      * @return void
      */
     protected function populateEntityNamesMappingCache() : void {
+        $this->entityNamesMappingCache = [];
         $metadata = $this->entityManager->getMetadataFactory()->getAllMetadata();
         foreach ($metadata as $entityMetadata) {
             $baseName = $this->getEntityNameFromFullName($entityMetadata->getName());
@@ -105,7 +111,7 @@ class EntityUtils
 
     /**
      * Get the namespace from a fully qualified name
-     * Ex: '\App\Entity\Core\File' => '\App\Entity\Core'
+     * Ex: '\App\Entity\Core\File' => 'App\Entity\Core'
      *
      * @param string $entityName
      * @return string|null
@@ -114,6 +120,6 @@ class EntityUtils
     {
         $parts = explode('\\', $entityName);
         array_pop($parts);
-        return implode('\\', $parts);
+        return ltrim(implode('\\', $parts), '\\');
     }
 }

+ 1 - 1
tests/Unit/Service/Dolibarr/DolibarrAccountCreatorTest.php

@@ -118,7 +118,7 @@ class DolibarrAccountCreatorTest extends TestCase
         $accountData = [
             'id' => '2',
             'code_client' => 'C2',
-            'array_options' => ['2iopen_software_opentalent' => 'Opentalent Artist'],
+            'array_options' => ['options_2iopen_software_opentalent' => 'Opentalent Artist'],
         ];
 
         $dolibarrAccount = $dolibarrAccountCreator->createDolibarrAccount($organizationId, $accountData);

+ 194 - 9
tests/Unit/Service/Utils/EntityUtilsTest.php

@@ -8,10 +8,22 @@ use App\Entity\Billing\ResidenceArea;
 use App\Entity\Education\EducationTiming;
 use App\Entity\Organization\Organization;
 use App\Service\Utils\EntityUtils;
+use Doctrine\ORM\EntityManagerInterface;
+use Doctrine\Persistence\Mapping\ClassMetadata;
+use Doctrine\Persistence\Mapping\ClassMetadataFactory;
+use PHPUnit\Framework\MockObject\MockObject;
 use PHPUnit\Framework\TestCase;
 
 class TestableEntityUtils extends EntityUtils
 {
+    public function getEntityNamesMappingCache(): array {
+        return $this->entityNamesMappingCache;
+    }
+
+    public function setEntityNamesMappingCache(array $entityNamesMappingCache) {
+        $this->entityNamesMappingCache = $entityNamesMappingCache;
+    }
+
     public function organizationDefaultValue($entity, Access $access): void
     {
         parent::organizationDefaultValue($entity, $access);
@@ -21,18 +33,35 @@ class TestableEntityUtils extends EntityUtils
     {
         parent::billingSettingDefaultValueDefaultValue($entity, $access);
     }
+
+    public function populateEntityNamesMappingCache(): void
+    {
+        parent::populateEntityNamesMappingCache();
+    }
 }
 
 class EntityUtilsTest extends TestCase
 {
+    private EntityManagerInterface $entityManager;
+
+    public function setUp(): void {
+        $this->entityManager = $this->getMockBuilder(EntityManagerInterface::class)->disableOriginalConstructor()->getMock();
+    }
+
+    protected function getEntityUtilsMockFor(string $method): MockObject | TestableEntityUtils
+    {
+        return $this->getMockBuilder(TestableEntityUtils::class)
+            ->setConstructorArgs([$this->entityManager])
+            ->setMethodsExcept(['getEntityNamesMappingCache', 'setEntityNamesMappingCache', $method])
+            ->getMock();
+    }
+
     /**
      * @see EntityUtils::defaultValueSettersByAccess()
      */
     public function testDefaultValueSettersByAccess(): void
     {
-        $utils = $this->getMockBuilder(TestableEntityUtils::class)
-            ->setMethodsExcept(['defaultValueSettersByAccess'])
-            ->getMock();
+        $utils = $this->getEntityUtilsMockFor('defaultValueSettersByAccess');
 
         $entity = $this->getMockBuilder(Organization::class)->getMock();
         $access = $this->getMockBuilder(Access::class)->getMock();
@@ -48,9 +77,7 @@ class EntityUtilsTest extends TestCase
      */
     public function testOrganizationDefaultValue(): void
     {
-        $utils = $this->getMockBuilder(TestableEntityUtils::class)
-            ->setMethodsExcept(['organizationDefaultValue'])
-            ->getMock();
+        $utils = $this->getEntityUtilsMockFor('organizationDefaultValue');
 
         $organization = $this->getMockBuilder(Organization::class)->getMock();
 
@@ -69,9 +96,7 @@ class EntityUtilsTest extends TestCase
      */
     public function testBillingSettingDefaultValueDefaultValue(): void
     {
-        $utils = $this->getMockBuilder(TestableEntityUtils::class)
-            ->setMethodsExcept(['billingSettingDefaultValueDefaultValue'])
-            ->getMock();
+        $utils = $this->getEntityUtilsMockFor('billingSettingDefaultValueDefaultValue');
 
         $entity = new ResidenceArea();  // Can't test this method with a mocked entity...
 
@@ -87,4 +112,164 @@ class EntityUtilsTest extends TestCase
 
         $this->assertEquals($billingSetting, $entity->getBillingSetting());
     }
+
+    public function testGetEntityNameFromFullName(): void {
+        $utils = $this->getEntityUtilsMockFor('getEntityNameFromFullName');
+
+        $this->assertEquals(
+            'File',
+            $utils->getEntityNameFromFullName('\App\Entity\Core\File')
+        );
+        $this->assertEquals(
+            'File',
+            $utils->getEntityNameFromFullName('\File')
+        );
+        $this->assertEquals(
+            'File',
+            $utils->getEntityNameFromFullName('File')
+        );
+    }
+
+    public function testGetFullNameFromEntityName(): void {
+        $utils = $this->getEntityUtilsMockFor('getFullNameFromEntityName');
+
+        $utils->setEntityNamesMappingCache(['File' => '\App\Entity\Core\File']);
+
+        $utils->expects(self::never())->method('populateEntityNamesMappingCache');
+
+        $this->assertEquals(
+            '\App\Entity\Core\File',
+            $utils->getFullNameFromEntityName('File')
+        );
+    }
+
+    public function testGetFullNameFromEntityNameEmptyCache(): void {
+        $utils = $this->getEntityUtilsMockFor('getFullNameFromEntityName');
+
+        $utils->setEntityNamesMappingCache([]);
+
+        $utils
+            ->expects(self::once())
+            ->method('populateEntityNamesMappingCache')
+            ->willReturnCallback(function () use ($utils) {
+                $utils->setEntityNamesMappingCache(['File' => '\App\Entity\Core\File']);})
+        ;
+
+        $this->assertEquals(
+            '\App\Entity\Core\File',
+            $utils->getFullNameFromEntityName('File')
+        );
+    }
+
+    public function testGetFullNameFromEntityNameNonExistingEntity(): void {
+        $utils = $this->getEntityUtilsMockFor('getFullNameFromEntityName');
+
+        $utils->setEntityNamesMappingCache(['File' => '\App\Entity\Core\File']);
+
+        $utils->expects(self::never())->method('populateEntityNamesMappingCache');
+
+        $this->expectException(\LogicException::class);
+        $this->expectExceptionMessage('No entity found for name `Foo`');
+
+        $utils->getFullNameFromEntityName('Foo');
+    }
+
+    public function testPopulateEntityNamesMappingCache(): void {
+        $utils = $this->getEntityUtilsMockFor('populateEntityNamesMappingCache');
+
+        $metadataFactory = $this->getMockBuilder(ClassMetadataFactory::class)->getMock();
+
+        $this->entityManager
+            ->expects(self::once())
+            ->method('getMetadataFactory')
+            ->willReturn($metadataFactory);
+
+        $entityMetadata1 = $this->getMockBuilder(ClassMetadata::class)->getMock();
+        $entityMetadata1->method('getName')->willReturn('/Namespace/Entity1');
+
+        $entityMetadata2 = $this->getMockBuilder(ClassMetadata::class)->getMock();
+        $entityMetadata2->method('getName')->willReturn('/Namespace/Entity2');
+
+        $entityMetadata3 = $this->getMockBuilder(ClassMetadata::class)->getMock();
+        $entityMetadata3->method('getName')->willReturn('/Namespace/Entity3');
+
+        $metadataFactory
+            ->method('getAllMetadata')
+            ->willReturn([$entityMetadata1, $entityMetadata2, $entityMetadata3]);
+
+        $utils->method('getEntityNameFromFullName')->willReturnMap(
+            [
+                ['/Namespace/Entity1', 'Entity1'],
+                ['/Namespace/Entity2', 'Entity2'],
+                ['/Namespace/Entity3', 'Entity3'],
+            ]
+        );
+
+        $this->assertEquals(
+            [],
+            $utils->getEntityNamesMappingCache()
+        );
+
+        $utils->populateEntityNamesMappingCache();
+
+        $this->assertEquals(
+            [
+                'Entity1' => '/Namespace/Entity1',
+                'Entity2' => '/Namespace/Entity2',
+                'Entity3' => '/Namespace/Entity3',
+            ],
+            $utils->getEntityNamesMappingCache()
+        );
+    }
+
+    public function testPopulateEntityNamesMappingCacheWithExistingCache(): void {
+        $utils = $this->getEntityUtilsMockFor('populateEntityNamesMappingCache');
+
+        $metadataFactory = $this->getMockBuilder(ClassMetadataFactory::class)->getMock();
+
+        $this->entityManager
+            ->expects(self::once())
+            ->method('getMetadataFactory')
+            ->willReturn($metadataFactory);
+
+        $entityMetadata1 = $this->getMockBuilder(ClassMetadata::class)->getMock();
+        $entityMetadata1->method('getName')->willReturn('/Namespace/Entity');
+
+        $metadataFactory
+            ->method('getAllMetadata')
+            ->willReturn([$entityMetadata1]);
+
+        $utils->method('getEntityNameFromFullName')->willReturnMap(
+            [
+                ['/Namespace/Entity', 'Entity'],
+            ]
+        );
+
+        $utils->setEntityNamesMappingCache(['OtherEntity' => '/Namespace/OtherEntity']);
+
+        $this->assertEquals(
+            ['OtherEntity' => '/Namespace/OtherEntity',],
+            $utils->getEntityNamesMappingCache()
+        );
+
+        $utils->populateEntityNamesMappingCache();
+
+        $this->assertEquals(
+            ['Entity' => '/Namespace/Entity'],
+            $utils->getEntityNamesMappingCache()
+        );
+    }
+
+    public function testGetNamespaceFromName(): void {
+        $utils = $this->getEntityUtilsMockFor('getNamespaceFromName');
+
+        $this->assertEquals(
+            'App\Entity\Core',
+            $utils->getNamespaceFromName('\App\Entity\Core\File')
+        );
+        $this->assertEquals(
+            '',
+            $utils->getNamespaceFromName('\File')
+        );
+    }
 }