Files
2025-08-02 16:30:27 +02:00

373 lines
14 KiB
PHP

<?php
declare(strict_types=1);
namespace External\HannahBundle\Controller;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use External\HannahBundle\Email\OCPartnerRegistrationEmail;
use External\HannahBundle\Email\OCProfiPartnerRegistrationEmail;
use External\HannahBundle\Email\OCRegistrationEmail;
use External\HannahBundle\Email\OCSellerRegistrationEmail;
use External\HannahBundle\SAP\Exception\SAPException;
use External\HannahBundle\SAP\Synchronizer\UserSynchronizer;
use External\HannahBundle\SAP\Util\SAPClient;
use External\HannahBundle\Util\Product\ProductRelatedVariationsUtil;
use External\HannahBundle\Util\User\UserCardGenerator;
use KupShop\AdminBundle\Util\LegacyAdminCredentials;
use KupShop\ContentBundle\View\Exception\ValidationException;
use KupShop\KupShopBundle\Context\ContextManager;
use KupShop\KupShopBundle\Context\DomainContext;
use KupShop\KupShopBundle\Context\LanguageContext;
use KupShop\KupShopBundle\Context\UserContext;
use KupShop\KupShopBundle\Exception\RedirectException;
use KupShop\KupShopBundle\Util\Database\QueryHint;
use KupShop\KupShopBundle\Util\Mail\EmailCheck;
use KupShop\KupShopBundle\Views\View;
use KupShop\SellerBundle\Utils\SellerUtil;
use Query\Operator;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\MapQueryParameter;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Contracts\Service\Attribute\Required;
class OCController extends AbstractController
{
#[Required]
public ContextManager $contextManager;
#[Required]
public SellerUtil $sellerUtil;
#[Required]
public OCSellerRegistrationEmail $sellerRegistrationEmail;
#[Required]
public OCPartnerRegistrationEmail $partnerRegistrationEmail;
#[Required]
public OCProfiPartnerRegistrationEmail $profiPartnerRegistrationEmail;
#[Required]
public EmailCheck $emailCheck;
#[Required]
public SAPClient $sapClient;
#[Required]
public UserCardGenerator $userCardGenerator;
#[Route('/_oc/product-collection/{productId}/related-variation-ids/{variationId}/', requirements: ['productId' => '\d+', 'variationId' => '\d+'])]
public function getProductCollectionsRelatedVariationIds(ProductRelatedVariationsUtil $productRelatedVariationsUtil, int $productId, int $variationId): JsonResponse
{
$product = new \Product();
$product->createFromDB($productId);
$productRelatedVariationsUtil->fetchForProduct($product, $variationId);
$result = [];
foreach ($product->fetchCollections() as $item) {
if (empty($item)) {
continue;
}
$result[$item->id] = $item->relatedVariationId ?? null;
}
return new JsonResponse(array_filter($result));
}
/**
* Registrace uzivatele na prodejne.
*/
#[Route('/registrace-na-prodejne/{token}/{sellerId}/', requirements: ['sellerId' => '\d+'])]
#[Route('/registrace-na-prodejne/{token}/')]
public function sellerRegistration(Request $request, LegacyAdminCredentials $credentials, UserSynchronizer $userSynchronizer, string $token, ?int $sellerId = null): Response
{
if (!$credentials->loginByHash($token)) {
throw new NotFoundHttpException('Token is not valid');
}
if ($request->isMethod('POST') && $request->get('Submit')) {
try {
if ([$user, $cardNumber] = $this->handleSellerRegistration($request)) {
addUserMessage('Uživatel byl úspěšně zaregistrován.', 'success');
// zkusim uzivatele rovnou zapsat do SAPu, aby na pokladne nemuseli cekat
try {
QueryHint::withRouteToMaster(fn () => $userSynchronizer->updateUserToSAP(['id' => $user->id, 'id_sap' => null]));
addUserMessage('Uživatel byl úspěšně zapsán do SAPu.', 'success');
} catch (\Throwable $e) {
}
}
throw new RedirectException(
path('external_hannah_oc_sellerregistration', [
'token' => $token,
'sellerId' => $request->get('seller'),
'success' => 1,
'userId' => $user->id,
'cardNumber' => $cardNumber,
])
);
} catch (ValidationException $e) {
addUserMessage($e->getMessage());
}
}
$view = new class extends View {
protected $template = 'seller/seller.registration.tpl';
public function getTitle()
{
return 'Registrace na prodejně';
}
};
return $view
->addBodyVariables([
'token' => $token,
'invoice' => $request->get('invoice', []),
'delivery' => $request->get('delivery', []),
'sellerId' => $sellerId ?: $request->get('seller'),
'card_number' => $request->get('customer_card')['number'] ?? '',
])
->getResponse();
}
/**
* Registrace partnera, viz. #15748.
*/
#[Route('/registrace-partnera/')]
public function partnerRegistration(Request $request, LegacyAdminCredentials $legacyAdminCredentials, UserSynchronizer $userSynchronizer, View $view): Response
{
// musi byz prihlaseny jako admin, aby byla URL pristupna
if (!$legacyAdminCredentials->isLogged()) {
return new RedirectResponse(
path('kupshop_admin_admin_index', ['url' => $request->getPathInfo()])
);
}
if ($request->isMethod('POST') && $request->get('Submit')) {
try {
if ([$user, $cardNumber] = $this->handlePartnerRegistration($request)) {
addUserMessage('Uživatel byl úspěšně zaregistrován.', 'success');
// zkusim uzivatele rovnou zapsat do SAPu, aby na pokladne nemuseli cekat
try {
QueryHint::withRouteToMaster(fn () => $userSynchronizer->updateUserToSAP(['id' => $user->id, 'id_sap' => null]));
addUserMessage('Uživatel byl úspěšně zapsán do SAPu.', 'success');
} catch (\Throwable $e) {
}
}
throw new RedirectException(
path('external_hannah_oc_partnerregistration', [
'success' => 1,
'userId' => $user->id,
'cardNumber' => $cardNumber,
])
);
} catch (ValidationException $e) {
addUserMessage($e->getMessage());
}
}
return $view
->setTemplate('oc/oc.partner-registration.tpl')
->addBodyVariables([
'invoice' => $request->get('invoice', []),
'delivery' => $request->get('delivery', []),
'generate' => $request->get('customer_card')['generate'] ?? '',
'card_number' => $request->get('customer_card')['number'] ?? '',
])
->getResponse();
}
#[Route('/uzivatel/{userId}/zakaznicka-karta/', requirements: ['userId' => '\d+'])]
public function userCardPDF(UserCardGenerator $userCardGenerator, int $userId, #[MapQueryParameter] $cardNumber = null): Response
{
if (!($pdf = $userCardGenerator->generateUserCardPDF($userId, $cardNumber))) {
throw new NotFoundHttpException();
}
return new Response($pdf, headers: ['Content-Type' => 'application/pdf']);
}
private function handlePartnerRegistration(Request $request): array
{
[$user, $userCardNumber] = $this->handleRegistration($request, null);
$email = match ($request->get('customer_card')['generate'] ?? null) {
'9997' => $this->profiPartnerRegistrationEmail,
'9996' => $this->partnerRegistrationEmail,
default => null,
};
if ($email) {
$this->sendRegistrationEmail($email, $user);
}
return [$user, $userCardNumber];
}
/**
* Registrace uzivatele na prodejne.
*/
private function handleSellerRegistration(Request $request): array
{
if (!($sellerId = $request->get('seller'))) {
throw new ValidationException('Není vybrána prodejna!');
}
[$user, $userCardNumber] = $this->handleRegistration($request);
// nastavim uzivateli skupinu podle prodejny
$this->setUserGroupBySellerId((int) $user->id, (int) $sellerId);
// odeslu uzivateli email s nastavenim hesla
$this->sendRegistrationEmail(
$this->sellerRegistrationEmail,
$user
);
return [$user, $userCardNumber];
}
/**
* Vytvoreni uzivatele.
*/
private function handleRegistration(Request $request, ?int $cardEanFourthPositionDigit = UserCardGenerator::EAN_FOURTH_POSITION_DIGIT): array
{
$user = new \User();
// nactu si data
$invoice = $request->get('invoice');
$delivery = $request->get('delivery');
$customerCard = $request->get('customer_card');
// pokud se jedna o elektronickou kartu, tak ji chceme vygenerovat
if (($customerCard['type'] ?? null) === 'electronic') {
$prefixes = explode(',', $customerCard['generate'] ?? '');
$customerCardNumber = $this->userCardGenerator->generateCustomerCardEAN(
(string) $prefixes[array_rand($prefixes)],
$cardEanFourthPositionDigit
);
} else {
$customerCardNumber = $customerCard['number'] ?? null;
}
$customData = [];
if ($customerCardNumber) {
$customData = [
'sap' => [
'cards' => [$customerCardNumber],
],
];
}
foreach ($customData as $key => $value) {
$user->setCustomData($key, $value);
}
// zvaliduju email
if (!$this->emailCheck->isEmailDomainValid($invoice['email'])) {
throw new ValidationException('Zadaný e-mail není validní!');
}
try {
$result = $this->sapClient->customerValidate($invoice['email'], '');
if (!empty($result->CustomerData->CustomerId)) {
throw new ValidationException('Uživatel se zadaným e-mailem už existuje!');
}
} catch (SAPException $e) {
}
// ignorujeme chyby
try {
$user->updateAddresses($invoice, $delivery);
} catch (ValidationException $e) {
}
try {
// zkusim vytvorit uzivatele
$userId = $this->contextManager->activateContexts([UserContext::class => ContextManager::FORCE_EMPTY], function () use ($user) {
return sqlGetConnection()->transactional(function () use ($user) {
return $user->update();
});
});
} catch (UniqueConstraintViolationException $e) {
throw new ValidationException('Uživatel se zadaným e-mailem už existuje!');
}
if (!$userId) {
throw new ValidationException('Uživatele se nepodařilo vytvořit.');
}
// nactu si uzivatele
$user = sqlGetConnection()->transactional(function () use ($userId) {
return \User::createFromId($userId);
});
return [$user, $customerCardNumber];
}
private function sendRegistrationEmail(OCRegistrationEmail $email, \User $user): void
{
$message = $this->contextManager->activateContexts(
[
LanguageContext::class => $user->id_language ?? null,
DomainContext::class => $this->contextManager->getDomainFromLanguage($user->id_language ?? null),
],
function () use ($email, $user) {
$email->setUser($user);
return $email->getEmail();
}
);
$message['to'] = $user['email'];
$email->sendEmail($message);
}
private function setUserGroupBySellerId(int $userId, int $sellerId): void
{
if (!($seller = $this->sellerUtil->getSeller($sellerId))) {
return;
}
$userGroupId = sqlQueryBuilder()
->select('id')
->from('users_groups')
->where(Operator::equals(['descr' => $sellerId]))
->execute()->fetchOne();
if (!$userGroupId) {
$userGroupId = sqlGetConnection()->transactional(function () use ($seller) {
sqlQueryBuilder()
->insert('users_groups')
->directValues(
[
'name' => 'Prodejna: '.$seller['title'],
'descr' => $seller['id'],
]
)->execute();
return (int) sqlInsertId();
});
}
sqlQueryBuilder()
->insert('users_groups_relations')
->directValues(
[
'id_user' => $userId,
'id_group' => $userGroupId,
]
)->execute();
}
}