logger = $adminLogger; } /** * Créé une nouvelle organisation à partir des données contenues dans une OrganizationCreationRequest * * @param OrganizationCreationRequest $organizationCreationRequest * @return Organization * @throws TransportExceptionInterface * @throws Throwable */ public function create(OrganizationCreationRequest $organizationCreationRequest): Organization { $this->logger->info( 'Start the creation of a new organization named ' . $organizationCreationRequest->getName() ); $this->entityManager->beginTransaction(); try { if ($this->isExistingOrganization($organizationCreationRequest)) { throw new \RuntimeException('An organization named ' . $organizationCreationRequest->getName() . ' already exists.'); } $this->validateSubdomain($organizationCreationRequest->getSubdomain()); $this->logger->info("Subdomain is valid and available : " . $organizationCreationRequest->getSubdomain()); // Création de l'organisation $organization = $this->makeOrganization($organizationCreationRequest); $this->logger->debug(" - Organization created"); // Création des Parameters $parameters = $this->makeParameters($organizationCreationRequest); $organization->setParameters($parameters); $this->logger->debug(" - Parameters created"); // Création des Settings $settings = $this->makeSettings($organizationCreationRequest); $organization->setSettings($settings); $this->logger->debug(" - Settings created"); // Création de l'adresse postale $organizationAddressPostal = $this->makePostalAddress($organizationCreationRequest); $organization->addOrganizationAddressPostal($organizationAddressPostal); $this->logger->debug(" - OrganizationAddressPostal created"); // Création du point de contact $contactPoint = $this->makeContactPoint($organizationCreationRequest); $organization->addContactPoint($contactPoint); $this->logger->debug(" - ContactPoint created"); // Rattachement au réseau $networkOrganization = $this->makeNetworkOrganization($organizationCreationRequest); $organization->addNetworkOrganization($networkOrganization); $this->logger->debug(" - NetworkOrganization created"); // Créé l'admin $adminAccess = $this->makeAdminAccess($organizationCreationRequest); $organization->addAccess($adminAccess); $this->logger->debug(" - Admin access created"); // Création des cycles foreach ($this->makeCycles() as $cycle) { $organization->addCycle($cycle); } $this->logger->debug(" - Cycles created"); // Création du président (si renseigné) $presidentCreationRequest = $organizationCreationRequest->getPresident(); if ($presidentCreationRequest !== null) { $presidentAccess = $this->makeAccess($presidentCreationRequest); $organization->addAccess($presidentAccess); $this->logger->debug(" - President access created"); } // Création du directeur (si renseigné) $directorCreationRequest = $organizationCreationRequest->getDirector(); if ($directorCreationRequest !== null) { $directorAccess = $this->makeAccess($directorCreationRequest); $organization->addAccess($directorAccess); $this->logger->debug(" - Director access created"); } $subdomain = new Subdomain(); $subdomain->setSubdomain($organizationCreationRequest->getSubdomain()); $subdomain->setOrganization($organization); $subdomain->setActive(true); $this->entityManager->persist($subdomain); // <--- Pour la rétrocompatibilité avec la v1 ; pourra être supprimé lorsque la migration sera achevée $parameters = $organization->getParameters(); $parameters->setSubDomain($organizationCreationRequest->getSubdomain()); $parameters->setOtherWebsite('https://' . $organizationCreationRequest->getSubdomain() . '.opentalent.fr'); $this->entityManager->persist($parameters); // ---> // Création de la société Dolibarr $dolibarrId = $this->dolibarrApiService->createSociety($organization); $this->logger->info("New dolibarr structure created (uid : " . $dolibarrId . ")"); $this->entityManager->persist($organization); $this->entityManager->flush(); $this->entityManager->commit(); $this->logger->debug(" - New records commited"); $this->logger->info("Organization created in the DB"); } catch (\Exception $e) { $this->logger->critical("An error happened, operation cancelled : " . $e); $this->entityManager->rollback(); throw $e; } // Création du site typo3 if ($organizationCreationRequest->getCreateWebsite()) { $response = $this->typo3Service->createSite($organization->getId()); // TODO: revoir l'utilité du champs cmsId $rootPageUid = json_decode($response->getContent(), true); $organization->setCmsId($rootPageUid); $this->entityManager->persist($organization); $this->entityManager->flush(); $this->logger->info("New typo3 website created (root uid : " . $rootPageUid . ")"); } else { $this->logger->warning("Typo3 website creation was not required"); } // Register the subdomain into the BindFile (takes up to 5min to take effect) $this->bindFileService->registerSubdomain($subdomain->getSubdomain()); $this->logger->info("Subdomain registered"); return $organization; } /** * Une organisation du même nom existe-t-elle déjà à la même adresse ? * * @param OrganizationCreationRequest $organizationCreationRequest * @return bool */ protected function isExistingOrganization(OrganizationCreationRequest $organizationCreationRequest): bool { return $this ->organizationRepository ->count( [ 'name' => $organizationCreationRequest->getName(), ] ) > 0; } /** * Vérifie la disponibilité et la validité d'un sous domaine * * @param string $subdomainValue * @return void * @throws \Exception */ protected function validateSubdomain(string $subdomainValue): void { if (!$this->subdomainService->isValidSubdomain($subdomainValue)) { throw new \RuntimeException("Not a valid subdomain :" . $subdomainValue); } if ($this->subdomainService->isReservedSubdomain($subdomainValue)) { throw new \RuntimeException("This subdomain is not available :" . $subdomainValue); } if ($this->subdomainService->isRegistered($subdomainValue)) { throw new \RuntimeException("This subdomain is already registered :" . $subdomainValue); } } /** * Créé une nouvelle instance d'organisation * * @param OrganizationCreationRequest $organizationCreationRequest * @return Organization */ protected function makeOrganization(OrganizationCreationRequest $organizationCreationRequest): Organization { // Création de l'organisation $organization = new Organization(); $organization->setName($organizationCreationRequest->getName()); $organization->setLegalStatus($organizationCreationRequest->getLegalStatus()); $organization->setPrincipalType($organizationCreationRequest->getPrincipalType()); $this->entityManager->persist($organization); return $organization; } /** * Create a new Parameters object from the data in an OrganizationCreationRequest * * @param OrganizationCreationRequest $organizationCreationRequest The organization creation request * @return Parameters The created Parameters object * @throws Throwable If there is an error */ protected function makeParameters(OrganizationCreationRequest $organizationCreationRequest): Parameters { $parameters = new Parameters(); $this->entityManager->persist($parameters); return $parameters; } /** * Creates a new instance of the Settings class based on the given OrganizationCreationRequest object. * * @param OrganizationCreationRequest $organizationCreationRequest The OrganizationCreationRequest object containing the required data. * * @return Settings The newly created instance of the Settings class. */ protected function makeSettings(OrganizationCreationRequest $organizationCreationRequest): Settings { $settings = new Settings(); $settings->setProduct($organizationCreationRequest->getProduct()); $this->entityManager->persist($settings); return $settings; } /** * Creates a new instance of the OrganizationAddressPostal class based on the given OrganizationCreationRequest object. * * @param OrganizationCreationRequest $organizationCreationRequest The OrganizationCreationRequest object containing the required data. * * @return OrganizationAddressPostal The newly created instance of the OrganizationAddressPostal class. */ protected function makePostalAddress(OrganizationCreationRequest $organizationCreationRequest): OrganizationAddressPostal { $addressPostal = new AddressPostal(); $addressPostal->setStreetAddress($organizationCreationRequest->getStreetAddress1()); $addressPostal->setStreetAddressSecond($organizationCreationRequest->getStreetAddress2()); $addressPostal->setStreetAddressThird($organizationCreationRequest->getStreetAddress3()); $addressPostal->setPostalCode($organizationCreationRequest->getPostalCode()); $addressPostal->setAddressCity($organizationCreationRequest->getCity()); $country = $this->countryRepository->find($organizationCreationRequest->getCountryId()); $addressPostal->setAddressCountry($country); $this->entityManager->persist($addressPostal); $organizationAddressPostal = new OrganizationAddressPostal(); $organizationAddressPostal->setAddressPostal($addressPostal); $organizationAddressPostal->setType(AddressPostalOrganizationTypeEnum::ADDRESS_HEAD_OFFICE); $this->entityManager->persist($organizationAddressPostal); return $organizationAddressPostal; } /** * Creates a new instance of the ContactPoint class based on the given OrganizationCreationRequest object. * * @param OrganizationCreationRequest $organizationCreationRequest The OrganizationCreationRequest object containing the required data. * * @return ContactPoint The newly created instance of the ContactPoint class. */ protected function makeContactPoint(OrganizationCreationRequest $organizationCreationRequest): ContactPoint { $phoneUtil = PhoneNumberUtil::getInstance(); $phoneNumber = $phoneUtil->parse($organizationCreationRequest->getPhoneNumber()); $contactPoint = new ContactPoint(); $contactPoint->setContactType(ContactPointTypeEnum::PRINCIPAL); $contactPoint->setEmail($organizationCreationRequest->getEmail()); $contactPoint->setTelphone($phoneNumber); $this->entityManager->persist($contactPoint); return $contactPoint; } /** * Creates a new instance of the NetworkOrganization class based on the given OrganizationCreationRequest object. * * @param OrganizationCreationRequest $organizationCreationRequest The OrganizationCreationRequest object containing the required data. * * @return NetworkOrganization The newly created instance of the NetworkOrganization class. * * @throws \RuntimeException|\Exception if no parent organization is found for the given parent ID or if no network is found for the given network ID. */ protected function makeNetworkOrganization(OrganizationCreationRequest $organizationCreationRequest): NetworkOrganization { $parent = $this->organizationRepository->find($organizationCreationRequest->getParentId()); if (!$parent) { throw new \RuntimeException('No parent organization found for id ' . $organizationCreationRequest->getParentId()); } $network = $this->networkRepository->find($organizationCreationRequest->getNetworkId()); if (!$network) { throw new \RuntimeException('No network found for id ' . $organizationCreationRequest->getNetworkId()); } $networkOrganization = new NetworkOrganization(); $networkOrganization->setParent($parent); $networkOrganization->setNetwork($network); $networkOrganization->setStartDate(DatesUtils::new()); $this->entityManager->persist($networkOrganization); return $networkOrganization; } /** * Creates a new instance of the Access class with admin access based on the given OrganizationCreationRequest object. * * @param OrganizationCreationRequest $organizationCreationRequest The OrganizationCreationRequest object containing the required data. * * @return Access The newly created instance of the Access class with admin access. */ protected function makeAdminAccess(OrganizationCreationRequest $organizationCreationRequest): Access { $admin = new Person(); $admin->setUsername('admin' . strtolower($organizationCreationRequest->getSubdomain())); $randomString = ByteString::fromRandom(32)->toString(); $admin->setPassword($randomString); $this->entityManager->persist($admin); $adminAccess = new Access(); $adminAccess->setAdminAccess(true); $adminAccess->setPerson($admin); $this->entityManager->persist($adminAccess); return $adminAccess; } /** * Creates an array of Cycle objects based on a predefined set of data. * * @return Cycle[] An array of Cycle objects. */ protected function makeCycles(): array { $cyclesData = [ ['Cycle initiation', 10, CycleEnum::INITIATION_CYCLE], ['Cycle 1', 20, CycleEnum::CYCLE_1], ['Cycle 2', 30, CycleEnum::CYCLE_2], ['Cycle 3', 40, CycleEnum::CYCLE_3], ['Cycle 4', 50, CycleEnum::CYCLE_4], ['Hors cycle', 60, CycleEnum::OUT_CYCLE], ]; $cycles = []; foreach ($cyclesData as $cycleData) { $cycle = new Cycle(); $cycle->setLabel($cycleData[0]); $cycle->setOrder($cycleData[1]); $cycle->setCycleEnum($cycleData[2]); $cycle->setIsSystem(false); $this->entityManager->persist($cycle); $cycles[] = $cycle; } return $cycles; } /** * Creates an Access object based on the given OrganizationMemberCreationRequest. * * @param int|OrganizationMemberCreationRequest $organizationMemberCreationRequest The request object containing the * necessary data for creating a * Person object, or the id of an * existing one. * @return Access The created Access object. */ protected function makeAccess(int|OrganizationMemberCreationRequest $organizationMemberCreationRequest): Access { if (is_int($organizationMemberCreationRequest)) { $person = $this->personRepository->find($organizationMemberCreationRequest); } else { $person = new Person(); $person->setUsername( strtolower(str_replace(' ', '-', $organizationMemberCreationRequest->getName())) ); $person->setPassword(ByteString::fromRandom(32)->toString()); $person->setGender($organizationMemberCreationRequest->getGender()); $person->setName($organizationMemberCreationRequest->getName()); $person->setGivenName($organizationMemberCreationRequest->getGivenName()); $personPostalAddress = $this->makeAccessPostalAddress($organizationMemberCreationRequest); $person->addPersonAddressPostal($personPostalAddress); $contactPoint = $this->makeAccessContactPoint($organizationMemberCreationRequest); $person->addContactPoint($contactPoint); $this->entityManager->persist($person); } $access = new Access(); $access->setPerson($person); $this->entityManager->persist($access); return $access; } /** * Creates a PersonAddressPostal object based on the given OrganizationMemberCreationRequest. * * @param OrganizationMemberCreationRequest $organizationMemberCreationRequest The request object containing the * necessary data for creating a * PersonAddressPostal object. * @return PersonAddressPostal The created PersonAddressPostal object. */ protected function makeAccessPostalAddress(OrganizationMemberCreationRequest $organizationMemberCreationRequest): PersonAddressPostal { $addressPostal = new AddressPostal(); $addressPostal->setStreetAddress($organizationMemberCreationRequest->getStreetAddress1()); $addressPostal->setStreetAddressSecond($organizationMemberCreationRequest->getStreetAddress2()); $addressPostal->setStreetAddressThird($organizationMemberCreationRequest->getStreetAddress3()); $addressPostal->setPostalCode($organizationMemberCreationRequest->getPostalCode()); $addressPostal->setAddressCity($organizationMemberCreationRequest->getCity()); $country = $this->countryRepository->find($organizationMemberCreationRequest->getCountryId()); $addressPostal->setAddressCountry($country); $this->entityManager->persist($addressPostal); $personAddressPostal = new PersonAddressPostal(); $personAddressPostal->setAddressPostal($addressPostal); $personAddressPostal->setType(AddressPostalPersonTypeEnum::ADDRESS_PRINCIPAL); $this->entityManager->persist($personAddressPostal); return $personAddressPostal; } /** * Creates a new instance of the ContactPoint class based on the given OrganizationCreationRequest object. * * @param OrganizationMemberCreationRequest $organizationMemberCreationRequest The OrganizationMemberCreationRequest object containing the required data. * * @return ContactPoint The newly created instance of the ContactPoint class. * @throws NumberParseException */ protected function makeAccessContactPoint(OrganizationMemberCreationRequest $organizationMemberCreationRequest): ContactPoint { $phoneUtil = PhoneNumberUtil::getInstance(); $phoneNumber = $phoneUtil->parse($organizationMemberCreationRequest->getPhone()); $contactPoint = new ContactPoint(); $contactPoint->setContactType(ContactPointTypeEnum::PRINCIPAL); $contactPoint->setEmail($organizationMemberCreationRequest->getEmail()); $contactPoint->setTelphone($phoneNumber); if ($organizationMemberCreationRequest->getMobile() !== null) { $mobileNumber = $phoneUtil->parse($organizationMemberCreationRequest->getMobile()); $contactPoint->setMobilPhone($mobileNumber); } $this->entityManager->persist($contactPoint); return $contactPoint; } }