|
|
@@ -7,21 +7,32 @@ namespace App\Service\Shop;
|
|
|
use App\ApiResources\Organization\OrganizationCreationRequest;
|
|
|
use App\ApiResources\Shop\NewStructureArtistPremiumTrialRequest;
|
|
|
use App\Entity\Organization\Organization;
|
|
|
+use App\Entity\Organization\Subdomain;
|
|
|
use App\Entity\Shop\ShopRequest;
|
|
|
+use App\Enum\Access\AccessIdsEnum;
|
|
|
+use App\Enum\Organization\SettingsProductEnum;
|
|
|
use App\Enum\Shop\ShopRequestStatus;
|
|
|
use App\Enum\Shop\ShopRequestType;
|
|
|
use App\Message\Message\Shop\NewStructureArtistPremiumTrial;
|
|
|
+use App\Repository\Organization\OrganizationRepository;
|
|
|
use App\Service\ApiLegacy\ApiLegacyRequestService;
|
|
|
+use App\Service\Dolibarr\DolibarrApiService;
|
|
|
+use App\Service\Dolibarr\DolibarrUtils;
|
|
|
use App\Service\Mailer\Mailer;
|
|
|
-use App\Service\Mailer\Model\NewStructureTrialRequestValidationModel;
|
|
|
+use App\Service\Mailer\Model\NewStructureArtistPremiumTrialRequestValidationModel;
|
|
|
+use App\Service\Mailer\Model\SubdomainChangeModel;
|
|
|
use App\Service\Organization\OrganizationFactory;
|
|
|
use App\Service\Utils\UrlBuilder;
|
|
|
+use Doctrine\DBAL\Exception;
|
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
|
+use JsonException;
|
|
|
+use Psr\Log\LoggerInterface;
|
|
|
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\Serializer\SerializerInterface;
|
|
|
use Symfony\Component\Uid\Uuid;
|
|
|
|
|
|
/**
|
|
|
@@ -30,12 +41,15 @@ use Symfony\Component\Uid\Uuid;
|
|
|
readonly class ShopService
|
|
|
{
|
|
|
public function __construct(
|
|
|
- private EntityManagerInterface $entityManager,
|
|
|
- private Mailer $mailer,
|
|
|
- private string $baseUrl,
|
|
|
- private MessageBusInterface $messageBus,
|
|
|
- private ApiLegacyRequestService $apiLegacyRequestService,
|
|
|
- private OrganizationFactory $organizationFactory,
|
|
|
+ private EntityManagerInterface $entityManager,
|
|
|
+ private Mailer $mailer,
|
|
|
+ private string $publicBaseUrl,
|
|
|
+ private OrganizationFactory $organizationFactory,
|
|
|
+ private SerializerInterface $serializer,
|
|
|
+ private LoggerInterface $logger,
|
|
|
+ private DolibarrApiService $dolibarrApiService,
|
|
|
+ private DolibarrUtils $dolibarrUtils,
|
|
|
+ private MessageBusInterface $messageBus,
|
|
|
) {
|
|
|
}
|
|
|
|
|
|
@@ -91,18 +105,20 @@ readonly class ShopService
|
|
|
*/
|
|
|
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();
|
|
|
-
|
|
|
- // 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');
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -132,14 +148,16 @@ readonly class ShopService
|
|
|
protected function sendRequestValidationLink(ShopRequest $shopRequest): void
|
|
|
{
|
|
|
$validationUrl = UrlBuilder::concat(
|
|
|
- $this->baseUrl,
|
|
|
- ['shop/validate', $shopRequest->getToken()]
|
|
|
+ $this->publicBaseUrl,
|
|
|
+ ['/api/public/shop/validate', $shopRequest->getToken()]
|
|
|
);
|
|
|
|
|
|
$data = $shopRequest->getData();
|
|
|
|
|
|
- $model = new NewStructureTrialRequestValidationModel();
|
|
|
- $model->setToken($shopRequest->getToken())
|
|
|
+ $model = new NewStructureArtistPremiumTrialRequestValidationModel();
|
|
|
+ $model
|
|
|
+ ->setSenderId(AccessIdsEnum::ADMIN_2IOPENSERVICE->value)
|
|
|
+ ->setToken($shopRequest->getToken())
|
|
|
->setRepresentativeEmail($data['representativeEmail'] ?? '')
|
|
|
->setRepresentativeFirstName($data['representativeFirstName'] ?? '')
|
|
|
->setRepresentativeLastName($data['representativeLastName'] ?? '')
|
|
|
@@ -159,44 +177,133 @@ readonly class ShopService
|
|
|
* @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
|
|
|
+ * @throws Exception
|
|
|
+ * @throws JsonException
|
|
|
*/
|
|
|
- public function startArtistPremiumTrial(Organization $organization, NewStructureArtistPremiumTrialRequest $request): bool
|
|
|
+ public function startArtistPremiumTrial(Organization $organization, NewStructureArtistPremiumTrialRequest $request): void
|
|
|
{
|
|
|
- // 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;
|
|
|
+ // Update settings
|
|
|
+ $settings = $organization->getSettings();
|
|
|
+ $settings->setProductBeforeTrial( $organization->getSettings()->getProduct());
|
|
|
+ $settings->setTrialActive(true);
|
|
|
+ $settings->setLastTrialStartDate(new \DateTime('now'));
|
|
|
+ $settings->setProduct(SettingsProductEnum::ARTIST_PREMIUM);
|
|
|
+ $this->entityManager->persist($settings);
|
|
|
+ $this->entityManager->flush();
|
|
|
+
|
|
|
+ $dolibarrSocietyId = $this->dolibarrApiService->getSocietyId($organization->getId());
|
|
|
+
|
|
|
+ // Create contract in dolibarr
|
|
|
+ $dolibarrProductId = $this->dolibarrUtils->getProductId(
|
|
|
+ SettingsProductEnum::ARTIST_PREMIUM, true
|
|
|
+ );
|
|
|
+
|
|
|
+ $contractId = $this->dolibarrApiService->createContract(
|
|
|
+ $dolibarrSocietyId, $dolibarrProductId, true, 1
|
|
|
+ );
|
|
|
+
|
|
|
+ $this->dolibarrApiService->createContractLine($contractId, $dolibarrProductId, 1);
|
|
|
+
|
|
|
+ // Maj le représentant commercial dans dolibarr
|
|
|
+ $this->dolibarrUtils->updateSocietyCommercialsWithApi($dolibarrSocietyId);
|
|
|
+
|
|
|
+ // Met à jour le produit dans Dolibarr
|
|
|
+ $productName = $this->dolibarrUtils->getDolibarrProductName(SettingsProductEnum::ARTIST_PREMIUM, true);
|
|
|
+ $this->dolibarrApiService->updateSocietyProduct($dolibarrSocietyId, $productName);
|
|
|
+
|
|
|
+ // Ajoute une entrée aux actions commerciales dolibarr
|
|
|
+ $message = sprintf(
|
|
|
+ "Action réalisé par : %s %s.<br>Fonction : %s<br>Mail:%s<br>Tel:%s",
|
|
|
+ $request->getRepresentativeFirstName(),
|
|
|
+ $request->getRepresentativeLastName(),
|
|
|
+ $request->getRepresentativeFunction(),
|
|
|
+ $request->getRepresentativeEmail(),
|
|
|
+ $request->getRepresentativePhone()
|
|
|
+ );
|
|
|
+
|
|
|
+ $this->dolibarrUtils->addActionComm(
|
|
|
+ $dolibarrSocietyId, "Ouverture de la période d’essai", $message
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ protected 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);
|
|
|
+
|
|
|
+ // Start the artist premium trial
|
|
|
+ $this->startArtistPremiumTrial($organization, $trialRequest);
|
|
|
+
|
|
|
+ $this->logger->info('Successfully processed NewStructureArtistPremiumTrial for token: ' . $token);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected function createOrganization(NewStructureArtistPremiumTrialRequest $trialRequest): Organization
|
|
|
+ {
|
|
|
+ // Generate an OrganizationCreationRequest object
|
|
|
+ $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());
|
|
|
+
|
|
|
+ // TODO: à améliorer
|
|
|
+ $organizationCreationRequest->setPhoneNumber(
|
|
|
+ '+33' . substr($trialRequest->getRepresentativePhone(), 1)
|
|
|
+ );
|
|
|
+
|
|
|
+ // Generate a subdomain from the structure name
|
|
|
+ // TODO: à améliorer
|
|
|
+ $subdomain = $this->generateSubdomain($trialRequest->getStructureName());
|
|
|
+ $organizationCreationRequest->setSubdomain($subdomain);
|
|
|
+
|
|
|
+ // Set default values
|
|
|
+ $organizationCreationRequest->setProduct(SettingsProductEnum::FREEMIUM);
|
|
|
+ $organizationCreationRequest->setCreateWebsite(false);
|
|
|
+ $organizationCreationRequest->setClient(false);
|
|
|
+ $organizationCreationRequest->setCreationDate(new \DateTime());
|
|
|
+
|
|
|
+ // Create the organization
|
|
|
+ return $this->organizationFactory->create($organizationCreationRequest);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Generate a subdomain from a structure name.
|
|
|
+ */
|
|
|
+ private function generateSubdomain(string $name): string
|
|
|
+ {
|
|
|
+ // Remove accents and special characters
|
|
|
+ $subdomain = iconv('UTF-8', 'ASCII//TRANSLIT', $name);
|
|
|
+ // Replace spaces and special characters with hyphens
|
|
|
+ $subdomain = preg_replace('/[^a-zA-Z0-9]/', '-', $subdomain);
|
|
|
+ // Convert to lowercase
|
|
|
+ $subdomain = strtolower($subdomain);
|
|
|
+ // Remove consecutive hyphens
|
|
|
+ $subdomain = preg_replace('/-+/', '-', $subdomain);
|
|
|
+ // Trim hyphens from beginning and end
|
|
|
+ $subdomain = trim($subdomain, '-');
|
|
|
+ // Limit length
|
|
|
+ $subdomain = substr($subdomain, 0, 30);
|
|
|
+
|
|
|
+ return $subdomain;
|
|
|
}
|
|
|
}
|