|
@@ -0,0 +1,202 @@
|
|
|
|
|
+<?php
|
|
|
|
|
+
|
|
|
|
|
+declare(strict_types=1);
|
|
|
|
|
+
|
|
|
|
|
+namespace App\Service\Shop;
|
|
|
|
|
+
|
|
|
|
|
+use App\ApiResources\Organization\OrganizationCreationRequest;
|
|
|
|
|
+use App\ApiResources\Shop\NewStructureArtistPremiumTrialRequest;
|
|
|
|
|
+use App\Entity\Organization\Organization;
|
|
|
|
|
+use App\Entity\Shop\ShopRequest;
|
|
|
|
|
+use App\Enum\Shop\NewStructureTrialRequestStatusEnum;
|
|
|
|
|
+use App\Enum\Shop\ShopRequestType;
|
|
|
|
|
+use App\Message\Message\Shop\NewStructureArtistPremiumTrial;
|
|
|
|
|
+use App\Service\ApiLegacy\ApiLegacyRequestService;
|
|
|
|
|
+use App\Service\Mailer\Mailer;
|
|
|
|
|
+use App\Service\Mailer\Model\NewStructureTrialRequestValidationModel;
|
|
|
|
|
+use App\Service\Organization\OrganizationFactory;
|
|
|
|
|
+use App\Service\Utils\UrlBuilder;
|
|
|
|
|
+use Doctrine\ORM\EntityManagerInterface;
|
|
|
|
|
+use RuntimeException;
|
|
|
|
|
+use Symfony\Component\HttpFoundation\Response;
|
|
|
|
|
+use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
|
|
|
|
|
+use Symfony\Component\Messenger\Exception\ExceptionInterface;
|
|
|
|
|
+use Symfony\Component\Messenger\MessageBusInterface;
|
|
|
|
|
+use Symfony\Component\Uid\Uuid;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Service for managing shop requests.
|
|
|
|
|
+ */
|
|
|
|
|
+readonly class ShopService
|
|
|
|
|
+{
|
|
|
|
|
+ public function __construct(
|
|
|
|
|
+ private EntityManagerInterface $entityManager,
|
|
|
|
|
+ private Mailer $mailer,
|
|
|
|
|
+ private string $baseUrl,
|
|
|
|
|
+ private MessageBusInterface $messageBus,
|
|
|
|
|
+ private ApiLegacyRequestService $apiLegacyRequestService,
|
|
|
|
|
+ private OrganizationFactory $organizationFactory,
|
|
|
|
|
+ ) {
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * A new shop request has been submitted.
|
|
|
|
|
+ * Register the request, and send the validation link by email.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param ShopRequestType $type
|
|
|
|
|
+ * @param array<string, mixed> $data
|
|
|
|
|
+ * @return ShopRequest
|
|
|
|
|
+ * @throws TransportExceptionInterface
|
|
|
|
|
+ */
|
|
|
|
|
+ public function registerNewShopRequest(ShopRequestType $type, array $data): ShopRequest
|
|
|
|
|
+ {
|
|
|
|
|
+ $this->validateShopRequest($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 ShopRequestType $type
|
|
|
|
|
+ * @param array<string, mixed> $data
|
|
|
|
|
+ */
|
|
|
|
|
+ protected function validateShopRequest(ShopRequestType $type, array $data): void
|
|
|
|
|
+ {
|
|
|
|
|
+ if ($type === ShopRequestType::NEW_STRUCTURE_ARTIST_PREMIUM_TRIAL) {
|
|
|
|
|
+ // Create a minimal OrganizationCreationRequest with required info
|
|
|
|
|
+ $organizationCreationRequest = new OrganizationCreationRequest();
|
|
|
|
|
+ $organizationCreationRequest->setName($data['structureName'] ?? '');
|
|
|
|
|
+ $organizationCreationRequest->setCity($data['city'] ?? '');
|
|
|
|
|
+ $organizationCreationRequest->setPostalCode($data['postalCode'] ?? '');
|
|
|
|
|
+ $organizationCreationRequest->setStreetAddress1($data['address'] ?? '');
|
|
|
|
|
+ $organizationCreationRequest->setStreetAddress2($data['addressComplement'] ?? '');
|
|
|
|
|
+ $organizationCreationRequest->setStreetAddress3('');
|
|
|
|
|
+
|
|
|
|
|
+ // Check if organization already exists
|
|
|
|
|
+ $this->organizationFactory->interruptIfOrganizationExists($organizationCreationRequest);
|
|
|
|
|
+ } 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
|
|
|
|
|
+ {
|
|
|
|
|
+ $shopRequest->setStatus(NewStructureTrialRequestStatusEnum::VALIDATED);
|
|
|
|
|
+ $this->entityManager->persist($shopRequest);
|
|
|
|
|
+ $this->entityManager->flush();
|
|
|
|
|
+
|
|
|
|
|
+ // Dispatch appropriate job based on request type
|
|
|
|
|
+ if ($shopRequest->getType() === ShopRequestType::NEW_STRUCTURE_ARTIST_PREMIUM_TRIAL) {
|
|
|
|
|
+ $this->messageBus->dispatch(
|
|
|
|
|
+ new NewStructureArtistPremiumTrial($shopRequest->getToken())
|
|
|
|
|
+ );
|
|
|
|
|
+ } else {
|
|
|
|
|
+ throw new RuntimeException('Unknown request type');
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Create and persist a new ShopRequest entity.
|
|
|
|
|
+ * @param ShopRequestType $type
|
|
|
|
|
+ * @param array<string, mixed> $data
|
|
|
|
|
+ * @return ShopRequest
|
|
|
|
|
+ */
|
|
|
|
|
+ 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->baseUrl,
|
|
|
|
|
+ ['new-structure-trial-request', $shopRequest->getToken()]
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ $data = $shopRequest->getData();
|
|
|
|
|
+
|
|
|
|
|
+ $model = new NewStructureTrialRequestValidationModel();
|
|
|
|
|
+ $model->setToken($shopRequest->getToken())
|
|
|
|
|
+ ->setRepresentativeEmail($data['representativeEmail'] ?? '')
|
|
|
|
|
+ ->setRepresentativeFirstName($data['representativeFirstName'] ?? '')
|
|
|
|
|
+ ->setRepresentativeLastName($data['representativeLastName'] ?? '')
|
|
|
|
|
+ ->setStructureName($data['structureName'] ?? '')
|
|
|
|
|
+ ->setValidationUrl($validationUrl);
|
|
|
|
|
+
|
|
|
|
|
+ $this->mailer->main($model);
|
|
|
|
|
+
|
|
|
|
|
+ $shopRequest->setStatus(NewStructureTrialRequestStatusEnum::ACTIVATION_LINK_SENT);
|
|
|
|
|
+ $this->entityManager->persist($shopRequest);
|
|
|
|
|
+ $this->entityManager->flush();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Start an artist premium trial for an organization.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param Organization $organization The organization to start the trial for
|
|
|
|
|
+ * @param NewStructureArtistPremiumTrialRequest $request The trial request data
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return bool True if the trial was started successfully, false otherwise
|
|
|
|
|
+ *
|
|
|
|
|
+ * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
|
|
|
|
|
+ */
|
|
|
|
|
+ public function startArtistPremiumTrial(Organization $organization, NewStructureArtistPremiumTrialRequest $request): bool
|
|
|
|
|
+ {
|
|
|
|
|
+ // Prepare the request data
|
|
|
|
|
+ $data = [
|
|
|
|
|
+ "organization" => [
|
|
|
|
|
+ "streetAddress" => $request->getAddress(),
|
|
|
|
|
+ "streetAddressSecond" => $request->getAddressComplement(),
|
|
|
|
|
+ "streetAddressThird" => "",
|
|
|
|
|
+ "cp" => $request->getPostalCode(),
|
|
|
|
|
+ "city" => $request->getCity(),
|
|
|
|
|
+ "name" => $organization->getName(),
|
|
|
|
|
+ "organizationAddressPostalId" => null
|
|
|
|
|
+ ],
|
|
|
|
|
+ "access" => [
|
|
|
|
|
+ "isAdmin" => true,
|
|
|
|
|
+ "email" => $request->getRepresentativeEmail(),
|
|
|
|
|
+ "contactPointId" => null,
|
|
|
|
|
+ "name" => $request->getRepresentativeLastName(),
|
|
|
|
|
+ "givenName" => $request->getRepresentativeFirstName(),
|
|
|
|
|
+ "function" => $request->getRepresentativeFunction(),
|
|
|
|
|
+ "telphone" => $request->getRepresentativePhone()
|
|
|
|
|
+ ]
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ $response = $this->apiLegacyRequestService->request(
|
|
|
|
|
+ 'POST',
|
|
|
|
|
+ '/api/trial/artist_premium',
|
|
|
|
|
+ $data
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ return $response->getStatusCode() === Response::HTTP_OK;
|
|
|
|
|
+ } catch (\Exception $e) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|