<?php
namespace App\Controller\Front;
use App\Adapter\ProductAdapter;
use App\Constants\Setting as SettingConst;
use App\Entity\CustomerProduct;
use App\Entity\CustomProduct;
use App\Entity\CustomProductField;
use App\Entity\CustomProductOrder;
use App\Entity\CustomProductType;
use App\Entity\RequestProductAvailable;
use App\Entity\ServicePro;
use App\Entity\ServiceProField;
use App\Entity\ServiceUser;
use App\Entity\User;
use App\Exception\CatalogueException;
use App\Exception\PurchaseDeclarationException;
use App\Services\Common\ModuleSettingService;
use App\Services\Common\Point\UserPointService;
use App\Form\Type\AddToCartType;
use App\Model\Product;
use App\Model\ProductDeclination;
use App\Services\Common\AclServiceV2;
use App\Services\Common\MailerService;
use App\Services\Common\PlatformService;
use App\Services\Common\Point\TransactionService;
use App\Services\Common\Point\UserPointServiceInterface;
use App\Services\Common\SettingStatusService;
use App\Services\Common\StockService;
use App\Services\Common\Translation\CatalogueTranslation;
use App\Services\Common\Translation\TranslationBase;
use App\Services\Common\UserService;
use App\Services\CommonServices;
use App\Services\DTV\YamlConfig\YamlReader;
use App\Services\Front\CartService;
use App\Services\Front\Catalogue\CatalogueService;
use App\Services\Front\Catalogue\ElasticSearchCatalogueService;
use App\Services\Front\Catalogue\JsonCatalogueService;
use App\Services\Old\CatalogSearch;
use App\Services\Old\PriceManager;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use JMS\Serializer\SerializationContext;
use JMS\Serializer\SerializerInterface;
use JsonException;
use SlopeIt\BreadcrumbBundle\Annotation\Breadcrumb;
use SlopeIt\BreadcrumbBundle\Service\BreadcrumbBuilder;
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\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\Translation\TranslatorInterface;
use Throwable;
/**
* @Breadcrumb({"label" = "Accueil", "route" = "front_homepage" })
*/
class CatalogueController extends AbstractController
{
public const WARNINGCBPAYMENTREQUIRED = 4;
public const LABEL_CATALOGUE = [
'pub' => 'Objets pub',
'service' => 'Service pro',
'services' => 'Services pro',
'shopping' => 'Shopping',
'evasion' => 'evasion',
'paniers_garnis' => 'Paniers garnis',
'cheques_cadeaux' => 'Chèques cadeaux',
];
private RequestStack $requestStack;
private CatalogSearch $catalogSearch;
private PriceManager $priceManager;
private EntityManagerInterface $em;
private PlatformService $platformService;
private MailerService $mailerService;
private CartService $cartService;
private YamlReader $yamlReader;
private JsonCatalogueService $jsonCatalogueService;
private ElasticSearchCatalogueService $elasticSearchCatalogueService;
private CommonServices $commonServices;
private ProductAdapter $productAdapter;
private SerializerInterface $serializer;
private UserPointServiceInterface $userPointService;
private TranslationBase $translationBase;
private CatalogueTranslation $catalogueTranslation;
private TranslatorInterface $translator;
private CatalogueService $catalogueService;
private BreadcrumbBuilder $breadcrumbBuilder;
private StockService $stockService;
private AclServiceV2 $aclService;
private SettingStatusService $settingStatusService;
private TransactionService $transactionService;
private ModuleSettingService $moduleSettingService;
private UserService $userService;
/**
* @param RequestStack $requestStack
* @param CatalogSearch $catalogSearch
* @param PriceManager $priceManager
* @param EntityManagerInterface $em
* @param PlatformService $platformService
* @param CartService $cartService
* @param YamlReader $yamlReader
* @param JsonCatalogueService $jsonCatalogueService
* @param ElasticSearchCatalogueService $elasticSearchCatalogueService
* @param MailerService $mailerService
* @param ProductAdapter $productAdapter
* @param CommonServices $commonServices
* @param SerializerInterface $serializer
* @param UserPointService $userPointService
* @param TranslationBase $translationBase
* @param CatalogueTranslation $catalogueTranslation
* @param TranslatorInterface $translator
* @param CatalogueService $catalogueService
* @param BreadcrumbBuilder $breadcrumbBuilder
* @param StockService $stockService
* @param AclServiceV2 $aclService
* @param SettingStatusService $settingStatusService
* @param TransactionService $transactionService
* @param ModuleSettingService $moduleSettingService
* @param UserService $userService
*
* @throws Exception
*/
public function __construct(
RequestStack $requestStack,
CatalogSearch $catalogSearch,
PriceManager $priceManager,
EntityManagerInterface $em,
PlatformService $platformService,
CartService $cartService,
YamlReader $yamlReader,
JsonCatalogueService $jsonCatalogueService,
ElasticSearchCatalogueService $elasticSearchCatalogueService,
MailerService $mailerService,
ProductAdapter $productAdapter,
CommonServices $commonServices,
SerializerInterface $serializer,
UserPointService $userPointService,
TranslationBase $translationBase,
CatalogueTranslation $catalogueTranslation,
TranslatorInterface $translator,
CatalogueService $catalogueService,
BreadcrumbBuilder $breadcrumbBuilder,
StockService $stockService,
AclServiceV2 $aclService,
SettingStatusService $settingStatusService,
TransactionService $transactionService,
ModuleSettingService $moduleSettingService,
UserService $userService
) {
$this->cartService = $cartService;
$this->yamlReader = $yamlReader;
$this->jsonCatalogueService = $jsonCatalogueService;
$this->elasticSearchCatalogueService = $elasticSearchCatalogueService;
$this->requestStack = $requestStack;
$this->catalogSearch = $catalogSearch;
$this->priceManager = $priceManager;
$this->em = $em;
$this->platformService = $platformService;
$this->mailerService = $mailerService;
$this->productAdapter = $productAdapter;
$this->commonServices = $commonServices;
$this->serializer = $serializer;
$this->userPointService = $userPointService;
$this->translationBase = $translationBase;
$this->catalogueTranslation = $catalogueTranslation;
$this->translator = $translator;
$this->catalogueService = $catalogueService;
$this->breadcrumbBuilder = $breadcrumbBuilder;
$this->stockService = $stockService;
$this->aclService = $aclService;
$this->settingStatusService = $settingStatusService;
$this->transactionService = $transactionService;
$this->moduleSettingService = $moduleSettingService;
$this->userService = $userService;}
/**
* Page du catalogue
*
* @param Request $request
*
* @return Response
*
* @throws CatalogueException
* @throws JsonException
*/
public function show(Request $request): Response
{
$global = $this->yamlReader->getGlobal();
// Hack de redirection des services pros à partir de la version 1.4.0
if (
$this->platformService->versionIsGreaterOrEqualThan('1.4.0') &&
in_array($request->get('catalogue'), [
'service',
'services',
'services-pro',
])
) {
foreach($global[ 'shop' ][ 'catalogues' ] as $catalog) {
if($catalog['slug'] === 'service'){
$label = $catalog['label'];
}
}
return new RedirectResponse(
$this->generateUrl('front_catalogue_service_pros', [
'label' => $this->commonServices->toURL($label),
]),
);
}
// fin de hack
$catalogueType = $this->catalogueService->getCatalogueSlugIfNotExists($request->get('catalogue'));
$session = $this->requestStack->getSession();
$session->set('last-catalogue', $catalogueType);
// on regarde si le user à le droit de regarder le catalogue
if (!$this->aclService->userIsGrantedCatalogue($this->getUser(), $catalogueType, TRUE)) {
throw $this->createAccessDeniedException('Vous ne disposez pas des droits suffisants pour voir ce catalogue');
}
$catalogues = $this->yamlReader->getShop()[ "catalogues" ] ?? [];
$catalogue = array_filter($catalogues, static function ($catalogue) use ($catalogueType) {
return $catalogue[ 'slug' ] === $catalogueType;
}) ?? [];
$catalogue = array_shift($catalogue);
if (isset($catalogue[ 'types' ]) && in_array('customer', $catalogue[ 'types' ], TRUE)) {
/** @var User $user */
$user = $this->getUser();
$pointConfig = $this->yamlReader->getPoint();
$displayConfig = $pointConfig->getDisplayByUser($user);
$catalogueName = $catalogue[ 'label' ];
$displayConfig = [
'display_config' => [
'round_price' => $this->settingStatusService->isSettingStatusEnabled(SettingConst::POINT_ENABLED),
// On arrondit les prix si les points sont activés
'symbol' => $displayConfig->getSymbol(),
'label' => $displayConfig->getLabel(),
'multiplication' => $displayConfig->getMultiplication(),
]
];
$customerProducts = array_merge(
$this->em->getRepository(CustomerProduct::class)->getAllEnabledJson(false),
$displayConfig
);
$params = [
'parameters' => [],
'availablestock' => FALSE,
'customerProducts' => json_encode($customerProducts),
];
} else {
$this->catalogSearch->setParameters($request);
$catalogueName = $this->catalogueService->getCatalogueName($catalogueType);
$params = [
'parameters' => $this->catalogSearch->getParameters(),
'availablestock' => $this->getParameter("display_available_stock"),
'customerProducts' => NULL,
];
}
$params[ 'catalogue' ] = $catalogueName;
$params[ 'catalogueSlug' ] = $catalogueType;
$this->breadcrumbBuilder->addItem($catalogueName);
return $this->render('front/catalogue/index.html.twig', $params);
}
/**
* @param $label
*
* @return Response
* @deprecated
*/
public function serviceProList($label): Response
{
$services = $this->em->getRepository(ServicePro::class)->findBy(
[
'status' => TRUE,
],
);
return $this->render('front/catalogue/service-pro.html.twig', [
'label' => $label,
'services' => $services,
]);
}
/**
* @param Request $request
* @param ServicePro $service
*
* @return Response
* @throws Exception
* @deprecated
*/
public function serviceProShow(Request $request, ServicePro $service): Response
{
if (!$service->isStatus()) {
throw $this->createNotFoundException("Cette page n'existe pas (ou plus) !");
}
if (strtolower($request->getMethod()) == 'post') {
$fields = $request->request->get('service');
$quantity = $request->request->get('quantity');
$formatted_fields = [];
if (is_array($fields)) {
foreach ($fields as $key => $value) {
$index = str_replace('field_', '', $key);
$field = $this->em->getRepository(ServiceProField::class)->find($index);
if (!empty($field)) {
$formatted_fields[] = [
'label' => $field->getLabel(),
'value' => $value,
];
} else {
$formatted_fields[] = [
'label' => $key,
'value' => $value,
];
}
}
}
/** @var User $currentUser */
$currentUser = $this->getUser();
$mailConfig = $this->platformService->getMailerConfig();
$email = $this->renderView('front/catalogue/service-pro-email.html.twig', [
'service' => $service,
'fields' => $formatted_fields,
'user' => $currentUser,
'header' => $mailConfig[ 'template' ][ 'header' ],
'project' => $this->platformService->getDomain(),
'footer' => $mailConfig[ 'template' ][ 'footer' ],
'quantity' => $quantity,
]);
$content = [
'service' => [
'title' => $service->getTitle(),
'description' => $service->getDescription(),
'value' => $service->getValue(),
'contacts' => $service->getContactEmails(),
],
'user' => [
'id' => $currentUser->getId(),
'firstName' => $currentUser->getFirstName(),
'lastName' => $currentUser->getLastName(),
'email' => $currentUser->getEmail(),
],
];
$content = array_merge($content, ['formatted_fields' => $formatted_fields]);
$serviceUser = (new ServiceUser())
->setUser($currentUser)
->setQuantity($quantity)
->setContent(json_encode($content))
->setTitle($service->getTitle())
->setDescription($service->getDescription() ?? ' ')
->setImage($service->getImage() ?? ' ')
->setStatus(0)
->setCreatedAt(new DateTime())
;
$this->em->persist($serviceUser);
$this->em->flush();
$to = $service->getContactEmails();
$subject = 'Une commande de services pros a été passée';
$this->mailerService->sendMailRaw('from', $to, $subject, $email);
$this->addFlash('success', 'Votre commande a été enregistrée avec succès !');
return $this->redirectToRoute('front_user_order');
}
return $this->render('front/catalogue/service-pro-show.html.twig', [
'service' => $service,
]);
}
/**
* Liste des produits personnalisés
*
*
* @param string $slug
*
* @return Response
*/
public function customProductList(string $slug): Response
{
$products = $this->em->getRepository(CustomProduct::class)->findByEnabledTypeStockNullOrSuppZero($slug);
$rate = $this->yamlReader->getGlobal()[ 'price' ][ 'rate' ] ?? 1;
$type = $this->em->getRepository(CustomProductType::class)->findOneBy(['slug' => $slug]);
return $this->render('front/catalogue/custom-product-list.html.twig', [
'slug' => $slug,
'type' => $type,
'products' => $products,
'rate' => $rate,
]);
}
/**
* Focus sur un produit personnalisé
*
*
* @param Request $request
* @param string $slug
* @param CustomProduct $product
*
* @return Response
* @throws Exception
*/
public function customProductShow(Request $request, string $slug, CustomProduct $product): Response
{
$pointConfig = $this->yamlReader->getPoint();
if (!$product->isEnabled()) {
throw $this->createNotFoundException("Cette page n'existe pas (ou plus) !");
}
if ($product->getSku()) {
$catalogueType = 'catalogue-v2';
$productObject = $this->jsonCatalogueService->getProductBySkuFromCatalogue($product->getSku(), $catalogueType);
return $this->productFocus($request, $productObject->getSku(), $catalogueType);
}
if (strtolower($request->getMethod()) === 'post') {
$catalogueSlugs = [];
$totalProductPrice = [];
$fields = $request->request->get('product');
$quantity = $request->request->get('quantity');
$catalogueTypes = $this->em->getRepository(CustomProductType::class)->findAll();
$availablePoints = $this->userPointService->getAvailablePoints($this->getUser(), NULL, TRUE);
if ($this->moduleSettingService->isModuleActive('quotas_orders_products')) {
// check tous les quotas produits/commandes
$canBuy = $this->userService->checkQuotasProductOrder($this->getUser(), $product, $product->getType()->getSlug(), $quantity);
if(!$canBuy['valide']) {
$this->addFlash('danger', $canBuy['message']);
return $this->redirectToRoute('front_catalogue_custom_product_show', [
'slug' => $slug,
'product' => $product->getId(),
]);
}
}
if($pointConfig->getPointCategory()) {
$categoryValues = $product->getArrayCategoryValues();
foreach ($categoryValues as $catSlug => $categoryValue) {
$totalProductPrice[$catSlug] = $categoryValue * (int) $quantity;
}
try {
$this->cartService->checkRemainingPointWithProduct($availablePoints, $totalProductPrice);
}catch (\Exception $e){
$this->addFlash('danger', $e->getMessage());
return $this->redirectToRoute('front_catalogue_custom_product_show', [
'slug' => $slug,
'product' => $product->getId(),
]);
}
}else{
// check point valable pour l'utilisateur
if($availablePoints < $quantity * $product->getValue()){
$this->addFlash('danger', "Vous n'avez pas assez de points pour commander ce produit !");
return $this->redirectToRoute('front_catalogue_custom_product_show', [
'slug' => $slug,
'product' => $product->getId(),
]);
}
}
// check stock produit
if($product->getStock() && ($quantity > $product->getStock())){
$this->addFlash('danger', "La quantité demandée est supérieur au stock actuel !");
return $this->redirectToRoute('front_catalogue_custom_product_show', [
'slug' => $slug,
'product' => $product->getId(),
]);
}
foreach ($catalogueTypes as $catalogueType){
$catalogueSlugs[] = $catalogueType->getSlug();
}
$domain = $this->yamlReader->getGlobal()[ 'subdomain' ];
$files = $request->files->get('product') ?? [];
$uploadDir = $this->getParameter('kernel.project_dir') . '/medias/' . $domain;
$fileNames = [];
// enregistrement fichier si champs "file" dans le formulaire
foreach ($files as $key => $file) {
if($file){
$clientOriginalName = str_replace('.' . $file->guessExtension(), '', $file->getClientOriginalName());
$newFilename = $clientOriginalName . '_' . md5(uniqid()) . '.' . $file->guessExtension();
$file->move(
$uploadDir,
$newFilename,
);
$fileNames[$key] = $newFilename;
}
}
$fields = array_merge($fields,$fileNames);
// enregistrement des champs du formulaire en json dans la commande
$formatted_fields = [];
if (is_array($fields)) {
foreach ($fields as $key => $value) {
$index = str_replace('field_', '', $key);
if (in_array($slug, $catalogueSlugs, TRUE)) {
$field = $this->em->getRepository(CustomProductField::class)->find($index);
} else {
$field = $this->em->getRepository(ServiceProField::class)->find($index);
}
if (!empty($field)) {
if($field instanceof CustomProductField){
$formatted_fields[] = [
'label' => $field->getLabel(),
'value' => $value,
'type' => $field->getType(),
'position' => $field->getPosition(),
'required' => $field->isRequired(),
];
}else{
$formatted_fields[] = [
'label' => $key,
'value' => $value,
];
}
} else {
$formatted_fields[] = [
'label' => $key,
'value' => $value,
];
}
}
}
/** @var User $currentUser */
$currentUser = $this->getUser();
if($pointConfig->getPointCategory()) {
$totalValue = json_encode($this->cartService->getTotalChosenSpentPointsWithProduct($availablePoints, $totalProductPrice));
}else{
$totalValue = json_encode($product->getValue() * $quantity);
}
// creation de la customProductOrder
$order = (new CustomProductOrder())
->setUser($currentUser)
->setQuantity($quantity)
->setType($product->getType())
->setFormData(json_encode($formatted_fields))
->setValue($totalValue)
->setProduct(
$this->serializer->serialize(
$product,
'json',
SerializationContext::create()
->setGroups(['customProduct:item']),
),
)
;
$this->em->persist($order);
// décrément le stock du produit si stock
if($product->getStock()){
$product->setStock($product->getStock() - $quantity);
}
$this->em->flush();
// creation de la transaction
$this->transactionService->createOrderTransactionWithCustomProduct($order);
// met à jour les points des utilisateurs
$this->userPointService->getPointsOfUser($currentUser, null, true);
$this->addFlash('success', 'Votre commande a été enregistrée avec succès !');
return $this->redirectToRoute('front_user_order');
}
return $this->render('front/catalogue/custom-product-show.html.twig', [
'slug' => $slug,
'product' => $product,
]);
}
/**
* Focus sur un produit
*
*
* @param Request $request
* @param string $sku
* @param string $catalogueType
*
* @return Response
*
* @throws Exception
*/
public function productFocus(Request $request, string $sku, string $catalogueType): Response
{
/** @var User $user */
$user = $this->getUser();
$displayIfNoStock = false;
// Modification des catalogues depuis la version 1.4.0 : pub.json devient obj_pub.json
if ($catalogueType === 'pub') $catalogueType = 'obj_pub';
// Fin de modification
$catalogueType = $this->catalogueService->getCatalogueSlugIfNotExists($catalogueType);
$catalogueConfig = $this->catalogueService->getCatalogueConfigByType($catalogueType);
if(isset($catalogueConfig["displayIfNoStock"])) {
$displayIfNoStock = $catalogueConfig["displayIfNoStock"];
}
$file = $this->getParameter('kernel.project_dir') . '/data/catalogue/' . $this->platformService->getDomain() . '/' . $catalogueType . '.json';
if (!file_exists($file)) {
return new Response("Le catalogue $catalogueType n'existe pas.", 404);
}
$content = file_get_contents($file);
$parsedJson = json_decode($content, TRUE);
$searchSku = $sku;
$searchProduct = array_filter($parsedJson[ 'products' ], function ($element) use ($searchSku) {
return isset($element[ 'sku' ]) && $element[ 'sku' ] === $searchSku;
});
$product = reset($searchProduct);
if (($product[ 'sku' ] ?? 'not found') != $sku) {
return new Response("L'article ($sku) n'a pas été trouvé.", 404);
}
$productFocus = $this->productAdapter->getProduct($product);
if ($this->translationBase->translationIsEnabled()) {
$locale = $this->translationBase->getLanguageFromCurrentUser();
$productFocus = $this->catalogueTranslation->getTranslatedProduct($productFocus, $locale, $catalogueType);
}
$form = $this->createForm(AddToCartType::class, NULL, [
'exploded' => FALSE,
'quantity' => 1,
'product' => $productFocus,
'catalogueType' => $request->attributes->get('catalogueType'),
]);
$declinations = [];
/** @var ProductDeclination $declination */
foreach ($productFocus->getDeclinations() as $declination) {
$declinations[] = $declination->getName();
}
// Breadcrumb pour le catalogue correspondant
$catalogues = $this->yamlReader->getShop()[ "catalogues" ] ?? [];
$catalogue = array_filter($catalogues, static function ($catalogue) use ($catalogueType) {
return $catalogue[ 'slug' ] === $catalogueType;
});
$catalogue = reset($catalogue);
$this->breadcrumbBuilder->addItem($catalogue[ 'label' ], 'front_catalogue_homepage', ["catalogue" => $catalogueType]);
$this->breadcrumbBuilder->addItem($productFocus->getName());
$message = $this->cartService->userCanOrderVerbose($user);
$catalogOrderActive = $this->cartService->catalogOrderActive($catalogueType);
return $this->render('front/catalogue/productSheet/show.html.twig', [
"product" => $productFocus,
"form" => $form->createView(),
"declinations" => array_unique($declinations),
"catalogueType" => $catalogueType,
"closeEcommerceMessage" => $message,
'catalogOrderActive' => $catalogOrderActive,
'displayIfNoStock' => $displayIfNoStock
]);
}
/**
* Retourne le catalogue selon le type de catalogue
*
* @param string $catalogueType Type du catalogue (shopping, pub, ...)
*
* @return JsonResponse
*
* @throws Exception
*/
public function getCatalogueByType(string $catalogueType): JsonResponse
{
$catalogueType = $this->catalogueService->getCatalogueSlugIfNotExists($catalogueType);
$catalogueConfig = $this->catalogueService->getCatalogueConfigByType($catalogueType);
$jsonCatalogue = $this->jsonCatalogueService->getCatalogueByType($catalogueType);
$displayIfNoStock = false;
$displayIfPriceZero = false;
if(isset($catalogueConfig["displayIfNoStock"])) {
$displayIfNoStock = $catalogueConfig[ 'displayIfNoStock' ];
}
if(isset($catalogueConfig["displayIfPriceZero"])) {
$displayIfPriceZero = $catalogueConfig[ 'displayIfPriceZero' ];
}
/**
* START : Code pour minimiser le json.
* Sur OpenDream, il dépasse les 20mo et les navigateurs n'étaient plus en capacité de le traiter en js
*/
$json = json_decode($jsonCatalogue, TRUE);
$products = $json[ 'products' ] ?? '';
if(empty($products)) {
$products = [];
}
foreach ($products as $index => &$product)
{
// retire du json les produits qui n'ont pas de stock et qu'ils sont de type obj_pub et status inactif.
if (
!$product[ 'status' ] ||
($product[ 'type' ] === 'obj_pub' && ((int)$product[ 'totalstock' ] === 0 && !$displayIfNoStock)) ||
($product['type'] !== 'obj_pub' && (
!isset($product['level']) ||
!is_array($product['level']) ||
empty($product['level']['id']) ||
empty($product['level']['value'])
) && !$displayIfPriceZero)
) {
array_splice($products, $index, 1);
continue;
}
unset($products[ $index ][ 'description' ]);
unset($products[ $index ][ 'reference' ]);
unset($products[ $index ][ 'accroche' ]);
unset($products[ $index ][ 'status' ]);
unset($products[ $index ][ 'level' ]);
unset($products[ $index ][ 'slug' ]);
unset($products[ $index ][ 'slugs' ]);
unset($products[ $index ][ 'display_if_unavailable' ]);
unset($products[ $index ][ 'is_managed_by_customer' ]);
unset($products[ $index ][ 'campagnes' ]);
unset($products[ $index ][ 'enable_stock_alert' ]);
unset($products[ $index ][ 'stock_alert' ]);
unset($products[ $index ][ 'logistic_weight' ]);
unset($products[ $index ][ 'created_at' ]);
foreach ($products[ $index ][ 'categories' ] as $cat_index => $category) {
unset($products[ $index ][ 'categories' ][ $cat_index ][ 'description' ]);
unset($products[ $index ][ 'categories' ][ $cat_index ][ 'orderItem' ]);
}
unset($products[ $index ][ 'images' ][ 0 ][ 'id' ]);
unset($products[ $index ][ 'images' ][ 1 ]);
unset($products[ $index ][ 'images' ][ 2 ]);
unset($products[ $index ][ 'images' ][ 3 ]);
unset($products[ $index ][ 'images' ][ 4 ]);
unset($products[ $index ][ 'images' ][ 5 ]);
if (isset($product[ 'categories' ])) {
foreach ($product[ 'categories' ] as $cat_index => $category) {
$products[ $index ][ 'categories' ][ $cat_index ][ 'title' ] = $this->translator->trans($category[ 'title' ]);
}
}
}
unset($product);
$json[ 'totalHits' ] = count($products);
$json[ 'products' ] = $products;
$jsonCatalogue = json_encode($json);
/**
* END
*/
$pointConfig = $this->yamlReader->getPoint();
/** @var User $currentUser */
$currentUser = $this->getUser();
$displayConfig = $pointConfig->getDisplayByUser($currentUser);
$response = [
'products' => $jsonCatalogue,
'display_config' => [
'round_price' => $this->settingStatusService->isSettingStatusEnabled(SettingConst::POINT_ENABLED),
// On arrondit les prix si les points sont activés
'symbol' => $displayConfig->getSymbol(),
'label' => $displayConfig->getLabel(),
'multiplication' => $displayConfig->getMultiplication(),
],
];
return new JsonResponse(
$response,
Response::HTTP_OK,
);
}
// /**
// * @param Request $request
// *
// * @return JsonResponse
// *
// * @throws Exception
// */
// public function search( Request $request ): JsonResponse
// {
// $session = $request->getSession();
//
// return $this->elasticSearchCatalogueService->getProducts( $session, $request );
// }
/**
* Focus sur un produit
*
*
* @param Request $request
* @param CustomerProduct $customerProduct
*
* @return Response
*
*/
public function customerProductFocus(Request $request, CustomerProduct $customerProduct): Response
{
$catalogueType = $request->get('catalogueType');
$catalogues = $this->yamlReader->getShop()[ "catalogues" ] ?? [];
$catalogue = array_filter($catalogues, static function ($catalogue) use ($catalogueType) {
return $catalogue[ 'slug' ] === $catalogueType;
}) ?? [];
$catalogue = array_shift($catalogue);
return $this->render('front/catalogue/productSheet/customer-show.html.twig', [
'product' => $customerProduct,
'catalogue' => $catalogue,
]);
}
/**
* Ajoute un produit dans le panier
*
* @param Request $request
*
* @return JsonResponse
*
* @throws Exception
*/
public function addToCart(Request $request): JsonResponse
{
$cart = $this->cartService->load();
$catalogueType = $request->request->get("catalogueType");
$catalogue = $request->request->get("catalogue");
try {
$declinations = $request->request->get("declinations");
if ($declinations && count($declinations) > 0) {
foreach ($declinations as $declination) {
if (isset($declination[ "sku" ])) {
$product = $this->jsonCatalogueService->findProductBySku($declination[ "sku" ]);
$this->cartService->addProduct($cart, $product, $declination[ "quantity" ], $catalogueType);
}
}
} else {
if ($catalogue && isset($catalogue[ 'types' ]) && in_array('customer', $catalogue[ 'types' ], TRUE)) {
$product = $this->em->getRepository(CustomerProduct::class)->findOneBy([
'id' => $request->request->get("id")
]);
$sku = $product->getName();
}else{
$sku = $request->request->get('product');
$product = $this->jsonCatalogueService->findProductBySku($sku);
}
if(!$product)
{
return new JsonResponse(
[
"quantity" => 0,
"error" => 500,
'message' => "Le produit $sku est introuvable",
], Response::HTTP_OK,
);
}
$cart = $this->cartService->addProduct($cart, $product, $request->request->get('quantityTotal'), $catalogueType);
}
}
catch (Exception $e)
{
return new JsonResponse(
[
"quantity" => 0,
"error" => $e->getCode(),
'message' => $e->getMessage(),
], Response::HTTP_OK,
);
}
return new JsonResponse(
[
"quantity" => $cart->totalQuantity(),
"error" => 0,
], Response::HTTP_OK,
);
}
/**
* @param Request $request
*
* @return JsonResponse
*
* @throws Exception|Throwable
*/
public function declinationAjax(Request $request): JsonResponse
{
$idProduct = $request->request->get("product");
$idDeclination = $request->request->get("declination");
$typeDeclination = $request->request->get("type");
$es = $this->catalogSearch;
/** @var Product $product */
$product = $es->find($idProduct);
$declinations = $product->getDeclinations();
//récupère productDeclinationId
$productDeclinationIds = [];
$declinationNextField = [];
$priceManager = $this->priceManager;
if ($idDeclination !== "") {
foreach ($declinations as $declination) {
if ($declination->getId() === $idDeclination) {
$productDeclinationIds[] = $declination->getDeclinationId();
}
}
} else {
foreach ($declinations as $declination) {
$productDeclinationIds[] = $declination->getDeclinationId();
}
}
//vérifie si c'est par lot
$unit = (bool)$product->getCombinationValueByKey("lot_de_x_pieces");
foreach ($declinations as $declination2) {
if ($declination2->getStatus() && in_array(
$declination2->getDeclinationId(),
$productDeclinationIds,
TRUE,
) && $typeDeclination === $this->validFieldName($declination2->getName())) {
$declinationNextField[ $declination2->getId() ] =
[
"id" => $declination2->getId(),
"name" => $declination2->getName(),
"value" => ucfirst(
$this->get("translator")
->trans(
$declination2->getValue(),
[],
"declinations",
),
),
"sku" => $declination2->getSku(),
"enableStock" => $product->getEnableStockAlert(),
"displayStock" => $this->getParameter('display_available_stock'),
"stock" => $declination2->getStock(),
"price" => $declination2->getPrice(),
"priceHtml" => $priceManager->setProduct($declination2->getProduct())
->getTransformPriceValuetoHtml(
$declination2->getPrice(),
[
"unit" => $unit,
"display" => TRUE,
],
),
"priceHtmlbatchof" => $priceManager->setProduct($declination2->getProduct())
->getTransformPriceValuetoHtml(
$declination2->getPrice(),
[
"unit" => FALSE,
"display" => FALSE,
],
),
"status" => $declination2->getStatus(),
];
}
}
$declinationNextField = array_values($declinationNextField);
$response = new JsonResponse();
$response->setData($declinationNextField);
return $response;
}
/**
* @param $name
*
* @return string
*/
private function validFieldName($name): string
{
return strtolower(preg_replace("/\s+/", "_", $name));
}
/**
* Récupère le stock en temps réel pour un produit
*
* @param Request $request
*
* @return JsonResponse
*/
public function getProductStockFromBo(Request $request): JsonResponse
{
$sku = $request->request->get("sku");
$stock = $this->stockService->getProductStockFromBoAndPendingOrder($sku);
return new JsonResponse(
[
'stock' => $stock,
'sku' => $sku,
'displayStockInformation' => TRUE,
],
Response::HTTP_OK,
);
}
/**
* @param Request $request
*
* @return Response
*/
public function requestAvailableAjax(Request $request): Response
{
/** @var User $user */
$user = $this->getUser();
$rpa = (new RequestProductAvailable())
->setUser($user)
->setSku($request->get("sku"))
->setQuantity($request->get("quantity"))
;
$user->addRequestProductAvailable($rpa);
$this->em->persist($user);
$this->em->persist($rpa);
$this->em->flush();
// @TODO : envoi email
return new Response(NULL, 200);
}
/**
* Traduction des titres des produits
*
* @param Request $request
*
* @return JsonResponse
*
* @throws JsonException
*/
public function translateProductTitles(Request $request): JsonResponse
{
if (!$this->translationBase->translationIsEnabled('product_title')) {
return new JsonResponse(['error' => 'La traduction n\'est pas active'], Response::HTTP_OK);
}
$products = $request->get('productTranslation');
if ($products === NULL) {
return new JsonResponse(['error' => 'Aucun produit à traduire'], Response::HTTP_OK);
}
$formattedProducts = [];
foreach ($products as $product) {
$formattedProducts[ $product[ 'sku' ] ] = $product[ 'name' ];
}
$catalogue = $request->get('catalogue');
$locale = $this->translationBase->getLanguageFromCurrentUser();
$translations = $this->catalogueTranslation->getTranslatedTitlesWithSku($formattedProducts, $locale, $catalogue);
return new JsonResponse(['products' => $translations], Response::HTTP_OK);
}
}