phoneNumberUtil = PhoneNumberUtil::getInstance(); } /** * A new shop request has been submitted. * Register the request, and send the validation link by email. * * @param array $data * * @throws TransportExceptionInterface */ public function registerNewShopRequest(ShopRequestType $type, array $data): ShopRequest { $this->controlShopRequestData($type, $data); $request = $this->createRequest($type, $data); $this->sendRequestValidationLink($request); return $request; } /** * Validate the shop request based on its type. * For NEW_STRUCTURE_ARTIST_PREMIUM_TRIAL, check if the organization already exists. * For other types, throw an error. * * @param array $data */ protected function controlShopRequestData(ShopRequestType $type, array $data): void { // @phpstan-ignore-next-line identical.alwaysTrue if ($type === ShopRequestType::NEW_STRUCTURE_ARTIST_PREMIUM_TRIAL) { $this->validateNewStructureArtistPremiumTrialRequest($data); } else { throw new \RuntimeException('request type not supported'); } } /** * Validate the request and dispatch the appropriate job based on the request type. * * @throws \RuntimeException|ExceptionInterface */ public function processShopRequest(ShopRequest $shopRequest): void { // Dispatch appropriate job based on request type switch ($shopRequest->getType()->value) { case ShopRequestType::NEW_STRUCTURE_ARTIST_PREMIUM_TRIAL->value: $this->messageBus->dispatch( new NewStructureArtistPremiumTrial($shopRequest->getToken()) ); break; default: throw new \RuntimeException('request type not supported'); } $shopRequest->setStatus(ShopRequestStatus::VALIDATED); $this->entityManager->persist($shopRequest); $this->entityManager->flush(); } /** * Create and persist a new ShopRequest entity. * * @param array $data */ protected function createRequest(ShopRequestType $type, array $data): ShopRequest { $shopRequest = new ShopRequest(); $shopRequest->setToken(Uuid::v4()->toRfc4122()); $shopRequest->setType($type); $shopRequest->setData($data); $this->entityManager->persist($shopRequest); $this->entityManager->flush(); return $shopRequest; } /** * Send validation email with link. * * @throws TransportExceptionInterface */ protected function sendRequestValidationLink(ShopRequest $shopRequest): void { $validationUrl = UrlBuilder::concat( $this->softwareWebsiteUrl, ['/shop/try/validation'], ['token' => $shopRequest->getToken()] ); $data = $shopRequest->getData(); $model = new TokenValidationModel(); $model ->setToken($shopRequest->getToken()) ->setRepresentativeEmail($data['representativeEmail'] ?? '') ->setRepresentativeFirstName($data['representativeFirstName'] ?? '') ->setRepresentativeLastName($data['representativeLastName'] ?? '') ->setStructureName($data['structureName'] ?? '') ->setValidationUrl($validationUrl) ->setSenderId(AccessIdsEnum::ADMIN_2IOPENSERVICE->value); $this->mailer->main($model); $shopRequest->setStatus(ShopRequestStatus::ACTIVATION_LINK_SENT); $this->entityManager->persist($shopRequest); $this->entityManager->flush(); } /** * Handles the processing of a new structure artist premium trial request. * * @param string $token The token identifying the shop request * * @throws Exception * @throws \JsonException * @throws ORMException * @throws OptimisticLockException */ public function handleNewStructureArtistPremiumTrialRequest(string $token): void { // Retrieve the ShopRequest entity using its token $shopRequest = $this->entityManager->find(ShopRequest::class, $token); if (!$shopRequest) { $this->logger->error('Cannot find ShopRequest with token: '.$token); return; } // Convert the stored JSON data to a NewStructureArtistPremiumTrialRequest object $data = $shopRequest->getData(); $trialRequest = $this->serializer->deserialize( json_encode($data), NewStructureArtistPremiumTrialRequest::class, 'json' ); $organization = $this->createOrganization($trialRequest); // Set the admin account password $this->organizationFactory->setAdminAccountPassword($organization, $trialRequest->getPassword()); // Start the artist premium trial $this->trial->startArtistPremiumTrialForNewStructure($organization, $trialRequest); // Send email to sales administration $this->sendMailToSalesAdministration($trialRequest); // Send email to representative $this->sendConfirmationMailToRepresentative($trialRequest); $this->logger->info('Successfully processed NewStructureArtistPremiumTrial for token: '.$token); } /** * Creates a new organization based on a trial request. * * @param NewStructureArtistPremiumTrialRequest $trialRequest The trial request containing organization data * * @return Organization The created organization */ protected function createOrganization(NewStructureArtistPremiumTrialRequest $trialRequest): Organization { // Generate an OrganizationCreationRequest object $organizationCreationRequest = $this->createOrganizationCreationRequestFromTrialRequest($trialRequest); // Create the organization return $this->organizationFactory->create($organizationCreationRequest); } /** * Vérifie la validité d'une requête d'essai artist premium pour une nouvelle structure. */ protected function validateNewStructureArtistPremiumTrialRequest( array $data, ): void { $trialRequestObj = $this->serializer->deserialize( json_encode($data), NewStructureArtistPremiumTrialRequest::class, 'json' ); // Validate phone number if (!$this->phoneNumberUtil->isPossibleNumber($trialRequestObj->getRepresentativePhone())) { throw new \RuntimeException('Invalid phone number'); } // Check if organization already exists $organizationCreationRequest = $this->createOrganizationCreationRequestFromTrialRequest($trialRequestObj); $this->organizationFactory->interruptIfOrganizationExists($organizationCreationRequest); } /** * Creates an OrganizationCreationRequest from a NewStructureArtistPremiumTrialRequest. * * @param NewStructureArtistPremiumTrialRequest $trialRequest The trial request containing organization data * * @return OrganizationCreationRequest The created organization creation request * * @throws \Exception */ protected function createOrganizationCreationRequestFromTrialRequest( NewStructureArtistPremiumTrialRequest $trialRequest, ): OrganizationCreationRequest { $organizationCreationRequest = new OrganizationCreationRequest(); $organizationCreationRequest->setName($trialRequest->getStructureName()); $organizationCreationRequest->setStreetAddress1($trialRequest->getAddress()); $organizationCreationRequest->setStreetAddress2($trialRequest->getAddressComplement()); $organizationCreationRequest->setPostalCode($trialRequest->getPostalCode()); $organizationCreationRequest->setCity($trialRequest->getCity()); $organizationCreationRequest->setEmail($trialRequest->getStructureEmail()); $organizationCreationRequest->setPrincipalType($trialRequest->getStructureType()); $organizationCreationRequest->setLegalStatus($trialRequest->getLegalStatus()); $organizationCreationRequest->setSiretNumber($trialRequest->getSiren()); $organizationCreationRequest->setPhoneNumber($trialRequest->getRepresentativePhone()); $organizationCreationRequest->setSubdomain($trialRequest->getStructureIdentifier()); $organizationCreationRequest->setSendConfirmationEmailAt($trialRequest->getRepresentativeEmail()); // Set default values $organizationCreationRequest->setProduct(SettingsProductEnum::FREEMIUM); $organizationCreationRequest->setCreateWebsite(false); $organizationCreationRequest->setClient(false); $organizationCreationRequest->setCreationDate(DatesUtils::new()); return $organizationCreationRequest; } /** * Envoie un email à l'administration des ventes pour informer d'une nouvelle demande d'essai artist premium. * * @param NewStructureArtistPremiumTrialRequest $trialRequest La demande d'essai * * @throws TransportExceptionInterface */ protected function sendMailToSalesAdministration(NewStructureArtistPremiumTrialRequest $trialRequest): void { // Create the email model $model = new NotificationToSalesAdminModel(); $model ->setTrialRequest($trialRequest) ->setSenderId(AccessIdsEnum::ADMIN_2IOPENSERVICE->value); // Send the email to the sales administration $this->mailer->main($model); } /** * Envoie un email au représentant pour l'informer que sa demande d'essai artist premium a été validée * et lui fournir un lien pour créer son compte et accéder au logiciel. * * @param NewStructureArtistPremiumTrialRequest $trialRequest La demande d'essai * * @throws TransportExceptionInterface */ protected function sendConfirmationMailToRepresentative( NewStructureArtistPremiumTrialRequest $trialRequest, ): void { // Create the admin username $adminUsername = 'admin' . $trialRequest->getStructureIdentifier(); // Create the admin login URL $adminLoginUrl = UrlBuilder::concat($this->publicAdminBaseUrl, ['#/login/']); // Create the email model $model = new ConfirmationToRepresentativeModel(); $model ->setTrialRequest($trialRequest) ->setAccountCreationUrl(UrlBuilder::concat($this->publicBaseUrl, ['/account/create'])) ->setFaqUrl($this->faqUrl) ->setAdminUsername($adminUsername) ->setAdminLoginUrl($adminLoginUrl) ->setSenderId(AccessIdsEnum::ADMIN_2IOPENSERVICE->value); // Send the email to the representative $this->mailer->main($model); } }